source: src/Parser/TypeData.cc @ 44adf1b

Last change on this file since 44adf1b was 44adf1b, checked in by Andrew Beach <ajbeach@…>, 4 months ago

Removed casts around get_next (also replaced with direct field access) that are no longer needed.

  • Property mode set to 100644
File size: 43.3 KB
RevLine 
[b87a5ed]1//
2// Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
3//
4// The contents of this file are covered under the licence agreement in the
5// file "LICENCE" distributed with Cforall.
6//
[f1e012b]7// TypeData.cc --
[b87a5ed]8//
9// Author           : Rodolfo G. Esteves
10// Created On       : Sat May 16 15:12:51 2015
[b1f2007]11// Last Modified By : Peter A. Buhr
[4eb3a7c5]12// Last Modified On : Fri Feb 23 08:58:30 2024
13// Update Count     : 734
[b87a5ed]14//
15
[bb7422a]16#include "TypeData.h"
17
[d180746]18#include <cassert>                 // for assert
19#include <ostream>                 // for operator<<, ostream, basic_ostream
20
[bb7422a]21#include "AST/Decl.hpp"            // for AggregateDecl, ObjectDecl, TypeDe...
[4eb3a7c5]22#include "AST/Attribute.hpp"       // for Attribute
[bb7422a]23#include "AST/Init.hpp"            // for SingleInit, ListInit
24#include "AST/Print.hpp"           // for print
[d180746]25#include "Common/SemanticError.h"  // for SemanticError
[bb7422a]26#include "Common/utility.h"        // for splice, spliceBegin
[4eb3a7c5]27#include "Common/Iterate.hpp"      // for reverseIterate
[c468150]28#include "Parser/ExpressionNode.h" // for ExpressionNode
29#include "Parser/StatementNode.h"  // for StatementNode
[d180746]30
31class Attribute;
32
[2298f728]33using namespace std;
[51b7345]34
[0b0f1dd]35TypeData::TypeData( Kind k ) : location( yylloc ), kind( k ), base( nullptr ), forall( nullptr ) /*, PTR1( (void*)(0xdeadbeefdeadbeef)), PTR2( (void*)(0xdeadbeefdeadbeef) ) */ {
[b87a5ed]36        switch ( kind ) {
[702e826]37        case Unknown:
38        case Pointer:
39        case Reference:
40        case EnumConstant:
41        case GlobalScope:
42        case Basic:
43                // No unique data to initialize.
44                break;
45        case Array:
[2298f728]46                array.dimension = nullptr;
[8f6f47d7]47                array.isVarLen = false;
48                array.isStatic = false;
[b87a5ed]49                break;
[702e826]50        case Function:
[2298f728]51                function.params = nullptr;
52                function.idList = nullptr;
53                function.oldDeclList = nullptr;
54                function.body = nullptr;
[84276ba]55                function.withExprs = nullptr;
[b87a5ed]56                break;
[702e826]57        case Enum:
[e496303]58                enumeration.name = nullptr;
59                enumeration.constants = nullptr;
60                enumeration.body = false;
[3d7e53b]61                enumeration.anon = false;
[6926a6d]62                break;
[702e826]63        case Aggregate:
[bb7422a]64                aggregate.kind = ast::AggregateDecl::NoAggregate;
[2298f728]65                aggregate.name = nullptr;
66                aggregate.params = nullptr;
67                aggregate.actuals = nullptr;
68                aggregate.fields = nullptr;
[4a9ccc3]69                aggregate.body = false;
[d15a45d]70                aggregate.tagged = false;
71                aggregate.parent = nullptr;
[3d7e53b]72                aggregate.anon = false;
[b87a5ed]73                break;
[702e826]74        case AggregateInst:
[2298f728]75                aggInst.aggregate = nullptr;
76                aggInst.params = nullptr;
[8f91c9ae]77                aggInst.hoistType = false;
[b87a5ed]78                break;
[702e826]79        case Symbolic:
80        case SymbolicInst:
[2298f728]81                symbolic.name = nullptr;
82                symbolic.params = nullptr;
83                symbolic.actuals = nullptr;
84                symbolic.assertions = nullptr;
[b87a5ed]85                break;
[702e826]86        case Tuple:
[8f6f47d7]87                tuple = nullptr;
[b87a5ed]88                break;
[702e826]89        case Typeof:
90        case Basetypeof:
[8f6f47d7]91                typeexpr = nullptr;
[b87a5ed]92                break;
[702e826]93        case Vtable:
[bb7422a]94        case Builtin:
[702e826]95                // No unique data to initialize.
[93bbbc4]96                break;
[702e826]97        case Qualified:
[c194661]98                qualified.parent = nullptr;
99                qualified.child = nullptr;
[b87a5ed]100                break;
[68cd1ce]101        } // switch
[413ad05]102} // TypeData::TypeData
[51b7345]103
[201aeb9]104
[c8ffe20b]105TypeData::~TypeData() {
[b87a5ed]106        delete base;
107        delete forall;
108
109        switch ( kind ) {
[702e826]110        case Unknown:
111        case Pointer:
112        case Reference:
113        case EnumConstant:
114        case GlobalScope:
115        case Basic:
[bb7422a]116                // No unique data to deconstruct.
[b87a5ed]117                break;
[702e826]118        case Array:
[8f6f47d7]119                delete array.dimension;
[b87a5ed]120                break;
[702e826]121        case Function:
[8f6f47d7]122                delete function.params;
123                delete function.idList;
124                delete function.oldDeclList;
125                delete function.body;
[84276ba]126                delete function.withExprs;
[b87a5ed]127                break;
[702e826]128        case Aggregate:
[2298f728]129                delete aggregate.name;
[8f6f47d7]130                delete aggregate.params;
131                delete aggregate.actuals;
132                delete aggregate.fields;
[b87a5ed]133                break;
[702e826]134        case AggregateInst:
[8f6f47d7]135                delete aggInst.aggregate;
136                delete aggInst.params;
[b87a5ed]137                break;
[702e826]138        case Enum:
[2298f728]139                delete enumeration.name;
[8f6f47d7]140                delete enumeration.constants;
[b87a5ed]141                break;
[702e826]142        case Symbolic:
143        case SymbolicInst:
[2298f728]144                delete symbolic.name;
[8f6f47d7]145                delete symbolic.params;
146                delete symbolic.actuals;
147                delete symbolic.assertions;
[b87a5ed]148                break;
[702e826]149        case Tuple:
[b87a5ed]150                delete tuple;
151                break;
[702e826]152        case Typeof:
153        case Basetypeof:
[b87a5ed]154                delete typeexpr;
155                break;
[702e826]156        case Vtable:
157        case Builtin:
158                // No unique data to deconstruct.
[93bbbc4]159                break;
[702e826]160        case Qualified:
[c194661]161                delete qualified.parent;
162                delete qualified.child;
[702e826]163                break;
[68cd1ce]164        } // switch
[413ad05]165} // TypeData::~TypeData
[51b7345]166
[201aeb9]167
[413ad05]168TypeData * TypeData::clone() const {
169        TypeData * newtype = new TypeData( kind );
[738e304]170        newtype->qualifiers = qualifiers;
[5bf685f]171        newtype->base = maybeCopy( base );
172        newtype->forall = maybeCopy( forall );
[b87a5ed]173
174        switch ( kind ) {
[702e826]175        case Unknown:
176        case EnumConstant:
177        case Pointer:
178        case Reference:
179        case GlobalScope:
[b87a5ed]180                // nothing else to copy
181                break;
[702e826]182        case Basic:
[5b639ee]183                newtype->basictype = basictype;
184                newtype->complextype = complextype;
185                newtype->signedness = signedness;
186                newtype->length = length;
[b87a5ed]187                break;
[702e826]188        case Array:
[5bf685f]189                newtype->array.dimension = maybeCopy( array.dimension );
[8f6f47d7]190                newtype->array.isVarLen = array.isVarLen;
191                newtype->array.isStatic = array.isStatic;
[b87a5ed]192                break;
[702e826]193        case Function:
[5bf685f]194                newtype->function.params = maybeCopy( function.params );
195                newtype->function.idList = maybeCopy( function.idList );
196                newtype->function.oldDeclList = maybeCopy( function.oldDeclList );
197                newtype->function.body = maybeCopy( function.body );
198                newtype->function.withExprs = maybeCopy( function.withExprs );
[b87a5ed]199                break;
[702e826]200        case Aggregate:
[d15a45d]201                newtype->aggregate.kind = aggregate.kind;
[2298f728]202                newtype->aggregate.name = aggregate.name ? new string( *aggregate.name ) : nullptr;
[4eb3a7c5]203                newtype->aggregate.parent = aggregate.parent ? new string( *aggregate.parent ) : nullptr;
[5bf685f]204                newtype->aggregate.params = maybeCopy( aggregate.params );
205                newtype->aggregate.actuals = maybeCopy( aggregate.actuals );
206                newtype->aggregate.fields = maybeCopy( aggregate.fields );
[4eb3a7c5]207                newtype->aggregate.attributes = aggregate.attributes;
[8f6f47d7]208                newtype->aggregate.body = aggregate.body;
[3d7e53b]209                newtype->aggregate.anon = aggregate.anon;
[6ea87486]210                newtype->aggregate.tagged = aggregate.tagged;
[b87a5ed]211                break;
[702e826]212        case AggregateInst:
[5bf685f]213                newtype->aggInst.aggregate = maybeCopy( aggInst.aggregate );
214                newtype->aggInst.params = maybeCopy( aggInst.params );
[43c89a7]215                newtype->aggInst.hoistType = aggInst.hoistType;
[b87a5ed]216                break;
[702e826]217        case Enum:
[2298f728]218                newtype->enumeration.name = enumeration.name ? new string( *enumeration.name ) : nullptr;
[5bf685f]219                newtype->enumeration.constants = maybeCopy( enumeration.constants );
[ca1a547]220                newtype->enumeration.body = enumeration.body;
[3d7e53b]221                newtype->enumeration.anon = enumeration.anon;
[b87a5ed]222                break;
[702e826]223        case Symbolic:
224        case SymbolicInst:
[2298f728]225                newtype->symbolic.name = symbolic.name ? new string( *symbolic.name ) : nullptr;
[5bf685f]226                newtype->symbolic.params = maybeCopy( symbolic.params );
227                newtype->symbolic.actuals = maybeCopy( symbolic.actuals );
228                newtype->symbolic.assertions = maybeCopy( symbolic.assertions );
[8f6f47d7]229                newtype->symbolic.isTypedef = symbolic.isTypedef;
[b87a5ed]230                break;
[702e826]231        case Tuple:
[5bf685f]232                newtype->tuple = maybeCopy( tuple );
[b87a5ed]233                break;
[702e826]234        case Typeof:
235        case Basetypeof:
[5bf685f]236                newtype->typeexpr = maybeCopy( typeexpr );
[b87a5ed]237                break;
[702e826]238        case Vtable:
[93bbbc4]239                break;
[702e826]240        case Builtin:
[4cb935e]241                assert( builtintype == DeclarationNode::Zero || builtintype == DeclarationNode::One );
242                newtype->builtintype = builtintype;
[90c3b1c]243                break;
[702e826]244        case Qualified:
[5bf685f]245                newtype->qualified.parent = maybeCopy( qualified.parent );
246                newtype->qualified.child = maybeCopy( qualified.child );
[c194661]247                break;
[68cd1ce]248        } // switch
[b87a5ed]249        return newtype;
[413ad05]250} // TypeData::clone
[51b7345]251
[201aeb9]252
[2298f728]253void TypeData::print( ostream &os, int indent ) const {
[bb7422a]254        ast::print( os, qualifiers );
[b87a5ed]255
256        if ( forall ) {
257                os << "forall " << endl;
[721f17a]258                forall->printList( os, indent + 4 );
[68cd1ce]259        } // if
[b87a5ed]260
261        switch ( kind ) {
[702e826]262        case Basic:
[f7e4db27]263                if ( signedness != DeclarationNode::NoSignedness ) os << DeclarationNode::signednessNames[ signedness ] << " ";
264                if ( length != DeclarationNode::NoLength ) os << DeclarationNode::lengthNames[ length ] << " ";
[66406f3]265                if ( complextype != DeclarationNode::NoComplexType ) os << DeclarationNode::complexTypeNames[ complextype ] << " ";
266                if ( basictype != DeclarationNode::NoBasicType ) os << DeclarationNode::basicTypeNames[ basictype ] << " ";
[b87a5ed]267                break;
[702e826]268        case Pointer:
[b87a5ed]269                os << "pointer ";
270                if ( base ) {
271                        os << "to ";
272                        base->print( os, indent );
[68cd1ce]273                } // if
[b87a5ed]274                break;
[702e826]275        case Reference:
[f7e4db27]276                os << "reference ";
277                if ( base ) {
278                        os << "to ";
279                        base->print( os, indent );
280                } // if
[b87a5ed]281                break;
[702e826]282        case Array:
[8f6f47d7]283                if ( array.isStatic ) {
[b87a5ed]284                        os << "static ";
[68cd1ce]285                } // if
[8f6f47d7]286                if ( array.dimension ) {
[b87a5ed]287                        os << "array of ";
[8f6f47d7]288                        array.dimension->printOneLine( os, indent );
289                } else if ( array.isVarLen ) {
[b87a5ed]290                        os << "variable-length array of ";
291                } else {
292                        os << "open array of ";
[68cd1ce]293                } // if
[b87a5ed]294                if ( base ) {
295                        base->print( os, indent );
[68cd1ce]296                } // if
[b87a5ed]297                break;
[702e826]298        case Function:
[b87a5ed]299                os << "function" << endl;
[8f6f47d7]300                if ( function.params ) {
[721f17a]301                        os << string( indent + 2, ' ' ) << "with parameters " << endl;
[8f6f47d7]302                        function.params->printList( os, indent + 4 );
[b87a5ed]303                } else {
[07ec1a2]304                        os << string( indent + 2, ' ' ) << "with no parameters" << endl;
[68cd1ce]305                } // if
[8f6f47d7]306                if ( function.idList ) {
[721f17a]307                        os << string( indent + 2, ' ' ) << "with old-style identifier list " << endl;
[8f6f47d7]308                        function.idList->printList( os, indent + 4 );
[68cd1ce]309                } // if
[8f6f47d7]310                if ( function.oldDeclList ) {
[721f17a]311                        os << string( indent + 2, ' ' ) << "with old-style declaration list " << endl;
[8f6f47d7]312                        function.oldDeclList->printList( os, indent + 4 );
[68cd1ce]313                } // if
[721f17a]314                os << string( indent + 2, ' ' ) << "returning ";
[b87a5ed]315                if ( base ) {
[721f17a]316                        base->print( os, indent + 4 );
[b87a5ed]317                } else {
318                        os << "nothing ";
[68cd1ce]319                } // if
[b87a5ed]320                os << endl;
[8f6f47d7]321                if ( function.body ) {
[ca1a547]322                        os << string( indent + 2, ' ' ) << "with body " << endl;
[8f6f47d7]323                        function.body->printList( os, indent + 2 );
[68cd1ce]324                } // if
[b87a5ed]325                break;
[702e826]326        case Aggregate:
[bb7422a]327                os << ast::AggregateDecl::aggrString( aggregate.kind ) << ' ' << *aggregate.name << endl;
[8f6f47d7]328                if ( aggregate.params ) {
[07ec1a2]329                        os << string( indent + 2, ' ' ) << "with type parameters" << endl;
[8f6f47d7]330                        aggregate.params->printList( os, indent + 4 );
[68cd1ce]331                } // if
[8f6f47d7]332                if ( aggregate.actuals ) {
[07ec1a2]333                        os << string( indent + 2, ' ' ) << "instantiated with actual parameters" << endl;
[8f6f47d7]334                        aggregate.actuals->printList( os, indent + 4 );
[68cd1ce]335                } // if
[8f6f47d7]336                if ( aggregate.fields ) {
[07ec1a2]337                        os << string( indent + 2, ' ' ) << "with members" << endl;
[8f6f47d7]338                        aggregate.fields->printList( os, indent + 4 );
[5d125e4]339                } // if
[8f6f47d7]340                if ( aggregate.body ) {
[4eb3a7c5]341                        os << string( indent + 2, ' ' ) << "with body" << endl;
342                } // if
343                if ( ! aggregate.attributes.empty() ) {
344                        os << string( indent + 2, ' ' ) << "with attributes" << endl;
345                        for ( ast::ptr<ast::Attribute> const & attr : reverseIterate( aggregate.attributes ) ) {
346                                os << string( indent + 4, ' ' );
347                                ast::print( os, attr, indent + 2 );
348                        } // for
[68cd1ce]349                } // if
[b87a5ed]350                break;
[702e826]351        case AggregateInst:
[8f6f47d7]352                if ( aggInst.aggregate ) {
[b87a5ed]353                        os << "instance of " ;
[8f6f47d7]354                        aggInst.aggregate->print( os, indent );
[b87a5ed]355                } else {
356                        os << "instance of an unspecified aggregate ";
[68cd1ce]357                } // if
[8f6f47d7]358                if ( aggInst.params ) {
[07ec1a2]359                        os << string( indent + 2, ' ' ) << "with parameters" << endl;
[8f6f47d7]360                        aggInst.params->printList( os, indent + 2 );
[68cd1ce]361                } // if
[b87a5ed]362                break;
[702e826]363        case Enum:
[2d37a788]364                os << "enumeration " << *enumeration.name << endl;;
[8f6f47d7]365                if ( enumeration.constants ) {
[b87a5ed]366                        os << "with constants" << endl;
[8f6f47d7]367                        enumeration.constants->printList( os, indent + 2 );
[68cd1ce]368                } // if
[ca1a547]369                if ( enumeration.body ) {
[4eb3a7c5]370                        os << string( indent + 2, ' ' ) << "with body" << endl;
[ca1a547]371                } // if
[9e7236f4]372                if ( base ) {
373                        os << "for ";
374                        base->print( os, indent + 2 );
375                } // if
[b87a5ed]376                break;
[702e826]377        case EnumConstant:
[f7e4db27]378                os << "enumeration constant ";
[b87a5ed]379                break;
[702e826]380        case Symbolic:
[8f6f47d7]381                if ( symbolic.isTypedef ) {
[b87a5ed]382                        os << "typedef definition ";
383                } else {
384                        os << "type definition ";
[68cd1ce]385                } // if
[8f6f47d7]386                if ( symbolic.params ) {
[721f17a]387                        os << endl << string( indent + 2, ' ' ) << "with parameters" << endl;
[8f6f47d7]388                        symbolic.params->printList( os, indent + 2 );
[68cd1ce]389                } // if
[8f6f47d7]390                if ( symbolic.assertions ) {
[721f17a]391                        os << endl << string( indent + 2, ' ' ) << "with assertions" << endl;
[8f6f47d7]392                        symbolic.assertions->printList( os, indent + 4 );
[721f17a]393                        os << string( indent + 2, ' ' );
[68cd1ce]394                } // if
[b87a5ed]395                if ( base ) {
396                        os << "for ";
397                        base->print( os, indent + 2 );
[68cd1ce]398                } // if
[b87a5ed]399                break;
[702e826]400        case SymbolicInst:
[f7e4db27]401                os << *symbolic.name;
402                if ( symbolic.actuals ) {
403                        os << "(";
404                        symbolic.actuals->printList( os, indent + 2 );
405                        os << ")";
406                } // if
407                break;
[702e826]408        case Tuple:
[b87a5ed]409                os << "tuple ";
[8f6f47d7]410                if ( tuple ) {
[07ec1a2]411                        os << "with members" << endl;
[8f6f47d7]412                        tuple->printList( os, indent + 2 );
[68cd1ce]413                } // if
[b87a5ed]414                break;
[702e826]415        case Basetypeof:
[f855545]416                os << "base-";
[c45b304]417                #if defined(__GNUC__) && __GNUC__ >= 7
418                        __attribute__((fallthrough));
419                #endif
[66406f3]420                // FALL THROUGH
[702e826]421        case Typeof:
[b87a5ed]422                os << "type-of expression ";
[8f6f47d7]423                if ( typeexpr ) {
424                        typeexpr->print( os, indent + 2 );
[68cd1ce]425                } // if
[b87a5ed]426                break;
[702e826]427        case Vtable:
[66406f3]428                os << "vtable";
429                break;
[702e826]430        case Builtin:
[9dc31c10]431                os << DeclarationNode::builtinTypeNames[builtintype];
[90c3b1c]432                break;
[702e826]433        case GlobalScope:
[f7e4db27]434                break;
[702e826]435        case Qualified:
[f7e4db27]436                qualified.parent->print( os );
437                os << ".";
438                qualified.child->print( os );
439                break;
[702e826]440        case Unknown:
[f7e4db27]441                os << "entity of unknown type ";
442                break;
[702e826]443        default:
[5b639ee]444                os << "internal error: TypeData::print " << kind << endl;
[1db21619]445                assert( false );
[68cd1ce]446        } // switch
[413ad05]447} // TypeData::print
[51b7345]448
[7de22b28]449const std::string * TypeData::leafName() const {
450        switch ( kind ) {
[702e826]451        case Unknown:
452        case Pointer:
453        case Reference:
454        case EnumConstant:
455        case GlobalScope:
456        case Array:
457        case Basic:
458        case Function:
459        case AggregateInst:
460        case Tuple:
461        case Typeof:
462        case Basetypeof:
463        case Builtin:
464        case Vtable:
[7de22b28]465                assertf(false, "Tried to get leaf name from kind without a name: %d", kind);
466                break;
[702e826]467        case Aggregate:
[7de22b28]468                return aggregate.name;
[702e826]469        case Enum:
[7de22b28]470                return enumeration.name;
[702e826]471        case Symbolic:
472        case SymbolicInst:
[7de22b28]473                return symbolic.name;
[702e826]474        case Qualified:
[7de22b28]475                return qualified.child->leafName();
476        } // switch
477        assert(false);
478}
479
[201aeb9]480
[bb7422a]481void buildForall(
482                const DeclarationNode * firstNode,
483                std::vector<ast::ptr<ast::TypeInstType>> &outputList ) {
484        {
485                std::vector<ast::ptr<ast::Type>> tmpList;
486                buildTypeList( firstNode, tmpList );
487                for ( auto tmp : tmpList ) {
488                        outputList.emplace_back(
489                                strict_dynamic_cast<const ast::TypeInstType *>(
490                                        tmp.release() ) );
491                }
492        }
[f0ecf9b]493        auto n = firstNode;
[bb7422a]494        for ( auto i = outputList.begin() ;
495                        i != outputList.end() ;
[44adf1b]496                        ++i, n = n->next ) {
[bb7422a]497                // Only the object type class adds additional assertions.
498                if ( n->variable.tyClass != ast::TypeDecl::Otype ) {
499                        continue;
500                }
501
502                ast::TypeDecl const * td = i->strict_as<ast::TypeDecl>();
503                std::vector<ast::ptr<ast::DeclWithType>> newAssertions;
504                auto mutTypeDecl = ast::mutate( td );
505                const CodeLocation & location = mutTypeDecl->location;
506                *i = mutTypeDecl;
507
508                // add assertion parameters to `type' tyvars in reverse order
509                // add assignment operator:  T * ?=?(T *, T)
510                newAssertions.push_back( new ast::FunctionDecl(
511                        location,
512                        "?=?",
513                        {}, // forall
514                        {}, // assertions
515                        {
516                                new ast::ObjectDecl(
517                                        location,
518                                        "",
519                                        new ast::ReferenceType( i->get() ),
520                                        (ast::Init *)nullptr,
521                                        ast::Storage::Classes(),
522                                        ast::Linkage::Cforall,
523                                        (ast::Expr *)nullptr
524                                ),
525                                new ast::ObjectDecl(
526                                        location,
527                                        "",
528                                        i->get(),
529                                        (ast::Init *)nullptr,
530                                        ast::Storage::Classes(),
531                                        ast::Linkage::Cforall,
532                                        (ast::Expr *)nullptr
533                                ),
534                        }, // params
535                        {
536                                new ast::ObjectDecl(
537                                        location,
538                                        "",
539                                        i->get(),
540                                        (ast::Init *)nullptr,
541                                        ast::Storage::Classes(),
542                                        ast::Linkage::Cforall,
543                                        (ast::Expr *)nullptr
544                                ),
545                        }, // returns
546                        (ast::CompoundStmt *)nullptr,
547                        ast::Storage::Classes(),
548                        ast::Linkage::Cforall
549                ) );
550
551                // add default ctor:  void ?{}(T *)
552                newAssertions.push_back( new ast::FunctionDecl(
553                        location,
554                        "?{}",
555                        {}, // forall
556                        {}, // assertions
557                        {
558                                new ast::ObjectDecl(
559                                        location,
560                                        "",
561                                        new ast::ReferenceType( i->get() ),
562                                        (ast::Init *)nullptr,
563                                        ast::Storage::Classes(),
564                                        ast::Linkage::Cforall,
565                                        (ast::Expr *)nullptr
566                                ),
567                        }, // params
568                        {}, // returns
569                        (ast::CompoundStmt *)nullptr,
570                        ast::Storage::Classes(),
571                        ast::Linkage::Cforall
572                ) );
573
574                // add copy ctor:  void ?{}(T *, T)
575                newAssertions.push_back( new ast::FunctionDecl(
576                        location,
577                        "?{}",
578                        {}, // forall
579                        {}, // assertions
580                        {
581                                new ast::ObjectDecl(
582                                        location,
583                                        "",
584                                        new ast::ReferenceType( i->get() ),
585                                        (ast::Init *)nullptr,
586                                        ast::Storage::Classes(),
587                                        ast::Linkage::Cforall,
588                                        (ast::Expr *)nullptr
589                                ),
590                                new ast::ObjectDecl(
591                                        location,
592                                        "",
593                                        i->get(),
594                                        (ast::Init *)nullptr,
595                                        ast::Storage::Classes(),
596                                        ast::Linkage::Cforall,
597                                        (ast::Expr *)nullptr
598                                ),
599                        }, // params
600                        {}, // returns
601                        (ast::CompoundStmt *)nullptr,
602                        ast::Storage::Classes(),
603                        ast::Linkage::Cforall
604                ) );
605
606                // add dtor:  void ^?{}(T *)
607                newAssertions.push_back( new ast::FunctionDecl(
608                        location,
609                        "^?{}",
610                        {}, // forall
611                        {}, // assertions
612                        {
613                                new ast::ObjectDecl(
614                                        location,
615                                        "",
616                                        new ast::ReferenceType( i->get() ),
617                                        (ast::Init *)nullptr,
618                                        ast::Storage::Classes(),
619                                        ast::Linkage::Cforall,
620                                        (ast::Expr *)nullptr
621                                ),
622                        }, // params
623                        {}, // returns
624                        (ast::CompoundStmt *)nullptr,
625                        ast::Storage::Classes(),
626                        ast::Linkage::Cforall
627                ) );
628
629                spliceBegin( mutTypeDecl->assertions, newAssertions );
630        } // for
631}
632
633
634void buildForall(
635                const DeclarationNode * firstNode,
636                std::vector<ast::ptr<ast::TypeDecl>> &outputForall ) {
637        buildList( firstNode, outputForall );
638        auto n = firstNode;
639        for ( auto i = outputForall.begin() ;
640                        i != outputForall.end() ;
[44adf1b]641                        ++i, n = n->next ) {
[bb7422a]642                // Only the object type class adds additional assertions.
643                if ( n->variable.tyClass != ast::TypeDecl::Otype ) {
644                        continue;
645                }
646
647                ast::TypeDecl const * td = i->strict_as<ast::TypeDecl>();
648                std::vector<ast::ptr<ast::DeclWithType>> newAssertions;
649                auto mutTypeDecl = ast::mutate( td );
650                const CodeLocation & location = mutTypeDecl->location;
651                *i = mutTypeDecl;
652
653                // add assertion parameters to `type' tyvars in reverse order
654                // add assignment operator:  T * ?=?(T *, T)
655                newAssertions.push_back( new ast::FunctionDecl(
656                        location,
657                        "?=?",
658                        {}, // forall
659                        {}, // assertions
660                        {
661                                new ast::ObjectDecl(
662                                        location,
663                                        "",
664                                        new ast::ReferenceType( new ast::TypeInstType( td->name, *i ) ),
665                                        (ast::Init *)nullptr,
666                                        ast::Storage::Classes(),
667                                        ast::Linkage::Cforall,
668                                        (ast::Expr *)nullptr
669                                ),
670                                new ast::ObjectDecl(
671                                        location,
672                                        "",
673                                        new ast::TypeInstType( td->name, *i ),
674                                        (ast::Init *)nullptr,
675                                        ast::Storage::Classes(),
676                                        ast::Linkage::Cforall,
677                                        (ast::Expr *)nullptr
678                                ),
679                        }, // params
680                        {
681                                new ast::ObjectDecl(
682                                        location,
683                                        "",
684                                        new ast::TypeInstType( td->name, *i ),
685                                        (ast::Init *)nullptr,
686                                        ast::Storage::Classes(),
687                                        ast::Linkage::Cforall,
688                                        (ast::Expr *)nullptr
689                                ),
690                        }, // returns
691                        (ast::CompoundStmt *)nullptr,
692                        ast::Storage::Classes(),
693                        ast::Linkage::Cforall
694                ) );
695
696                // add default ctor:  void ?{}(T *)
697                newAssertions.push_back( new ast::FunctionDecl(
698                        location,
699                        "?{}",
700                        {}, // forall
701                        {}, // assertions
702                        {
703                                new ast::ObjectDecl(
704                                        location,
705                                        "",
706                                        new ast::ReferenceType(
707                                                new ast::TypeInstType( td->name, i->get() ) ),
708                                        (ast::Init *)nullptr,
709                                        ast::Storage::Classes(),
710                                        ast::Linkage::Cforall,
711                                        (ast::Expr *)nullptr
712                                ),
713                        }, // params
714                        {}, // returns
715                        (ast::CompoundStmt *)nullptr,
716                        ast::Storage::Classes(),
717                        ast::Linkage::Cforall
718                ) );
719
720                // add copy ctor:  void ?{}(T *, T)
721                newAssertions.push_back( new ast::FunctionDecl(
722                        location,
723                        "?{}",
724                        {}, // forall
725                        {}, // assertions
726                        {
727                                new ast::ObjectDecl(
728                                        location,
729                                        "",
730                                        new ast::ReferenceType(
731                                                new ast::TypeInstType( td->name, *i ) ),
732                                        (ast::Init *)nullptr,
733                                        ast::Storage::Classes(),
734                                        ast::Linkage::Cforall,
735                                        (ast::Expr *)nullptr
736                                ),
737                                new ast::ObjectDecl(
738                                        location,
739                                        "",
740                                        new ast::TypeInstType( td->name, *i ),
741                                        (ast::Init *)nullptr,
742                                        ast::Storage::Classes(),
743                                        ast::Linkage::Cforall,
744                                        (ast::Expr *)nullptr
745                                ),
746                        }, // params
747                        {}, // returns
748                        (ast::CompoundStmt *)nullptr,
749                        ast::Storage::Classes(),
750                        ast::Linkage::Cforall
751                ) );
752
753                // add dtor:  void ^?{}(T *)
754                newAssertions.push_back( new ast::FunctionDecl(
755                        location,
756                        "^?{}",
757                        {}, // forall
758                        {}, // assertions
759                        {
760                                new ast::ObjectDecl(
761                                        location,
762                                        "",
763                                        new ast::ReferenceType(
764                                                new ast::TypeInstType( i->get() )
765                                        ),
766                                        (ast::Init *)nullptr,
767                                        ast::Storage::Classes(),
768                                        ast::Linkage::Cforall,
769                                        (ast::Expr *)nullptr
770                                ),
771                        }, // params
772                        {}, // returns
773                        (ast::CompoundStmt *)nullptr,
774                        ast::Storage::Classes(),
775                        ast::Linkage::Cforall
776                ) );
777
778                spliceBegin( mutTypeDecl->assertions, newAssertions );
[68cd1ce]779        } // for
[201aeb9]780} // buildForall
781
[51b7345]782
[bb7422a]783ast::Type * typebuild( const TypeData * td ) {
[413ad05]784        assert( td );
785        switch ( td->kind ) {
[702e826]786        case TypeData::Unknown:
[07de76b]787                // fill in implicit int
[bb7422a]788                return new ast::BasicType(
789                        ast::BasicType::SignedInt,
790                        buildQualifiers( td )
791                );
[702e826]792        case TypeData::Basic:
[07de76b]793                return buildBasicType( td );
[702e826]794        case TypeData::Pointer:
[07de76b]795                return buildPointer( td );
[702e826]796        case TypeData::Array:
[07de76b]797                return buildArray( td );
[702e826]798        case TypeData::Reference:
[07de76b]799                return buildReference( td );
[702e826]800        case TypeData::Function:
[bb7422a]801                return buildFunctionType( td );
[702e826]802        case TypeData::AggregateInst:
[07de76b]803                return buildAggInst( td );
[702e826]804        case TypeData::EnumConstant:
[bb7422a]805                return new ast::EnumInstType( "", buildQualifiers( td ) );
[702e826]806        case TypeData::SymbolicInst:
[07de76b]807                return buildSymbolicInst( td );
[702e826]808        case TypeData::Tuple:
[07de76b]809                return buildTuple( td );
[702e826]810        case TypeData::Typeof:
811        case TypeData::Basetypeof:
[07de76b]812                return buildTypeof( td );
[702e826]813        case TypeData::Vtable:
[93bbbc4]814                return buildVtable( td );
[702e826]815        case TypeData::Builtin:
[07de76b]816                switch ( td->builtintype ) {
[702e826]817                case DeclarationNode::Zero:
[bb7422a]818                        return new ast::ZeroType();
[702e826]819                case DeclarationNode::One:
[bb7422a]820                        return new ast::OneType();
[702e826]821                default:
[bb7422a]822                        return new ast::VarArgsType( buildQualifiers( td ) );
[07de76b]823                } // switch
[702e826]824        case TypeData::GlobalScope:
[bb7422a]825                return new ast::GlobalScopeType();
[702e826]826        case TypeData::Qualified:
[bb7422a]827                return new ast::QualifiedType(
828                        typebuild( td->qualified.parent ),
829                        typebuild( td->qualified.child ),
830                        buildQualifiers( td )
831                );
[702e826]832        case TypeData::Symbolic:
833        case TypeData::Enum:
834        case TypeData::Aggregate:
[07de76b]835                assert( false );
[68cd1ce]836        } // switch
[c194661]837
[2298f728]838        return nullptr;
[413ad05]839} // typebuild
840
[201aeb9]841
[413ad05]842TypeData * typeextractAggregate( const TypeData * td, bool toplevel ) {
[2298f728]843        TypeData * ret = nullptr;
[51b7345]844
[413ad05]845        switch ( td->kind ) {
[702e826]846        case TypeData::Aggregate:
[b2da0574]847                if ( ! toplevel && td->aggregate.body ) {
[413ad05]848                        ret = td->clone();
849                } // if
850                break;
[702e826]851        case TypeData::Enum:
[b2da0574]852                if ( ! toplevel && td->enumeration.body ) {
[413ad05]853                        ret = td->clone();
854                } // if
855                break;
[702e826]856        case TypeData::AggregateInst:
[8f6f47d7]857                if ( td->aggInst.aggregate ) {
858                        ret = typeextractAggregate( td->aggInst.aggregate, false );
[413ad05]859                } // if
860                break;
[702e826]861        default:
[413ad05]862                if ( td->base ) {
863                        ret = typeextractAggregate( td->base, false );
864                } // if
865        } // switch
866        return ret;
867} // typeextractAggregate
868
[201aeb9]869
[bb7422a]870ast::CV::Qualifiers buildQualifiers( const TypeData * td ) {
[738e304]871        return td->qualifiers;
[413ad05]872} // buildQualifiers
[51b7345]873
[201aeb9]874
875static string genTSError( string msg, DeclarationNode::BasicType basictype ) {
[b1f2007]876        SemanticError( yylloc, "invalid type specifier \"%s\" for type \"%s\".", msg.c_str(), DeclarationNode::basicTypeNames[basictype] );
[201aeb9]877} // genTSError
878
[bb7422a]879ast::Type * buildBasicType( const TypeData * td ) {
880        ast::BasicType::Kind ret;
[b87a5ed]881
[5b639ee]882        switch ( td->basictype ) {
[702e826]883        case DeclarationNode::Void:
[201aeb9]884                if ( td->signedness != DeclarationNode::NoSignedness ) {
885                        genTSError( DeclarationNode::signednessNames[ td->signedness ], td->basictype );
886                } // if
887                if ( td->length != DeclarationNode::NoLength ) {
888                        genTSError( DeclarationNode::lengthNames[ td->length ], td->basictype );
[68cd1ce]889                } // if
[bb7422a]890                return new ast::VoidType( buildQualifiers( td ) );
[5b639ee]891                break;
892
[702e826]893        case DeclarationNode::Bool:
[5b639ee]894                if ( td->signedness != DeclarationNode::NoSignedness ) {
[201aeb9]895                        genTSError( DeclarationNode::signednessNames[ td->signedness ], td->basictype );
[5b639ee]896                } // if
897                if ( td->length != DeclarationNode::NoLength ) {
[201aeb9]898                        genTSError( DeclarationNode::lengthNames[ td->length ], td->basictype );
[68cd1ce]899                } // if
[51b7345]900
[bb7422a]901                ret = ast::BasicType::Bool;
[5b639ee]902                break;
903
[702e826]904        case DeclarationNode::Char:
[5b639ee]905                // C11 Standard 6.2.5.15: The three types char, signed char, and unsigned char are collectively called the
906                // character types. The implementation shall define char to have the same range, representation, and behavior as
907                // either signed char or unsigned char.
[bb7422a]908                static ast::BasicType::Kind chartype[] = { ast::BasicType::SignedChar, ast::BasicType::UnsignedChar, ast::BasicType::Char };
[5b639ee]909
910                if ( td->length != DeclarationNode::NoLength ) {
[201aeb9]911                        genTSError( DeclarationNode::lengthNames[ td->length ], td->basictype );
[5b639ee]912                } // if
913
914                ret = chartype[ td->signedness ];
915                break;
916
[702e826]917        case DeclarationNode::Int:
[bb7422a]918                static ast::BasicType::Kind inttype[2][4] = {
919                        { ast::BasicType::ShortSignedInt, ast::BasicType::LongSignedInt, ast::BasicType::LongLongSignedInt, ast::BasicType::SignedInt },
920                        { ast::BasicType::ShortUnsignedInt, ast::BasicType::LongUnsignedInt, ast::BasicType::LongLongUnsignedInt, ast::BasicType::UnsignedInt },
[5b639ee]921                };
922
[702e826]923        Integral: ;
[5b639ee]924                if ( td->signedness == DeclarationNode::NoSignedness ) {
925                        const_cast<TypeData *>(td)->signedness = DeclarationNode::Signed;
926                } // if
927                ret = inttype[ td->signedness ][ td->length ];
928                break;
929
[702e826]930        case DeclarationNode::Int128:
[bb7422a]931                ret = td->signedness == DeclarationNode::Unsigned ? ast::BasicType::UnsignedInt128 : ast::BasicType::SignedInt128;
[201aeb9]932                if ( td->length != DeclarationNode::NoLength ) {
933                        genTSError( DeclarationNode::lengthNames[ td->length ], td->basictype );
934                } // if
935                break;
936
[702e826]937        case DeclarationNode::Float:
938        case DeclarationNode::Double:
939        case DeclarationNode::LongDouble:                                       // not set until below
940        case DeclarationNode::uuFloat80:
941        case DeclarationNode::uuFloat128:
942        case DeclarationNode::uFloat16:
943        case DeclarationNode::uFloat32:
944        case DeclarationNode::uFloat32x:
945        case DeclarationNode::uFloat64:
946        case DeclarationNode::uFloat64x:
947        case DeclarationNode::uFloat128:
948        case DeclarationNode::uFloat128x:
[bb7422a]949                static ast::BasicType::Kind floattype[2][12] = {
950                        { ast::BasicType::FloatComplex, ast::BasicType::DoubleComplex, ast::BasicType::LongDoubleComplex, (ast::BasicType::Kind)-1, (ast::BasicType::Kind)-1, ast::BasicType::uFloat16Complex, ast::BasicType::uFloat32Complex, ast::BasicType::uFloat32xComplex, ast::BasicType::uFloat64Complex, ast::BasicType::uFloat64xComplex, ast::BasicType::uFloat128Complex, ast::BasicType::uFloat128xComplex, },
951                        { ast::BasicType::Float, ast::BasicType::Double, ast::BasicType::LongDouble, ast::BasicType::uuFloat80, ast::BasicType::uuFloat128, ast::BasicType::uFloat16, ast::BasicType::uFloat32, ast::BasicType::uFloat32x, ast::BasicType::uFloat64, ast::BasicType::uFloat64x, ast::BasicType::uFloat128, ast::BasicType::uFloat128x, },
[5b639ee]952                };
953
[702e826]954        FloatingPoint: ;
[5b639ee]955                if ( td->signedness != DeclarationNode::NoSignedness ) {
[201aeb9]956                        genTSError( DeclarationNode::signednessNames[ td->signedness ], td->basictype );
[5b639ee]957                } // if
958                if ( td->length == DeclarationNode::Short || td->length == DeclarationNode::LongLong ) {
[201aeb9]959                        genTSError( DeclarationNode::lengthNames[ td->length ], td->basictype );
[5b639ee]960                } // if
[4ee3b0c1]961                if ( td->basictype != DeclarationNode::Double && td->length == DeclarationNode::Long ) {
[201aeb9]962                        genTSError( DeclarationNode::lengthNames[ td->length ], td->basictype );
[5b639ee]963                } // if
[ba01b14]964                if ( td->complextype == DeclarationNode::Imaginary ) {
965                        genTSError( DeclarationNode::complexTypeNames[ td->complextype ], td->basictype );
966                } // if
[e15853c]967                if ( (td->basictype == DeclarationNode::uuFloat80 || td->basictype == DeclarationNode::uuFloat128) && td->complextype == DeclarationNode::Complex ) { // gcc unsupported
[ba01b14]968                        genTSError( DeclarationNode::complexTypeNames[ td->complextype ], td->basictype );
969                } // if
[5b639ee]970                if ( td->length == DeclarationNode::Long ) {
971                        const_cast<TypeData *>(td)->basictype = DeclarationNode::LongDouble;
972                } // if
973
974                ret = floattype[ td->complextype ][ td->basictype - DeclarationNode::Float ];
[ba01b14]975                //printf( "XXXX %d %d %d %d\n", td->complextype, td->basictype, DeclarationNode::Float, ret );
[5b639ee]976                break;
977
[702e826]978        case DeclarationNode::NoBasicType:
[5b639ee]979                // No basic type in declaration => default double for Complex/Imaginary and int type for integral types
980                if ( td->complextype == DeclarationNode::Complex || td->complextype == DeclarationNode::Imaginary ) {
981                        const_cast<TypeData *>(td)->basictype = DeclarationNode::Double;
982                        goto FloatingPoint;
983                } // if
984
985                const_cast<TypeData *>(td)->basictype = DeclarationNode::Int;
986                goto Integral;
[702e826]987        default:
988                assertf( false, "unknown basic type" );
[2ee5426]989                return nullptr;
[5b639ee]990        } // switch
991
[bb7422a]992        ast::BasicType * bt = new ast::BasicType( ret, buildQualifiers( td ) );
[b87a5ed]993        return bt;
[413ad05]994} // buildBasicType
[51b7345]995
[201aeb9]996
[bb7422a]997ast::PointerType * buildPointer( const TypeData * td ) {
998        ast::PointerType * pt;
[413ad05]999        if ( td->base ) {
[bb7422a]1000                pt = new ast::PointerType(
1001                        typebuild( td->base ),
1002                        buildQualifiers( td )
1003                );
[b87a5ed]1004        } else {
[bb7422a]1005                pt = new ast::PointerType(
1006                        new ast::BasicType( ast::BasicType::SignedInt ),
1007                        buildQualifiers( td )
1008                );
[68cd1ce]1009        } // if
[b87a5ed]1010        return pt;
[413ad05]1011} // buildPointer
[51b7345]1012
[201aeb9]1013
[bb7422a]1014ast::ArrayType * buildArray( const TypeData * td ) {
1015        ast::ArrayType * at;
[413ad05]1016        if ( td->base ) {
[bb7422a]1017                at = new ast::ArrayType(
1018                        typebuild( td->base ),
1019                        maybeBuild( td->array.dimension ),
1020                        td->array.isVarLen ? ast::VariableLen : ast::FixedLen,
1021                        td->array.isStatic ? ast::StaticDim : ast::DynamicDim,
1022                        buildQualifiers( td )
1023                );
[b87a5ed]1024        } else {
[bb7422a]1025                at = new ast::ArrayType(
1026                        new ast::BasicType( ast::BasicType::SignedInt ),
1027                        maybeBuild( td->array.dimension ),
1028                        td->array.isVarLen ? ast::VariableLen : ast::FixedLen,
1029                        td->array.isStatic ? ast::StaticDim : ast::DynamicDim,
1030                        buildQualifiers( td )
1031                );
[68cd1ce]1032        } // if
[b87a5ed]1033        return at;
[ce8c12f]1034} // buildArray
1035
[201aeb9]1036
[bb7422a]1037ast::ReferenceType * buildReference( const TypeData * td ) {
1038        ast::ReferenceType * rt;
[ce8c12f]1039        if ( td->base ) {
[bb7422a]1040                rt = new ast::ReferenceType(
1041                        typebuild( td->base ),
1042                        buildQualifiers( td )
1043                );
[ce8c12f]1044        } else {
[bb7422a]1045                rt = new ast::ReferenceType(
1046                        new ast::BasicType( ast::BasicType::SignedInt ),
1047                        buildQualifiers( td )
1048                );
[ce8c12f]1049        } // if
1050        return rt;
1051} // buildReference
[51b7345]1052
[201aeb9]1053
[bb7422a]1054ast::AggregateDecl * buildAggregate( const TypeData * td, std::vector<ast::ptr<ast::Attribute>> attributes, ast::Linkage::Spec linkage ) {
[413ad05]1055        assert( td->kind == TypeData::Aggregate );
[bb7422a]1056        ast::AggregateDecl * at;
[8f6f47d7]1057        switch ( td->aggregate.kind ) {
[bb7422a]1058        case ast::AggregateDecl::Struct:
1059        case ast::AggregateDecl::Coroutine:
1060        case ast::AggregateDecl::Exception:
1061        case ast::AggregateDecl::Generator:
1062        case ast::AggregateDecl::Monitor:
1063        case ast::AggregateDecl::Thread:
1064                at = new ast::StructDecl( td->location,
1065                        *td->aggregate.name,
1066                        td->aggregate.kind,
1067                        std::move( attributes ),
1068                        linkage
1069                );
1070                buildForall( td->aggregate.params, at->params );
1071                break;
1072        case ast::AggregateDecl::Union:
1073                at = new ast::UnionDecl( td->location,
1074                        *td->aggregate.name,
1075                        std::move( attributes ),
1076                        linkage
1077                );
1078                buildForall( td->aggregate.params, at->params );
1079                break;
1080        case ast::AggregateDecl::Trait:
1081                at = new ast::TraitDecl( td->location,
1082                        *td->aggregate.name,
1083                        std::move( attributes ),
1084                        linkage
1085                );
1086                buildList( td->aggregate.params, at->params );
[b87a5ed]1087                break;
[702e826]1088        default:
[b87a5ed]1089                assert( false );
[68cd1ce]1090        } // switch
[4e06c1e]1091
[bb7422a]1092        buildList( td->aggregate.fields, at->members );
[8f6f47d7]1093        at->set_body( td->aggregate.body );
[b87a5ed]1094
1095        return at;
[413ad05]1096} // buildAggregate
[51b7345]1097
[201aeb9]1098
[bb7422a]1099ast::BaseInstType * buildComAggInst(
[4eb3a7c5]1100                const TypeData * td,
[bb7422a]1101                std::vector<ast::ptr<ast::Attribute>> && attributes,
1102                ast::Linkage::Spec linkage ) {
[4eb3a7c5]1103        switch ( td->kind ) {
[702e826]1104        case TypeData::Enum:
[4eb3a7c5]1105                if ( td->enumeration.body ) {
[bb7422a]1106                        ast::EnumDecl * typedecl =
[4eb3a7c5]1107                                buildEnum( td, std::move( attributes ), linkage );
[bb7422a]1108                        return new ast::EnumInstType(
1109                                typedecl,
[4eb3a7c5]1110                                buildQualifiers( td )
[bb7422a]1111                        );
[702e826]1112                } else {
[bb7422a]1113                        return new ast::EnumInstType(
[4eb3a7c5]1114                                *td->enumeration.name,
1115                                buildQualifiers( td )
[bb7422a]1116                        );
[702e826]1117                } // if
[bb7422a]1118                break;
[702e826]1119        case TypeData::Aggregate:
[4eb3a7c5]1120                if ( td->aggregate.body ) {
[bb7422a]1121                        ast::AggregateDecl * typedecl =
[4eb3a7c5]1122                                buildAggregate( td, std::move( attributes ), linkage );
1123                        switch ( td->aggregate.kind ) {
[bb7422a]1124                        case ast::AggregateDecl::Struct:
1125                        case ast::AggregateDecl::Coroutine:
1126                        case ast::AggregateDecl::Monitor:
1127                        case ast::AggregateDecl::Thread:
1128                                return new ast::StructInstType(
1129                                        strict_dynamic_cast<ast::StructDecl *>( typedecl ),
[4eb3a7c5]1130                                        buildQualifiers( td )
[bb7422a]1131                                );
1132                        case ast::AggregateDecl::Union:
1133                                return new ast::UnionInstType(
1134                                        strict_dynamic_cast<ast::UnionDecl *>( typedecl ),
[4eb3a7c5]1135                                        buildQualifiers( td )
[bb7422a]1136                                );
1137                        case ast::AggregateDecl::Trait:
[702e826]1138                                assert( false );
1139                                break;
1140                        default:
1141                                assert( false );
1142                        } // switch
1143                } else {
[4eb3a7c5]1144                        switch ( td->aggregate.kind ) {
[bb7422a]1145                        case ast::AggregateDecl::Struct:
1146                        case ast::AggregateDecl::Coroutine:
1147                        case ast::AggregateDecl::Monitor:
1148                        case ast::AggregateDecl::Thread:
1149                                return new ast::StructInstType(
[4eb3a7c5]1150                                        *td->aggregate.name,
1151                                        buildQualifiers( td )
[bb7422a]1152                                );
1153                        case ast::AggregateDecl::Union:
1154                                return new ast::UnionInstType(
[4eb3a7c5]1155                                        *td->aggregate.name,
1156                                        buildQualifiers( td )
[bb7422a]1157                                );
1158                        case ast::AggregateDecl::Trait:
1159                                return new ast::TraitInstType(
[4eb3a7c5]1160                                        *td->aggregate.name,
1161                                        buildQualifiers( td )
[bb7422a]1162                                );
[702e826]1163                        default:
1164                                assert( false );
1165                        } // switch
[bb7422a]1166                        break;
[702e826]1167                } // if
[bb7422a]1168                break;
[702e826]1169        default:
[43c89a7]1170                assert( false );
1171        } // switch
[bb7422a]1172        assert( false );
[43c89a7]1173} // buildAggInst
1174
[201aeb9]1175
[bb7422a]1176ast::BaseInstType * buildAggInst( const TypeData * td ) {
[413ad05]1177        assert( td->kind == TypeData::AggregateInst );
[b87a5ed]1178
[bb7422a]1179        ast::BaseInstType * ret = nullptr;
[43c89a7]1180        TypeData * type = td->aggInst.aggregate;
1181        switch ( type->kind ) {
[702e826]1182        case TypeData::Enum:
[bb7422a]1183                return new ast::EnumInstType(
1184                        *type->enumeration.name,
1185                        buildQualifiers( type )
1186                );
[702e826]1187        case TypeData::Aggregate:
1188                switch ( type->aggregate.kind ) {
[bb7422a]1189                case ast::AggregateDecl::Struct:
1190                case ast::AggregateDecl::Coroutine:
1191                case ast::AggregateDecl::Monitor:
1192                case ast::AggregateDecl::Thread:
1193                        ret = new ast::StructInstType(
1194                                *type->aggregate.name,
1195                                buildQualifiers( type )
1196                        );
[702e826]1197                        break;
[bb7422a]1198                case ast::AggregateDecl::Union:
1199                        ret = new ast::UnionInstType(
1200                                *type->aggregate.name,
1201                                buildQualifiers( type )
1202                        );
[702e826]1203                        break;
[bb7422a]1204                case ast::AggregateDecl::Trait:
1205                        ret = new ast::TraitInstType(
1206                                *type->aggregate.name,
1207                                buildQualifiers( type )
1208                        );
[702e826]1209                        break;
1210                default:
1211                        assert( false );
1212                } // switch
1213                break;
1214        default:
[43c89a7]1215                assert( false );
1216        } // switch
1217
[bb7422a]1218        ret->hoistType = td->aggInst.hoistType;
1219        buildList( td->aggInst.params, ret->params );
[b87a5ed]1220        return ret;
[413ad05]1221} // buildAggInst
1222
[201aeb9]1223
[bb7422a]1224ast::NamedTypeDecl * buildSymbolic(
1225                const TypeData * td,
1226                std::vector<ast::ptr<ast::Attribute>> attributes,
1227                const std::string & name,
1228                ast::Storage::Classes scs,
1229                ast::Linkage::Spec linkage ) {
[413ad05]1230        assert( td->kind == TypeData::Symbolic );
[bb7422a]1231        ast::NamedTypeDecl * ret;
[413ad05]1232        assert( td->base );
[8f6f47d7]1233        if ( td->symbolic.isTypedef ) {
[bb7422a]1234                ret = new ast::TypedefDecl(
1235                        td->location,
1236                        name,
1237                        scs,
1238                        typebuild( td->base ),
1239                        linkage
1240                );
[b87a5ed]1241        } else {
[bb7422a]1242                ret = new ast::TypeDecl(
1243                        td->location,
1244                        name,
1245                        scs,
1246                        typebuild( td->base ),
1247                        ast::TypeDecl::Dtype,
1248                        true
1249                );
[68cd1ce]1250        } // if
[bb7422a]1251        buildList( td->symbolic.assertions, ret->assertions );
1252        splice( ret->base.get_and_mutate()->attributes, attributes );
[b87a5ed]1253        return ret;
[413ad05]1254} // buildSymbolic
[51b7345]1255
[201aeb9]1256
[bb7422a]1257ast::EnumDecl * buildEnum(
1258                const TypeData * td,
1259                std::vector<ast::ptr<ast::Attribute>> && attributes,
1260                ast::Linkage::Spec linkage ) {
[413ad05]1261        assert( td->kind == TypeData::Enum );
[bb7422a]1262        ast::Type * baseType = td->base ? typebuild(td->base) : nullptr;
1263        ast::EnumDecl * ret = new ast::EnumDecl(
1264                td->location,
1265                *td->enumeration.name,
1266                td->enumeration.typed,
1267                std::move( attributes ),
1268                linkage,
1269                baseType
1270        );
1271        buildList( td->enumeration.constants, ret->members );
1272        auto members = ret->members.begin();
1273        ret->hide = td->enumeration.hiding == EnumHiding::Hide ? ast::EnumDecl::EnumHiding::Hide : ast::EnumDecl::EnumHiding::Visible;
[44adf1b]1274        for ( const DeclarationNode * cur = td->enumeration.constants; cur != nullptr; cur = cur->next, ++members ) {
[1e30df7]1275                if ( cur->enumInLine ) {
[e874605]1276                        // Do Nothing
1277                } else if ( ret->isTyped && !ret->base && cur->has_enumeratorValue() ) {
[b0d9ff7]1278                        SemanticError( td->location, "Enumerator of enum(void) cannot have an explicit initializer value." );
1279                } else if ( cur->has_enumeratorValue() ) {
[bb7422a]1280                        ast::Decl * member = members->get_and_mutate();
1281                        ast::ObjectDecl * object = strict_dynamic_cast<ast::ObjectDecl *>( member );
1282                        object->init = new ast::SingleInit(
1283                                td->location,
1284                                maybeMoveBuild( cur->consume_enumeratorValue() ),
1285                                ast::NoConstruct
1286                        );
[9e7236f4]1287                } else if ( !cur->initializer ) {
[bb7422a]1288                        if ( baseType && (!dynamic_cast<ast::BasicType *>(baseType) || !dynamic_cast<ast::BasicType *>(baseType)->isInteger())) {
[b0d9ff7]1289                                SemanticError( td->location, "Enumerators of an non-integer typed enum must be explicitly initialized." );
[f238fcc2]1290                        }
[9e7236f4]1291                }
1292                // else cur is a List Initializer and has been set as init in buildList()
1293                // if
[90c3b1c]1294        } // for
[bb7422a]1295        ret->body = td->enumeration.body;
[b87a5ed]1296        return ret;
[413ad05]1297} // buildEnum
[51b7345]1298
[201aeb9]1299
[bb7422a]1300ast::TypeInstType * buildSymbolicInst( const TypeData * td ) {
[413ad05]1301        assert( td->kind == TypeData::SymbolicInst );
[bb7422a]1302        ast::TypeInstType * ret = new ast::TypeInstType(
1303                *td->symbolic.name,
1304                ast::TypeDecl::Dtype,
1305                buildQualifiers( td )
1306        );
1307        buildList( td->symbolic.actuals, ret->params );
[b87a5ed]1308        return ret;
[413ad05]1309} // buildSymbolicInst
[51b7345]1310
[201aeb9]1311
[bb7422a]1312ast::TupleType * buildTuple( const TypeData * td ) {
[413ad05]1313        assert( td->kind == TypeData::Tuple );
[bb7422a]1314        std::vector<ast::ptr<ast::Type>> types;
[62423350]1315        buildTypeList( td->tuple, types );
[bb7422a]1316        ast::TupleType * ret = new ast::TupleType(
1317                std::move( types ),
1318                buildQualifiers( td )
1319        );
[b87a5ed]1320        return ret;
[413ad05]1321} // buildTuple
1322
[201aeb9]1323
[bb7422a]1324ast::TypeofType * buildTypeof( const TypeData * td ) {
[f855545]1325        assert( td->kind == TypeData::Typeof || td->kind == TypeData::Basetypeof );
[413ad05]1326        assert( td->typeexpr );
[bb7422a]1327        return new ast::TypeofType(
1328                td->typeexpr->build(),
1329                td->kind == TypeData::Typeof
1330                        ? ast::TypeofType::Typeof : ast::TypeofType::Basetypeof,
1331                buildQualifiers( td )
1332        );
[413ad05]1333} // buildTypeof
1334
[201aeb9]1335
[bb7422a]1336ast::VTableType * buildVtable( const TypeData * td ) {
[93bbbc4]1337        assert( td->base );
[bb7422a]1338        return new ast::VTableType(
1339                typebuild( td->base ),
1340                buildQualifiers( td )
1341        );
[93bbbc4]1342} // buildVtable
1343
1344
[bb7422a]1345ast::FunctionDecl * buildFunctionDecl(
1346                const TypeData * td,
1347                const string &name,
1348                ast::Storage::Classes scs,
1349                ast::Function::Specs funcSpec,
1350                ast::Linkage::Spec linkage,
1351                ast::Expr * asmName,
1352                std::vector<ast::ptr<ast::Attribute>> && attributes ) {
1353        assert( td->kind == TypeData::Function );
1354        // For some reason FunctionDecl takes a bool instead of an ArgumentFlag.
1355        bool isVarArgs = !td->function.params || td->function.params->hasEllipsis;
1356        ast::CV::Qualifiers cvq = buildQualifiers( td );
1357        std::vector<ast::ptr<ast::TypeDecl>> forall;
1358        std::vector<ast::ptr<ast::DeclWithType>> assertions;
1359        std::vector<ast::ptr<ast::DeclWithType>> params;
1360        std::vector<ast::ptr<ast::DeclWithType>> returns;
1361        buildList( td->function.params, params );
1362        buildForall( td->forall, forall );
1363        // Functions do not store their assertions there anymore.
1364        for ( ast::ptr<ast::TypeDecl> & type_param : forall ) {
1365                auto mut = type_param.get_and_mutate();
1366                splice( assertions, mut->assertions );
1367        }
1368        if ( td->base ) {
1369                switch ( td->base->kind ) {
1370                case TypeData::Tuple:
1371                        buildList( td->base->tuple, returns );
1372                        break;
1373                default:
1374                        returns.push_back( dynamic_cast<ast::DeclWithType *>(
1375                                buildDecl(
1376                                        td->base,
1377                                        "",
1378                                        ast::Storage::Classes(),
1379                                        (ast::Expr *)nullptr, // bitfieldWidth
1380                                        ast::Function::Specs(),
1381                                        ast::Linkage::Cforall,
1382                                        (ast::Expr *)nullptr // asmName
1383                                )
1384                        ) );
1385                } // switch
1386        } else {
1387                returns.push_back( new ast::ObjectDecl(
1388                        td->location,
1389                        "",
1390                        new ast::BasicType( ast::BasicType::SignedInt ),
1391                        (ast::Init *)nullptr,
1392                        ast::Storage::Classes(),
1393                        ast::Linkage::Cforall
1394                ) );
1395        } // if
1396        ast::Stmt * stmt = maybeBuild( td->function.body );
1397        ast::CompoundStmt * body = dynamic_cast<ast::CompoundStmt *>( stmt );
1398        ast::FunctionDecl * decl = new ast::FunctionDecl( td->location,
1399                name,
1400                std::move( forall ),
1401                std::move( assertions ),
1402                std::move( params ),
1403                std::move( returns ),
1404                body,
1405                scs,
1406                linkage,
1407                std::move( attributes ),
1408                funcSpec,
[3e94a23]1409                (isVarArgs) ? ast::VariableArgs : ast::FixedArgs
[bb7422a]1410        );
1411        buildList( td->function.withExprs, decl->withExprs );
1412        decl->asmName = asmName;
1413        // This may be redundant on a declaration.
1414        decl->type.get_and_mutate()->qualifiers = cvq;
1415        return decl;
1416} // buildFunctionDecl
1417
1418
1419ast::Decl * buildDecl(
1420                const TypeData * td,
1421                const string &name,
1422                ast::Storage::Classes scs,
1423                ast::Expr * bitfieldWidth,
1424                ast::Function::Specs funcSpec,
1425                ast::Linkage::Spec linkage,
1426                ast::Expr * asmName,
1427                ast::Init * init,
1428                std::vector<ast::ptr<ast::Attribute>> && attributes ) {
[413ad05]1429        if ( td->kind == TypeData::Function ) {
[ca1a547]1430                if ( td->function.idList ) {                                    // KR function ?
1431                        buildKRFunction( td->function );                        // transform into C11 function
[3a5131ed]1432                } // if
1433
[bb7422a]1434                return buildFunctionDecl(
1435                        td, name, scs, funcSpec, linkage,
1436                        asmName, std::move( attributes ) );
[413ad05]1437        } else if ( td->kind == TypeData::Aggregate ) {
[bb7422a]1438                return buildAggregate( td, std::move( attributes ), linkage );
[413ad05]1439        } else if ( td->kind == TypeData::Enum ) {
[bb7422a]1440                return buildEnum( td, std::move( attributes ), linkage );
[413ad05]1441        } else if ( td->kind == TypeData::Symbolic ) {
[bb7422a]1442                return buildSymbolic( td, std::move( attributes ), name, scs, linkage );
[413ad05]1443        } else {
[bb7422a]1444                auto ret = new ast::ObjectDecl( td->location,
1445                        name,
1446                        typebuild( td ),
1447                        init,
1448                        scs,
1449                        linkage,
1450                        bitfieldWidth,
1451                        std::move( attributes )
1452                );
1453                ret->asmName = asmName;
1454                return ret;
[413ad05]1455        } // if
[2298f728]1456        return nullptr;
[413ad05]1457} // buildDecl
1458
[201aeb9]1459
[bb7422a]1460ast::FunctionType * buildFunctionType( const TypeData * td ) {
[413ad05]1461        assert( td->kind == TypeData::Function );
[bb7422a]1462        ast::FunctionType * ft = new ast::FunctionType(
1463                ( !td->function.params || td->function.params->hasEllipsis )
1464                        ? ast::VariableArgs : ast::FixedArgs,
1465                buildQualifiers( td )
1466        );
1467        buildTypeList( td->function.params, ft->params );
[704d11e]1468        buildForall( td->forall, ft->forall );
[413ad05]1469        if ( td->base ) {
1470                switch ( td->base->kind ) {
[702e826]1471                case TypeData::Tuple:
[bb7422a]1472                        buildTypeList( td->base->tuple, ft->returns );
[413ad05]1473                        break;
[702e826]1474                default:
[bb7422a]1475                        ft->returns.push_back( typebuild( td->base ) );
1476                        break;
[413ad05]1477                } // switch
1478        } else {
[bb7422a]1479                ft->returns.push_back(
1480                        new ast::BasicType( ast::BasicType::SignedInt ) );
[413ad05]1481        } // if
1482        return ft;
[bb7422a]1483} // buildFunctionType
[b87a5ed]1484
[201aeb9]1485
[a7c4921]1486// Transform KR routine declarations into C99 routine declarations:
1487//
1488//    rtn( a, b, c ) int a, c; double b {}  =>  int rtn( int a, double c, int b ) {}
1489//
1490// The type information for each post-declaration is moved to the corresponding pre-parameter and the post-declaration
1491// is deleted. Note, the order of the parameter names may not be the same as the declaration names. Duplicate names and
1492// extra names are disallowed.
1493//
1494// Note, there is no KR routine-prototype syntax:
1495//
1496//    rtn( a, b, c ) int a, c; double b; // invalid KR prototype
1497//    rtn(); // valid KR prototype
1498
[3a5131ed]1499void buildKRFunction( const TypeData::Function_t & function ) {
1500        assert( ! function.params );
[a7c4921]1501        // loop over declaration first as it is easier to spot errors
[44adf1b]1502        for ( DeclarationNode * decl = function.oldDeclList; decl != nullptr; decl = decl->next ) {
[a7c4921]1503                // scan ALL parameter names for each declaration name to check for duplicates
[44adf1b]1504                for ( DeclarationNode * param = function.idList; param != nullptr; param = param->next ) {
[3a5131ed]1505                        if ( *decl->name == *param->name ) {
[a7c4921]1506                                // type set => parameter name already transformed by a declaration names so there is a duplicate
1507                                // declaration name attempting a second transformation
[ca9d65e]1508                                if ( param->type ) SemanticError( param->location, "duplicate declaration name \"%s\".", param->name->c_str() );
[a7c4921]1509                                // declaration type reset => declaration already transformed by a parameter name so there is a duplicate
1510                                // parameter name attempting a second transformation
[ca9d65e]1511                                if ( ! decl->type ) SemanticError( param->location, "duplicate parameter name \"%s\".", param->name->c_str() );
[a7c4921]1512                                param->type = decl->type;                               // set copy declaration type to parameter type
1513                                decl->type = nullptr;                                   // reset declaration type
[bb7422a]1514                                // Copy and reset attributes from declaration to parameter:
1515                                splice( param->attributes, decl->attributes );
[3a5131ed]1516                        } // if
1517                } // for
[a7c4921]1518                // declaration type still set => type not moved to a matching parameter so there is a missing parameter name
[b1f2007]1519                if ( decl->type ) SemanticError( decl->location, "missing name in parameter list %s", decl->name->c_str() );
[3a5131ed]1520        } // for
[a7c4921]1521
1522        // Parameter names without a declaration default to type int:
1523        //
1524        //    rtb( a, b, c ) const char * b; {} => int rtn( int a, const char * b, int c ) {}
1525
[44adf1b]1526        for ( DeclarationNode * param = function.idList; param != nullptr; param = param->next ) {
[ca1a547]1527                if ( ! param->type ) {                                                  // generate type int for empty parameter type
[3a5131ed]1528                        param->type = new TypeData( TypeData::Basic );
1529                        param->type->basictype = DeclarationNode::Int;
1530                } // if
1531        } // for
1532
[a7c4921]1533        function.params = function.idList;                                      // newly modified idList becomes parameters
1534        function.idList = nullptr;                                                      // idList now empty
1535        delete function.oldDeclList;                                            // deletes entire list
1536        function.oldDeclList = nullptr;                                         // reset
[3a5131ed]1537} // buildKRFunction
1538
[b87a5ed]1539// Local Variables: //
1540// tab-width: 4 //
1541// mode: c++ //
1542// compile-command: "make install" //
1543// End: //
Note: See TracBrowser for help on using the repository browser.