Changeset 90152a4 for src/Common


Ignore:
Timestamp:
Aug 27, 2018, 4:40:34 PM (8 years ago)
Author:
Rob Schluntz <rschlunt@…>
Branches:
ADT, arm-eh, ast-experimental, cleanup-dtors, enum, forall-pointer-decay, jacob/cs343-translation, jenkins-sandbox, master, new-ast, new-ast-unique-expr, pthread-emulation, qualifiedEnum, stuck-waitfor-destruct
Children:
b7c89aa
Parents:
f9feab8 (diff), 305581d (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' into cleanup-dtors

Location:
src/Common
Files:
4 added
9 edited

Legend:

Unmodified
Added
Removed
  • src/Common/Debug.h

    rf9feab8 r90152a4  
    2828namespace Debug {
    2929        /// debug codegen a translation unit
    30         static inline void codeGen( __attribute__((unused)) const std::list< Declaration * > & translationUnit, __attribute__((unused)) const std::string & label ) {
     30        static inline void codeGen( __attribute__((unused)) const std::list< Declaration * > & translationUnit, __attribute__((unused)) const std::string & label, __attribute__((unused)) LinkageSpec::Spec linkageFilter = LinkageSpec::Builtin ) {
    3131        #ifdef DEBUG
    3232                std::list< Declaration * > decls;
    3333
    34                 filter( translationUnit.begin(), translationUnit.end(), back_inserter( decls ), []( Declaration * decl ) {
    35                         return ! LinkageSpec::isBuiltin( decl->get_linkage() );
     34                filter( translationUnit.begin(), translationUnit.end(), back_inserter( decls ), [linkageFilter]( Declaration * decl ) {
     35                        return ! (decl->linkage & linkageFilter);
    3636                });
    3737
    3838                std::cerr << "======" << label << "======" << std::endl;
    39                 CodeGen::generate( decls, std::cerr, false, true );
     39                CodeGen::generate(
     40                        decls,
     41                        std::cerr,
     42                        true /* doIntrinsics */,
     43                        true /* pretty */,
     44                        false /* generateC */,
     45                        false /* lineMarks */,
     46                        true /* printTypeExpr */
     47                );
    4048        #endif
    4149        } // dump
    4250
    43         static inline void treeDump( __attribute__((unused)) const std::list< Declaration * > & translationUnit, __attribute__((unused)) const std::string & label ) {
     51        static inline void treeDump( __attribute__((unused)) const std::list< Declaration * > & translationUnit, __attribute__((unused)) const std::string & label, __attribute__((unused)) LinkageSpec::Spec linkageFilter = LinkageSpec::Compiler ) {
    4452        #ifdef DEBUG
    4553                std::list< Declaration * > decls;
    4654
    47                 filter( translationUnit.begin(), translationUnit.end(), back_inserter( decls ), []( Declaration * decl ) {
    48                         return ! LinkageSpec::isBuiltin( decl->get_linkage() );
     55                filter( translationUnit.begin(), translationUnit.end(), back_inserter( decls ), [linkageFilter]( Declaration * decl ) {
     56                        return ! (decl->linkage & linkageFilter);
    4957                });
    5058
  • src/Common/PassVisitor.h

    rf9feab8 r90152a4  
    1919#include "SynTree/Expression.h"
    2020#include "SynTree/Constant.h"
    21 #include "SynTree/TypeSubstitution.h"
     21
     22class TypeSubstitution;
    2223
    2324#include "PassVisitor.proto.h"
     
    6566        virtual void visit( TypedefDecl * typeDecl ) override final;
    6667        virtual void visit( AsmDecl * asmDecl ) override final;
     68        virtual void visit( StaticAssertDecl * assertDecl ) override final;
    6769
    6870        virtual void visit( CompoundStmt * compoundStmt ) override final;
    6971        virtual void visit( ExprStmt * exprStmt ) override final;
    7072        virtual void visit( AsmStmt * asmStmt ) override final;
     73        virtual void visit( DirectiveStmt * dirStmt ) override final;
    7174        virtual void visit( IfStmt * ifStmt ) override final;
    7275        virtual void visit( WhileStmt * whileStmt ) override final;
     
    9093        virtual void visit( NameExpr * nameExpr ) override final;
    9194        virtual void visit( CastExpr * castExpr ) override final;
     95        virtual void visit( KeywordCastExpr * castExpr ) override final;
    9296        virtual void visit( VirtualCastExpr * castExpr ) override final;
    9397        virtual void visit( AddressExpr * addressExpr ) override final;
     
    118122        virtual void visit( StmtExpr *  stmtExpr ) override final;
    119123        virtual void visit( UniqueExpr *  uniqueExpr ) override final;
     124        virtual void visit( UntypedInitExpr *  initExpr ) override final;
     125        virtual void visit( InitExpr *  initExpr ) override final;
     126        virtual void visit( DeletedExpr *  delExpr ) override final;
     127        virtual void visit( DefaultArgExpr * argExpr ) override final;
     128        virtual void visit( GenericExpr * genExpr ) override final;
    120129
    121130        virtual void visit( VoidType * basicType ) override final;
     
    124133        virtual void visit( ArrayType * arrayType ) override final;
    125134        virtual void visit( ReferenceType * referenceType ) override final;
     135        virtual void visit( QualifiedType * qualType ) override final;
    126136        virtual void visit( FunctionType * functionType ) override final;
    127137        virtual void visit( StructInstType * aggregateUseType ) override final;
     
    136146        virtual void visit( ZeroType * zeroType ) override final;
    137147        virtual void visit( OneType * oneType ) override final;
     148        virtual void visit( GlobalScopeType * globalType ) override final;
    138149
    139150        virtual void visit( Designation * designation ) override final;
     
    157168        virtual Declaration * mutate( TypedefDecl * typeDecl ) override final;
    158169        virtual AsmDecl * mutate( AsmDecl * asmDecl ) override final;
     170        virtual StaticAssertDecl * mutate( StaticAssertDecl * assertDecl ) override final;
    159171
    160172        virtual CompoundStmt * mutate( CompoundStmt * compoundStmt ) override final;
    161173        virtual Statement * mutate( ExprStmt * exprStmt ) override final;
    162174        virtual Statement * mutate( AsmStmt * asmStmt ) override final;
     175        virtual Statement * mutate( DirectiveStmt * dirStmt ) override final;
    163176        virtual Statement * mutate( IfStmt * ifStmt ) override final;
    164177        virtual Statement * mutate( WhileStmt * whileStmt ) override final;
     
    181194        virtual Expression * mutate( UntypedExpr * untypedExpr ) override final;
    182195        virtual Expression * mutate( NameExpr * nameExpr ) override final;
    183         virtual Expression * mutate( AddressExpr * castExpr ) override final;
     196        virtual Expression * mutate( AddressExpr * addrExpr ) override final;
    184197        virtual Expression * mutate( LabelAddressExpr * labAddressExpr ) override final;
    185198        virtual Expression * mutate( CastExpr * castExpr ) override final;
     199        virtual Expression * mutate( KeywordCastExpr * castExpr ) override final;
    186200        virtual Expression * mutate( VirtualCastExpr * castExpr ) override final;
    187201        virtual Expression * mutate( UntypedMemberExpr * memberExpr ) override final;
     
    210224        virtual Expression * mutate( StmtExpr *  stmtExpr ) override final;
    211225        virtual Expression * mutate( UniqueExpr *  uniqueExpr ) override final;
     226        virtual Expression * mutate( UntypedInitExpr *  initExpr ) override final;
     227        virtual Expression * mutate( InitExpr *  initExpr ) override final;
     228        virtual Expression * mutate( DeletedExpr *  delExpr ) override final;
     229        virtual Expression * mutate( DefaultArgExpr * argExpr ) override final;
     230        virtual Expression * mutate( GenericExpr * genExpr ) override final;
    212231
    213232        virtual Type * mutate( VoidType * basicType ) override final;
     
    216235        virtual Type * mutate( ArrayType * arrayType ) override final;
    217236        virtual Type * mutate( ReferenceType * referenceType ) override final;
     237        virtual Type * mutate( QualifiedType * qualType ) override final;
    218238        virtual Type * mutate( FunctionType * functionType ) override final;
    219239        virtual Type * mutate( StructInstType * aggregateUseType ) override final;
     
    228248        virtual Type * mutate( ZeroType * zeroType ) override final;
    229249        virtual Type * mutate( OneType * oneType ) override final;
     250        virtual Type * mutate( GlobalScopeType * globalType ) override final;
    230251
    231252        virtual Designation * mutate( Designation * designation ) override final;
     
    243264
    244265private:
     266        bool inFunction = false;
     267
    245268        template<typename pass_t> friend void acceptAll( std::list< Declaration* > &decls, PassVisitor< pass_t >& visitor );
    246269        template<typename pass_t> friend void mutateAll( std::list< Declaration* > &decls, PassVisitor< pass_t >& visitor );
     
    286309        bool_ref * get_visit_children_ptr() { return visit_children_impl(pass, 0); }
    287310
    288         void indexerScopeEnter  ()                             { indexer_impl_enterScope  ( pass, 0       ); }
    289         void indexerScopeLeave  ()                             { indexer_impl_leaveScope  ( pass, 0       ); }
    290         void indexerAddId       ( DeclarationWithType * node ) { indexer_impl_addId       ( pass, 0, node ); }
    291         void indexerAddType     ( NamedTypeDecl       * node ) { indexer_impl_addType     ( pass, 0, node ); }
    292         void indexerAddStruct   ( const std::string   & id   ) { indexer_impl_addStruct   ( pass, 0, id   ); }
    293         void indexerAddStruct   ( StructDecl          * node ) { indexer_impl_addStruct   ( pass, 0, node ); }
    294         void indexerAddStructFwd( StructDecl          * node ) { indexer_impl_addStructFwd( pass, 0, node ); }
    295         void indexerAddEnum     ( EnumDecl            * node ) { indexer_impl_addEnum     ( pass, 0, node ); }
    296         void indexerAddUnion    ( const std::string   & id   ) { indexer_impl_addUnion    ( pass, 0, id   ); }
    297         void indexerAddUnion    ( UnionDecl           * node ) { indexer_impl_addUnion    ( pass, 0, node ); }
    298         void indexerAddUnionFwd ( UnionDecl           * node ) { indexer_impl_addUnionFwd ( pass, 0, node ); }
    299         void indexerAddTrait    ( TraitDecl           * node ) { indexer_impl_addTrait    ( pass, 0, node ); }
    300         void indexerAddWith     ( WithStmt            * node ) { indexer_impl_addWith    ( pass, 0, node ); }
     311        void indexerScopeEnter  ()                                    { indexer_impl_enterScope  ( pass, 0       ); }
     312        void indexerScopeLeave  ()                                    { indexer_impl_leaveScope  ( pass, 0       ); }
     313        void indexerAddId       ( DeclarationWithType       * node ) { indexer_impl_addId       ( pass, 0, node ); }
     314        void indexerAddType     ( NamedTypeDecl             * node ) { indexer_impl_addType     ( pass, 0, node ); }
     315        void indexerAddStruct   ( const std::string         & id    ) { indexer_impl_addStruct   ( pass, 0, id   ); }
     316        void indexerAddStruct   ( StructDecl                * node ) { indexer_impl_addStruct   ( pass, 0, node ); }
     317        void indexerAddStructFwd( StructDecl                * node ) { indexer_impl_addStructFwd( pass, 0, node ); }
     318        void indexerAddEnum     ( EnumDecl                  * node ) { indexer_impl_addEnum     ( pass, 0, node ); }
     319        void indexerAddUnion    ( const std::string         & id    ) { indexer_impl_addUnion    ( pass, 0, id   ); }
     320        void indexerAddUnion    ( UnionDecl                 * node ) { indexer_impl_addUnion    ( pass, 0, node ); }
     321        void indexerAddUnionFwd ( UnionDecl                 * node ) { indexer_impl_addUnionFwd ( pass, 0, node ); }
     322        void indexerAddTrait    ( TraitDecl                 * node ) { indexer_impl_addTrait    ( pass, 0, node ); }
     323        void indexerAddWith     ( std::list< Expression * > & exprs, BaseSyntaxNode * withStmt ) { indexer_impl_addWith( pass, 0, exprs, withStmt ); }
    301324
    302325
     
    403426};
    404427
     428#include "SynTree/TypeSubstitution.h"
    405429#include "PassVisitor.impl.h"
  • src/Common/PassVisitor.impl.h

    rf9feab8 r90152a4  
    6262
    6363template< typename pass_type >
    64 static inline void acceptAll( std::list< Declaration* > &decls, PassVisitor< pass_type >& visitor ) {
     64inline void acceptAll( std::list< Declaration* > &decls, PassVisitor< pass_type >& visitor ) {
    6565        DeclList_t* beforeDecls = visitor.get_beforeDecls();
    6666        DeclList_t* afterDecls  = visitor.get_afterDecls();
    67         SemanticError errors;
     67        SemanticErrorException errors;
    6868
    6969        for ( std::list< Declaration* >::iterator i = decls.begin(); ; ++i ) {
     
    7676                        // run visitor on declaration
    7777                        maybeAccept_impl( *i, visitor );
    78                 } catch( SemanticError &e ) {
    79                         e.set_location( (*i)->location );
     78                } catch( SemanticErrorException &e ) {
    8079                        errors.append( e );
    8180                }
     
    9089
    9190template< typename pass_type >
    92 static inline void mutateAll( std::list< Declaration* > &decls, PassVisitor< pass_type >& mutator ) {
     91inline void mutateAll( std::list< Declaration* > &decls, PassVisitor< pass_type >& mutator ) {
    9392        DeclList_t* beforeDecls = mutator.get_beforeDecls();
    9493        DeclList_t* afterDecls  = mutator.get_afterDecls();
    95         SemanticError errors;
     94        SemanticErrorException errors;
    9695
    9796        for ( std::list< Declaration* >::iterator i = decls.begin(); ; ++i ) {
     
    103102                        // run mutator on declaration
    104103                        maybeMutate_impl( *i, mutator );
    105                 } catch( SemanticError &e ) {
    106                         e.set_location( (*i)->location );
     104                } catch( SemanticErrorException &e ) {
    107105                        errors.append( e );
    108106                }
     
    127125inline void maybeAccept_impl( Container & container, PassVisitor< pass_type > & visitor ) {
    128126        if ( ! visitor.get_visit_children() ) return;
    129         SemanticError errors;
     127        SemanticErrorException errors;
    130128        for ( typename Container::iterator i = container.begin(); i != container.end(); ++i ) {
    131129                try {
     
    133131                                (*i)->accept( visitor );
    134132                        }
    135                 } catch( SemanticError &e ) {
    136                         e.set_location( (*i)->location );
     133                } catch( SemanticErrorException &e ) {
    137134                        errors.append( e );
    138135                }
     
    155152inline void maybeMutate_impl( Container & container, PassVisitor< pass_type > & mutator ) {
    156153        if ( ! mutator.get_visit_children() ) return;
    157         SemanticError errors;
     154        SemanticErrorException errors;
    158155        for ( typename Container::iterator i = container.begin(); i != container.end(); ++i ) {
    159156                try {
     
    162159                                assert( *i );
    163160                        } // if
    164                 } catch( SemanticError &e ) {
    165                         e.set_location( (*i)->location );
     161                } catch( SemanticErrorException &e ) {
    166162                        errors.append( e );
    167163                } // try
     
    176172void PassVisitor< pass_type >::handleStatementList( std::list< Statement * > & statements, func_t func ) {
    177173        if ( ! get_visit_children() ) return;
    178         SemanticError errors;
     174        SemanticErrorException errors;
    179175
    180176        // don't want statements from outer CompoundStmts to be added to this CompoundStmt
     
    199195                            || ( empty( beforeDecls ) && empty( afterDecls )) );
    200196
    201                 } catch ( SemanticError &e ) {
    202                         e.set_location( (*i)->location );
     197                } catch ( SemanticErrorException &e ) {
    203198                        errors.append( e );
    204199                }
     
    365360        maybeAccept_impl   ( node->attributes   , *this );
    366361
    367         if ( node->name != "" ) {
    368                 indexerAddId( node );
    369         }
     362        indexerAddId( node );
    370363
    371364        VISIT_END( node );
     
    381374        maybeMutate_impl   ( node->attributes   , *this );
    382375
    383         if ( node->name != "" ) {
    384                 indexerAddId( node );
    385         }
     376        indexerAddId( node );
    386377
    387378        MUTATE_END( DeclarationWithType, node );
     
    394385        VISIT_START( node );
    395386
    396         if ( node->name != "" ) {
    397                 indexerAddId( node );
    398         }
    399 
     387        indexerAddId( node );
     388
     389        maybeAccept_impl( node->withExprs, *this );
    400390        {
     391                // with clause introduces a level of scope (for the with expression members).
     392                // with clause exprs are added to the indexer before parameters so that parameters
     393                // shadow with exprs and not the other way around.
    401394                auto guard = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } );
    402                 // implicit add __func__ identifier as specified in the C manual 6.4.2.2
    403                 static ObjectDecl func(
    404                         "__func__", noStorageClasses, LinkageSpec::C, nullptr,
    405                         new ArrayType( Type::Qualifiers(), new BasicType( Type::Qualifiers( Type::Const ), BasicType::Char ), nullptr, true, false ),
    406                         nullptr
    407                 );
    408                 indexerAddId( &func );
    409                 maybeAccept_impl( node->type, *this );
    410                 maybeAccept_impl( node->statements, *this );
    411                 maybeAccept_impl( node->attributes, *this );
     395                indexerAddWith( node->withExprs, node );
     396                {
     397                        auto guard = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } );
     398                        // implicit add __func__ identifier as specified in the C manual 6.4.2.2
     399                        static ObjectDecl func(
     400                                "__func__", noStorageClasses, LinkageSpec::C, nullptr,
     401                                new ArrayType( Type::Qualifiers(), new BasicType( Type::Qualifiers( Type::Const ), BasicType::Char ), nullptr, true, false ),
     402                                nullptr
     403                        );
     404                        indexerAddId( &func );
     405                        maybeAccept_impl( node->type, *this );
     406                        // function body needs to have the same scope as parameters - CompoundStmt will not enter
     407                        // a new scope if inFunction is true
     408                        ValueGuard< bool > oldInFunction( inFunction );
     409                        inFunction = true;
     410                        maybeAccept_impl( node->statements, *this );
     411                        maybeAccept_impl( node->attributes, *this );
     412                }
    412413        }
    413414
     
    419420        MUTATE_START( node );
    420421
    421         if ( node->name != "" ) {
    422                 indexerAddId( node );
    423         }
     422        indexerAddId( node );
    424423
    425424        {
     425                // with clause introduces a level of scope (for the with expression members).
     426                // with clause exprs are added to the indexer before parameters so that parameters
     427                // shadow with exprs and not the other way around.
    426428                auto guard = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } );
    427                 // implicit add __func__ identifier as specified in the C manual 6.4.2.2
    428                 static ObjectDecl func(
    429                         "__func__", noStorageClasses, LinkageSpec::C, nullptr,
    430                         new ArrayType( Type::Qualifiers(), new BasicType( Type::Qualifiers( Type::Const ), BasicType::Char ), nullptr, true, false ),
    431                         nullptr
    432                 );
    433                 indexerAddId( &func );
    434                 maybeMutate_impl( node->type, *this );
    435                 maybeMutate_impl( node->statements, *this );
    436                 maybeMutate_impl( node->attributes, *this );
     429                indexerAddWith( node->withExprs, node );
     430                {
     431                        auto guard = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } );
     432                        // implicit add __func__ identifier as specified in the C manual 6.4.2.2
     433                        static ObjectDecl func(
     434                                "__func__", noStorageClasses, LinkageSpec::C, nullptr,
     435                                new ArrayType( Type::Qualifiers(), new BasicType( Type::Qualifiers( Type::Const ), BasicType::Char ), nullptr, true, false ),
     436                                nullptr
     437                        );
     438                        indexerAddId( &func );
     439                        maybeMutate_impl( node->type, *this );
     440                        // function body needs to have the same scope as parameters - CompoundStmt will not enter
     441                        // a new scope if inFunction is true
     442                        ValueGuard< bool > oldInFunction( inFunction );
     443                        inFunction = true;
     444                        maybeMutate_impl( node->statements, *this );
     445                        maybeMutate_impl( node->attributes, *this );
     446                }
    437447        }
    438448
     
    683693
    684694//--------------------------------------------------------------------------
     695// StaticAssertDecl
     696template< typename pass_type >
     697void PassVisitor< pass_type >::visit( StaticAssertDecl * node ) {
     698        VISIT_START( node );
     699
     700        node->condition = visitExpression( node->condition );
     701        maybeAccept_impl( node->message, *this );
     702
     703        VISIT_END( node );
     704}
     705
     706template< typename pass_type >
     707StaticAssertDecl * PassVisitor< pass_type >::mutate( StaticAssertDecl * node ) {
     708        MUTATE_START( node );
     709
     710        node->condition = mutateExpression( node->condition );
     711        maybeMutate_impl( node->message, *this );
     712
     713        MUTATE_END( StaticAssertDecl, node );
     714}
     715
     716//--------------------------------------------------------------------------
    685717// CompoundStmt
    686718template< typename pass_type >
     
    688720        VISIT_START( node );
    689721        {
    690                 auto guard1 = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } );
     722                // do not enter a new scope if inFunction is true - needs to check old state before the assignment
     723                ValueGuard< bool > oldInFunction( inFunction );
     724                auto guard1 = makeFuncGuard( [this, &oldInFunction]() { if ( ! oldInFunction.old ) indexerScopeEnter(); }, [this, &oldInFunction]() { if ( ! oldInFunction.old ) indexerScopeLeave(); } );
    691725                auto guard2 = makeFuncGuard( [this]() { call_beginScope();   }, [this]() { call_endScope();     } );
     726                inFunction = false;
    692727                visitStatementList( node->kids );
    693728        }
     
    699734        MUTATE_START( node );
    700735        {
    701                 auto guard1 = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } );
     736                // do not enter a new scope if inFunction is true - needs to check old state before the assignment
     737                ValueGuard< bool > oldInFunction( inFunction );
     738                auto guard1 = makeFuncGuard( [this, &oldInFunction]() { if ( ! oldInFunction.old ) indexerScopeEnter(); }, [this, &oldInFunction]() { if ( ! oldInFunction.old ) indexerScopeLeave(); } );
    702739                auto guard2 = makeFuncGuard( [this]() { call_beginScope();   }, [this]() { call_endScope();     } );
     740                inFunction = false;
    703741                mutateStatementList( node->kids );
    704742        }
     
    730768template< typename pass_type >
    731769void PassVisitor< pass_type >::visit( AsmStmt * node ) {
    732         VISIT_BODY( node );
     770        VISIT_START( node )
     771
     772        maybeAccept_impl( node->instruction, *this );
     773        maybeAccept_impl( node->output, *this );
     774        maybeAccept_impl( node->input, *this );
     775        maybeAccept_impl( node->clobber, *this );
     776
     777        VISIT_END( node );
    733778}
    734779
    735780template< typename pass_type >
    736781Statement * PassVisitor< pass_type >::mutate( AsmStmt * node ) {
    737         MUTATE_BODY( Statement, node );
     782        MUTATE_START( node );
     783
     784        maybeMutate_impl( node->instruction, *this );
     785        maybeMutate_impl( node->output, *this );
     786        maybeMutate_impl( node->input, *this );
     787        maybeMutate_impl( node->clobber, *this );
     788
     789        MUTATE_END( Statement, node );
     790}
     791
     792//--------------------------------------------------------------------------
     793// AsmStmt
     794template< typename pass_type >
     795void PassVisitor< pass_type >::visit( DirectiveStmt * node ) {
     796        VISIT_START( node )
     797
     798        VISIT_END( node );
     799}
     800
     801template< typename pass_type >
     802Statement * PassVisitor< pass_type >::mutate( DirectiveStmt * node ) {
     803        MUTATE_START( node );
     804
     805        MUTATE_END( Statement, node );
    738806}
    739807
     
    774842        VISIT_START( node );
    775843
    776         visitExpression( node->condition );
    777         node->body = visitStatement( node->body );
     844        {
     845                // while statements introduce a level of scope (for the initialization)
     846                auto guard = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } );
     847                maybeAccept_impl( node->initialization, *this );
     848                visitExpression ( node->condition );
     849                node->body = visitStatement( node->body );
     850        }
    778851
    779852        VISIT_END( node );
     
    784857        MUTATE_START( node );
    785858
    786         node->condition = mutateExpression( node->condition );
    787         node->body      = mutateStatement ( node->body      );
     859        {
     860                // while statements introduce a level of scope (for the initialization)
     861                auto guard = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } );
     862                maybeMutate_impl( node->initialization, *this );
     863                node->condition = mutateExpression( node->condition );
     864                node->body      = mutateStatement ( node->body      );
     865        }
     866
    788867
    789868        MUTATE_END( Statement, node );
     
    868947template< typename pass_type >
    869948void PassVisitor< pass_type >::visit( BranchStmt * node ) {
    870         VISIT_BODY( node );
     949        VISIT_START( node );
     950        VISIT_END( node );
    871951}
    872952
    873953template< typename pass_type >
    874954Statement * PassVisitor< pass_type >::mutate( BranchStmt * node ) {
    875         MUTATE_BODY( Statement, node );
     955        MUTATE_START( node );
     956        MUTATE_END( Statement, node );
    876957}
    877958
     
    901982template< typename pass_type >
    902983void PassVisitor< pass_type >::visit( ThrowStmt * node ) {
    903         VISIT_BODY( node );
     984        VISIT_START( node );
     985
     986        maybeAccept_impl( node->expr, *this );
     987        maybeAccept_impl( node->target, *this );
     988
     989        VISIT_END( node );
    904990}
    905991
    906992template< typename pass_type >
    907993Statement * PassVisitor< pass_type >::mutate( ThrowStmt * node ) {
    908         MUTATE_BODY( Statement, node );
     994        MUTATE_START( node );
     995
     996        maybeMutate_impl( node->expr, *this );
     997        maybeMutate_impl( node->target, *this );
     998
     999        MUTATE_END( Statement, node );
    9091000}
    9101001
     
    9651056template< typename pass_type >
    9661057void PassVisitor< pass_type >::visit( FinallyStmt * node ) {
    967         VISIT_BODY( node );
     1058        VISIT_START( node );
     1059
     1060        maybeAccept_impl( node->block, *this );
     1061
     1062        VISIT_END( node );
    9681063}
    9691064
    9701065template< typename pass_type >
    9711066Statement * PassVisitor< pass_type >::mutate( FinallyStmt * node ) {
    972         MUTATE_BODY( Statement, node );
     1067        MUTATE_START( node );
     1068
     1069        maybeMutate_impl( node->block, *this );
     1070
     1071        MUTATE_END( Statement, node );
    9731072}
    9741073
     
    9771076template< typename pass_type >
    9781077void PassVisitor< pass_type >::visit( WaitForStmt * node ) {
    979         VISIT_BODY( node );
     1078        VISIT_START( node );
     1079
     1080        for( auto & clause : node->clauses ) {
     1081                maybeAccept_impl( clause.target.function, *this );
     1082                maybeAccept_impl( clause.target.arguments, *this );
     1083
     1084                maybeAccept_impl( clause.statement, *this );
     1085                maybeAccept_impl( clause.condition, *this );
     1086        }
     1087
     1088        maybeAccept_impl( node->timeout.time, *this );
     1089        maybeAccept_impl( node->timeout.statement, *this );
     1090        maybeAccept_impl( node->timeout.condition, *this );
     1091        maybeAccept_impl( node->orelse.statement, *this );
     1092        maybeAccept_impl( node->orelse.condition, *this );
     1093
     1094        VISIT_END( node );
    9801095}
    9811096
    9821097template< typename pass_type >
    9831098Statement * PassVisitor< pass_type >::mutate( WaitForStmt * node ) {
    984         MUTATE_BODY( Statement, node );
     1099        MUTATE_START( node );
     1100
     1101        for( auto & clause : node->clauses ) {
     1102                maybeMutate_impl( clause.target.function, *this );
     1103                maybeMutate_impl( clause.target.arguments, *this );
     1104
     1105                maybeMutate_impl( clause.statement, *this );
     1106                maybeMutate_impl( clause.condition, *this );
     1107        }
     1108
     1109        maybeMutate_impl( node->timeout.time, *this );
     1110        maybeMutate_impl( node->timeout.statement, *this );
     1111        maybeMutate_impl( node->timeout.condition, *this );
     1112        maybeMutate_impl( node->orelse.statement, *this );
     1113        maybeMutate_impl( node->orelse.condition, *this );
     1114
     1115        MUTATE_END( Statement, node );
    9851116}
    9861117
     
    9961127                // catch statements introduce a level of scope (for the caught exception)
    9971128                auto guard = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } );
    998                 indexerAddWith( node );
     1129                indexerAddWith( node->exprs, node );
    9991130                maybeAccept_impl( node->stmt, *this );
    10001131        }
     
    10091140                // catch statements introduce a level of scope (for the caught exception)
    10101141                auto guard = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } );
    1011                 indexerAddWith( node );
     1142                indexerAddWith( node->exprs, node );
    10121143                maybeMutate_impl( node->stmt, *this );
    10131144        }
     
    10191150template< typename pass_type >
    10201151void PassVisitor< pass_type >::visit( NullStmt * node ) {
    1021         VISIT_BODY( node );
     1152        VISIT_START( node );
     1153        VISIT_END( node );
    10221154}
    10231155
    10241156template< typename pass_type >
    10251157NullStmt * PassVisitor< pass_type >::mutate( NullStmt * node ) {
    1026         MUTATE_BODY( NullStmt, node );
     1158        MUTATE_START( node );
     1159        MUTATE_END( NullStmt, node );
    10271160}
    10281161
     
    10311164template< typename pass_type >
    10321165void PassVisitor< pass_type >::visit( DeclStmt * node ) {
    1033         VISIT_BODY( node );
     1166        VISIT_START( node );
     1167
     1168        maybeAccept_impl( node->decl, *this );
     1169
     1170        VISIT_END( node );
    10341171}
    10351172
    10361173template< typename pass_type >
    10371174Statement * PassVisitor< pass_type >::mutate( DeclStmt * node ) {
    1038         MUTATE_BODY( Statement, node );
     1175        MUTATE_START( node );
     1176
     1177        maybeMutate_impl( node->decl, *this );
     1178
     1179        MUTATE_END( Statement, node );
    10391180}
    10401181
     
    10431184template< typename pass_type >
    10441185void PassVisitor< pass_type >::visit( ImplicitCtorDtorStmt * node ) {
    1045         VISIT_BODY( node );
     1186        VISIT_START( node );
     1187
     1188        maybeAccept_impl( node->callStmt, *this );
     1189
     1190        VISIT_END( node );
    10461191}
    10471192
    10481193template< typename pass_type >
    10491194Statement * PassVisitor< pass_type >::mutate( ImplicitCtorDtorStmt * node ) {
    1050         MUTATE_BODY( Statement, node );
     1195        MUTATE_START( node );
     1196
     1197        maybeMutate_impl( node->callStmt, *this );
     1198
     1199        MUTATE_END( Statement, node );
    10511200}
    10521201
     
    11411290template< typename pass_type >
    11421291Expression * PassVisitor< pass_type >::mutate( CastExpr * node ) {
     1292        MUTATE_START( node );
     1293
     1294        indexerScopedMutate( node->env   , *this );
     1295        indexerScopedMutate( node->result, *this );
     1296        maybeMutate_impl   ( node->arg   , *this );
     1297
     1298        MUTATE_END( Expression, node );
     1299}
     1300
     1301//--------------------------------------------------------------------------
     1302// KeywordCastExpr
     1303template< typename pass_type >
     1304void PassVisitor< pass_type >::visit( KeywordCastExpr * node ) {
     1305        VISIT_START( node );
     1306
     1307        indexerScopedAccept( node->result, *this );
     1308        maybeAccept_impl        ( node->arg   , *this );
     1309
     1310        VISIT_END( node );
     1311}
     1312
     1313template< typename pass_type >
     1314Expression * PassVisitor< pass_type >::mutate( KeywordCastExpr * node ) {
    11431315        MUTATE_START( node );
    11441316
     
    14041576        indexerScopedAccept( node->result, *this );
    14051577        maybeAccept_impl   ( node->type  , *this );
    1406         maybeAccept_impl   ( node->member, *this );
    14071578
    14081579        VISIT_END( node );
     
    14161587        indexerScopedMutate( node->result, *this );
    14171588        maybeMutate_impl   ( node->type  , *this );
    1418         maybeMutate_impl   ( node->member, *this );
    14191589
    14201590        MUTATE_END( Expression, node );
     
    18532023}
    18542024
     2025//--------------------------------------------------------------------------
     2026// UntypedInitExpr
     2027template< typename pass_type >
     2028void PassVisitor< pass_type >::visit( UntypedInitExpr * node ) {
     2029        VISIT_START( node );
     2030
     2031        indexerScopedAccept( node->result, *this );
     2032        maybeAccept_impl   ( node->expr  , *this );
     2033        // not currently visiting initAlts, but this doesn't matter since this node is only used in the resolver.
     2034
     2035        VISIT_END( node );
     2036}
     2037
     2038template< typename pass_type >
     2039Expression * PassVisitor< pass_type >::mutate( UntypedInitExpr * node ) {
     2040        MUTATE_START( node );
     2041
     2042        indexerScopedMutate( node->env   , *this );
     2043        indexerScopedMutate( node->result, *this );
     2044        maybeMutate_impl   ( node->expr  , *this );
     2045        // not currently visiting initAlts, but this doesn't matter since this node is only used in the resolver.
     2046
     2047        MUTATE_END( Expression, node );
     2048}
     2049
     2050//--------------------------------------------------------------------------
     2051// InitExpr
     2052template< typename pass_type >
     2053void PassVisitor< pass_type >::visit( InitExpr * node ) {
     2054        VISIT_START( node );
     2055
     2056        indexerScopedAccept( node->result, *this );
     2057        maybeAccept_impl   ( node->expr  , *this );
     2058        maybeAccept_impl   ( node->designation, *this );
     2059
     2060        VISIT_END( node );
     2061}
     2062
     2063template< typename pass_type >
     2064Expression * PassVisitor< pass_type >::mutate( InitExpr * node ) {
     2065        MUTATE_START( node );
     2066
     2067        indexerScopedMutate( node->env   , *this );
     2068        indexerScopedMutate( node->result, *this );
     2069        maybeMutate_impl   ( node->expr  , *this );
     2070        maybeMutate_impl   ( node->designation, *this );
     2071
     2072        MUTATE_END( Expression, node );
     2073}
     2074
     2075//--------------------------------------------------------------------------
     2076// DeletedExpr
     2077template< typename pass_type >
     2078void PassVisitor< pass_type >::visit( DeletedExpr * node ) {
     2079        VISIT_START( node );
     2080
     2081        indexerScopedAccept( node->result, *this );
     2082        maybeAccept_impl( node->expr, *this );
     2083        // don't visit deleteStmt, because it is a pointer to somewhere else in the tree.
     2084
     2085        VISIT_END( node );
     2086}
     2087
     2088template< typename pass_type >
     2089Expression * PassVisitor< pass_type >::mutate( DeletedExpr * node ) {
     2090        MUTATE_START( node );
     2091
     2092        indexerScopedMutate( node->env, *this );
     2093        indexerScopedMutate( node->result, *this );
     2094        maybeMutate_impl( node->expr, *this );
     2095
     2096        MUTATE_END( Expression, node );
     2097}
     2098
     2099//--------------------------------------------------------------------------
     2100// DefaultArgExpr
     2101template< typename pass_type >
     2102void PassVisitor< pass_type >::visit( DefaultArgExpr * node ) {
     2103        VISIT_START( node );
     2104
     2105        indexerScopedAccept( node->result, *this );
     2106        maybeAccept_impl( node->expr, *this );
     2107
     2108        VISIT_END( node );
     2109}
     2110
     2111template< typename pass_type >
     2112Expression * PassVisitor< pass_type >::mutate( DefaultArgExpr * node ) {
     2113        MUTATE_START( node );
     2114
     2115        indexerScopedMutate( node->env, *this );
     2116        indexerScopedMutate( node->result, *this );
     2117        maybeMutate_impl( node->expr, *this );
     2118
     2119        MUTATE_END( Expression, node );
     2120}
     2121
     2122//--------------------------------------------------------------------------
     2123// GenericExpr
     2124template< typename pass_type >
     2125void PassVisitor< pass_type >::visit( GenericExpr * node ) {
     2126        VISIT_START( node );
     2127
     2128        indexerScopedAccept( node->result, *this );
     2129        maybeAccept_impl( node->control, *this );
     2130        for ( GenericExpr::Association & assoc : node->associations ) {
     2131                indexerScopedAccept( assoc.type, *this );
     2132                maybeAccept_impl( assoc.expr, *this );
     2133        }
     2134
     2135        VISIT_END( node );
     2136}
     2137
     2138template< typename pass_type >
     2139Expression * PassVisitor< pass_type >::mutate( GenericExpr * node ) {
     2140        MUTATE_START( node );
     2141
     2142        indexerScopedMutate( node->env, *this );
     2143        indexerScopedMutate( node->result, *this );
     2144        maybeMutate_impl( node->control, *this );
     2145        for ( GenericExpr::Association & assoc : node->associations ) {
     2146                indexerScopedMutate( assoc.type, *this );
     2147                maybeMutate_impl( assoc.expr, *this );
     2148        }
     2149
     2150        MUTATE_END( Expression, node );
     2151}
     2152
     2153//--------------------------------------------------------------------------
     2154// VoidType
    18552155template< typename pass_type >
    18562156void PassVisitor< pass_type >::visit( VoidType * node ) {
    1857         VISIT_BODY( node );
    1858 }
    1859 
     2157        VISIT_START( node );
     2158
     2159        maybeAccept_impl( node->forall, *this );
     2160
     2161        VISIT_END( node );
     2162}
     2163
     2164template< typename pass_type >
     2165Type * PassVisitor< pass_type >::mutate( VoidType * node ) {
     2166        MUTATE_START( node );
     2167
     2168        maybeMutate_impl( node->forall, *this );
     2169
     2170        MUTATE_END( Type, node );
     2171}
     2172
     2173//--------------------------------------------------------------------------
     2174// BasicType
    18602175template< typename pass_type >
    18612176void PassVisitor< pass_type >::visit( BasicType * node ) {
    1862         VISIT_BODY( node );
    1863 }
    1864 
     2177        VISIT_START( node );
     2178
     2179        maybeAccept_impl( node->forall, *this );
     2180
     2181        VISIT_END( node );
     2182}
     2183
     2184template< typename pass_type >
     2185Type * PassVisitor< pass_type >::mutate( BasicType * node ) {
     2186        MUTATE_START( node );
     2187
     2188        maybeMutate_impl( node->forall, *this );
     2189
     2190        MUTATE_END( Type, node );
     2191}
     2192
     2193//--------------------------------------------------------------------------
     2194// PointerType
    18652195template< typename pass_type >
    18662196void PassVisitor< pass_type >::visit( PointerType * node ) {
    1867         VISIT_BODY( node );
    1868 }
    1869 
     2197        VISIT_START( node );
     2198
     2199        maybeAccept_impl( node->forall, *this );
     2200        // xxx - should PointerType visit/mutate dimension?
     2201        maybeAccept_impl( node->base, *this );
     2202
     2203        VISIT_END( node );
     2204}
     2205
     2206template< typename pass_type >
     2207Type * PassVisitor< pass_type >::mutate( PointerType * node ) {
     2208        MUTATE_START( node );
     2209
     2210        maybeMutate_impl( node->forall, *this );
     2211        // xxx - should PointerType visit/mutate dimension?
     2212        maybeMutate_impl( node->base, *this );
     2213
     2214        MUTATE_END( Type, node );
     2215}
     2216
     2217//--------------------------------------------------------------------------
     2218// ArrayType
    18702219template< typename pass_type >
    18712220void PassVisitor< pass_type >::visit( ArrayType * node ) {
    1872         VISIT_BODY( node );
    1873 }
    1874 
     2221        VISIT_START( node );
     2222
     2223        maybeAccept_impl( node->forall, *this );
     2224        maybeAccept_impl( node->dimension, *this );
     2225        maybeAccept_impl( node->base, *this );
     2226
     2227        VISIT_END( node );
     2228}
     2229
     2230template< typename pass_type >
     2231Type * PassVisitor< pass_type >::mutate( ArrayType * node ) {
     2232        MUTATE_START( node );
     2233
     2234        maybeMutate_impl( node->forall, *this );
     2235        maybeMutate_impl( node->dimension, *this );
     2236        maybeMutate_impl( node->base, *this );
     2237
     2238        MUTATE_END( Type, node );
     2239}
     2240
     2241//--------------------------------------------------------------------------
     2242// ReferenceType
    18752243template< typename pass_type >
    18762244void PassVisitor< pass_type >::visit( ReferenceType * node ) {
    1877         VISIT_BODY( node );
    1878 }
    1879 
     2245        VISIT_START( node );
     2246
     2247        maybeAccept_impl( node->forall, *this );
     2248        maybeAccept_impl( node->base, *this );
     2249
     2250        VISIT_END( node );
     2251}
     2252
     2253template< typename pass_type >
     2254Type * PassVisitor< pass_type >::mutate( ReferenceType * node ) {
     2255        MUTATE_START( node );
     2256
     2257        maybeMutate_impl( node->forall, *this );
     2258        maybeMutate_impl( node->base, *this );
     2259
     2260        MUTATE_END( Type, node );
     2261}
     2262
     2263//--------------------------------------------------------------------------
     2264// QualifiedType
     2265template< typename pass_type >
     2266void PassVisitor< pass_type >::visit( QualifiedType * node ) {
     2267        VISIT_START( node );
     2268
     2269        maybeAccept_impl( node->forall, *this );
     2270        maybeAccept_impl( node->parent, *this );
     2271        maybeAccept_impl( node->child, *this );
     2272
     2273        VISIT_END( node );
     2274}
     2275
     2276template< typename pass_type >
     2277Type * PassVisitor< pass_type >::mutate( QualifiedType * node ) {
     2278        MUTATE_START( node );
     2279
     2280        maybeMutate_impl( node->forall, *this );
     2281        maybeMutate_impl( node->parent, *this );
     2282        maybeMutate_impl( node->child, *this );
     2283
     2284        MUTATE_END( Type, node );
     2285}
     2286
     2287//--------------------------------------------------------------------------
     2288// FunctionType
    18802289template< typename pass_type >
    18812290void PassVisitor< pass_type >::visit( FunctionType * node ) {
    1882         VISIT_BODY( node );
     2291        VISIT_START( node );
     2292
     2293        maybeAccept_impl( node->forall, *this );
     2294        maybeAccept_impl( node->returnVals, *this );
     2295        maybeAccept_impl( node->parameters, *this );
     2296
     2297        VISIT_END( node );
     2298}
     2299
     2300template< typename pass_type >
     2301Type * PassVisitor< pass_type >::mutate( FunctionType * node ) {
     2302        MUTATE_START( node );
     2303
     2304        maybeMutate_impl( node->forall, *this );
     2305        maybeMutate_impl( node->returnVals, *this );
     2306        maybeMutate_impl( node->parameters, *this );
     2307
     2308        MUTATE_END( Type, node );
    18832309}
    18842310
     
    19512377template< typename pass_type >
    19522378void PassVisitor< pass_type >::visit( EnumInstType * node ) {
    1953         VISIT_BODY( node );
     2379        VISIT_START( node );
     2380
     2381        maybeAccept_impl( node->forall, *this );
     2382        maybeAccept_impl( node->parameters, *this );
     2383
     2384        VISIT_END( node );
    19542385}
    19552386
    19562387template< typename pass_type >
    19572388Type * PassVisitor< pass_type >::mutate( EnumInstType * node ) {
    1958         MUTATE_BODY( Type, node );
     2389        MUTATE_START( node );
     2390
     2391        maybeMutate_impl( node->forall, *this );
     2392        maybeMutate_impl( node->parameters, *this );
     2393
     2394        MUTATE_END( Type, node );
    19592395}
    19602396
     
    19852421template< typename pass_type >
    19862422void PassVisitor< pass_type >::visit( TypeInstType * node ) {
    1987         VISIT_BODY( node );
    1988 }
    1989 
     2423        VISIT_START( node );
     2424
     2425        maybeAccept_impl( node->forall    , *this );
     2426        maybeAccept_impl( node->parameters, *this );
     2427
     2428        VISIT_END( node );
     2429}
     2430
     2431template< typename pass_type >
     2432Type * PassVisitor< pass_type >::mutate( TypeInstType * node ) {
     2433        MUTATE_START( node );
     2434
     2435        maybeMutate_impl( node->forall    , *this );
     2436        maybeMutate_impl( node->parameters, *this );
     2437
     2438        MUTATE_END( Type, node );
     2439}
     2440
     2441//--------------------------------------------------------------------------
     2442// TupleType
    19902443template< typename pass_type >
    19912444void PassVisitor< pass_type >::visit( TupleType * node ) {
    1992         VISIT_BODY( node );
    1993 }
    1994 
     2445        VISIT_START( node );
     2446
     2447        maybeAccept_impl( node->forall, *this );
     2448        maybeAccept_impl( node->types, *this );
     2449        maybeAccept_impl( node->members, *this );
     2450
     2451        VISIT_END( node );
     2452}
     2453
     2454template< typename pass_type >
     2455Type * PassVisitor< pass_type >::mutate( TupleType * node ) {
     2456        MUTATE_START( node );
     2457
     2458        maybeMutate_impl( node->forall, *this );
     2459        maybeMutate_impl( node->types, *this );
     2460        maybeMutate_impl( node->members, *this );
     2461
     2462        MUTATE_END( Type, node );
     2463}
     2464
     2465//--------------------------------------------------------------------------
     2466// TypeofType
    19952467template< typename pass_type >
    19962468void PassVisitor< pass_type >::visit( TypeofType * node ) {
    1997         VISIT_BODY( node );
    1998 }
    1999 
     2469        VISIT_START( node );
     2470
     2471        assert( node->expr );
     2472        maybeAccept_impl( node->expr, *this );
     2473
     2474        VISIT_END( node );
     2475}
     2476
     2477template< typename pass_type >
     2478Type * PassVisitor< pass_type >::mutate( TypeofType * node ) {
     2479        MUTATE_START( node );
     2480
     2481        assert( node->expr );
     2482        maybeMutate_impl( node->expr, *this );
     2483
     2484        MUTATE_END( Type, node );
     2485}
     2486
     2487//--------------------------------------------------------------------------
     2488// AttrType
    20002489template< typename pass_type >
    20012490void PassVisitor< pass_type >::visit( AttrType * node ) {
    2002         VISIT_BODY( node );
    2003 }
    2004 
     2491        VISIT_START( node );
     2492
     2493        if ( node->isType ) {
     2494                assert( node->type );
     2495                maybeAccept_impl( node->type, *this );
     2496        } else {
     2497                assert( node->expr );
     2498                maybeAccept_impl( node->expr, *this );
     2499        } // if
     2500
     2501        VISIT_END( node );
     2502}
     2503
     2504template< typename pass_type >
     2505Type * PassVisitor< pass_type >::mutate( AttrType * node ) {
     2506        MUTATE_START( node );
     2507
     2508        if ( node->isType ) {
     2509                assert( node->type );
     2510                maybeMutate_impl( node->type, *this );
     2511        } else {
     2512                assert( node->expr );
     2513                maybeMutate_impl( node->expr, *this );
     2514        } // if
     2515
     2516        MUTATE_END( Type, node );
     2517}
     2518
     2519//--------------------------------------------------------------------------
     2520// VarArgsType
    20052521template< typename pass_type >
    20062522void PassVisitor< pass_type >::visit( VarArgsType * node ) {
    2007         VISIT_BODY( node );
    2008 }
    2009 
     2523        VISIT_START( node );
     2524
     2525        maybeAccept_impl( node->forall, *this );
     2526
     2527        VISIT_END( node );
     2528}
     2529
     2530template< typename pass_type >
     2531Type * PassVisitor< pass_type >::mutate( VarArgsType * node ) {
     2532        MUTATE_START( node );
     2533
     2534        maybeMutate_impl( node->forall, *this );
     2535
     2536        MUTATE_END( Type, node );
     2537}
     2538
     2539//--------------------------------------------------------------------------
     2540// ZeroType
    20102541template< typename pass_type >
    20112542void PassVisitor< pass_type >::visit( ZeroType * node ) {
    2012         VISIT_BODY( node );
    2013 }
    2014 
     2543        VISIT_START( node );
     2544
     2545        maybeAccept_impl( node->forall, *this );
     2546
     2547        VISIT_END( node );
     2548}
     2549
     2550template< typename pass_type >
     2551Type * PassVisitor< pass_type >::mutate( ZeroType * node ) {
     2552        MUTATE_START( node );
     2553
     2554        maybeMutate_impl( node->forall, *this );
     2555
     2556        MUTATE_END( Type, node );
     2557}
     2558
     2559//--------------------------------------------------------------------------
     2560// OneType
    20152561template< typename pass_type >
    20162562void PassVisitor< pass_type >::visit( OneType * node ) {
    2017         VISIT_BODY( node );
    2018 }
    2019 
     2563        VISIT_START( node );
     2564
     2565        maybeAccept_impl( node->forall, *this );
     2566
     2567        VISIT_END( node );
     2568}
     2569
     2570template< typename pass_type >
     2571Type * PassVisitor< pass_type >::mutate( OneType * node ) {
     2572        MUTATE_START( node );
     2573
     2574        maybeMutate_impl( node->forall, *this );
     2575
     2576        MUTATE_END( Type, node );
     2577}
     2578
     2579//--------------------------------------------------------------------------
     2580// GlobalScopeType
     2581template< typename pass_type >
     2582void PassVisitor< pass_type >::visit( GlobalScopeType * node ) {
     2583        VISIT_START( node );
     2584
     2585        maybeAccept_impl( node->forall, *this );
     2586
     2587        VISIT_END( node );
     2588}
     2589
     2590template< typename pass_type >
     2591Type * PassVisitor< pass_type >::mutate( GlobalScopeType * node ) {
     2592        MUTATE_START( node );
     2593
     2594        maybeMutate_impl( node->forall, *this );
     2595
     2596        MUTATE_END( Type, node );
     2597}
     2598
     2599//--------------------------------------------------------------------------
     2600// Designation
    20202601template< typename pass_type >
    20212602void PassVisitor< pass_type >::visit( Designation * node ) {
    20222603        VISIT_START( node );
    20232604
    2024         maybeAccept_impl( node->get_designators(), *this );
     2605        maybeAccept_impl( node->designators, *this );
    20252606
    20262607        VISIT_END( node );
     
    20312612        MUTATE_START( node );
    20322613
    2033         maybeMutate_impl( node->get_designators(), *this );
     2614        maybeMutate_impl( node->designators, *this );
    20342615
    20352616        MUTATE_END( Designation, node );
     
    20422623        VISIT_START( node );
    20432624
    2044         visitExpression( node->get_value() );
     2625        visitExpression( node->value );
    20452626
    20462627        VISIT_END( node );
     
    20512632        MUTATE_START( node );
    20522633
    2053         node->set_value( mutateExpression( node->get_value() ) );
     2634        node->value = mutateExpression( node->value );
    20542635
    20552636        MUTATE_END( Initializer, node );
    20562637}
    20572638
     2639//--------------------------------------------------------------------------
     2640// ListInit
    20582641template< typename pass_type >
    20592642void PassVisitor< pass_type >::visit( ListInit * node ) {
    2060         VISIT_BODY( node );
    2061 }
    2062 
     2643        VISIT_START( node );
     2644
     2645        maybeAccept_impl( node->designations, *this );
     2646        maybeAccept_impl( node->initializers, *this );
     2647
     2648        VISIT_END( node );
     2649}
     2650
     2651template< typename pass_type >
     2652Initializer * PassVisitor< pass_type >::mutate( ListInit * node ) {
     2653        MUTATE_START( node );
     2654
     2655        maybeMutate_impl( node->designations, *this );
     2656        maybeMutate_impl( node->initializers, *this );
     2657
     2658        MUTATE_END( Initializer, node );
     2659}
     2660
     2661//--------------------------------------------------------------------------
     2662// ConstructorInit
    20632663template< typename pass_type >
    20642664void PassVisitor< pass_type >::visit( ConstructorInit * node ) {
    2065         VISIT_BODY( node );
    2066 }
    2067 
     2665        VISIT_START( node );
     2666
     2667        maybeAccept_impl( node->ctor, *this );
     2668        maybeAccept_impl( node->dtor, *this );
     2669        maybeAccept_impl( node->init, *this );
     2670
     2671        VISIT_END( node );
     2672}
     2673
     2674template< typename pass_type >
     2675Initializer * PassVisitor< pass_type >::mutate( ConstructorInit * node ) {
     2676        MUTATE_START( node );
     2677
     2678        maybeMutate_impl( node->ctor, *this );
     2679        maybeMutate_impl( node->dtor, *this );
     2680        maybeMutate_impl( node->init, *this );
     2681
     2682        MUTATE_END( Initializer, node );
     2683}
     2684
     2685//--------------------------------------------------------------------------
     2686// Subrange
    20682687template< typename pass_type >
    20692688void PassVisitor< pass_type >::visit( Subrange * node ) {
    2070         VISIT_BODY( node );
    2071 }
    2072 
     2689        VISIT_START( node );
     2690
     2691        VISIT_END( node );
     2692}
     2693
     2694template< typename pass_type >
     2695Subrange * PassVisitor< pass_type >::mutate( Subrange * node  )  {
     2696        MUTATE_START( node );
     2697
     2698        MUTATE_END( Subrange, node );
     2699}
     2700
     2701//--------------------------------------------------------------------------
     2702// Attribute
    20732703template< typename pass_type >
    20742704void PassVisitor< pass_type >::visit( Constant * node ) {
    2075         VISIT_BODY( node );
    2076 }
    2077 
     2705        VISIT_START( node );
     2706
     2707        VISIT_END( node );
     2708}
     2709
     2710template< typename pass_type >
     2711Constant * PassVisitor< pass_type >::mutate( Constant * node  )  {
     2712        MUTATE_START( node );
     2713
     2714        MUTATE_END( Constant, node );
     2715}
     2716
     2717//--------------------------------------------------------------------------
     2718// Attribute
    20782719template< typename pass_type >
    20792720void PassVisitor< pass_type >::visit( Attribute * node ) {
    2080         VISIT_BODY( node );
    2081 }
    2082 
    2083 //---------------------------------------------------------------------------------------------------------------
    2084 template< typename pass_type >
    2085 Type * PassVisitor< pass_type >::mutate( VoidType * node ) {
    2086         MUTATE_BODY( Type, node );
    2087 }
    2088 
    2089 template< typename pass_type >
    2090 Type * PassVisitor< pass_type >::mutate( BasicType * node ) {
    2091         MUTATE_BODY( Type, node );
    2092 }
    2093 
    2094 template< typename pass_type >
    2095 Type * PassVisitor< pass_type >::mutate( PointerType * node ) {
    2096         MUTATE_BODY( Type, node );
    2097 }
    2098 
    2099 template< typename pass_type >
    2100 Type * PassVisitor< pass_type >::mutate( ArrayType * node ) {
    2101         MUTATE_BODY( Type, node );
    2102 }
    2103 
    2104 template< typename pass_type >
    2105 Type * PassVisitor< pass_type >::mutate( ReferenceType * node ) {
    2106         MUTATE_BODY( Type, node );
    2107 }
    2108 
    2109 template< typename pass_type >
    2110 Type * PassVisitor< pass_type >::mutate( FunctionType * node ) {
    2111         MUTATE_BODY( Type, node );
    2112 }
    2113 
    2114 template< typename pass_type >
    2115 Type * PassVisitor< pass_type >::mutate( TypeInstType * node ) {
    2116         MUTATE_BODY( Type, node );
    2117 }
    2118 
    2119 template< typename pass_type >
    2120 Type * PassVisitor< pass_type >::mutate( TupleType * node ) {
    2121         MUTATE_BODY( Type, node );
    2122 }
    2123 
    2124 template< typename pass_type >
    2125 Type * PassVisitor< pass_type >::mutate( TypeofType * node ) {
    2126         MUTATE_BODY( Type, node );
    2127 }
    2128 
    2129 template< typename pass_type >
    2130 Type * PassVisitor< pass_type >::mutate( AttrType * node ) {
    2131         MUTATE_BODY( Type, node );
    2132 }
    2133 
    2134 template< typename pass_type >
    2135 Type * PassVisitor< pass_type >::mutate( VarArgsType * node ) {
    2136         MUTATE_BODY( Type, node );
    2137 }
    2138 
    2139 template< typename pass_type >
    2140 Type * PassVisitor< pass_type >::mutate( ZeroType * node ) {
    2141         MUTATE_BODY( Type, node );
    2142 }
    2143 
    2144 template< typename pass_type >
    2145 Type * PassVisitor< pass_type >::mutate( OneType * node ) {
    2146         MUTATE_BODY( Type, node );
    2147 }
    2148 
    2149 template< typename pass_type >
    2150 Initializer * PassVisitor< pass_type >::mutate( ListInit * node ) {
    2151         MUTATE_BODY( Initializer, node );
    2152 }
    2153 
    2154 template< typename pass_type >
    2155 Initializer * PassVisitor< pass_type >::mutate( ConstructorInit * node ) {
    2156         MUTATE_BODY( Initializer, node );
    2157 }
    2158 
    2159 template< typename pass_type >
    2160 Subrange * PassVisitor< pass_type >::mutate( Subrange * node  )  {
    2161         MUTATE_BODY( Subrange, node );
    2162 }
    2163 
    2164 template< typename pass_type >
    2165 Constant * PassVisitor< pass_type >::mutate( Constant * node  )  {
    2166         MUTATE_BODY( Constant, node );
     2721        VISIT_START( node );
     2722
     2723        maybeAccept_impl( node->parameters, *this );
     2724
     2725        VISIT_END( node );
    21672726}
    21682727
    21692728template< typename pass_type >
    21702729Attribute * PassVisitor< pass_type >::mutate( Attribute * node  )  {
    2171         MUTATE_BODY( Attribute, node );
    2172 }
    2173 
     2730        MUTATE_START( node );
     2731
     2732        maybeMutate_impl( node->parameters, *this );
     2733
     2734        MUTATE_END( Attribute, node );
     2735}
     2736
     2737//--------------------------------------------------------------------------
     2738// TypeSubstitution
    21742739template< typename pass_type >
    21752740TypeSubstitution * PassVisitor< pass_type >::mutate( TypeSubstitution * node ) {
  • src/Common/PassVisitor.proto.h

    rf9feab8 r90152a4  
    4747
    4848        operator bool() { return m_ref ? *m_ref : true; }
    49         bool operator=( bool val ) { return *m_ref = val; }
     49        bool operator=( bool val ) { assert(m_ref); return *m_ref = val; }
    5050
    5151private:
     
    5353        friend class ChildrenGuard;
    5454
    55         bool * set( bool & val ) {
     55        bool * set( bool * val ) {
    5656                bool * prev = m_ref;
    57                 m_ref = &val;
     57                m_ref = val;
    5858                return prev;
    5959        }
     
    6767        ChildrenGuard( bool_ref * ref )
    6868                : m_val ( true )
    69                 , m_prev( ref ? ref->set( m_val ) : nullptr )
     69                , m_prev( ref ? ref->set( &m_val ) : nullptr )
    7070                , m_ref ( ref )
    7171        {}
     
    7373        ~ChildrenGuard() {
    7474                if( m_ref ) {
    75                         m_ref->set( *m_prev );
     75                        m_ref->set( m_prev );
    7676                }
    7777        }
     
    193193
    194194
    195 #define INDEXER_FUNC( func, type )                                                                                             \
     195#define INDEXER_FUNC1( func, type )                                                                                             \
    196196template<typename pass_type>                                                                                                   \
    197197static inline auto indexer_impl_##func ( pass_type & pass, int, type arg ) -> decltype( pass.indexer.func( arg ), void() ) {   \
     
    202202static inline void indexer_impl_##func ( pass_type &, long, type ) { }                                                          \
    203203
    204 INDEXER_FUNC( addId     , DeclarationWithType * );
    205 INDEXER_FUNC( addType   , NamedTypeDecl *       );
    206 INDEXER_FUNC( addStruct , StructDecl *          );
    207 INDEXER_FUNC( addEnum   , EnumDecl *            );
    208 INDEXER_FUNC( addUnion  , UnionDecl *           );
    209 INDEXER_FUNC( addTrait  , TraitDecl *           );
    210 INDEXER_FUNC( addWith   , WithStmt *            );
     204#define INDEXER_FUNC2( func, type1, type2 )                                                                                             \
     205template<typename pass_type>                                                                                                   \
     206static inline auto indexer_impl_##func ( pass_type & pass, int, type1 arg1, type2 arg2 ) -> decltype( pass.indexer.func( arg1, arg2 ), void() ) {   \
     207        pass.indexer.func( arg1, arg2 );                                                                                                \
     208}                                                                                                                              \
     209                                                                                                                               \
     210template<typename pass_type>                                                                                                   \
     211static inline void indexer_impl_##func ( pass_type &, long, type1, type2 ) { }
     212
     213
     214INDEXER_FUNC1( addId     , DeclarationWithType *       );
     215INDEXER_FUNC1( addType   , NamedTypeDecl *             );
     216INDEXER_FUNC1( addStruct , StructDecl *                );
     217INDEXER_FUNC1( addEnum   , EnumDecl *                  );
     218INDEXER_FUNC1( addUnion  , UnionDecl *                 );
     219INDEXER_FUNC1( addTrait  , TraitDecl *                 );
     220INDEXER_FUNC2( addWith   , std::list< Expression * > &, BaseSyntaxNode * );
    211221
    212222
  • src/Common/ScopedMap.h

    rf9feab8 r90152a4  
    1010// Created On       : Wed Dec 2 11:37:00 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Fri Jul 21 22:18:24 2017
    13 // Update Count     : 2
     12// Last Modified On : Mon May 21 15:22:40 2018
     13// Update Count     : 3
    1414//
    1515
     
    2222#include <vector>
    2323
     24/// Default (empty) ScopedMap note type
     25struct EmptyNote {};
     26
    2427/// A map where the items are placed into nested scopes;
    25 /// inserted items are placed into the innermost scope, lookup looks from the innermost scope outward
    26 template<typename Key, typename Value>
     28/// inserted items are placed into the innermost scope, lookup looks from the innermost scope outward.
     29/// Scopes may be annotated with a value; the annotation defaults to empty
     30template<typename Key, typename Value, typename Note = EmptyNote>
    2731class ScopedMap {
    28         typedef std::map< Key, Value > Scope;
     32        typedef std::map< Key, Value > MapType;
     33        struct Scope {
     34                MapType map;
     35                Note note;
     36
     37                template<typename N>
     38                Scope(N&& n) : map(), note(std::forward<N>(n)) {}
     39               
     40                Scope() = default;
     41                Scope(const Scope&) = default;
     42                Scope(Scope&&) = default;
     43                Scope& operator= (const Scope&) = default;
     44                Scope& operator= (Scope&&) = default;
     45        };
    2946        typedef std::vector< Scope > ScopeList;
    3047
    3148        ScopeList scopes; ///< scoped list of maps
    3249public:
    33         typedef typename Scope::key_type key_type;
    34         typedef typename Scope::mapped_type mapped_type;
    35         typedef typename Scope::value_type value_type;
     50        typedef typename MapType::key_type key_type;
     51        typedef typename MapType::mapped_type mapped_type;
     52        typedef typename MapType::value_type value_type;
    3653        typedef typename ScopeList::size_type size_type;
    3754        typedef typename ScopeList::difference_type difference_type;
    38         typedef typename Scope::reference reference;
    39         typedef typename Scope::const_reference const_reference;
    40         typedef typename Scope::pointer pointer;
    41         typedef typename Scope::const_pointer const_pointer;
     55        typedef typename MapType::reference reference;
     56        typedef typename MapType::const_reference const_reference;
     57        typedef typename MapType::pointer pointer;
     58        typedef typename MapType::const_pointer const_pointer;
    4259
    4360        class iterator : public std::iterator< std::bidirectional_iterator_tag,
     
    4562        friend class ScopedMap;
    4663        friend class const_iterator;
    47                 typedef typename std::map< Key, Value >::iterator wrapped_iterator;
    48                 typedef typename std::vector< std::map< Key, Value > > scope_list;
     64                typedef typename ScopedMap::MapType::iterator wrapped_iterator;
     65                typedef typename ScopedMap::ScopeList scope_list;
    4966                typedef typename scope_list::size_type size_type;
    5067
    5168                /// Checks if this iterator points to a valid item
    5269                bool is_valid() const {
    53                         return it != (*scopes)[level].end();
     70                        return it != (*scopes)[level].map.end();
    5471                }
    5572
     
    7996
    8097                iterator& operator++ () {
    81                         if ( it == (*scopes)[level].end() ) {
     98                        if ( it == (*scopes)[level].map.end() ) {
    8299                                if ( level == 0 ) return *this;
    83100                                --level;
    84                                 it = (*scopes)[level].begin();
     101                                it = (*scopes)[level].map.begin();
    85102                        } else {
    86103                                ++it;
     
    92109                iterator& operator-- () {
    93110                        // may fail if this is the begin iterator; allowed by STL spec
    94                         if ( it == (*scopes)[level].begin() ) {
     111                        if ( it == (*scopes)[level].map.begin() ) {
    95112                                ++level;
    96                                 it = (*scopes)[level].end();
     113                                it = (*scopes)[level].map.end();
    97114                        }
    98115                        --it;
     
    107124
    108125                size_type get_level() const { return level; }
     126
     127                Note& get_note() { return (*scopes)[level].note; }
     128                const Note& get_note() const { return (*scopes)[level].note; }
    109129
    110130        private:
     
    117137                                                     value_type > {
    118138        friend class ScopedMap;
    119                 typedef typename std::map< Key, Value >::iterator wrapped_iterator;
    120                 typedef typename std::map< Key, Value >::const_iterator wrapped_const_iterator;
    121                 typedef typename std::vector< std::map< Key, Value > > scope_list;
     139                typedef typename ScopedMap::MapType::iterator wrapped_iterator;
     140                typedef typename ScopedMap::MapType::const_iterator wrapped_const_iterator;
     141                typedef typename ScopedMap::ScopeList scope_list;
    122142                typedef typename scope_list::size_type size_type;
    123143
    124144                /// Checks if this iterator points to a valid item
    125145                bool is_valid() const {
    126                         return it != (*scopes)[level].end();
     146                        return it != (*scopes)[level].map.end();
    127147                }
    128148
     
    157177
    158178                const_iterator& operator++ () {
    159                         if ( it == (*scopes)[level].end() ) {
     179                        if ( it == (*scopes)[level].map.end() ) {
    160180                                if ( level == 0 ) return *this;
    161181                                --level;
    162                                 it = (*scopes)[level].begin();
     182                                it = (*scopes)[level].map.begin();
    163183                        } else {
    164184                                ++it;
     
    170190                const_iterator& operator-- () {
    171191                        // may fail if this is the begin iterator; allowed by STL spec
    172                         if ( it == (*scopes)[level].begin() ) {
     192                        if ( it == (*scopes)[level].map.begin() ) {
    173193                                ++level;
    174                                 it = (*scopes)[level].end();
     194                                it = (*scopes)[level].map.end();
    175195                        }
    176196                        --it;
     
    185205
    186206                size_type get_level() const { return level; }
     207
     208                const Note& get_note() const { return (*scopes)[level].note; }
    187209
    188210        private:
     
    197219        }
    198220
     221        // Starts a new scope with the given note
     222        template<typename N>
     223        void beginScope( N&& n ) {
     224                scopes.emplace_back( std::forward<N>(n) );
     225        }
     226
    199227        /// Ends a scope; invalidates any iterators pointing to elements of that scope
    200228        void endScope() {
     
    204232
    205233        /// Default constructor initializes with one scope
    206         ScopedMap() { beginScope(); }
    207 
    208         iterator begin() { return iterator(scopes, scopes.back().begin(), currentScope()).next_valid(); }
    209         const_iterator begin() const { return const_iterator(scopes, scopes.back().begin(), currentScope()).next_valid(); }
    210         const_iterator cbegin() const { return const_iterator(scopes, scopes.back().begin(), currentScope()).next_valid(); }
    211         iterator end() { return iterator(scopes, scopes[0].end(), 0); }
    212         const_iterator end() const { return const_iterator(scopes, scopes[0].end(), 0); }
    213         const_iterator cend() const { return const_iterator(scopes, scopes[0].end(), 0); }
     234        ScopedMap() : scopes() { beginScope(); }
     235
     236        /// Constructs with a given note on the outermost scope
     237        template<typename N>
     238        ScopedMap( N&& n ) : scopes() { beginScope(std::forward<N>(n)); }
     239
     240        iterator begin() { return iterator(scopes, scopes.back().map.begin(), currentScope()).next_valid(); }
     241        const_iterator begin() const { return const_iterator(scopes, scopes.back().map.begin(), currentScope()).next_valid(); }
     242        const_iterator cbegin() const { return const_iterator(scopes, scopes.back().map.begin(), currentScope()).next_valid(); }
     243        iterator end() { return iterator(scopes, scopes[0].map.end(), 0); }
     244        const_iterator end() const { return const_iterator(scopes, scopes[0].map.end(), 0); }
     245        const_iterator cend() const { return const_iterator(scopes, scopes[0].map.end(), 0); }
    214246
    215247        /// Gets the index of the current scope (counted from 1)
    216248        size_type currentScope() const { return scopes.size() - 1; }
     249
     250        /// Gets the note at the given scope
     251        Note& getNote( size_type i ) { return scopes[i].note; }
     252        const Note& getNote( size_type i ) const { return scopes[i].note; }
    217253
    218254        /// Finds the given key in the outermost scope it occurs; returns end() for none such
    219255        iterator find( const Key &key ) {
    220256                for ( size_type i = scopes.size() - 1; ; --i ) {
    221                         typename Scope::iterator val = scopes[i].find( key );
    222                         if ( val != scopes[i].end() ) return iterator( scopes, val, i );
     257                        typename MapType::iterator val = scopes[i].map.find( key );
     258                        if ( val != scopes[i].map.end() ) return iterator( scopes, val, i );
    223259                        if ( i == 0 ) break;
    224260                }
     
    226262        }
    227263        const_iterator find( const Key &key ) const {
    228                         return const_iterator( const_cast< ScopedMap< Key, Value >* >(this)->find( key ) );
     264                        return const_iterator( const_cast< ScopedMap< Key, Value, Note >* >(this)->find( key ) );
    229265        }
    230266
    231267        /// Finds the given key in the provided scope; returns end() for none such
    232268        iterator findAt( size_type scope, const Key& key ) {
    233                 typename Scope::iterator val = scopes[scope].find( key );
    234                 if ( val != scopes[scope].end() ) return iterator( scopes, val, scope );
     269                typename MapType::iterator val = scopes[scope].map.find( key );
     270                if ( val != scopes[scope].map.end() ) return iterator( scopes, val, scope );
    235271                return end();
    236272        }
    237273        const_iterator findAt( size_type scope, const Key& key ) const {
    238                 return const_iterator( const_cast< ScopedMap< Key, Value >* >(this)->findAt( scope, key ) );
     274                return const_iterator( const_cast< ScopedMap< Key, Value, Note >* >(this)->findAt( scope, key ) );
    239275        }
    240276
     
    243279                if ( it.level == 0 ) return end();
    244280                for ( size_type i = it.level - 1; ; --i ) {
    245                         typename Scope::iterator val = scopes[i].find( key );
    246                         if ( val != scopes[i].end() ) return iterator( scopes, val, i );
     281                        typename MapType::iterator val = scopes[i].map.find( key );
     282                        if ( val != scopes[i].map.end() ) return iterator( scopes, val, i );
    247283                        if ( i == 0 ) break;
    248284                }
     
    250286        }
    251287        const_iterator findNext( const_iterator &it, const Key &key ) const {
    252                         return const_iterator( const_cast< ScopedMap< Key, Value >* >(this)->findNext( it, key ) );
     288                        return const_iterator( const_cast< ScopedMap< Key, Value, Note >* >(this)->findNext( it, key ) );
    253289        }
    254290
     
    256292        template< typename value_type_t >
    257293        std::pair< iterator, bool > insert( value_type_t&& value ) {
    258                 std::pair< typename Scope::iterator, bool > res = scopes.back().insert( std::forward<value_type_t>( value ) );
     294                std::pair< typename MapType::iterator, bool > res = scopes.back().map.insert( std::forward<value_type_t>( value ) );
    259295                return std::make_pair( iterator(scopes, std::move( res.first ), scopes.size()-1), std::move( res.second ) );
    260296        }
     
    262298        template< typename value_type_t >
    263299        std::pair< iterator, bool > insert( iterator at, value_type_t&& value ) {
    264                 Scope& scope = (*at.scopes) [ at.level ];
    265                 std::pair< typename Scope::iterator, bool > res = scope.insert( std::forward<value_type_t>( value ) );
     300                MapType& scope = (*at.scopes)[ at.level ].map;
     301                std::pair< typename MapType::iterator, bool > res = scope.insert( std::forward<value_type_t>( value ) );
    266302                return std::make_pair( iterator(scopes, std::move( res.first ), at.level), std::move( res.second ) );
    267303        }
     
    272308        template< typename value_type_t >
    273309        std::pair< iterator, bool > insertAt( size_type scope, value_type_t&& value ) {
    274                 std::pair< typename Scope::iterator, bool > res = scopes.at(scope).insert( std::forward<value_type_t>( value ) );
     310                std::pair< typename MapType::iterator, bool > res = scopes.at(scope).map.insert( std::forward<value_type_t>( value ) );
    275311                return std::make_pair( iterator(scopes, std::move( res.first ), scope), std::move( res.second ) );
     312        }
     313
     314        template< typename value_t >
     315        std::pair< iterator, bool > insertAt( size_type scope, const Key& key, value_t&& value ) {
     316                return insertAt( scope, std::make_pair( key, std::forward<value_t>( value ) ) );
    276317        }
    277318
     
    283324
    284325        iterator erase( iterator pos ) {
    285                 Scope& scope = (*pos.scopes) [ pos.level ];
     326                MapType& scope = (*pos.scopes)[ pos.level ].map;
    286327                const typename iterator::wrapped_iterator& new_it = scope.erase( pos.it );
    287328                iterator it( *pos.scopes, new_it, pos.level );
  • src/Common/SemanticError.cc

    rf9feab8 r90152a4  
    77// SemanticError.cc --
    88//
    9 // Author           : Richard C. Bilson
     9// Author           : Thierry Delisle
    1010// Created On       : Mon May 18 07:44:20 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Tue Aug 29 18:17:35 2017
    13 // Update Count     : 3
     12// Last Modified On : Thu Jun  7 08:05:26 2018
     13// Update Count     : 10
    1414//
    1515
     16#include <cstdarg>
    1617#include <cstdio>                                                                               // for fileno, stderr
     18#include <cstring>
    1719#include <unistd.h>                                                                             // for isatty
    1820#include <iostream>                                                                             // for basic_ostream, operator<<, ostream
    1921#include <list>                                                                                 // for list, _List_iterator
    2022#include <string>                                                                               // for string, operator<<, operator+, to_string
     23#include <vector>
    2124
    2225#include "Common/utility.h"                                                             // for to_string, CodeLocation (ptr only)
    2326#include "SemanticError.h"
    2427
    25 SemanticError::SemanticError() {
     28//-----------------------------------------------------------------------------
     29// Severity Handling
     30std::vector<Severity> & get_severities() {
     31        static std::vector<Severity> severities;
     32        if(severities.empty()) {
     33                severities.reserve((size_t)Warning::NUMBER_OF_WARNINGS);
     34                for ( const auto w : WarningFormats ) {
     35                        severities.push_back( w.default_severity );
     36                } // for
     37        }
     38        return severities;
    2639}
    2740
    28 SemanticError::SemanticError( std::string error ) {
    29         append( error );
     41void SemanticWarning_SuppressAll() {
     42        for( auto & s : get_severities() ) {
     43                s = Severity::Suppress;
     44        }
    3045}
    3146
    32 void SemanticError::append( SemanticError &other ) {
     47void SemanticWarning_EnableAll() {
     48        for( auto & s : get_severities() ) {
     49                s = Severity::Warn;
     50        }
     51}
     52
     53void SemanticWarning_WarningAsError() {
     54        for( auto & s : get_severities() ) {
     55                if(s == Severity::Warn) s = Severity::Error;
     56        }
     57}
     58
     59void SemanticWarning_Set(const char * const name, Severity s) {
     60        size_t idx = 0;
     61        for ( const auto & w : WarningFormats ) {
     62                if ( std::strcmp( name, w.name ) == 0 ) {
     63                        get_severities()[idx] = s;
     64                        break;
     65                }
     66                idx++;
     67        }
     68}
     69
     70//-----------------------------------------------------------------------------
     71// Semantic Error
     72bool SemanticErrorThrow = false;
     73
     74SemanticErrorException::SemanticErrorException( CodeLocation location, std::string error ) {
     75        append( location, error );
     76}
     77
     78void SemanticErrorException::append( SemanticErrorException &other ) {
    3379        errors.splice( errors.end(), other.errors );
    3480}
    3581
    36 void SemanticError::append( const std::string & msg ) {
    37         errors.emplace_back( error_str() + msg );
     82void SemanticErrorException::append( CodeLocation location, const std::string & msg ) {
     83        errors.emplace_back( location, msg );
    3884}
    3985
    40 bool SemanticError::isEmpty() const {
     86bool SemanticErrorException::isEmpty() const {
    4187        return errors.empty();
    4288}
    4389
    44 void SemanticError::print( std::ostream &os ) {
     90void SemanticErrorException::print() {
    4591        using std::to_string;
    4692        for( auto err : errors ) {
    47                 os << err.location << err.description << std::endl;
     93                std::cerr << ErrorHelpers::bold() << err.location << ErrorHelpers::error_str() << ErrorHelpers::reset_font() << err.description << std::endl;
    4894        }
    4995}
    5096
    51 void SemanticError::set_location( const CodeLocation& location ) {
    52         errors.begin()->maybeSet( location );
     97void SemanticError( CodeLocation location, std::string error ) {
     98        SemanticErrorThrow = true;
     99        throw SemanticErrorException( location, error );
     100}
     101
     102namespace {
     103        // convert format string and arguments into a single string
     104        std::string fmtToString(const char * fmt, va_list ap) {
     105                int size = 128;
     106                while ( true ) {
     107                        char buf[size];
     108                        va_list args;
     109                        va_copy( args, ap );
     110                        int n = vsnprintf(&buf[0], size, fmt, args);
     111                        va_end( args );
     112                        if ( n < size && n >= 0 ) return buf;
     113                        size *= 2;
     114                }
     115                assert( false );
     116        }
     117}
     118
     119void SemanticWarningImpl( CodeLocation location, Warning warning, const char * const fmt, ... ) {
     120        Severity severity = get_severities()[(int)warning];
     121        switch(severity) {
     122        case Severity::Suppress :
     123                break;
     124        case Severity::Warn :
     125                {
     126                        va_list args;
     127                        va_start(args, fmt);
     128                        std::string msg = fmtToString( fmt, args );
     129                        va_end(args);
     130                        std::cerr << ErrorHelpers::bold() << location << ErrorHelpers::warning_str() << ErrorHelpers::reset_font() << msg << std::endl;
     131                }
     132                break;
     133        case Severity::Error :
     134                {
     135                        va_list args;
     136                        va_start(args, fmt);
     137                        std::string msg = fmtToString( fmt, args );
     138                        va_end(args);
     139                        SemanticError(location, msg);
     140                }
     141                break;
     142        case Severity::Critical :
     143                assertf(false, "Critical errors not implemented yet");
     144                break;
     145        }
     146}
     147
     148//-----------------------------------------------------------------------------
     149// Helpers
     150namespace ErrorHelpers {
     151        const std::string & error_str() {
     152                static std::string str = isatty( STDERR_FILENO ) ? "\e[31merror:\e[39m " : "error: ";
     153                return str;
     154        }
     155
     156        const std::string & warning_str() {
     157                static std::string str = isatty( STDERR_FILENO ) ? "\e[95mwarning:\e[39m " : "warning: ";
     158                return str;
     159        }
     160
     161        const std::string & bold_ttycode() {
     162                static std::string str = isatty( STDERR_FILENO ) ? "\e[1m" : "";
     163                return str;
     164        }
     165
     166        const std::string & reset_font_ttycode() {
     167                static std::string str = isatty( STDERR_FILENO ) ? "\e[0m" : "";
     168                return str;
     169        }
     170
     171        std::string make_bold( const std::string & str ) {
     172                return bold_ttycode() + str + reset_font_ttycode();
     173        }
     174
     175        std::ostream & operator<<(std::ostream & os, bold) {
     176                os << bold_ttycode();
     177                return os;
     178        }
     179
     180        std::ostream & operator<<(std::ostream & os, reset_font) {
     181                os << reset_font_ttycode();
     182                return os;
     183        }
    53184}
    54185
  • src/Common/SemanticError.h

    rf9feab8 r90152a4  
    77// SemanticError.h --
    88//
    9 // Author           : Richard C. Bilson
     9// Author           : Thierry Delisle
    1010// Created On       : Mon May 18 07:44:20 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Tue Aug 29 22:03:36 2017
    13 // Update Count     : 17
     12// Last Modified On : Thu Jul 19 10:09:17 2018
     13// Update Count     : 31
    1414//
    1515
    1616#pragma once
    1717
    18 #include <exception>                                                                    // for exception
    19 #include <iostream>                                                                             // for ostream
    20 #include <list>                                                                                 // for list
    21 #include <string>                                                                               // for string
    22 #include <unistd.h>                                                                             // for isatty
     18#include "ErrorObjects.h"
     19#include <cstring>
    2320
    24 #include "CodeLocation.h"                                                               // for CodeLocation, toString
     21//-----------------------------------------------------------------------------
     22// Errors
    2523
    26 struct error {
    27         std::string description;
    28         CodeLocation location;
     24extern bool SemanticErrorThrow;
    2925
    30         error() = default;
    31         error( const std::string & str ) : description( str ) {}
     26__attribute__((noreturn)) void SemanticError( CodeLocation location, std::string error );
    3227
    33         void maybeSet( const CodeLocation & location ) {
    34                 if( this->location.isUnset() ) {
    35                         this->location = location;
    36                 }
    37         }
     28template< typename T >
     29__attribute__((noreturn)) static inline void SemanticError( const T * obj, const std::string & error ) {
     30        SemanticError( obj->location, toString( error, obj ) );
     31}
     32
     33template< typename T >
     34__attribute__((noreturn)) static inline void SemanticError( CodeLocation location, const T * obj, const std::string & error ) {
     35        SemanticError( location, toString( error, obj ) );
     36}
     37
     38//-----------------------------------------------------------------------------
     39// Warnings
     40
     41enum class Severity {
     42        Suppress,
     43        Warn,
     44        Error,
     45        Critical
    3846};
    3947
    40 class SemanticError : public std::exception {
    41   public:
    42         SemanticError();
    43         SemanticError( std::string error );
    44         template< typename T > SemanticError( const std::string & error, const T * obj );
    45         ~SemanticError() throw() {}
    46 
    47         static inline const std::string & error_str() {
    48                 static std::string str = isatty( STDERR_FILENO ) ? "\e[31merror:\e[39m " : "error: ";
    49                 return str;
    50         }
    51 
    52         void append( SemanticError & other );
    53         void append( const std::string & );
    54         bool isEmpty() const;
    55         void print( std::ostream & os );
    56 
    57         void set_location( const CodeLocation & location );
    58         // constructs an exception using the given message and the printed representation of the obj (T must have a print
    59         // method)
    60   private:
    61         std::list< error > errors;
     48struct WarningData {
     49        const char * const name;
     50        const char * const message;
     51        const Severity default_severity;
    6252};
    6353
    64 template< typename T >
    65 SemanticError::SemanticError( const std::string & error, const T * obj ) {
    66         append( toString( error, obj ) );
     54constexpr WarningData WarningFormats[] = {
     55        {"self-assign"            , "self assignment of expression: %s"            , Severity::Warn},
     56        {"reference-conversion"   , "rvalue to reference conversion of rvalue: %s" , Severity::Warn},
     57        {"qualifiers-zero_t-one_t", "questionable use of type qualifier %s with %s", Severity::Warn},
     58        {"aggregate-forward-decl" , "forward declaration of nested aggregate: %s"  , Severity::Warn},
     59        {"superfluous-decl"       , "declaration does not allocate storage: %s"    , Severity::Warn},
     60        {"gcc-attributes"         , "invalid attribute: %s"                        , Severity::Warn},
     61};
     62
     63enum class Warning {
     64        SelfAssignment,
     65        RvalueToReferenceConversion,
     66        BadQualifiersZeroOne,
     67        AggrForwardDecl,
     68        SuperfluousDecl,
     69        GccAttributes,
     70        NUMBER_OF_WARNINGS, // This MUST be the last warning
     71};
     72
     73static_assert(
     74        (sizeof(WarningFormats) / sizeof(WarningFormats[0])) == ((unsigned long)Warning::NUMBER_OF_WARNINGS),
     75        "Each warning format should have a corresponding warning enum value"
     76);
     77
     78#define SemanticWarning(loc, id, ...) SemanticWarningImpl(loc, id, WarningFormats[(int)id].message, __VA_ARGS__)
     79
     80void SemanticWarningImpl (CodeLocation loc, Warning warn, const char * const fmt, ...) __attribute__((format(printf, 3, 4)));
     81
     82void SemanticWarning_SuppressAll   ();
     83void SemanticWarning_EnableAll     ();
     84void SemanticWarning_WarningAsError();
     85void SemanticWarning_Set           (const char * const name, Severity s);
     86
     87// SKULLDUGGERY: cfa.cc is built before SemanticError.cc but needs this routine.
     88static inline bool SemanticWarning_Exist(const char * const name) {
     89        for ( const auto & w : WarningFormats ) {
     90                if ( std::strcmp( name, w.name ) == 0 ) return true;
     91        }
     92        return false;
     93}
     94
     95//-----------------------------------------------------------------------------
     96// Helpers
     97namespace ErrorHelpers {
     98        const std::string & error_str();
     99        const std::string & warning_str();
     100        const std::string & bold_ttycode();
     101        const std::string & reset_font_ttycode();
     102
     103        std::string make_bold( const std::string & str );
     104
     105        struct bold {};
     106        std::ostream & operator<<(std::ostream & os, bold);
     107
     108        struct reset_font {};
     109        std::ostream & operator<<(std::ostream & os, reset_font);
    67110}
    68111
  • src/Common/module.mk

    rf9feab8 r90152a4  
    66## file "LICENCE" distributed with Cforall.
    77##
    8 ## module.mk -- 
     8## module.mk --
    99##
    1010## Author           : Richard C. Bilson
     
    1818       Common/UniqueName.cc \
    1919       Common/DebugMalloc.cc \
    20        Common/Assert.cc
     20       Common/Assert.cc \
     21       Common/Heap.cc \
     22       Common/Eval.cc
  • src/Common/utility.h

    rf9feab8 r90152a4  
    99// Author           : Richard C. Bilson
    1010// Created On       : Mon May 18 07:44:20 2015
    11 // Last Modified By : Andrew Beach
    12 // Last Modified On : Thr Aug 17 11:38:00 2017
    13 // Update Count     : 34
     11// Last Modified By : Peter A. Buhr
     12// Last Modified On : Sun May  6 22:24:16 2018
     13// Update Count     : 40
    1414//
    1515
     
    3131#include "Common/Indenter.h"
    3232
     33class Expression;
     34
    3335template< typename T >
    3436static inline T * maybeClone( const T *orig ) {
     
    98100}
    99101
     102template< typename SrcContainer, typename DestContainer, typename Predicate >
     103void cloneAll_if( const SrcContainer &src, DestContainer &dest, Predicate pred ) {
     104        std::back_insert_iterator< DestContainer > out( dest );
     105        for ( auto x : src ) {
     106                if ( pred(x) ) {
     107                        *out++ = x->clone();
     108                }
     109        } // while
     110}
     111
    100112template< typename Container >
    101113void assertAll( const Container &container ) {
     
    151163        return os.str();
    152164}
     165
     166#define toCString( ... ) toString( __VA_ARGS__ ).c_str()
    153167
    154168// replace element of list with all elements of another list
     
    424438}
    425439
    426 
     440// -----------------------------------------------------------------------------
     441// O(1) polymorphic integer ilog2, using clz, which returns the number of leading 0-bits, starting at the most
     442// significant bit (single instruction on x86)
     443
     444template<typename T>
     445inline
     446#if defined(__GNUC__) && __GNUC__ > 4
     447constexpr
     448#endif
     449T ilog2(const T & t) {
     450        if(std::is_integral<T>::value) {
     451                const constexpr int r = sizeof(t) * __CHAR_BIT__ - 1;
     452                if( sizeof(T) == sizeof(unsigned       int) ) return r - __builtin_clz  ( t );
     453                if( sizeof(T) == sizeof(unsigned      long) ) return r - __builtin_clzl ( t );
     454                if( sizeof(T) == sizeof(unsigned long long) ) return r - __builtin_clzll( t );
     455        }
     456        assert(false);
     457        return -1;
     458} // ilog2
     459
     460// -----------------------------------------------------------------------------
     461/// evaluates expr as a long long int. If second is false, expr could not be evaluated
     462std::pair<long long int, bool> eval(Expression * expr);
    427463
    428464// Local Variables: //
Note: See TracChangeset for help on using the changeset viewer.