Changeset f6e8c67 for src


Ignore:
Timestamp:
Mar 6, 2024, 6:06:43 AM (19 months ago)
Author:
JiadaL <j82liang@…>
Branches:
master
Children:
647d633
Parents:
bbf2cb1 (diff), af60383 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge branch 'master' of plg.uwaterloo.ca:software/cfa/cfa-cc

Location:
src
Files:
13 edited

Legend:

Unmodified
Added
Removed
  • src/Parser/DeclarationNode.cc

    rbbf2cb1 rf6e8c67  
    8282
    8383DeclarationNode::~DeclarationNode() {
     84        delete name;
     85
    8486//      delete variable.name;
    8587        delete variable.assertions;
     
    99101DeclarationNode * DeclarationNode::clone() const {
    100102        DeclarationNode * newnode = new DeclarationNode;
    101         newnode->set_next( maybeCopy( get_next() ) );
     103        newnode->next = maybeCopy( next );
    102104        newnode->name = name ? new string( *name ) : nullptr;
    103105
    104         newnode->builtin = NoBuiltinType;
    105106        newnode->type = maybeCopy( type );
    106107        newnode->inLine = inLine;
     
    170171
    171172void DeclarationNode::printList( std::ostream & os, int indent ) const {
    172         ParseNode::printList( os, indent );
     173        ParseList::printList( os, indent );
    173174        if ( hasEllipsis ) {
    174175                os << string( indent, ' ' )  << "and a variable number of other arguments" << endl;
     
    433434        DeclarationNode * newnode = new DeclarationNode;
    434435        newnode->type = new TypeData( TypeData::Builtin );
    435         newnode->builtin = bt;
    436         newnode->type->builtintype = newnode->builtin;
     436        newnode->type->builtintype = bt;
    437437        return newnode;
    438438} // DeclarationNode::newBuiltinType
     
    554554} // DeclarationNode::copySpecifiers
    555555
    556 static void addQualifiersToType( TypeData *& src, TypeData * dst ) {
    557         if ( dst->base ) {
    558                 addQualifiersToType( src, dst->base );
    559         } else if ( dst->kind == TypeData::Function ) {
    560                 dst->base = src;
    561                 src = nullptr;
    562         } else {
    563                 dst->qualifiers |= src->qualifiers;
    564         } // if
    565 } // addQualifiersToType
    566 
    567556DeclarationNode * DeclarationNode::addQualifiers( DeclarationNode * q ) {
    568557        if ( ! q ) { return this; }                                                     // empty qualifier
     
    580569        } // if
    581570
    582         if ( q->type->forall ) {                                                        // forall qualifier ?
    583                 if ( type->forall ) {                                                   // polymorphic routine ?
    584                         type->forall->appendList( q->type->forall ); // augment forall qualifier
    585                 } else {
    586                         if ( type->kind == TypeData::Aggregate ) {      // struct/union ?
    587                                 if ( type->aggregate.params ) {                 // polymorphic ?
    588                                         type->aggregate.params->appendList( q->type->forall ); // augment forall qualifier
    589                                 } else {                                                                // not polymorphic
    590                                         type->aggregate.params = q->type->forall; // set forall qualifier
    591                                 } // if
    592                         } else {                                                                        // not polymorphic
    593                                 type->forall = q->type->forall;                 // make polymorphic routine
    594                         } // if
    595                 } // if
    596                 q->type->forall = nullptr;                                              // forall qualifier moved
    597         } // if
    598 
    599571        checkQualifiers( type, q->type );
     572        BuiltinType const builtin = type->builtintype;
    600573        if ( (builtin == Zero || builtin == One) && q->type->qualifiers.any() && error.length() == 0 ) {
    601574                SemanticWarning( yylloc, Warning::BadQualifiersZeroOne, builtinTypeNames[builtin] );
    602575        } // if
    603         addQualifiersToType( q->type, type );
     576        type = ::addQualifiers( q->type, type );
     577        q->type = nullptr;
    604578
    605579        delete q;
     
    607581} // addQualifiers
    608582
    609 static void addTypeToType( TypeData *& src, TypeData *& dst ) {
    610         if ( src->forall && dst->kind == TypeData::Function ) {
    611                 if ( dst->forall ) {
    612                         dst->forall->appendList( src->forall );
    613                 } else {
    614                         dst->forall = src->forall;
    615                 } // if
    616                 src->forall = nullptr;
    617         } // if
    618         if ( dst->base ) {
    619                 addTypeToType( src, dst->base );
    620         } else {
    621                 switch ( dst->kind ) {
    622                 case TypeData::Unknown:
    623                         src->qualifiers |= dst->qualifiers;
    624                         dst = src;
    625                         src = nullptr;
    626                         break;
    627                 case TypeData::Basic:
    628                         dst->qualifiers |= src->qualifiers;
    629                         if ( src->kind != TypeData::Unknown ) {
    630                                 assert( src->kind == TypeData::Basic );
    631 
    632                                 if ( dst->basictype == DeclarationNode::NoBasicType ) {
    633                                         dst->basictype = src->basictype;
    634                                 } else if ( src->basictype != DeclarationNode::NoBasicType )
    635                                         SemanticError( yylloc, "multiple declaration types \"%s\" and \"%s\".",
    636                                                                    DeclarationNode::basicTypeNames[ dst->basictype ],
    637                                                                    DeclarationNode::basicTypeNames[ src->basictype ] );
    638                                 if ( dst->complextype == DeclarationNode::NoComplexType ) {
    639                                         dst->complextype = src->complextype;
    640                                 } else if ( src->complextype != DeclarationNode::NoComplexType )
    641                                         SemanticError( yylloc, "multiple declaration types \"%s\" and \"%s\".",
    642                                                                    DeclarationNode::complexTypeNames[ src->complextype ],
    643                                                                    DeclarationNode::complexTypeNames[ src->complextype ] );
    644                                 if ( dst->signedness == DeclarationNode::NoSignedness ) {
    645                                         dst->signedness = src->signedness;
    646                                 } else if ( src->signedness != DeclarationNode::NoSignedness )
    647                                         SemanticError( yylloc, "conflicting type specifier \"%s\" and \"%s\".",
    648                                                                    DeclarationNode::signednessNames[ dst->signedness ],
    649                                                                    DeclarationNode::signednessNames[ src->signedness ] );
    650                                 if ( dst->length == DeclarationNode::NoLength ) {
    651                                         dst->length = src->length;
    652                                 } else if ( dst->length == DeclarationNode::Long && src->length == DeclarationNode::Long ) {
    653                                         dst->length = DeclarationNode::LongLong;
    654                                 } else if ( src->length != DeclarationNode::NoLength )
    655                                         SemanticError( yylloc, "conflicting type specifier \"%s\" and \"%s\".",
    656                                                                    DeclarationNode::lengthNames[ dst->length ],
    657                                                                    DeclarationNode::lengthNames[ src->length ] );
    658                         } // if
    659                         break;
    660                 default:
    661                         switch ( src->kind ) {
    662                         case TypeData::Aggregate:
    663                         case TypeData::Enum:
    664                                 dst->base = new TypeData( TypeData::AggregateInst );
    665                                 dst->base->aggInst.aggregate = src;
    666                                 if ( src->kind == TypeData::Aggregate ) {
    667                                         dst->base->aggInst.params = maybeCopy( src->aggregate.actuals );
    668                                 } // if
    669                                 dst->base->qualifiers |= src->qualifiers;
    670                                 src = nullptr;
    671                                 break;
    672                         default:
    673                                 if ( dst->forall ) {
    674                                         dst->forall->appendList( src->forall );
    675                                 } else {
    676                                         dst->forall = src->forall;
    677                                 } // if
    678                                 src->forall = nullptr;
    679                                 dst->base = src;
    680                                 src = nullptr;
    681                         } // switch
    682                 } // switch
    683         } // if
    684 }
    685 
    686583DeclarationNode * DeclarationNode::addType( DeclarationNode * o, bool copyattr ) {
    687         if ( o ) {
    688                 checkSpecifiers( o );
    689                 copySpecifiers( o, copyattr );
    690                 if ( o->type ) {
    691                         if ( ! type ) {
    692                                 if ( o->type->kind == TypeData::Aggregate || o->type->kind == TypeData::Enum ) {
    693                                         // Hide type information aggregate instances.
    694                                         type = new TypeData( TypeData::AggregateInst );
    695                                         type->aggInst.aggregate = o->type;      // change ownership
    696                                         type->aggInst.aggregate->aggregate.attributes.swap( o->attributes ); // change ownership                                       
    697                                         if ( o->type->kind == TypeData::Aggregate ) {
    698                                                 type->aggInst.hoistType = o->type->aggregate.body;
    699                                                 type->aggInst.params = maybeCopy( o->type->aggregate.actuals );
    700                                         } else {
    701                                                 type->aggInst.hoistType = o->type->enumeration.body;
    702                                         } // if
    703                                         type->qualifiers |= o->type->qualifiers;
    704                                 } else {
    705                                         type = o->type;
    706                                 } // if
    707                                 o->type = nullptr;                                              // change ownership
    708                         } else {
    709                                 addTypeToType( o->type, type );
    710                         } // if
    711                 } // if
    712                 if ( o->bitfieldWidth ) {
    713                         bitfieldWidth = o->bitfieldWidth;
    714                 } // if
    715 
    716                 // there may be typedefs chained onto the type
    717                 if ( o->get_next() ) {
    718                         set_last( o->get_next()->clone() );
    719                 } // if
    720         } // if
     584        if ( !o ) return this;
     585
     586        checkSpecifiers( o );
     587        copySpecifiers( o, copyattr );
     588        if ( o->type ) {
     589                type = ::addType( o->type, type, o->attributes );
     590                o->type = nullptr;
     591        } // if
     592        if ( o->bitfieldWidth ) {
     593                bitfieldWidth = o->bitfieldWidth;
     594        } // if
     595
     596        // there may be typedefs chained onto the type
     597        if ( o->next ) {
     598                set_last( o->next->clone() );
     599        } // if
     600
    721601        delete o;
    722 
    723602        return this;
    724603}
    725604
    726605DeclarationNode * DeclarationNode::addEnumBase( DeclarationNode * o ) {
    727         if ( o && o->type) {
    728                 type->base= o->type;
     606        if ( o && o->type ) {
     607                type->base = o->type;
    729608        } // if
    730609        delete o;
     
    745624        if ( variable.tyClass != ast::TypeDecl::NUMBER_OF_KINDS ) {
    746625                if ( variable.assertions ) {
    747                         variable.assertions->appendList( assertions );
     626                        variable.assertions->set_last( assertions );
    748627                } else {
    749628                        variable.assertions = assertions;
     
    756635        case TypeData::Symbolic:
    757636                if ( type->symbolic.assertions ) {
    758                         type->symbolic.assertions->appendList( assertions );
     637                        type->symbolic.assertions->set_last( assertions );
    759638                } else {
    760639                        type->symbolic.assertions = assertions;
     
    810689DeclarationNode * DeclarationNode::setBase( TypeData * newType ) {
    811690        if ( type ) {
    812                 TypeData * prevBase = type;
    813                 TypeData * curBase = type->base;
    814                 while ( curBase != nullptr ) {
    815                         prevBase = curBase;
    816                         curBase = curBase->base;
    817                 } // while
    818                 prevBase->base = newType;
     691                type->setLastBase( newType );
    819692        } else {
    820693                type = newType;
     
    857730                assert( p->type->kind == TypeData::Pointer || p->type->kind == TypeData::Reference );
    858731                if ( type ) {
    859                         switch ( type->kind ) {
    860                         case TypeData::Aggregate:
    861                         case TypeData::Enum:
    862                                 p->type->base = new TypeData( TypeData::AggregateInst );
    863                                 p->type->base->aggInst.aggregate = type;
    864                                 if ( type->kind == TypeData::Aggregate ) {
    865                                         p->type->base->aggInst.params = maybeCopy( type->aggregate.actuals );
    866                                 } // if
    867                                 p->type->base->qualifiers |= type->qualifiers;
    868                                 break;
    869 
    870                         default:
    871                                 p->type->base = type;
    872                         } // switch
     732                        p->type->base = makeNewBase( type );
    873733                        type = nullptr;
    874734                } // if
     
    880740}
    881741
    882 static TypeData * findLast( TypeData * a ) {
    883         assert( a );
    884         TypeData * cur = a;
    885         while ( cur->base ) {
    886                 cur = cur->base;
    887         } // while
    888         return cur;
    889 }
    890 
    891742DeclarationNode * DeclarationNode::addNewArray( DeclarationNode * a ) {
    892743        if ( ! a ) return this;
    893744        assert( a->type->kind == TypeData::Array );
    894         TypeData * lastArray = findLast( a->type );
    895745        if ( type ) {
    896                 switch ( type->kind ) {
    897                 case TypeData::Aggregate:
    898                 case TypeData::Enum:
    899                         lastArray->base = new TypeData( TypeData::AggregateInst );
    900                         lastArray->base->aggInst.aggregate = type;
    901                         if ( type->kind == TypeData::Aggregate ) {
    902                                 lastArray->base->aggInst.params = maybeCopy( type->aggregate.actuals );
    903                         } // if
    904                         lastArray->base->qualifiers |= type->qualifiers;
    905                         break;
    906                 default:
    907                         lastArray->base = type;
    908                 } // switch
     746                a->type->setLastBase( makeNewBase( type ) );
    909747                type = nullptr;
    910748        } // if
     
    960798DeclarationNode * DeclarationNode::cloneBaseType( DeclarationNode * o, bool copyattr ) {
    961799        if ( ! o ) return nullptr;
    962 
    963800        o->copySpecifiers( this, copyattr );
    964801        if ( type ) {
    965                 TypeData * srcType = type;
    966 
    967                 // search for the base type by scanning off pointers and array designators
    968                 while ( srcType->base ) {
    969                         srcType = srcType->base;
    970                 } // while
    971 
    972                 TypeData * newType = srcType->clone();
    973                 if ( newType->kind == TypeData::AggregateInst ) {
    974                         // don't duplicate members
    975                         if ( newType->aggInst.aggregate->kind == TypeData::Enum ) {
    976                                 delete newType->aggInst.aggregate->enumeration.constants;
    977                                 newType->aggInst.aggregate->enumeration.constants = nullptr;
    978                                 newType->aggInst.aggregate->enumeration.body = false;
    979                         } else {
    980                                 assert( newType->aggInst.aggregate->kind == TypeData::Aggregate );
    981                                 delete newType->aggInst.aggregate->aggregate.fields;
    982                                 newType->aggInst.aggregate->aggregate.fields = nullptr;
    983                                 newType->aggInst.aggregate->aggregate.body = false;
    984                         } // if
    985                         // don't hoist twice
    986                         newType->aggInst.hoistType = false;
    987                 } // if
    988 
    989                 newType->forall = maybeCopy( type->forall );
    990                 if ( ! o->type ) {
    991                         o->type = newType;
    992                 } else {
    993                         addTypeToType( newType, o->type );
    994                         delete newType;
    995                 } // if
     802                o->type = ::cloneBaseType( type, o->type );
    996803        } // if
    997804        return o;
     
    1099906        std::back_insert_iterator<std::vector<ast::ptr<ast::Decl>>> out( outputList );
    1100907
    1101         for ( const DeclarationNode * cur = firstNode ; cur ; cur = strict_next( cur ) ) {
     908        for ( const DeclarationNode * cur = firstNode ; cur ; cur = cur->next ) {
    1102909                try {
    1103910                        bool extracted_named = false;
     
    1167974        std::back_insert_iterator<std::vector<ast::ptr<ast::DeclWithType>>> out( outputList );
    1168975
    1169         for ( const DeclarationNode * cur = firstNode; cur; cur = strict_next( cur ) ) {
     976        for ( const DeclarationNode * cur = firstNode; cur; cur = cur->next ) {
    1170977                try {
    1171978                        ast::Decl * decl = cur->build();
     
    12171024        std::back_insert_iterator<std::vector<ast::ptr<ast::Type>>> out( outputList );
    12181025
    1219         for ( const DeclarationNode * cur = firstNode ; cur ; cur = strict_next( cur ) ) {
     1026        for ( const DeclarationNode * cur = firstNode ; cur ; cur = cur->next ) {
    12201027                try {
    12211028                        * out++ = cur->buildType();
  • src/Parser/DeclarationNode.h

    rbbf2cb1 rf6e8c67  
    1919
    2020struct TypeData;
    21 class InitializerNode;
    22 
    23 struct DeclarationNode : public ParseNode {
     21struct InitializerNode;
     22
     23struct DeclarationNode final : public ParseList<DeclarationNode> {
    2424        // These enumerations must harmonize with their names in DeclarationNode.cc.
    2525        enum BasicType {
     
    108108        DeclarationNode * cloneBaseType( DeclarationNode * newdecl, bool = true );
    109109
    110         DeclarationNode * appendList( DeclarationNode * node ) {
    111                 return (DeclarationNode *)set_last( node );
    112         }
    113 
    114110        virtual void print( __attribute__((unused)) std::ostream & os, __attribute__((unused)) int indent = 0 ) const override;
    115111        virtual void printList( __attribute__((unused)) std::ostream & os, __attribute__((unused)) int indent = 0 ) const override;
     
    129125        DeclarationNode * set_inLine( bool inL ) { inLine = inL; return this; }
    130126
    131         DeclarationNode * get_last() { return (DeclarationNode *)ParseNode::get_last(); }
     127        const std::string * name = nullptr;
    132128
    133129        struct Variable_t {
     
    144140        };
    145141        StaticAssert_t assert;
    146 
    147         BuiltinType builtin = NoBuiltinType;
    148142
    149143        TypeData * type = nullptr;
     
    177171}
    178172
    179 template<typename NodeType>
    180 NodeType * strict_next( NodeType * node ) {
    181         ParseNode * next = node->get_next();
    182         if ( nullptr == next ) return nullptr;
    183         if ( NodeType * ret = dynamic_cast<NodeType *>( next ) ) return ret;
    184         SemanticError( next->location, "internal error, non-homogeneous nodes founds in buildList processing." );
    185 }
    186 
    187173// This generic buildList is here along side its overloads.
    188174template<typename AstType, typename NodeType,
     
    193179        std::back_insert_iterator<Container<ast::ptr<AstType>, Args...>> out( output );
    194180
    195         for ( NodeType * cur = firstNode ; cur ; cur = strict_next( cur ) ) {
     181        for ( NodeType * cur = firstNode ; cur ; cur = cur->next ) {
    196182                try {
    197183                        AstType * node = dynamic_cast<AstType *>( maybeBuild( cur ) );
  • src/Parser/ExpressionNode.h

    rbbf2cb1 rf6e8c67  
    1818#include "ParseNode.h"
    1919
    20 class InitializerNode;
     20struct InitializerNode;
    2121
    22 class ExpressionNode final : public ParseNode {
    23 public:
     22struct ExpressionNode final : public ParseList<ExpressionNode> {
    2423        ExpressionNode( ast::Expr * expr = nullptr ) : expr( expr ) {}
    2524        virtual ~ExpressionNode() {}
    2625        virtual ExpressionNode * clone() const override {
    2726                if ( nullptr == expr ) return nullptr;
    28                 return static_cast<ExpressionNode*>(
    29                         (new ExpressionNode( ast::shallowCopy( expr.get() ) ))->set_next( maybeCopy( get_next() ) ));
     27                ExpressionNode * node = new ExpressionNode( ast::shallowCopy( expr.get() ) );
     28                node->next = maybeCopy( next );
     29                return node;
    3030        }
    3131
  • src/Parser/InitializerNode.cc

    rbbf2cb1 rf6e8c67  
    3636                : expr( _expr ), aggregate( aggrp ), designator( des ), kids( nullptr ), maybeConstructed( true ), isDelete( false ) {
    3737        if ( aggrp )
    38                 kids = dynamic_cast< InitializerNode * >( get_next() );
     38                kids = next;
    3939
    4040        if ( kids )
     
    4848
    4949        if ( aggrp )
    50                 kids = dynamic_cast< InitializerNode * >( get_next() );
     50                kids = next;
    5151
    5252        if ( kids )
    53                 set_next( nullptr );
     53                next = nullptr;
    5454} // InitializerNode::InitializerNode
    5555
     
    7373                        while ( curdes != nullptr) {
    7474                                curdes->printOneLine(os);
    75                                 curdes = (ExpressionNode *)(curdes->get_next());
     75                                curdes = curdes->next;
    7676                                if ( curdes ) os << ", ";
    7777                        } // while
     
    8787
    8888        InitializerNode *moreInit;
    89         if ( (moreInit = dynamic_cast< InitializerNode * >( get_next() ) ) ) {
     89        if ( ( moreInit = next ) ) {
    9090                moreInit->printOneLine( os );
    9191        } // if
     
    9898                std::vector<ast::ptr<ast::Designation>> designlist;
    9999                InitializerNode * child = next_init();
    100                 for ( ; child != nullptr ; child = dynamic_cast< InitializerNode * >( child->get_next() ) ) {
     100                for ( ; child != nullptr ; child = child->next ) {
    101101                        std::deque<ast::ptr<ast::Expr>> desList;
    102102                        buildList( child->designator, desList );
  • src/Parser/InitializerNode.h

    rbbf2cb1 rf6e8c67  
    1818#include "ParseNode.h"
    1919
    20 class InitializerNode : public ParseNode {
    21 public:
     20struct InitializerNode final : public ParseList<InitializerNode> {
    2221        InitializerNode( ExpressionNode *, bool aggrp = false, ExpressionNode * des = nullptr );
    2322        InitializerNode( InitializerNode *, bool aggrp = false, ExpressionNode * des = nullptr );
  • src/Parser/ParseNode.h

    rbbf2cb1 rf6e8c67  
    3333
    3434struct DeclarationNode;
    35 class InitializerNode;
    36 class ExpressionNode;
     35struct InitializerNode;
     36struct ExpressionNode;
    3737struct StatementNode;
    3838
     
    4545extern YYLTYPE yylloc;
    4646
    47 class ParseNode {
    48   public:
    49         ParseNode() {};
    50         virtual ~ParseNode() { delete next; delete name; };
     47struct ParseNode {
     48        ParseNode() {}
     49        virtual ~ParseNode() {}
    5150        virtual ParseNode * clone() const = 0;
    5251
    53         ParseNode * get_next() const { return next; }
    54         ParseNode * set_next( ParseNode * newlink ) { next = newlink; return this; }
     52        virtual void print( __attribute__((unused)) std::ostream & os, __attribute__((unused)) int indent = 0 ) const {}
    5553
    56         ParseNode * get_last() {
    57                 ParseNode * current;
    58                 for ( current = this; current->get_next() != nullptr; current = current->get_next() );
     54        static int indent_by;
     55
     56        CodeLocation location = yylloc;
     57}; // ParseNode
     58
     59/// Only ever use in the form `struct NAME final : public ParseList<NAME>`!
     60template<typename Next>
     61struct ParseList : public ParseNode {
     62        ParseList() {}
     63        virtual ~ParseList() { delete next; };
     64        virtual ParseList<Next> * clone() const = 0;
     65
     66        Next * get_last() {
     67                Next * current = static_cast<Next *>( this );
     68                while ( current->next != nullptr ) current = current->next;
    5969                return current;
    6070        }
    61         ParseNode * set_last( ParseNode * newlast ) {
    62                 if ( newlast != nullptr ) get_last()->set_next( newlast );
    63                 return this;
     71        Next * set_last( Next * newlast ) {
     72                if ( newlast != nullptr ) get_last()->next = newlast;
     73                return static_cast<Next *>( this );
    6474        }
    6575
    66         virtual void print( __attribute__((unused)) std::ostream & os, __attribute__((unused)) int indent = 0 ) const {}
    6776        virtual void printList( std::ostream & os, int indent = 0 ) const {
    6877                print( os, indent );
     
    7079        }
    7180
    72         static int indent_by;
    73 
    74         ParseNode * next = nullptr;
    75         const std::string * name = nullptr;
    76         CodeLocation location = yylloc;
    77 }; // ParseNode
     81        Next * next = nullptr;
     82};
    7883
    7984// Must harmonize with OperName.
  • src/Parser/StatementNode.cc

    rbbf2cb1 rf6e8c67  
    5454                StatementNode * nextStmt = new StatementNode(
    5555                        new ast::DeclStmt( decl->location, maybeBuild( decl ) ) );
    56                 set_next( nextStmt );
    57                 if ( decl->get_next() ) {
    58                         get_next()->set_next( new StatementNode( dynamic_cast< DeclarationNode * >(decl->get_next()) ) );
    59                         decl->set_next( 0 );
     56                next = nextStmt;
     57                if ( decl->next ) {
     58                        next->next = new StatementNode( decl->next );
     59                        decl->next = nullptr;
    6060                } // if
    6161        } else {
    62                 if ( decl->get_next() ) {
    63                         set_next( new StatementNode( dynamic_cast< DeclarationNode * >( decl->get_next() ) ) );
    64                         decl->set_next( 0 );
     62                if ( decl->next ) {
     63                        next = new StatementNode( decl->next );
     64                        decl->next = nullptr;
    6565                } // if
    6666                agg = decl;
     
    8787        ClauseNode * prev = this;
    8888        // find end of list and maintain previous pointer
    89         for ( ClauseNode * curr = prev; curr != nullptr; curr = (ClauseNode *)curr->get_next() ) {
    90                 ClauseNode * node = strict_dynamic_cast< ClauseNode * >(curr);
     89        for ( ClauseNode * curr = prev; curr != nullptr; curr = curr->next ) {
     90                ClauseNode * node = curr;
    9191                assert( dynamic_cast<ast::CaseClause *>( node->clause.get() ) );
    9292                prev = curr;
    9393        } // for
    94         ClauseNode * node = dynamic_cast< ClauseNode * >(prev);
     94        ClauseNode * node = prev;
    9595        // convert from StatementNode list to Statement list
    9696        std::vector<ast::ptr<ast::Stmt>> stmts;
     
    332332        clause->when_cond = notZeroExpr( maybeMoveBuild( when ) );
    333333
    334         ExpressionNode * next = dynamic_cast<ExpressionNode *>( targetExpr->get_next() );
    335         targetExpr->set_next( nullptr );
     334        ExpressionNode * next = targetExpr->next;
     335        targetExpr->next = nullptr;
    336336        buildMoveList( next, clause->target_args );
    337337
  • src/Parser/StatementNode.h

    rbbf2cb1 rf6e8c67  
    1818#include "ParseNode.h"
    1919
    20 struct StatementNode final : public ParseNode {
     20struct StatementNode final : public ParseList<StatementNode> {
    2121        StatementNode() : stmt( nullptr ) {}
    2222        StatementNode( ast::Stmt * stmt ) : stmt( stmt ) {}
     
    3939}; // StatementNode
    4040
    41 struct ClauseNode final : public ParseNode {
     41struct ClauseNode final : public ParseList<ClauseNode> {
    4242        ClauseNode( ast::StmtClause * clause ) : clause( clause ) {}
    4343        virtual ~ClauseNode() {}
    44 
    45         ClauseNode * set_last( ParseNode * newlast ) {
    46                 ParseNode::set_last( newlast );
    47         return this;
    48     }
    4944
    5045        virtual ClauseNode * clone() const final { assert( false ); return nullptr; }
  • src/Parser/TypeData.cc

    rbbf2cb1 rf6e8c67  
    479479
    480480
     481TypeData * TypeData::getLastBase() {
     482        TypeData * cur = this;
     483        while ( cur->base ) cur = cur->base;
     484        return cur;
     485}
     486
     487void TypeData::setLastBase( TypeData * newBase ) {
     488        getLastBase()->base = newBase;
     489}
     490
     491// Takes ownership of src.
     492static void addQualifiersToType( TypeData * dst, TypeData * src ) {
     493        if ( dst->base ) {
     494                addQualifiersToType( dst->base, src );
     495        } else if ( dst->kind == TypeData::Function ) {
     496                dst->base = src;
     497                src = nullptr;
     498    } else {
     499                dst->qualifiers |= src->qualifiers;
     500                delete src;
     501        } // if
     502}
     503
     504// Takes ownership of all arguments, gives ownership of return value.
     505TypeData * addQualifiers( TypeData * ltype, TypeData * rtype ) {
     506        if ( ltype->forall ) {
     507                if ( rtype->forall ) {
     508                        rtype->forall->set_last( ltype->forall );
     509                } else if ( TypeData::Aggregate != rtype->kind ) {
     510                        rtype->forall = ltype->forall;
     511                } else if ( rtype->aggregate.params ) {
     512                        rtype->aggregate.params->set_last( ltype->forall );
     513                } else {
     514                        rtype->aggregate.params = ltype->forall;
     515                }
     516                ltype->forall = nullptr;
     517        }
     518
     519        addQualifiersToType( rtype, ltype );
     520        return rtype;
     521}
     522
     523// Helper for addType and cloneBaseType.
     524static void addTypeToType( TypeData *& dst, TypeData *& src ) {
     525        if ( src->forall && dst->kind == TypeData::Function ) {
     526                if ( dst->forall ) {
     527                        dst->forall->set_last( src->forall );
     528                } else {
     529                        dst->forall = src->forall;
     530                } // if
     531                src->forall = nullptr;
     532        } // if
     533        if ( dst->base ) {
     534                addTypeToType( dst->base, src );
     535                return;
     536        }
     537        switch ( dst->kind ) {
     538        case TypeData::Unknown:
     539                src->qualifiers |= dst->qualifiers;
     540                // LEAKS dst?
     541                dst = src;
     542                src = nullptr;
     543                break;
     544        case TypeData::Basic:
     545                dst->qualifiers |= src->qualifiers;
     546                if ( src->kind != TypeData::Unknown ) {
     547                        assert( src->kind == TypeData::Basic );
     548
     549                        if ( dst->basictype == DeclarationNode::NoBasicType ) {
     550                                dst->basictype = src->basictype;
     551                        } else if ( src->basictype != DeclarationNode::NoBasicType ) {
     552                                SemanticError( yylloc, "multiple declaration types \"%s\" and \"%s\".",
     553                                        DeclarationNode::basicTypeNames[ dst->basictype ],
     554                                        DeclarationNode::basicTypeNames[ src->basictype ] );
     555                        }
     556                        if ( dst->complextype == DeclarationNode::NoComplexType ) {
     557                                dst->complextype = src->complextype;
     558                        } else if ( src->complextype != DeclarationNode::NoComplexType ) {
     559                                SemanticError( yylloc, "multiple declaration types \"%s\" and \"%s\".",
     560                                        DeclarationNode::complexTypeNames[ src->complextype ],
     561                                        DeclarationNode::complexTypeNames[ src->complextype ] );
     562                        }
     563                        if ( dst->signedness == DeclarationNode::NoSignedness ) {
     564                                dst->signedness = src->signedness;
     565                        } else if ( src->signedness != DeclarationNode::NoSignedness ) {
     566                                SemanticError( yylloc, "conflicting type specifier \"%s\" and \"%s\".",
     567                                        DeclarationNode::signednessNames[ dst->signedness ],
     568                                        DeclarationNode::signednessNames[ src->signedness ] );
     569                        }
     570                        if ( dst->length == DeclarationNode::NoLength ) {
     571                                dst->length = src->length;
     572                        } else if ( dst->length == DeclarationNode::Long && src->length == DeclarationNode::Long ) {
     573                                dst->length = DeclarationNode::LongLong;
     574                        } else if ( src->length != DeclarationNode::NoLength ) {
     575                                SemanticError( yylloc, "conflicting type specifier \"%s\" and \"%s\".",
     576                                        DeclarationNode::lengthNames[ dst->length ],
     577                                        DeclarationNode::lengthNames[ src->length ] );
     578                        }
     579                } // if
     580                break;
     581        default:
     582                switch ( src->kind ) {
     583                case TypeData::Aggregate:
     584                case TypeData::Enum:
     585                        dst->base = new TypeData( TypeData::AggregateInst );
     586                        dst->base->aggInst.aggregate = src;
     587                        if ( src->kind == TypeData::Aggregate ) {
     588                                dst->base->aggInst.params = maybeCopy( src->aggregate.actuals );
     589                        } // if
     590                        dst->base->qualifiers |= src->qualifiers;
     591                        src = nullptr;
     592                        break;
     593                default:
     594                        if ( dst->forall ) {
     595                                dst->forall->set_last( src->forall );
     596                        } else {
     597                                dst->forall = src->forall;
     598                        } // if
     599                        src->forall = nullptr;
     600                        dst->base = src;
     601                        src = nullptr;
     602                } // switch
     603        } // switch
     604}
     605
     606// Takes ownership of all arguments, gives ownership of return value.
     607TypeData * addType( TypeData * ltype, TypeData * rtype, std::vector<ast::ptr<ast::Attribute>> & attributes ) {
     608        if ( rtype ) {
     609                addTypeToType( rtype, ltype );
     610                return rtype;
     611        } else {
     612                if ( ltype->kind == TypeData::Aggregate || ltype->kind == TypeData::Enum ) {
     613                        // Hide type information aggregate instances.
     614                        rtype = new TypeData( TypeData::AggregateInst );
     615                        rtype->aggInst.aggregate = ltype;
     616                        rtype->aggInst.aggregate->aggregate.attributes.swap( attributes ); // change ownership
     617                        if ( ltype->kind == TypeData::Aggregate ) {
     618                                rtype->aggInst.hoistType = ltype->aggregate.body;
     619                                rtype->aggInst.params = maybeCopy( ltype->aggregate.actuals );
     620                        } else {
     621                                rtype->aggInst.hoistType = ltype->enumeration.body;
     622                        } // if
     623                        rtype->qualifiers |= ltype->qualifiers;
     624                } else {
     625                        rtype = ltype;
     626                } // if
     627                return rtype;
     628        } // if
     629}
     630
     631// Takes ownership of both arguments, gives ownership of return value.
     632TypeData * cloneBaseType( TypeData * type, TypeData * other ) {
     633        TypeData * newType = type->getLastBase()->clone();
     634        if ( newType->kind == TypeData::AggregateInst ) {
     635                // don't duplicate members
     636                if ( newType->aggInst.aggregate->kind == TypeData::Enum ) {
     637                        delete newType->aggInst.aggregate->enumeration.constants;
     638                        newType->aggInst.aggregate->enumeration.constants = nullptr;
     639                        newType->aggInst.aggregate->enumeration.body = false;
     640                } else {
     641                        assert( newType->aggInst.aggregate->kind == TypeData::Aggregate );
     642                        delete newType->aggInst.aggregate->aggregate.fields;
     643                        newType->aggInst.aggregate->aggregate.fields = nullptr;
     644                        newType->aggInst.aggregate->aggregate.body = false;
     645                } // if
     646                // don't hoist twice
     647                newType->aggInst.hoistType = false;
     648        } // if
     649        newType->forall = maybeCopy( type->forall );
     650
     651        if ( other ) {
     652                addTypeToType( other, newType );
     653                delete newType;
     654                return other;
     655        } // if
     656        return newType;
     657}
     658
     659TypeData * makeNewBase( TypeData * type ) {
     660        switch ( type->kind ) {
     661        case TypeData::Aggregate:
     662        case TypeData::Enum: {
     663                TypeData * out = new TypeData( TypeData::AggregateInst );
     664                out->aggInst.aggregate = type;
     665                if ( TypeData::Aggregate == type->kind ) {
     666                        out->aggInst.params = maybeCopy( type->aggregate.actuals );
     667                }
     668                out->qualifiers |= type->qualifiers;
     669                return out;
     670        }
     671        default:
     672                return type;
     673        } // switch
     674}
     675
     676
    481677void buildForall(
    482678                const DeclarationNode * firstNode,
     
    494690        for ( auto i = outputList.begin() ;
    495691                        i != outputList.end() ;
    496                         ++i, n = (DeclarationNode*)n->get_next() ) {
     692                        ++i, n = n->next ) {
    497693                // Only the object type class adds additional assertions.
    498694                if ( n->variable.tyClass != ast::TypeDecl::Otype ) {
     
    639835        for ( auto i = outputForall.begin() ;
    640836                        i != outputForall.end() ;
    641                         ++i, n = (DeclarationNode*)n->get_next() ) {
     837                        ++i, n = n->next ) {
    642838                // Only the object type class adds additional assertions.
    643839                if ( n->variable.tyClass != ast::TypeDecl::Otype ) {
     
    12721468        auto members = ret->members.begin();
    12731469        ret->hide = td->enumeration.hiding == EnumHiding::Hide ? ast::EnumDecl::EnumHiding::Hide : ast::EnumDecl::EnumHiding::Visible;
    1274         for ( const DeclarationNode * cur = td->enumeration.constants; cur != nullptr; cur = dynamic_cast< DeclarationNode * >( cur->get_next() ), ++members ) {
     1470        for ( const DeclarationNode * cur = td->enumeration.constants; cur != nullptr; cur = cur->next, ++members ) {
    12751471                if ( cur->enumInLine ) {
    12761472                        // Do Nothing
     
    15001696        assert( ! function.params );
    15011697        // loop over declaration first as it is easier to spot errors
    1502         for ( DeclarationNode * decl = function.oldDeclList; decl != nullptr; decl = dynamic_cast< DeclarationNode * >( decl->get_next() ) ) {
     1698        for ( DeclarationNode * decl = function.oldDeclList; decl != nullptr; decl = decl->next ) {
    15031699                // scan ALL parameter names for each declaration name to check for duplicates
    1504                 for ( DeclarationNode * param = function.idList; param != nullptr; param = dynamic_cast< DeclarationNode * >( param->get_next() ) ) {
     1700                for ( DeclarationNode * param = function.idList; param != nullptr; param = param->next ) {
    15051701                        if ( *decl->name == *param->name ) {
    15061702                                // type set => parameter name already transformed by a declaration names so there is a duplicate
     
    15241720        //    rtb( a, b, c ) const char * b; {} => int rtn( int a, const char * b, int c ) {}
    15251721
    1526         for ( DeclarationNode * param = function.idList; param != nullptr; param = dynamic_cast< DeclarationNode * >( param->get_next() ) ) {
     1722        for ( DeclarationNode * param = function.idList; param != nullptr; param = param->next ) {
    15271723                if ( ! param->type ) {                                                  // generate type int for empty parameter type
    15281724                        param->type = new TypeData( TypeData::Basic );
  • src/Parser/TypeData.h

    rbbf2cb1 rf6e8c67  
    111111
    112112        const std::string * leafName() const;
     113
     114        TypeData * getLastBase();
     115        void setLastBase( TypeData * );
    113116};
     117
     118TypeData * addQualifiers( TypeData * ltype, TypeData * rtype );
     119TypeData * addType( TypeData * ltype, TypeData * rtype, std::vector<ast::ptr<ast::Attribute>> & );
     120TypeData * cloneBaseType( TypeData * type, TypeData * other );
     121TypeData * makeNewBase( TypeData * type );
    114122
    115123ast::Type * typebuild( const TypeData * );
  • src/Parser/lex.ll

    rbbf2cb1 rf6e8c67  
    1010 * Created On       : Sat Sep 22 08:58:10 2001
    1111 * Last Modified By : Peter A. Buhr
    12  * Last Modified On : Tue Oct  3 17:10:57 2023
    13  * Update Count     : 773
     12 * Last Modified On : Sat Feb 24 11:47:24 2024
     13 * Update Count     : 777
    1414 */
    1515
     
    407407";"                             { ASCIIOP_RETURN(); }
    408408"."                             { ASCIIOP_RETURN(); }                                   // also operator
     409"@@"                    { NAMEDOP_RETURN(ATTR); }                               // CFA, attribute shorthand
    409410"..."                   { NAMEDOP_RETURN(ELLIPSIS); }
    410411
  • src/Parser/parser.yy

    rbbf2cb1 rf6e8c67  
    1010// Created On       : Sat Sep  1 20:22:55 2001
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Fri Feb 23 18:25:46 2024
    13 // Update Count     : 6484
     12// Last Modified On : Mon Mar  4 08:44:25 2024
     13// Update Count     : 6562
    1414//
    1515
     
    126126        DeclarationNode * cl = (new DeclarationNode)->addType( typeSpec ); // typeSpec IS DELETED!!!
    127127
    128         // Start at second variable in declaration list and clone the type specifiers for each variable..
    129         for ( DeclarationNode * cur = dynamic_cast<DeclarationNode *>( declList->get_next() ); cur != nullptr; cur = dynamic_cast<DeclarationNode *>( cur->get_next() ) ) {
     128        // Start at second variable in declaration list and clone the type specifiers for each variable.
     129        for ( DeclarationNode * cur = declList->next ; cur != nullptr; cur = cur->next ) {
    130130                cl->cloneBaseType( cur, copyattr );                             // cur is modified
    131131        } // for
     
    139139void distExt( DeclarationNode * declaration ) {
    140140        // distribute EXTENSION across all declarations
    141         for ( DeclarationNode *iter = declaration; iter != nullptr; iter = (DeclarationNode *)iter->get_next() ) {
     141        for ( DeclarationNode *iter = declaration ; iter != nullptr ; iter = iter->next ) {
    142142                iter->set_extension( true );
    143143        } // for
     
    146146void distInl( DeclarationNode * declaration ) {
    147147        // distribute INLINE across all declarations
    148         for ( DeclarationNode *iter = declaration; iter != nullptr; iter = (DeclarationNode *)iter->get_next() ) {
     148        for ( DeclarationNode *iter = declaration ; iter != nullptr ; iter = iter->next ) {
    149149                iter->set_inLine( true );
    150150        } // for
     
    153153void distQual( DeclarationNode * declaration, DeclarationNode * qualifiers ) {
    154154        // distribute qualifiers across all non-variable declarations in a distribution statemement
    155         for ( DeclarationNode * iter = declaration; iter != nullptr; iter = (DeclarationNode *)iter->get_next() ) {
     155        for ( DeclarationNode * iter = declaration ; iter != nullptr ; iter = iter->next ) {
    156156                // SKULLDUGGERY: Distributions are parsed inside out, so qualifiers are added to declarations inside out. Since
    157157                // addQualifiers appends to the back of the list, the forall clauses are in the wrong order (right to left). To
     
    389389%token LE GE EQ NE                                                                              // <=   >=      ==      !=
    390390%token ANDAND OROR                                                                              // &&   ||
    391 %token ELLIPSIS                                                                                 // ...
     391%token ATTR ELLIPSIS                                                                    // @@   ...
    392392
    393393%token EXPassign        MULTassign      DIVassign       MODassign       // \=   *=      /=      %=
     
    433433%type<stmt> statement                                   labeled_statement                       compound_statement
    434434%type<stmt> statement_decl                              statement_decl_list                     statement_list_nodecl
    435 %type<stmt> selection_statement                 if_statement
     435%type<stmt> selection_statement
    436436%type<clause> switch_clause_list_opt    switch_clause_list
    437437%type<expr> case_value
     
    500500%type<decl> cfa_identifier_parameter_declarator_tuple cfa_identifier_parameter_ptr
    501501
    502 %type<decl> cfa_parameter_declaration cfa_parameter_list cfa_parameter_ellipsis_list_opt
     502%type<decl> cfa_parameter_declaration cfa_parameter_list cfa_parameter_list_ellipsis_opt
    503503
    504504%type<decl> cfa_typedef_declaration cfa_variable_declaration cfa_variable_specifier
     
    508508%type<decl> KR_parameter_list KR_parameter_list_opt
    509509
    510 %type<decl> parameter_declaration parameter_list parameter_type_list_opt
     510%type<decl> parameter_declaration parameter_list parameter_list_ellipsis_opt
    511511
    512512%type<decl> paren_identifier paren_type
     
    530530%type<decl> type_parameter type_parameter_list type_initializer_opt
    531531
    532 %type<expr> type_parameters_opt type_list array_type_list
     532%type<expr> type_parameters_opt type_list array_type_list // array_dimension_list
    533533
    534534%type<decl> type_qualifier type_qualifier_name forall type_qualifier_list_opt type_qualifier_list
     
    12461246        ;
    12471247
     1248// if, switch, and choose require parenthesis around the conditional because it can be followed by a statement.
     1249// For example, without parenthesis:
     1250//
     1251//    if x + y + z; => "if ( x + y ) + z" or "if ( x ) + y + z"
     1252//    switch ( S ) { ... } => switch ( S ) { compound literal... } ... or
     1253
    12481254selection_statement:
    1249                         // pop causes a S/R conflict without separating the IF statement into a non-terminal even after resolving
    1250                         // the inherent S/R conflict with THEN/ELSE.
    1251         push if_statement pop
    1252                 { $$ = $2; }
     1255        IF '(' conditional_declaration ')' statement            %prec THEN
     1256                // explicitly deal with the shift/reduce conflict on if/else
     1257                { $$ = new StatementNode( build_if( yylloc, $3, maybe_build_compound( yylloc, $5 ), nullptr ) ); }
     1258        | IF '(' conditional_declaration ')' statement ELSE statement
     1259                { $$ = new StatementNode( build_if( yylloc, $3, maybe_build_compound( yylloc, $5 ), maybe_build_compound( yylloc, $7 ) ) ); }
    12531260        | SWITCH '(' comma_expression ')' case_clause
    12541261                { $$ = new StatementNode( build_switch( yylloc, true, $3, $5 ) ); }
     
    12741281        | CHOOSE '(' comma_expression ')' '{' error '}'         // CFA, invalid syntax rule
    12751282                { SemanticError( yylloc, "syntax error, declarations can only appear before the list of case clauses." ); $$ = nullptr; }
    1276         ;
    1277 
    1278 if_statement:
    1279         IF '(' conditional_declaration ')' statement            %prec THEN
    1280                 // explicitly deal with the shift/reduce conflict on if/else
    1281                 { $$ = new StatementNode( build_if( yylloc, $3, maybe_build_compound( yylloc, $5 ), nullptr ) ); }
    1282         | IF '(' conditional_declaration ')' statement ELSE statement
    1283                 { $$ = new StatementNode( build_if( yylloc, $3, maybe_build_compound( yylloc, $5 ), maybe_build_compound( yylloc, $7 ) ) ); }
    12841283        ;
    12851284
     
    18971896declaration_list:
    18981897        declaration
    1899         | declaration_list declaration          { $$ = $1->appendList( $2 ); }
     1898        | declaration_list declaration
     1899                { $$ = $1->set_last( $2 ); }
    19001900        ;
    19011901
     
    19101910                { $$ = $1; }
    19111911        | KR_parameter_list c_declaration ';'
    1912                 { $$ = $1->appendList( $2 ); }
     1912                { $$ = $1->set_last( $2 ); }
    19131913        ;
    19141914
     
    19681968                { $$ = $2->addQualifiers( $1 )->addInitializer( $3 ); }
    19691969        | cfa_variable_declaration pop ',' push identifier_or_type_name initializer_opt
    1970                 { $$ = $1->appendList( $1->cloneType( $5 )->addInitializer( $6 ) ); }
     1970                { $$ = $1->set_last( $1->cloneType( $5 )->addInitializer( $6 ) ); }
    19711971        ;
    19721972
     
    19901990        | declaration_qualifier_list type_qualifier_list cfa_function_specifier
    19911991                { $$ = $3->addQualifiers( $1 )->addQualifiers( $2 ); }
    1992         | cfa_function_declaration ',' identifier_or_type_name '(' push cfa_parameter_ellipsis_list_opt pop ')'
     1992        | cfa_function_declaration ',' identifier_or_type_name '(' push cfa_parameter_list_ellipsis_opt pop ')'
    19931993                {
    19941994                        // Append the return type at the start (left-hand-side) to each identifier in the list.
    19951995                        DeclarationNode * ret = new DeclarationNode;
    19961996                        ret->type = maybeCopy( $1->type->base );
    1997                         $$ = $1->appendList( DeclarationNode::newFunction( $3, ret, $6, nullptr ) );
     1997                        $$ = $1->set_last( DeclarationNode::newFunction( $3, ret, $6, nullptr ) );
    19981998                }
    19991999        ;
    20002000
    20012001cfa_function_specifier:                                                                 // CFA
    2002 //      '[' ']' identifier_or_type_name '(' push cfa_parameter_ellipsis_list_opt pop ')' // S/R conflict
    2003 //              {
    2004 //                      $$ = DeclarationNode::newFunction( $3, DeclarationNode::newTuple( 0 ), $6, nullptr, true );
    2005 //              }
    2006 //      '[' ']' identifier '(' push cfa_parameter_ellipsis_list_opt pop ')'
    2007 //              {
    2008 //                      typedefTable.setNextIdentifier( *$5 );
    2009 //                      $$ = DeclarationNode::newFunction( $5, DeclarationNode::newTuple( 0 ), $8, nullptr, true );
    2010 //              }
    2011 //      | '[' ']' TYPEDEFname '(' push cfa_parameter_ellipsis_list_opt pop ')'
    2012 //              {
    2013 //                      typedefTable.setNextIdentifier( *$5 );
    2014 //                      $$ = DeclarationNode::newFunction( $5, DeclarationNode::newTuple( 0 ), $8, nullptr, true );
    2015 //              }
    2016 //      | '[' ']' typegen_name
     2002        '[' ']' identifier '(' push cfa_parameter_list_ellipsis_opt pop ')' attribute_list_opt
     2003                { $$ = DeclarationNode::newFunction( $3,  DeclarationNode::newTuple( nullptr ), $6, nullptr )->addQualifiers( $9 ); }
     2004        | '[' ']' TYPEDEFname '(' push cfa_parameter_list_ellipsis_opt pop ')' attribute_list_opt
     2005                { $$ = DeclarationNode::newFunction( $3,  DeclarationNode::newTuple( nullptr ), $6, nullptr )->addQualifiers( $9 ); }
     2006        // | '[' ']' TYPEGENname '(' push cfa_parameter_list_ellipsis_opt pop ')' attribute_list_opt
     2007        //      { $$ = DeclarationNode::newFunction( $3,  DeclarationNode::newTuple( nullptr ), $6, nullptr )->addQualifiers( $9 ); }
     2008
    20172009                // identifier_or_type_name must be broken apart because of the sequence:
    20182010                //
    2019                 //   '[' ']' identifier_or_type_name '(' cfa_parameter_ellipsis_list_opt ')'
     2011                //   '[' ']' identifier_or_type_name '(' cfa_parameter_list_ellipsis_opt ')'
    20202012                //   '[' ']' type_specifier
    20212013                //
    20222014                // type_specifier can resolve to just TYPEDEFname (e.g., typedef int T; int f( T );). Therefore this must be
    20232015                // flattened to allow lookahead to the '(' without having to reduce identifier_or_type_name.
    2024         cfa_abstract_tuple identifier_or_type_name '(' push cfa_parameter_ellipsis_list_opt pop ')' attribute_list_opt
     2016        | cfa_abstract_tuple identifier_or_type_name '(' push cfa_parameter_list_ellipsis_opt pop ')' attribute_list_opt
    20252017                // To obtain LR(1 ), this rule must be factored out from function return type (see cfa_abstract_declarator).
    20262018                { $$ = DeclarationNode::newFunction( $2, $1, $5, nullptr )->addQualifiers( $8 ); }
    2027         | cfa_function_return identifier_or_type_name '(' push cfa_parameter_ellipsis_list_opt pop ')' attribute_list_opt
     2019        | cfa_function_return identifier_or_type_name '(' push cfa_parameter_list_ellipsis_opt pop ')' attribute_list_opt
    20282020                { $$ = DeclarationNode::newFunction( $2, $1, $5, nullptr )->addQualifiers( $8 ); }
    20292021        ;
     
    20322024        '[' push cfa_parameter_list pop ']'
    20332025                { $$ = DeclarationNode::newTuple( $3 ); }
    2034         | '[' push cfa_parameter_list pop ',' push cfa_abstract_parameter_list pop ']'
     2026        | '[' push cfa_parameter_list ',' cfa_abstract_parameter_list pop ']'
    20352027                // To obtain LR(1 ), the last cfa_abstract_parameter_list is added into this flattened rule to lookahead to the ']'.
    2036                 { $$ = DeclarationNode::newTuple( $3->appendList( $7 ) ); }
     2028                { $$ = DeclarationNode::newTuple( $3->set_last( $5 ) ); }
    20372029        ;
    20382030
     
    20482040                        $$ = $2->addTypedef();
    20492041                }
    2050         | cfa_typedef_declaration pop ',' push identifier
    2051                 {
    2052                         typedefTable.addToEnclosingScope( *$5, TYPEDEFname, "cfa_typedef_declaration 3" );
    2053                         $$ = $1->appendList( $1->cloneType( $5 ) );
     2042        | cfa_typedef_declaration ',' identifier
     2043                {
     2044                        typedefTable.addToEnclosingScope( *$3, TYPEDEFname, "cfa_typedef_declaration 3" );
     2045                        $$ = $1->set_last( $1->cloneType( $3 ) );
    20542046                }
    20552047        ;
     
    20692061                {
    20702062                        typedefTable.addToEnclosingScope( *$3->name, TYPEDEFname, "typedef_declaration 2" );
    2071                         $$ = $1->appendList( $1->cloneBaseType( $3 )->addTypedef() );
     2063                        $$ = $1->set_last( $1->cloneBaseType( $3 )->addTypedef() );
    20722064                }
    20732065        | type_qualifier_list TYPEDEF type_specifier declarator // remaining OBSOLESCENT (see 2 )
     
    21232115
    21242116        | declaring_list ',' attribute_list_opt declarator asm_name_opt initializer_opt
    2125                 { $$ = $1->appendList( $4->addQualifiers( $3 )->addAsmName( $5 )->addInitializer( $6 ) ); }
     2117                { $$ = $1->set_last( $4->addQualifiers( $3 )->addAsmName( $5 )->addInitializer( $6 ) ); }
    21262118        ;
    21272119
     
    25872579                { $$ = nullptr; }
    25882580        | field_declaration_list_opt field_declaration
    2589                 { $$ = $1 ? $1->appendList( $2 ) : $2; }
     2581                { $$ = $1 ? $1->set_last( $2 ) : $2; }
    25902582        ;
    25912583
     
    26352627        | field_declarator
    26362628        | field_declaring_list_opt ',' attribute_list_opt field_declarator
    2637                 { $$ = $1->appendList( $4->addQualifiers( $3 ) ); }
     2629                { $$ = $1->set_last( $4->addQualifiers( $3 ) ); }
    26382630        ;
    26392631
     
    26572649        | field_abstract
    26582650        | field_abstract_list_opt ',' attribute_list_opt field_abstract
    2659                 { $$ = $1->appendList( $4->addQualifiers( $3 ) ); }
     2651                { $$ = $1->set_last( $4->addQualifiers( $3 ) ); }
    26602652        ;
    26612653
     
    26702662                { $$ = $1->addName( $2 ); }
    26712663        | cfa_field_declaring_list ',' identifier_or_type_name
    2672                 { $$ = $1->appendList( $1->cloneType( $3 ) ); }
     2664                { $$ = $1->set_last( $1->cloneType( $3 ) ); }
    26732665        ;
    26742666
     
    26772669        cfa_abstract_declarator_tuple
    26782670        | cfa_field_abstract_list ','
    2679                 { $$ = $1->appendList( $1->cloneType( 0 ) ); }
     2671                { $$ = $1->set_last( $1->cloneType( 0 ) ); }
    26802672        ;
    26812673
     
    26902682                { $$ = $2; }
    26912683        ;
     2684
     2685// ***********
     2686// Enumeration
     2687// ***********
    26922688
    26932689enum_type:
     
    27192715        | ENUM '(' cfa_abstract_parameter_declaration ')' attribute_list_opt identifier attribute_list_opt
    27202716                {
    2721                         if ( $3 && ($3->storageClasses.any() || $3->type->qualifiers.val != 0 )) {
     2717                        if ( $3 && ($3->storageClasses.any() || $3->type->qualifiers.val != 0) ) {
    27222718                                SemanticError( yylloc, "syntax error, storage-class and CV qualifiers are not meaningful for enumeration constants, which are const." );
    27232719                        }
     
    27692765                { $$ = DeclarationNode::newEnumInLine( *$2->type->symbolic.name ); }
    27702766        | enumerator_list ',' visible_hide_opt identifier_or_type_name enumerator_value_opt
    2771                 { $$ = $1->appendList( DeclarationNode::newEnumValueGeneric( $4, $5 ) ); }
     2767                { $$ = $1->set_last( DeclarationNode::newEnumValueGeneric( $4, $5 ) ); }
    27722768        | enumerator_list ',' INLINE type_name enumerator_value_opt
    2773                 { $$ = $1->appendList( DeclarationNode::newEnumValueGeneric( new string("inline"), nullptr ) ); }
     2769                { $$ = $1->set_last( DeclarationNode::newEnumValueGeneric( new string("inline"), nullptr ) ); }
    27742770        ;
    27752771
     
    27892785        ;
    27902786
    2791 cfa_parameter_ellipsis_list_opt:                                                // CFA, abstract + real
    2792         // empty
    2793                 { $$ = DeclarationNode::newBasicType( DeclarationNode::Void ); }
    2794         | ELLIPSIS
    2795                 { $$ = nullptr; }
    2796         | cfa_abstract_parameter_list
    2797         | cfa_parameter_list
    2798         | cfa_parameter_list pop ',' push cfa_abstract_parameter_list
    2799                 { $$ = $1->appendList( $5 ); }
    2800         | cfa_abstract_parameter_list pop ',' push ELLIPSIS
    2801                 { $$ = $1->addVarArgs(); }
    2802         | cfa_parameter_list pop ',' push ELLIPSIS
    2803                 { $$ = $1->addVarArgs(); }
    2804         ;
    2805 
    2806 cfa_parameter_list:                                                                             // CFA
    2807                 // To obtain LR(1) between cfa_parameter_list and cfa_abstract_tuple, the last cfa_abstract_parameter_list is
    2808                 // factored out from cfa_parameter_list, flattening the rules to get lookahead to the ']'.
    2809         cfa_parameter_declaration
    2810         | cfa_abstract_parameter_list pop ',' push cfa_parameter_declaration
    2811                 { $$ = $1->appendList( $5 ); }
    2812         | cfa_parameter_list pop ',' push cfa_parameter_declaration
    2813                 { $$ = $1->appendList( $5 ); }
    2814         | cfa_parameter_list pop ',' push cfa_abstract_parameter_list pop ',' push cfa_parameter_declaration
    2815                 { $$ = $1->appendList( $5 )->appendList( $9 ); }
    2816         ;
    2817 
    2818 cfa_abstract_parameter_list:                                                    // CFA, new & old style abstract
    2819         cfa_abstract_parameter_declaration
    2820         | cfa_abstract_parameter_list pop ',' push cfa_abstract_parameter_declaration
    2821                 { $$ = $1->appendList( $5 ); }
    2822         ;
    2823 
    2824 parameter_type_list_opt:
     2787// *******************
     2788// Function parameters
     2789// *******************
     2790
     2791parameter_list_ellipsis_opt:
    28252792        // empty
    28262793                { $$ = nullptr; }
     
    28332800
    28342801parameter_list:                                                                                 // abstract + real
    2835         abstract_parameter_declaration
    2836         | parameter_declaration
     2802        parameter_declaration
     2803        | abstract_parameter_declaration
     2804        | parameter_list ',' parameter_declaration
     2805                { $$ = $1->set_last( $3 ); }
    28372806        | parameter_list ',' abstract_parameter_declaration
    2838                 { $$ = $1->appendList( $3 ); }
    2839         | parameter_list ',' parameter_declaration
    2840                 { $$ = $1->appendList( $3 ); }
     2807                { $$ = $1->set_last( $3 ); }
     2808        ;
     2809
     2810cfa_parameter_list_ellipsis_opt:                                                // CFA, abstract + real
     2811        // empty
     2812                { $$ = DeclarationNode::newBasicType( DeclarationNode::Void ); }
     2813        | ELLIPSIS
     2814                { $$ = nullptr; }
     2815        | cfa_parameter_list
     2816        | cfa_abstract_parameter_list
     2817        | cfa_parameter_list ',' cfa_abstract_parameter_list
     2818                { $$ = $1->set_last( $3 ); }
     2819        | cfa_parameter_list ',' ELLIPSIS
     2820                { $$ = $1->addVarArgs(); }
     2821        | cfa_abstract_parameter_list ',' ELLIPSIS
     2822                { $$ = $1->addVarArgs(); }
     2823        ;
     2824
     2825cfa_parameter_list:                                                                             // CFA
     2826                // To obtain LR(1) between cfa_parameter_list and cfa_abstract_tuple, the last cfa_abstract_parameter_list is
     2827                // factored out from cfa_parameter_list, flattening the rules to get lookahead to the ']'.
     2828        cfa_parameter_declaration
     2829        | cfa_abstract_parameter_list ',' cfa_parameter_declaration
     2830                { $$ = $1->set_last( $3 ); }
     2831        | cfa_parameter_list ',' cfa_parameter_declaration
     2832                { $$ = $1->set_last( $3 ); }
     2833        | cfa_parameter_list ',' cfa_abstract_parameter_list ',' cfa_parameter_declaration
     2834                { $$ = $1->set_last( $3 )->set_last( $5 ); }
     2835        ;
     2836
     2837cfa_abstract_parameter_list:                                                    // CFA, new & old style abstract
     2838        cfa_abstract_parameter_declaration
     2839        | cfa_abstract_parameter_list ',' cfa_abstract_parameter_declaration
     2840                { $$ = $1->set_last( $3 ); }
    28412841        ;
    28422842
    28432843// Provides optional identifier names (abstract_declarator/variable_declarator), no initialization, different semantics
    28442844// for typedef name by using type_parameter_redeclarator instead of typedef_redeclarator, and function prototypes.
     2845
     2846parameter_declaration:
     2847                // No SUE declaration in parameter list.
     2848        declaration_specifier_nobody identifier_parameter_declarator default_initializer_opt
     2849                { $$ = $2->addType( $1 )->addInitializer( $3 ? new InitializerNode( $3 ) : nullptr ); }
     2850        | declaration_specifier_nobody type_parameter_redeclarator default_initializer_opt
     2851                { $$ = $2->addType( $1 )->addInitializer( $3 ? new InitializerNode( $3 ) : nullptr ); }
     2852        ;
     2853
     2854abstract_parameter_declaration:
     2855        declaration_specifier_nobody default_initializer_opt
     2856                { $$ = $1->addInitializer( $2 ? new InitializerNode( $2 ) : nullptr ); }
     2857        | declaration_specifier_nobody abstract_parameter_declarator default_initializer_opt
     2858                { $$ = $2->addType( $1 )->addInitializer( $3 ? new InitializerNode( $3 ) : nullptr ); }
     2859        ;
    28452860
    28462861cfa_parameter_declaration:                                                              // CFA, new & old style parameter declaration
     
    28662881        ;
    28672882
    2868 parameter_declaration:
    2869                 // No SUE declaration in parameter list.
    2870         declaration_specifier_nobody identifier_parameter_declarator default_initializer_opt
    2871                 { $$ = $2->addType( $1 )->addInitializer( $3 ? new InitializerNode( $3 ) : nullptr ); }
    2872         | declaration_specifier_nobody type_parameter_redeclarator default_initializer_opt
    2873                 { $$ = $2->addType( $1 )->addInitializer( $3 ? new InitializerNode( $3 ) : nullptr ); }
    2874         ;
    2875 
    2876 abstract_parameter_declaration:
    2877         declaration_specifier_nobody default_initializer_opt
    2878                 { $$ = $1->addInitializer( $2 ? new InitializerNode( $2 ) : nullptr ); }
    2879         | declaration_specifier_nobody abstract_parameter_declarator default_initializer_opt
    2880                 { $$ = $2->addType( $1 )->addInitializer( $3 ? new InitializerNode( $3 ) : nullptr ); }
    2881         ;
    2882 
    28832883// ISO/IEC 9899:1999 Section 6.9.1(6) : "An identifier declared as a typedef name shall not be redeclared as a
    28842884// parameter." Because the scope of the K&R-style parameter-list sees the typedef first, the following is based only on
     
    28892889                { $$ = DeclarationNode::newName( $1 ); }
    28902890        | identifier_list ',' identifier
    2891                 { $$ = $1->appendList( DeclarationNode::newName( $3 ) ); }
     2891                { $$ = $1->set_last( DeclarationNode::newName( $3 ) ); }
    28922892        ;
    28932893
     
    29902990        type_parameter
    29912991        | type_parameter_list ',' type_parameter
    2992                 { $$ = $1->appendList( $3 ); }
     2992                { $$ = $1->set_last( $3 ); }
    29932993        ;
    29942994
     
    30633063        assertion
    30643064        | assertion_list assertion
    3065                 { $$ = $1->appendList( $2 ); }
     3065                { $$ = $1->set_last( $2 ); }
    30663066        ;
    30673067
     
    30913091                { $$ = $3->addQualifiers( $1 ); }
    30923092        | type_declaring_list ',' type_declarator
    3093                 { $$ = $1->appendList( $3->copySpecifiers( $1 ) ); }
     3093                { $$ = $1->set_last( $3->copySpecifiers( $1 ) ); }
    30943094        ;
    30953095
     
    31343134        trait_declaration
    31353135        | trait_declaration_list pop push trait_declaration
    3136                 { $$ = $1->appendList( $4 ); }
     3136                { $$ = $1->set_last( $4 ); }
    31373137        ;
    31383138
     
    31463146        | cfa_function_specifier
    31473147        | cfa_trait_declaring_list pop ',' push identifier_or_type_name
    3148                 { $$ = $1->appendList( $1->cloneType( $5 ) ); }
     3148                { $$ = $1->set_last( $1->cloneType( $5 ) ); }
    31493149        ;
    31503150
     
    31533153                { $$ = $2->addType( $1 ); }
    31543154        | trait_declaring_list pop ',' push declarator
    3155                 { $$ = $1->appendList( $1->cloneBaseType( $5 ) ); }
     3155                { $$ = $1->set_last( $1->cloneBaseType( $5 ) ); }
    31563156        ;
    31573157
     
    31613161        // empty, input file
    31623162        | external_definition_list
    3163                 { parseTree = parseTree ? parseTree->appendList( $1 ) : $1;     }
     3163                { parseTree = parseTree ? parseTree->set_last( $1 ) : $1;       }
    31643164        ;
    31653165
     
    31683168                { $$ = $2; }
    31693169        | external_definition_list push external_definition pop
    3170                 { $$ = $1 ? $1->appendList( $3 ) : $3; }
     3170                { $$ = $1 ? $1->set_last( $3 ) : $3; }
    31713171        ;
    31723172
     
    33953395        ATTRIBUTE '(' '(' attribute_name_list ')' ')'
    33963396                { $$ = $4; }
     3397        | ATTRIBUTE '(' attribute_name_list ')'                         // CFA
     3398                { $$ = $3; }
     3399        | ATTR '(' attribute_name_list ')'                                      // CFA
     3400                { $$ = $3; }
    33973401        ;
    33983402
     
    34993503
    35003504variable_function:
    3501         '(' variable_ptr ')' '(' parameter_type_list_opt ')' // empty parameter list OBSOLESCENT (see 3)
     3505        '(' variable_ptr ')' '(' parameter_list_ellipsis_opt ')' // empty parameter list OBSOLESCENT (see 3)
    35023506                { $$ = $2->addParamList( $5 ); }
    3503         | '(' attribute_list variable_ptr ')' '(' parameter_type_list_opt ')' // empty parameter list OBSOLESCENT (see 3)
     3507        | '(' attribute_list variable_ptr ')' '(' parameter_list_ellipsis_opt ')' // empty parameter list OBSOLESCENT (see 3)
    35043508                { $$ = $3->addQualifiers( $2 )->addParamList( $6 ); }
    35053509        | '(' variable_function ')'                                                     // redundant parenthesis
     
    35223526
    35233527function_no_ptr:
    3524         paren_identifier '(' parameter_type_list_opt ')' // empty parameter list OBSOLESCENT (see 3)
     3528        paren_identifier '(' parameter_list_ellipsis_opt ')' // empty parameter list OBSOLESCENT (see 3)
    35253529                { $$ = $1->addParamList( $3 ); }
    3526         | '(' function_ptr ')' '(' parameter_type_list_opt ')'
     3530        | '(' function_ptr ')' '(' parameter_list_ellipsis_opt ')'
    35273531                { $$ = $2->addParamList( $5 ); }
    3528         | '(' attribute_list function_ptr ')' '(' parameter_type_list_opt ')'
     3532        | '(' attribute_list function_ptr ')' '(' parameter_list_ellipsis_opt ')'
    35293533                { $$ = $3->addQualifiers( $2 )->addParamList( $6 ); }
    35303534        | '(' function_no_ptr ')'                                                       // redundant parenthesis
     
    35763580        paren_identifier '(' identifier_list ')'                        // function_declarator handles empty parameter
    35773581                { $$ = $1->addIdList( $3 ); }
    3578         | '(' KR_function_ptr ')' '(' parameter_type_list_opt ')'
     3582        | '(' KR_function_ptr ')' '(' parameter_list_ellipsis_opt ')'
    35793583                { $$ = $2->addParamList( $5 ); }
    3580         | '(' attribute_list KR_function_ptr ')' '(' parameter_type_list_opt ')'
     3584        | '(' attribute_list KR_function_ptr ')' '(' parameter_list_ellipsis_opt ')'
    35813585                { $$ = $3->addQualifiers( $2 )->addParamList( $6 ); }
    35823586        | '(' KR_function_no_ptr ')'                                            // redundant parenthesis
     
    36683672
    36693673variable_type_function:
    3670         '(' variable_type_ptr ')' '(' parameter_type_list_opt ')' // empty parameter list OBSOLESCENT (see 3)
     3674        '(' variable_type_ptr ')' '(' parameter_list_ellipsis_opt ')' // empty parameter list OBSOLESCENT (see 3)
    36713675                { $$ = $2->addParamList( $5 ); }
    3672         | '(' attribute_list variable_type_ptr ')' '(' parameter_type_list_opt ')' // empty parameter list OBSOLESCENT (see 3)
     3676        | '(' attribute_list variable_type_ptr ')' '(' parameter_list_ellipsis_opt ')' // empty parameter list OBSOLESCENT (see 3)
    36733677                { $$ = $3->addQualifiers( $2 )->addParamList( $6 ); }
    36743678        | '(' variable_type_function ')'                                        // redundant parenthesis
     
    36913695
    36923696function_type_no_ptr:
    3693         paren_type '(' parameter_type_list_opt ')' // empty parameter list OBSOLESCENT (see 3)
     3697        paren_type '(' parameter_list_ellipsis_opt ')' // empty parameter list OBSOLESCENT (see 3)
    36943698                { $$ = $1->addParamList( $3 ); }
    3695         | '(' function_type_ptr ')' '(' parameter_type_list_opt ')'
     3699        | '(' function_type_ptr ')' '(' parameter_list_ellipsis_opt ')'
    36963700                { $$ = $2->addParamList( $5 ); }
    3697         | '(' attribute_list function_type_ptr ')' '(' parameter_type_list_opt ')'
     3701        | '(' attribute_list function_type_ptr ')' '(' parameter_list_ellipsis_opt ')'
    36983702                { $$ = $3->addQualifiers( $2 )->addParamList( $6 ); }
    36993703        | '(' function_type_no_ptr ')'                                          // redundant parenthesis
     
    37383742                { $$ = $1->addQualifiers( $2 ); }
    37393743        | '&' MUTEX paren_identifier attribute_list_opt
    3740                 { $$ = $3->addPointer( DeclarationNode::newPointer( DeclarationNode::newTypeQualifier( ast::CV::Mutex ), OperKinds::AddressOf ) )->addQualifiers( $4 ); }
     3744                { $$ = $3->addPointer( DeclarationNode::newPointer( DeclarationNode::newTypeQualifier( ast::CV::Mutex ),
     3745                                                                                                                        OperKinds::AddressOf ) )->addQualifiers( $4 ); }
    37413746        | identifier_parameter_ptr
    37423747        | identifier_parameter_array attribute_list_opt
     
    37673772
    37683773identifier_parameter_function:
    3769         paren_identifier '(' parameter_type_list_opt ')' // empty parameter list OBSOLESCENT (see 3)
     3774        paren_identifier '(' parameter_list_ellipsis_opt ')' // empty parameter list OBSOLESCENT (see 3)
    37703775                { $$ = $1->addParamList( $3 ); }
    3771         | '(' identifier_parameter_ptr ')' '(' parameter_type_list_opt ')' // empty parameter list OBSOLESCENT (see 3)
     3776        | '(' identifier_parameter_ptr ')' '(' parameter_list_ellipsis_opt ')' // empty parameter list OBSOLESCENT (see 3)
    37723777                { $$ = $2->addParamList( $5 ); }
    37733778        | '(' identifier_parameter_function ')'                         // redundant parenthesis
     
    37883793                { $$ = $1->addQualifiers( $2 ); }
    37893794        | '&' MUTEX typedef_name attribute_list_opt
    3790                 { $$ = $3->addPointer( DeclarationNode::newPointer( DeclarationNode::newTypeQualifier( ast::CV::Mutex ), OperKinds::AddressOf ) )->addQualifiers( $4 ); }
     3795                { $$ = $3->addPointer( DeclarationNode::newPointer( DeclarationNode::newTypeQualifier( ast::CV::Mutex ),
     3796                                                                                                                        OperKinds::AddressOf ) )->addQualifiers( $4 ); }
    37913797        | type_parameter_ptr
    37923798        | type_parameter_array attribute_list_opt
     
    38203826
    38213827type_parameter_function:
    3822         typedef_name '(' parameter_type_list_opt ')' // empty parameter list OBSOLESCENT (see 3)
     3828        typedef_name '(' parameter_list_ellipsis_opt ')' // empty parameter list OBSOLESCENT (see 3)
    38233829                { $$ = $1->addParamList( $3 ); }
    3824         | '(' type_parameter_ptr ')' '(' parameter_type_list_opt ')' // empty parameter list OBSOLESCENT (see 3)
     3830        | '(' type_parameter_ptr ')' '(' parameter_list_ellipsis_opt ')' // empty parameter list OBSOLESCENT (see 3)
    38253831                { $$ = $2->addParamList( $5 ); }
    38263832        ;
     
    38703876
    38713877abstract_function:
    3872         '(' parameter_type_list_opt ')'                 // empty parameter list OBSOLESCENT (see 3)
     3878        '(' parameter_list_ellipsis_opt ')'                     // empty parameter list OBSOLESCENT (see 3)
    38733879                { $$ = DeclarationNode::newFunction( nullptr, nullptr, $2, nullptr ); }
    3874         | '(' abstract_ptr ')' '(' parameter_type_list_opt ')' // empty parameter list OBSOLESCENT (see 3)
     3880        | '(' abstract_ptr ')' '(' parameter_list_ellipsis_opt ')' // empty parameter list OBSOLESCENT (see 3)
    38753881                { $$ = $2->addParamList( $5 ); }
    38763882        | '(' abstract_function ')'                                                     // redundant parenthesis
     
    38883894                { $$ = DeclarationNode::newArray( $3, nullptr, false )->addArray( DeclarationNode::newArray( $6, nullptr, false ) ); }
    38893895                // { SemanticError( yylloc, "New array dimension is currently unimplemented." ); $$ = nullptr; }
     3896
     3897                // If needed, the following parses and does not use comma_expression, so the array structure can be built.
     3898        // | '[' push assignment_expression pop ',' push array_dimension_list pop ']' // CFA
     3899
    38903900        | '[' push array_type_list pop ']'                                      // CFA
    38913901                { $$ = DeclarationNode::newArray( $3, nullptr, false ); }
    38923902        | multi_array_dimension
    38933903        ;
     3904
     3905// array_dimension_list:
     3906//      assignment_expression
     3907//      | array_dimension_list ',' assignment_expression
     3908//      ;
    38943909
    38953910array_type_list:
     
    39934008
    39944009abstract_parameter_function:
    3995         '(' parameter_type_list_opt ')'                 // empty parameter list OBSOLESCENT (see 3)
     4010        '(' parameter_list_ellipsis_opt ')'                     // empty parameter list OBSOLESCENT (see 3)
    39964011                { $$ = DeclarationNode::newFunction( nullptr, nullptr, $2, nullptr ); }
    3997         | '(' abstract_parameter_ptr ')' '(' parameter_type_list_opt ')' // empty parameter list OBSOLESCENT (see 3)
     4012        | '(' abstract_parameter_ptr ')' '(' parameter_list_ellipsis_opt ')' // empty parameter list OBSOLESCENT (see 3)
    39984013                { $$ = $2->addParamList( $5 ); }
    39994014        | '(' abstract_parameter_function ')'                           // redundant parenthesis
     
    40724087
    40734088variable_abstract_function:
    4074         '(' variable_abstract_ptr ')' '(' parameter_type_list_opt ')' // empty parameter list OBSOLESCENT (see 3)
     4089        '(' variable_abstract_ptr ')' '(' parameter_list_ellipsis_opt ')' // empty parameter list OBSOLESCENT (see 3)
    40754090                { $$ = $2->addParamList( $5 ); }
    40764091        | '(' variable_abstract_function ')'                            // redundant parenthesis
     
    41584173//
    41594174//              cfa_abstract_tuple identifier_or_type_name
    4160 //              '[' cfa_parameter_list ']' identifier_or_type_name '(' cfa_parameter_ellipsis_list_opt ')'
     4175//              '[' cfa_parameter_list ']' identifier_or_type_name '(' cfa_parameter_list_ellipsis_opt ')'
    41614176//
    41624177// since a function return type can be syntactically identical to a tuple type:
     
    42244239
    42254240cfa_abstract_function:                                                                  // CFA
    4226 //      '[' ']' '(' cfa_parameter_ellipsis_list_opt ')'
    4227 //              { $$ = DeclarationNode::newFunction( nullptr, DeclarationNode::newTuple( nullptr ), $4, nullptr ); }
    4228         cfa_abstract_tuple '(' push cfa_parameter_ellipsis_list_opt pop ')'
     4241        '[' ']' '(' cfa_parameter_list_ellipsis_opt ')'
     4242                { $$ = DeclarationNode::newFunction( nullptr, DeclarationNode::newTuple( nullptr ), $4, nullptr ); }
     4243        | cfa_abstract_tuple '(' push cfa_parameter_list_ellipsis_opt pop ')'
    42294244                { $$ = DeclarationNode::newFunction( nullptr, $1, $4, nullptr ); }
    4230         | cfa_function_return '(' push cfa_parameter_ellipsis_list_opt pop ')'
     4245        | cfa_function_return '(' push cfa_parameter_list_ellipsis_opt pop ')'
    42314246                { $$ = DeclarationNode::newFunction( nullptr, $1, $4, nullptr ); }
    42324247        ;
  • src/ResolvExpr/Resolver.cc

    rbbf2cb1 rf6e8c67  
    412412
    413413        void resolveWithExprs(std::vector<ast::ptr<ast::Expr>> & exprs, std::list<ast::ptr<ast::Stmt>> & stmtsToAdd);
     414        bool shouldGenCtorInit( const ast::ObjectDecl * ) const;
    414415
    415416        void beginScope() { managedTypes.beginScope(); }
     
    581582}
    582583
     584bool Resolver::shouldGenCtorInit( ast::ObjectDecl const * decl ) const {
     585        // If we shouldn't try to construct it, then don't.
     586        if ( !InitTweak::tryConstruct( decl ) ) return false;
     587        // Otherwise, if it is a managed type, we may construct it.
     588        if ( managedTypes.isManaged( decl ) ) return true;
     589        // Skip construction if it is trivial at compile-time.
     590        if ( InitTweak::isConstExpr( decl->init ) ) return false;
     591        // Skip construction for local declarations.
     592        return ( !isInFunction() || decl->storage.is_static );
     593}
     594
    583595const ast::ObjectDecl * Resolver::previsit( const ast::ObjectDecl * objectDecl ) {
    584596        // To handle initialization of routine pointers [e.g. int (*fp)(int) = foo()],
     
    615627                        // this object in visitor pass, thus disabling CtorInit codegen.
    616628                        // this happens on aggregate members and function parameters.
    617                         if ( InitTweak::tryConstruct( mutDecl ) && ( managedTypes.isManaged( mutDecl ) || ((! isInFunction() || mutDecl->storage.is_static ) && ! InitTweak::isConstExpr( mutDecl->init ) ) ) ) {
     629                        if ( shouldGenCtorInit( mutDecl ) ) {
    618630                                // constructed objects cannot be designated
    619631                                if ( InitTweak::isDesignated( mutDecl->init ) ) {
Note: See TracChangeset for help on using the changeset viewer.