Changeset a362f97 for src/SymTab


Ignore:
Timestamp:
Jan 27, 2017, 3:27:34 PM (9 years ago)
Author:
Peter A. Buhr <pabuhr@…>
Branches:
ADT, aaron-thesis, arm-eh, ast-experimental, cleanup-dtors, deferred_resn, demangler, enum, forall-pointer-decay, jacob/cs343-translation, jenkins-sandbox, master, new-ast, new-ast-unique-expr, new-env, no_list, persistent-indexer, pthread-emulation, qualifiedEnum, resolv-new, with_gc
Children:
c0aa336
Parents:
6acb935 (diff), 0a86a30 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge branch 'master' of plg2:software/cfa/cfa-cc

Location:
src/SymTab
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • src/SymTab/Autogen.cc

    r6acb935 ra362f97  
    2525#include "Autogen.h"
    2626#include "GenPoly/ScopedSet.h"
     27#include "Common/ScopedMap.h"
    2728#include "SymTab/Mangler.h"
    2829#include "GenPoly/DeclMutator.h"
     
    3031namespace SymTab {
    3132        Type * SizeType = 0;
    32 
    33         class AutogenerateRoutines : public Visitor {
     33        typedef ScopedMap< std::string, bool > TypeMap;
     34
     35        /// Data used to generate functions generically. Specifically, the name of the generated function, a function which generates the routine protoype, and a map which contains data to determine whether a function should be generated.
     36        struct FuncData {
     37                typedef FunctionType * (*TypeGen)( Type * );
     38                FuncData( const std::string & fname, const TypeGen & genType, TypeMap & map ) : fname( fname ), genType( genType ), map( map ) {}
     39                std::string fname;
     40                TypeGen genType;
     41                TypeMap & map;
     42        };
     43
     44        class AutogenerateRoutines final : public Visitor {
    3445          public:
    3546                std::list< Declaration * > &get_declsToAdd() { return declsToAdd; }
     
    3748                typedef Visitor Parent;
    3849                using Parent::visit;
     50
     51                AutogenerateRoutines();
    3952
    4053                virtual void visit( EnumDecl *enumDecl );
     
    5770                std::set< std::string > structsDone;
    5871                unsigned int functionNesting = 0;     // current level of nested functions
     72                /// Note: the following maps could be ScopedSets, but it should be easier to work
     73                /// deleted functions in if they are maps, since the value false can be inserted
     74                /// at the current scope without affecting outer scopes or requiring copies.
     75                TypeMap copyable, assignable, constructable, destructable;
     76                std::vector< FuncData > data;
    5977        };
    6078
     
    144162                decl->fixUniqueId();
    145163                return decl;
     164        }
     165
     166        /// inserts base type of first argument into map if pred(funcDecl) is true
     167        void insert( FunctionDecl *funcDecl, TypeMap & map, FunctionDecl * (*pred)(Declaration *) ) {
     168                // insert type into constructable, etc. map if appropriate
     169                if ( pred( funcDecl ) ) {
     170                        FunctionType * ftype = funcDecl->get_functionType();
     171                        assert( ! ftype->get_parameters().empty() );
     172                        Type * t = safe_dynamic_cast< PointerType * >( ftype->get_parameters().front()->get_type() )->get_base();
     173                        map.insert( Mangler::mangleType( t ), true );
     174                }
     175        }
     176
     177        /// using map and t, determines if is constructable, etc.
     178        bool lookup( const TypeMap & map, Type * t ) {
     179                if ( dynamic_cast< PointerType * >( t ) ) {
     180                        // will need more complicated checking if we want this to work with pointer types, since currently
     181                        return true;
     182                } else if ( ArrayType * at = dynamic_cast< ArrayType * >( t ) ) {
     183                        // an array's constructor, etc. is generated on the fly based on the base type's constructor, etc.
     184                        return lookup( map, at->get_base() );
     185                }
     186                TypeMap::const_iterator it = map.find( Mangler::mangleType( t ) );
     187                if ( it != map.end() ) return it->second;
     188                // something that does not appear in the map is by default not constructable, etc.
     189                return false;
     190        }
     191
     192        /// using map and aggr, examines each member to determine if constructor, etc. should be generated
     193        template<typename AggrDecl>
     194        bool shouldGenerate( const TypeMap & map, AggrDecl * aggr ) {
     195                for ( Declaration * dcl : aggr->get_members() ) {
     196                        if ( DeclarationWithType * dwt = dynamic_cast< DeclarationWithType * >( dcl ) ) {
     197                                if ( ! lookup( map, dwt->get_type() ) ) return false;
     198                        }
     199                }
     200                return true;
     201        }
     202
     203        /// data structure for abstracting the generation of special functions
     204        template< typename OutputIterator >
     205        struct FuncGenerator {
     206                StructDecl *aggregateDecl;
     207                StructInstType *refType;
     208                unsigned int functionNesting;
     209                const std::list< TypeDecl* > & typeParams;
     210                OutputIterator out;
     211                FuncGenerator( StructDecl *aggregateDecl, StructInstType *refType, unsigned int functionNesting, const std::list< TypeDecl* > & typeParams, OutputIterator out ) : aggregateDecl( aggregateDecl ), refType( refType ), functionNesting( functionNesting ), typeParams( typeParams ), out( out ) {}
     212
     213                /// generates a function (?{}, ?=?, ^?{}) based on the data argument and members. If function is generated, inserts the type into the map.
     214                void gen( const FuncData & data ) {
     215                        if ( ! shouldGenerate( data.map, aggregateDecl ) ) return;
     216                        FunctionType * ftype = data.genType( refType );
     217                        cloneAll( typeParams, ftype->get_forall() );
     218                        *out++ = genFunc( data.fname, ftype, functionNesting );
     219                        data.map.insert( Mangler::mangleType( refType ), true );
     220                }
     221        };
     222
     223        template< typename OutputIterator >
     224        FuncGenerator<OutputIterator> makeFuncGenerator( StructDecl *aggregateDecl, StructInstType *refType, unsigned int functionNesting, const std::list< TypeDecl* > & typeParams, OutputIterator out ) {
     225                return FuncGenerator<OutputIterator>( aggregateDecl, refType, functionNesting, typeParams, out );
    146226        }
    147227
     
    308388
    309389        /// generates struct constructors, destructor, and assignment functions
    310         void makeStructFunctions( StructDecl *aggregateDecl, StructInstType *refType, unsigned int functionNesting, std::list< Declaration * > & declsToAdd ) {
    311 
     390        void makeStructFunctions( StructDecl *aggregateDecl, StructInstType *refType, unsigned int functionNesting, std::list< Declaration * > & declsToAdd, const std::vector< FuncData > & data ) {
    312391                // Make function polymorphic in same parameters as generic struct, if applicable
    313392                const std::list< TypeDecl* > & typeParams = aggregateDecl->get_parameters(); // List of type variables to be placed on the generated functions
    314393                bool isDynamicLayout = hasDynamicLayout( aggregateDecl );  // NOTE this flag is an incredibly ugly kludge; we should fix the assignment signature instead (ditto for union)
    315394
    316                 // T ?=?(T *, T);
    317                 FunctionType *assignType = genAssignType( refType );
    318                 cloneAll( typeParams, assignType->get_forall() );
    319 
    320                 // void ?{}(T *); void ^?{}(T *);
    321                 FunctionType *ctorType = genDefaultType( refType );
    322                 cloneAll( typeParams, ctorType->get_forall() );
    323                 FunctionType *dtorType = genDefaultType( refType );
    324                 cloneAll( typeParams, dtorType->get_forall() );
    325 
    326                 // void ?{}(T *, T);
    327                 FunctionType *copyCtorType = genCopyType( refType );
    328                 cloneAll( typeParams, copyCtorType->get_forall() );
    329 
    330                 FunctionDecl *assignDecl = genFunc( "?=?", assignType, functionNesting );
    331                 FunctionDecl *ctorDecl = genFunc( "?{}", ctorType, functionNesting );
    332                 FunctionDecl *copyCtorDecl = genFunc( "?{}", copyCtorType, functionNesting );
    333                 FunctionDecl *dtorDecl = genFunc( "^?{}", dtorType, functionNesting );
     395                // generate each of the functions based on the supplied FuncData objects
     396                std::list< FunctionDecl * > newFuncs;
     397                auto generator = makeFuncGenerator( aggregateDecl, refType, functionNesting, typeParams, back_inserter( newFuncs ) );
     398                for ( const FuncData & d : data ) {
     399                        generator.gen( d );
     400                }
     401                // field ctors are only generated if default constructor and copy constructor are both generated
     402                unsigned numCtors = std::count_if( newFuncs.begin(), newFuncs.end(), [](FunctionDecl * dcl) { return InitTweak::isConstructor( dcl->get_name() ); } );
    334403
    335404                if ( functionNesting == 0 ) {
     
    338407                        // Note: this is necessary if we want structs which contain
    339408                        // generic (otype) structs as members.
    340                         addForwardDecl( assignDecl, declsToAdd );
    341                         addForwardDecl( ctorDecl, declsToAdd );
    342                         addForwardDecl( copyCtorDecl, declsToAdd );
    343                         addForwardDecl( dtorDecl, declsToAdd );
     409                        for ( FunctionDecl * dcl : newFuncs ) {
     410                                addForwardDecl( dcl, declsToAdd );
     411                        }
     412                }
     413
     414                for ( FunctionDecl * dcl : newFuncs ) {
     415                        // generate appropriate calls to member ctor, assignment
     416                        // destructor needs to do everything in reverse, so pass "forward" based on whether the function is a destructor
     417                        if ( ! InitTweak::isDestructor( dcl->get_name() ) ) {
     418                                makeStructFunctionBody( aggregateDecl->get_members().begin(), aggregateDecl->get_members().end(), dcl, isDynamicLayout );
     419                        } else {
     420                                makeStructFunctionBody( aggregateDecl->get_members().rbegin(), aggregateDecl->get_members().rend(), dcl, isDynamicLayout, false );
     421                        }
     422                        if ( InitTweak::isAssignment( dcl->get_name() ) ) {
     423                                // assignment needs to return a value
     424                                FunctionType * assignType = dcl->get_functionType();
     425                                assert( assignType->get_parameters().size() == 2 );
     426                                ObjectDecl * srcParam = safe_dynamic_cast< ObjectDecl * >( assignType->get_parameters().back() );
     427                                dcl->get_statements()->get_kids().push_back( new ReturnStmt( noLabels, new VariableExpr( srcParam ) ) );
     428                        }
     429                        declsToAdd.push_back( dcl );
    344430                }
    345431
    346432                // create constructors which take each member type as a parameter.
    347433                // for example, for struct A { int x, y; }; generate
    348                 // void ?{}(A *, int) and void ?{}(A *, int, int)
    349                 std::list<Declaration *> memCtors;
    350                 FunctionType * memCtorType = ctorType->clone();
    351                 for ( std::list<Declaration *>::iterator i = aggregateDecl->get_members().begin(); i != aggregateDecl->get_members().end(); ++i ) {
    352                         DeclarationWithType * member = dynamic_cast<DeclarationWithType *>( *i );
    353                         assert( member );
    354                         if ( isUnnamedBitfield( dynamic_cast< ObjectDecl * > ( member ) ) ) {
    355                                 // don't make a function whose parameter is an unnamed bitfield
    356                                 continue;
    357                         } else if ( member->get_name() == "" ) {
    358                                 // don't assign to anonymous members
    359                                 // xxx - this is a temporary fix. Anonymous members tie into
    360                                 // our inheritance model. I think the correct way to handle this is to
    361                                 // cast the structure to the type of the member and let the resolver
    362                                 // figure out whether it's valid and have a pass afterwards that fixes
    363                                 // the assignment to use pointer arithmetic with the offset of the
    364                                 // member, much like how generic type members are handled.
    365                                 continue;
    366                         }
    367                         memCtorType->get_parameters().push_back( new ObjectDecl( member->get_name(), DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, member->get_type()->clone(), 0 ) );
    368                         FunctionDecl * ctor = genFunc( "?{}", memCtorType->clone(), functionNesting );
    369                         makeStructFieldCtorBody( aggregateDecl->get_members().begin(), aggregateDecl->get_members().end(), ctor, isDynamicLayout );
    370                         memCtors.push_back( ctor );
    371                 }
    372                 delete memCtorType;
    373 
    374                 // generate appropriate calls to member ctor, assignment
    375                 makeStructFunctionBody( aggregateDecl->get_members().begin(), aggregateDecl->get_members().end(), assignDecl, isDynamicLayout );
    376                 makeStructFunctionBody( aggregateDecl->get_members().begin(), aggregateDecl->get_members().end(), ctorDecl, isDynamicLayout );
    377                 makeStructFunctionBody( aggregateDecl->get_members().begin(), aggregateDecl->get_members().end(), copyCtorDecl, isDynamicLayout );
    378                 // needs to do everything in reverse, so pass "forward" as false
    379                 makeStructFunctionBody( aggregateDecl->get_members().rbegin(), aggregateDecl->get_members().rend(), dtorDecl, isDynamicLayout, false );
    380 
    381                 assert( assignType->get_parameters().size() == 2 );
    382                 ObjectDecl * srcParam = safe_dynamic_cast< ObjectDecl * >( assignType->get_parameters().back() );
    383                 assignDecl->get_statements()->get_kids().push_back( new ReturnStmt( noLabels, new VariableExpr( srcParam ) ) );
    384 
    385                 declsToAdd.push_back( ctorDecl );
    386                 declsToAdd.push_back( copyCtorDecl );
    387                 declsToAdd.push_back( dtorDecl );
    388                 declsToAdd.push_back( assignDecl ); // assignment should come last since it uses copy constructor in return
    389                 declsToAdd.splice( declsToAdd.end(), memCtors );
     434                //   void ?{}(A *, int) and void ?{}(A *, int, int)
     435                // Field constructors are only generated if default and copy constructor
     436                // are generated, since they need access to both
     437                if ( numCtors == 2 ) {
     438                        FunctionType * memCtorType = genDefaultType( refType );
     439                        cloneAll( typeParams, memCtorType->get_forall() );
     440                        for ( std::list<Declaration *>::iterator i = aggregateDecl->get_members().begin(); i != aggregateDecl->get_members().end(); ++i ) {
     441                                DeclarationWithType * member = dynamic_cast<DeclarationWithType *>( *i );
     442                                assert( member );
     443                                if ( isUnnamedBitfield( dynamic_cast< ObjectDecl * > ( member ) ) ) {
     444                                        // don't make a function whose parameter is an unnamed bitfield
     445                                        continue;
     446                                } else if ( member->get_name() == "" ) {
     447                                        // don't assign to anonymous members
     448                                        // xxx - this is a temporary fix. Anonymous members tie into
     449                                        // our inheritance model. I think the correct way to handle this is to
     450                                        // cast the structure to the type of the member and let the resolver
     451                                        // figure out whether it's valid and have a pass afterwards that fixes
     452                                        // the assignment to use pointer arithmetic with the offset of the
     453                                        // member, much like how generic type members are handled.
     454                                        continue;
     455                                }
     456                                memCtorType->get_parameters().push_back( new ObjectDecl( member->get_name(), DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, member->get_type()->clone(), 0 ) );
     457                                FunctionDecl * ctor = genFunc( "?{}", memCtorType->clone(), functionNesting );
     458                                makeStructFieldCtorBody( aggregateDecl->get_members().begin(), aggregateDecl->get_members().end(), ctor, isDynamicLayout );
     459                                declsToAdd.push_back( ctor );
     460                        }
     461                        delete memCtorType;
     462                }
    390463        }
    391464
     
    481554        }
    482555
     556        AutogenerateRoutines::AutogenerateRoutines() {
     557                // the order here determines the order that these functions are generated.
     558                // assignment should come last since it uses copy constructor in return.
     559                data.push_back( FuncData( "?{}", genDefaultType, constructable ) );
     560                data.push_back( FuncData( "?{}", genCopyType, copyable ) );
     561                data.push_back( FuncData( "^?{}", genDefaultType, destructable ) );
     562                data.push_back( FuncData( "?=?", genAssignType, assignable ) );
     563        }
     564
    483565        void AutogenerateRoutines::visit( EnumDecl *enumDecl ) {
    484566                if ( ! enumDecl->get_members().empty() ) {
     
    491573
    492574        void AutogenerateRoutines::visit( StructDecl *structDecl ) {
    493                 if ( ! structDecl->get_members().empty() && structsDone.find( structDecl->get_name() ) == structsDone.end() ) {
     575                if ( structDecl->has_body() && structsDone.find( structDecl->get_name() ) == structsDone.end() ) {
    494576                        StructInstType structInst( Type::Qualifiers(), structDecl->get_name() );
    495577                        for ( TypeDecl * typeDecl : structDecl->get_parameters() ) {
     578                                // need to visit assertions so that they are added to the appropriate maps
     579                                acceptAll( typeDecl->get_assertions(), *this );
    496580                                structInst.get_parameters().push_back( new TypeExpr( new TypeInstType( Type::Qualifiers(), typeDecl->get_name(), typeDecl ) ) );
    497581                        }
    498582                        structInst.set_baseStruct( structDecl );
    499                         makeStructFunctions( structDecl, &structInst, functionNesting, declsToAdd );
     583                        makeStructFunctions( structDecl, &structInst, functionNesting, declsToAdd, data );
    500584                        structsDone.insert( structDecl->get_name() );
    501585                } // if
     
    564648
    565649        void AutogenerateRoutines::visit( FunctionDecl *functionDecl ) {
     650                // record the existence of this function as appropriate
     651                insert( functionDecl, constructable, InitTweak::isDefaultConstructor );
     652                insert( functionDecl, assignable, InitTweak::isAssignment );
     653                insert( functionDecl, copyable, InitTweak::isCopyConstructor );
     654                insert( functionDecl, destructable, InitTweak::isDestructor );
     655
    566656                maybeAccept( functionDecl->get_functionType(), *this );
    567657                acceptAll( functionDecl->get_oldDecls(), *this );
     
    572662
    573663        void AutogenerateRoutines::visit( CompoundStmt *compoundStmt ) {
     664                constructable.beginScope();
     665                assignable.beginScope();
     666                copyable.beginScope();
     667                destructable.beginScope();
    574668                visitStatement( compoundStmt );
     669                constructable.endScope();
     670                assignable.endScope();
     671                copyable.endScope();
     672                destructable.endScope();
    575673        }
    576674
  • src/SymTab/FixFunction.cc

    r6acb935 ra362f97  
    2525
    2626        DeclarationWithType * FixFunction::mutate(FunctionDecl *functionDecl) {
    27                 ObjectDecl *pointer = new ObjectDecl( functionDecl->get_name(), functionDecl->get_storageClass(), functionDecl->get_linkage(), 0, new PointerType( Type::Qualifiers(), functionDecl->get_type()->clone() ), 0 );
     27                ObjectDecl *pointer = new ObjectDecl( functionDecl->get_name(), functionDecl->get_storageClass(), functionDecl->get_linkage(), 0, new PointerType( Type::Qualifiers(), functionDecl->get_type()->clone() ), 0, functionDecl->get_attributes() );
     28                functionDecl->get_attributes().clear();
    2829                delete functionDecl;
    2930                return pointer;
  • src/SymTab/Validate.cc

    r6acb935 ra362f97  
    114114                LinkReferenceToTypes( bool doDebug, const Indexer *indexer );
    115115          private:
    116                 using Indexer::visit;
     116                using Parent::visit;
    117117                void visit( StructInstType *structInst ) final;
    118118                void visit( UnionInstType *unionInst ) final;
     
    131131
    132132        /// Replaces array and function types in forall lists by appropriate pointer type
    133         class Pass3 : public Indexer {
     133        class Pass3 final : public Indexer {
    134134                typedef Indexer Parent;
    135135          public:
     136                using Parent::visit;
    136137                Pass3( const Indexer *indexer );
    137138          private:
    138                 virtual void visit( ObjectDecl *object );
    139                 virtual void visit( FunctionDecl *func );
     139                virtual void visit( ObjectDecl *object ) override;
     140                virtual void visit( FunctionDecl *func ) override;
    140141
    141142                const Indexer *indexer;
     
    375376        }
    376377
    377         void LinkReferenceToTypes::visit( TraitInstType *contextInst ) {
    378                 Parent::visit( contextInst );
    379                 if ( contextInst->get_name() == "sized" ) {
     378        void LinkReferenceToTypes::visit( TraitInstType *traitInst ) {
     379                Parent::visit( traitInst );
     380                if ( traitInst->get_name() == "sized" ) {
    380381                        // "sized" is a special trait with no members - just flick the sized status on for the type variable
    381                         if ( contextInst->get_parameters().size() != 1 ) {
    382                                 throw SemanticError( "incorrect number of context parameters: ", contextInst );
     382                        if ( traitInst->get_parameters().size() != 1 ) {
     383                                throw SemanticError( "incorrect number of trait parameters: ", traitInst );
    383384                        }
    384                         TypeExpr * param = safe_dynamic_cast< TypeExpr * > ( contextInst->get_parameters().front() );
     385                        TypeExpr * param = safe_dynamic_cast< TypeExpr * > ( traitInst->get_parameters().front() );
    385386                        TypeInstType * inst = safe_dynamic_cast< TypeInstType * > ( param->get_type() );
    386387                        TypeDecl * decl = inst->get_baseType();
     
    389390                        return;
    390391                }
    391                 TraitDecl *ctx = indexer->lookupTrait( contextInst->get_name() );
    392                 if ( ! ctx ) {
    393                         throw SemanticError( "use of undeclared context " + contextInst->get_name() );
    394                 } // if
    395                 for ( std::list< TypeDecl * >::const_iterator i = ctx->get_parameters().begin(); i != ctx->get_parameters().end(); ++i ) {
    396                         for ( std::list< DeclarationWithType * >::const_iterator assert = (*i )->get_assertions().begin(); assert != (*i )->get_assertions().end(); ++assert ) {
    397                                 if ( TraitInstType *otherCtx = dynamic_cast< TraitInstType * >(*assert ) ) {
    398                                         cloneAll( otherCtx->get_members(), contextInst->get_members() );
    399                                 } else {
    400                                         contextInst->get_members().push_back( (*assert )->clone() );
    401                                 } // if
     392                TraitDecl *traitDecl = indexer->lookupTrait( traitInst->get_name() );
     393                if ( ! traitDecl ) {
     394                        throw SemanticError( "use of undeclared trait " + traitInst->get_name() );
     395                } // if
     396                if ( traitDecl->get_parameters().size() != traitInst->get_parameters().size() ) {
     397                        throw SemanticError( "incorrect number of trait parameters: ", traitInst );
     398                } // if
     399
     400                for ( TypeDecl * td : traitDecl->get_parameters() ) {
     401                        for ( DeclarationWithType * assert : td->get_assertions() ) {
     402                                traitInst->get_members().push_back( assert->clone() );
    402403                        } // for
    403404                } // for
    404405
    405                 if ( ctx->get_parameters().size() != contextInst->get_parameters().size() ) {
    406                         throw SemanticError( "incorrect number of context parameters: ", contextInst );
    407                 } // if
    408 
    409                 // need to clone members of the context for ownership purposes
     406                // need to clone members of the trait for ownership purposes
    410407                std::list< Declaration * > members;
    411                 std::transform( ctx->get_members().begin(), ctx->get_members().end(), back_inserter( members ), [](Declaration * dwt) { return dwt->clone(); } );
    412 
    413                 applySubstitution( ctx->get_parameters().begin(), ctx->get_parameters().end(), contextInst->get_parameters().begin(), members.begin(), members.end(), back_inserter( contextInst->get_members() ) );
     408                std::transform( traitDecl->get_members().begin(), traitDecl->get_members().end(), back_inserter( members ), [](Declaration * dwt) { return dwt->clone(); } );
     409
     410                applySubstitution( traitDecl->get_parameters().begin(), traitDecl->get_parameters().end(), traitInst->get_parameters().begin(), members.begin(), members.end(), back_inserter( traitInst->get_members() ) );
     411
     412                // need to carry over the 'sized' status of each decl in the instance
     413                for ( auto p : group_iterate( traitDecl->get_parameters(), traitInst->get_parameters() ) ) {
     414                        TypeExpr * expr = safe_dynamic_cast< TypeExpr * >( std::get<1>(p) );
     415                        if ( TypeInstType * inst = dynamic_cast< TypeInstType * >( expr->get_type() ) ) {
     416                                TypeDecl * formalDecl = std::get<0>(p);
     417                                TypeDecl * instDecl = inst->get_baseType();
     418                                if ( formalDecl->get_sized() ) instDecl->set_sized( true );
     419                        }
     420                }
    414421        }
    415422
     
    457464        }
    458465
    459         /// Fix up assertions
    460         void forallFixer( Type *func ) {
    461                 for ( Type::ForallList::iterator type = func->get_forall().begin(); type != func->get_forall().end(); ++type ) {
     466        /// Fix up assertions - flattens assertion lists, removing all trait instances
     467        void forallFixer( Type * func ) {
     468                for ( TypeDecl * type : func->get_forall() ) {
    462469                        std::list< DeclarationWithType * > toBeDone, nextRound;
    463                         toBeDone.splice( toBeDone.end(), (*type )->get_assertions() );
     470                        toBeDone.splice( toBeDone.end(), type->get_assertions() );
    464471                        while ( ! toBeDone.empty() ) {
    465                                 for ( std::list< DeclarationWithType * >::iterator assertion = toBeDone.begin(); assertion != toBeDone.end(); ++assertion ) {
    466                                         if ( TraitInstType *ctx = dynamic_cast< TraitInstType * >( (*assertion )->get_type() ) ) {
    467                                                 for ( std::list< Declaration * >::const_iterator i = ctx->get_members().begin(); i != ctx->get_members().end(); ++i ) {
    468                                                         DeclarationWithType *dwt = dynamic_cast< DeclarationWithType * >( *i );
    469                                                         assert( dwt );
     472                                for ( DeclarationWithType * assertion : toBeDone ) {
     473                                        if ( TraitInstType *traitInst = dynamic_cast< TraitInstType * >( assertion->get_type() ) ) {
     474                                                // expand trait instance into all of its members
     475                                                for ( Declaration * member : traitInst->get_members() ) {
     476                                                        DeclarationWithType *dwt = safe_dynamic_cast< DeclarationWithType * >( member );
    470477                                                        nextRound.push_back( dwt->clone() );
    471478                                                }
    472                                                 delete ctx;
     479                                                delete traitInst;
    473480                                        } else {
     481                                                // pass assertion through
    474482                                                FixFunction fixer;
    475                                                 *assertion = (*assertion )->acceptMutator( fixer );
     483                                                assertion = assertion->acceptMutator( fixer );
    476484                                                if ( fixer.get_isVoid() ) {
    477485                                                        throw SemanticError( "invalid type void in assertion of function ", func );
    478486                                                }
    479                                                 (*type )->get_assertions().push_back( *assertion );
     487                                                type->get_assertions().push_back( assertion );
    480488                                        } // if
    481489                                } // for
     
    629637                if ( FunctionType *funtype = dynamic_cast<FunctionType *>( ret->get_type() ) ) {
    630638                        // replace the current object declaration with a function declaration
    631                         return new FunctionDecl( ret->get_name(), ret->get_storageClass(), ret->get_linkage(), funtype, 0, ret->get_isInline(), ret->get_isNoreturn() );
     639                        FunctionDecl * newDecl = new FunctionDecl( ret->get_name(), ret->get_storageClass(), ret->get_linkage(), funtype, 0, ret->get_isInline(), ret->get_isNoreturn(), objDecl->get_attributes() );
     640                        objDecl->get_attributes().clear();
     641                        delete objDecl;
     642                        return newDecl;
    632643                } else if ( objDecl->get_isInline() || objDecl->get_isNoreturn() ) {
    633644                        throw SemanticError( "invalid inline or _Noreturn specification in declaration of ", objDecl );
Note: See TracChangeset for help on using the changeset viewer.