Changes in / [73bf8cf2:aea7168]


Ignore:
Location:
src
Files:
19 edited

Legend:

Unmodified
Added
Removed
  • src/CodeGen/CodeGenerator.cc

    r73bf8cf2 raea7168  
    271271                printDesignators( init->get_designators() );
    272272                output << "{ ";
    273                 if ( init->begin() == init->end() ) {
     273                if ( init->begin_initializers() == init->end_initializers() ) {
    274274                        // illegal to leave initializer list empty for scalar initializers, but always legal to have 0
    275275                        output << "0";
    276276                } else {
    277                         genCommaList( init->begin(), init->end() );
     277                        genCommaList( init->begin_initializers(), init->end_initializers() );
    278278                }
    279279                output << " }";
  • src/GenPoly/DeclMutator.h

    r73bf8cf2 raea7168  
    2828        class DeclMutator : public Mutator {
    2929        public:
    30                 typedef Mutator Parent;
    31 
    3230                DeclMutator();
    3331                virtual ~DeclMutator();
    34 
    35                 using Parent::mutate;
     32               
    3633                virtual CompoundStmt* mutate(CompoundStmt *compoundStmt);
    3734                virtual Statement* mutate(IfStmt *ifStmt);
     
    4542                /// Mutates a list of declarations with this visitor
    4643                void mutateDeclarationList(std::list< Declaration* >& decls);
    47 
     44               
    4845                /// Called on entry to a new scope; overriders should call this as a super-class call
    4946                virtual void doBeginScope();
  • src/GenPoly/Specialize.cc

    r73bf8cf2 raea7168  
    3131#include "Common/UniqueName.h"
    3232#include "Common/utility.h"
    33 #include "InitTweak/InitTweak.h"
    3433
    3534namespace GenPoly {
     
    185184                mutateAll( appExpr->get_args(), *this );
    186185
    187                 if ( ! InitTweak::isIntrinsicCallExpr( appExpr ) ) {
    188                         // create thunks for the inferred parameters
    189                         // don't need to do this for intrinsic calls, because they aren't actually passed
    190                         for ( InferredParams::iterator inferParam = appExpr->get_inferParams().begin(); inferParam != appExpr->get_inferParams().end(); ++inferParam ) {
    191                                 inferParam->second.expr = doSpecialization( inferParam->second.formalType, inferParam->second.expr, &appExpr->get_inferParams() );
    192                         }
    193 
    194                         handleExplicitParams( appExpr );
    195                 }
     186                // create thunks for the inferred parameters
     187                for ( InferredParams::iterator inferParam = appExpr->get_inferParams().begin(); inferParam != appExpr->get_inferParams().end(); ++inferParam ) {
     188                        inferParam->second.expr = doSpecialization( inferParam->second.formalType, inferParam->second.expr, &appExpr->get_inferParams() );
     189                }
     190
     191                handleExplicitParams( appExpr );
    196192
    197193                return appExpr;
  • src/InitTweak/FixGlobalInit.cc

    r73bf8cf2 raea7168  
    4646                FunctionDecl * destroyFunction;
    4747        };
     48
     49        class ConstExprChecker : public Visitor {
     50        public:
     51                ConstExprChecker() : isConstExpr( true ) {}
     52
     53                virtual void visit( ApplicationExpr *applicationExpr ) { isConstExpr = false; }
     54                virtual void visit( UntypedExpr *untypedExpr ) { isConstExpr = false; }
     55                virtual void visit( NameExpr *nameExpr ) { isConstExpr = false; }
     56                virtual void visit( CastExpr *castExpr ) { isConstExpr = false; }
     57                virtual void visit( LabelAddressExpr *labAddressExpr ) { isConstExpr = false; }
     58                virtual void visit( UntypedMemberExpr *memberExpr ) { isConstExpr = false; }
     59                virtual void visit( MemberExpr *memberExpr ) { isConstExpr = false; }
     60                virtual void visit( VariableExpr *variableExpr ) { isConstExpr = false; }
     61                virtual void visit( ConstantExpr *constantExpr ) { /* bottom out */ }
     62                // these might be okay?
     63                // virtual void visit( SizeofExpr *sizeofExpr );
     64                // virtual void visit( AlignofExpr *alignofExpr );
     65                // virtual void visit( UntypedOffsetofExpr *offsetofExpr );
     66                // virtual void visit( OffsetofExpr *offsetofExpr );
     67                // virtual void visit( OffsetPackExpr *offsetPackExpr );
     68                // virtual void visit( AttrExpr *attrExpr );
     69                // virtual void visit( CommaExpr *commaExpr );
     70                // virtual void visit( LogicalExpr *logicalExpr );
     71                // virtual void visit( ConditionalExpr *conditionalExpr );
     72                virtual void visit( TupleExpr *tupleExpr ) { isConstExpr = false; }
     73                virtual void visit( SolvedTupleExpr *tupleExpr ) { isConstExpr = false; }
     74                virtual void visit( TypeExpr *typeExpr ) { isConstExpr = false; }
     75                virtual void visit( AsmExpr *asmExpr ) { isConstExpr = false; }
     76                virtual void visit( UntypedValofExpr *valofExpr ) { isConstExpr = false; }
     77                virtual void visit( CompoundLiteralExpr *compLitExpr ) { isConstExpr = false; }
     78
     79                bool isConstExpr;
     80        };
     81
     82        bool isConstExpr( Initializer * init ) {
     83                if ( init ) {
     84                        ConstExprChecker checker;
     85                        init->accept( checker );
     86                        return checker.isConstExpr;
     87                } // if
     88                // for all intents and purposes, no initializer means const expr
     89                return true;
     90        }
    4891
    4992        void fixGlobalInit( std::list< Declaration * > & translationUnit, const std::string & name, bool inLibrary ) {
     
    97140                std::list< Statement * > & destroyStatements = destroyFunction->get_statements()->get_kids();
    98141
     142                if ( ! tryConstruct( objDecl ) ) return; // don't construct @= or designated objects
     143                if ( objDecl->get_storageClass() == DeclarationNode::Extern ) return;
    99144                // C allows you to initialize objects with constant expressions
    100145                // xxx - this is an optimization. Need to first resolve constructors before we decide
     
    102147                // if ( isConstExpr( objDecl->get_init() ) ) return;
    103148
    104                 if ( ConstructorInit * ctorInit = dynamic_cast< ConstructorInit * >( objDecl->get_init() ) ) {
    105                         // a decision should have been made by the resolver, so ctor and init are not both non-NULL
    106                         assert( ! ctorInit->get_ctor() || ! ctorInit->get_init() );
     149                if ( dynamic_cast< ArrayType * > ( objDecl->get_type() ) ) {
     150                        // xxx - initialize each element of the array
     151                } else {
     152                        // steal initializer from object and attach it to a new temporary
     153                        ObjectDecl *newObj = new ObjectDecl( tempNamer.newName(), DeclarationNode::NoStorageClass, LinkageSpec::C, 0, objDecl->get_type()->clone(), objDecl->get_init() );
     154                        objDecl->set_init( NULL );
     155                        initStatements.push_back( new DeclStmt( noLabels, newObj ) );
    107156
    108                         Statement * dtor = ctorInit->get_dtor();
    109                         if ( dtor && ! isInstrinsicSingleArgCallStmt( dtor ) ) {
    110                                 // don't need to call intrinsic dtor, because it does nothing, but
    111                                 // non-intrinsic dtors must be called
    112                                 destroyStatements.push_front( dtor );
    113                                 ctorInit->set_dtor( NULL );
    114                         } // if
    115                         if ( Statement * ctor = ctorInit->get_ctor() ) {
    116                                 initStatements.push_back( ctor );
    117                                 objDecl->set_init( NULL );
    118                                 ctorInit->set_ctor( NULL );
    119                         } else if ( Initializer * init = ctorInit->get_init() ) {
    120                                 objDecl->set_init( init );
    121                                 ctorInit->set_init( NULL );
    122                         } else {
    123                                 // no constructor and no initializer, which is okay
    124                                 objDecl->set_init( NULL );
    125                         } // if
    126                         delete ctorInit;
     157                        // copy construct objDecl using temporary
     158                        UntypedExpr * init = new UntypedExpr( new NameExpr( "?{}" ) );
     159                        init->get_args().push_back( new AddressExpr( new VariableExpr( objDecl ) ) );
     160                        init->get_args().push_back( new VariableExpr( newObj ) );
     161                        initStatements.push_back( new ImplicitCtorDtorStmt( new ExprStmt( noLabels, init ) ) );
     162
     163                        // add destructor calls to global destroy function
     164                        UntypedExpr * destroy = new UntypedExpr( new NameExpr( "^?{}" ) );
     165                        destroy->get_args().push_back( new AddressExpr( new VariableExpr( objDecl ) ) );
     166                        destroyStatements.push_front( new ImplicitCtorDtorStmt( new ExprStmt( noLabels, destroy ) ) );
    127167                } // if
    128168        }
  • src/InitTweak/FixInit.cc

    r73bf8cf2 raea7168  
    1818#include <iterator>
    1919#include <algorithm>
     20#include "FixInit.h"
    2021#include "InitTweak.h"
    21 #include "FixInit.h"
    22 #include "FixGlobalInit.h"
    2322#include "ResolvExpr/Resolver.h"
    2423#include "ResolvExpr/typeops.h"
     
    8483                };
    8584
    86                 // debug
    8785                struct printSet {
    8886                        typedef ObjDeclCollector::ObjectSet ObjectSet;
     
    161159
    162160                        virtual DeclarationWithType * mutate( ObjectDecl *objDecl );
    163 
    164                         std::list< Declaration * > staticDtorDecls;
    165161                };
    166162
     
    175171        } // namespace
    176172
    177         void fix( std::list< Declaration * > & translationUnit, const std::string & filename, bool inLibrary ) {
    178                 // fixes ConstructorInit for global variables. should happen before fixInitializers.
    179                 InitTweak::fixGlobalInit( translationUnit, filename, inLibrary );
    180 
     173        void fix( std::list< Declaration * > & translationUnit ) {
    181174                InsertImplicitCalls::insert( translationUnit );
    182175                ResolveCopyCtors::resolveImplicitCalls( translationUnit );
     
    201194                void FixInit::fixInitializers( std::list< Declaration * > & translationUnit ) {
    202195                        FixInit fixer;
    203 
    204                         // can't use mutateAll, because need to insert declarations at top-level
    205                         // can't use DeclMutator, because sometimes need to insert IfStmt, etc.
    206                         SemanticError errors;
    207                         for ( std::list< Declaration * >::iterator i = translationUnit.begin(); i != translationUnit.end(); ++i ) {
    208                                 try {
    209                                         *i = maybeMutate( *i, fixer );
    210                                         // if (! fixer.staticDtorDecls.empty() ) {
    211                                                 translationUnit.splice( i, fixer.staticDtorDecls );
    212                                         // }
    213                                 } catch( SemanticError &e ) {
    214                                         errors.append( e );
    215                                 } // try
    216                         } // for
    217                         if ( ! errors.isEmpty() ) {
    218                                 throw errors;
    219                         } // if
     196                        mutateAll( translationUnit, fixer );
    220197                }
    221198
     
    445422                                if ( Statement * ctor = ctorInit->get_ctor() ) {
    446423                                        if ( objDecl->get_storageClass() == DeclarationNode::Static ) {
    447                                                 // originally wanted to take advantage of gcc nested functions, but
    448                                                 // we get memory errors with this approach. To remedy this, create a
    449                                                 // global static pointer that is set to refer to the object and make
    450                                                 // the dtor-caller function global so that.
    451                                                 //
    452424                                                // generate:
    453                                                 // T * __objName_static_ptrN;
    454                                                 // void __objName_dtor_atexitN() {
    455                                                 //   __dtor(__objName_static_ptrN);
     425                                                // static bool __objName_uninitialized = true;
     426                                                // if (__objName_uninitialized) {
     427                                                //   __ctor(__objName);
     428                                                //   void dtor_atexit() {
     429                                                //     __dtor(__objName);
     430                                                //   }
     431                                                //   on_exit(dtorOnExit, &__objName);
     432                                                //   __objName_uninitialized = false;
    456433                                                // }
    457                                                 // int f(...) {
    458                                                 //   ...
    459                                                 //   static T __objName;
    460                                                 //   static bool __objName_uninitialized = true;
    461                                                 //   if (__objName_uninitialized) {
    462                                                 //     __objName_ptr = &__objName;
    463                                                 //     __ctor(__objName);
    464                                                 //     on_exit(__objName_dtor_atexitN, &__objName);
    465                                                 //     __objName_uninitialized = false;
    466                                                 //   }
    467                                                 //   ...
    468                                                 // }
    469 
    470                                                 static UniqueName ptrNamer( "_static_ptr" );
    471                                                 static UniqueName dtorCallerNamer( "_dtor_atexit" );
    472 
    473                                                 // T * __objName_ptrN
    474                                                 ObjectDecl * objPtr = new ObjectDecl( objDecl->get_mangleName() + ptrNamer.newName(), DeclarationNode::Static, LinkageSpec::C, 0, new PointerType( Type::Qualifiers(), objDecl->get_type()->clone() ), 0 );
    475                                                 objPtr->fixUniqueId();
    476 
    477                                                 // void __objName_dtor_atexitN(...) {...}
    478                                                 // need to modify dtor call so that it refers to objPtr, since function will be global
    479                                                 Statement * dtorStmt = ctorInit->get_dtor()->clone();
    480                                                 ApplicationExpr * dtor = dynamic_cast< ApplicationExpr * >( InitTweak::getCtorDtorCall( dtorStmt ) );
    481                                                 assert( dtor );
    482                                                 delete dtor->get_args().front();
    483                                                 dtor->get_args().front() = new VariableExpr( objPtr );
    484 
    485                                                 FunctionDecl * dtorCaller = new FunctionDecl( objDecl->get_mangleName() + dtorCallerNamer.newName(), DeclarationNode::Static, LinkageSpec::C, new FunctionType( Type::Qualifiers(), false ), new CompoundStmt( noLabels ), false, false );
    486                                                 dtorCaller->fixUniqueId();
    487                                                 dtorCaller->get_statements()->get_kids().push_back( dtorStmt );
    488 
    489                                                 // static bool __objName_uninitialized = true
     434
     435                                                // generate first line
    490436                                                BasicType * boolType = new BasicType( Type::Qualifiers(), BasicType::Bool );
    491437                                                SingleInit * boolInitExpr = new SingleInit( new ConstantExpr( Constant( boolType->clone(), "1" ) ), noDesignators );
     
    493439                                                isUninitializedVar->fixUniqueId();
    494440
    495                                                 // __objName_static_ptrN = &__objName;
    496                                                 UntypedExpr * ptrAssign = new UntypedExpr( new NameExpr( "?=?" ) );
    497                                                 ptrAssign->get_args().push_back( new VariableExpr( objPtr ) );
    498                                                 ptrAssign->get_args().push_back( new AddressExpr( new VariableExpr( objDecl ) ) );
    499 
    500                                                 // atexit(dtor_atexit);
     441                                                // void dtor_atexit(...) {...}
     442                                                FunctionDecl * dtorCaller = new FunctionDecl( objDecl->get_mangleName() + "_dtor_atexit", DeclarationNode::NoStorageClass, LinkageSpec::C, new FunctionType( Type::Qualifiers(), false ), new CompoundStmt( noLabels ), false, false );
     443                                                dtorCaller->fixUniqueId();
     444                                                dtorCaller->get_statements()->get_kids().push_back( ctorInit->get_dtor()->clone() );
     445
     446                                                // on_exit(dtor_atexit);
    501447                                                UntypedExpr * callAtexit = new UntypedExpr( new NameExpr( "atexit" ) );
    502448                                                callAtexit->get_args().push_back( new VariableExpr( dtorCaller ) );
     
    511457                                                std::list< Statement * > & body = initStmts->get_kids();
    512458                                                body.push_back( ctor );
    513                                                 body.push_back( new ExprStmt( noLabels, ptrAssign ) );
     459                                                body.push_back( new DeclStmt( noLabels, dtorCaller ) );
    514460                                                body.push_back( new ExprStmt( noLabels, callAtexit ) );
    515461                                                body.push_back( new ExprStmt( noLabels, setTrue ) );
     
    519465                                                stmtsToAddAfter.push_back( new DeclStmt( noLabels, isUninitializedVar ) );
    520466                                                stmtsToAddAfter.push_back( ifStmt );
    521 
    522                                                 // add pointer and dtor caller decls to list of decls that will be added into global scope
    523                                                 staticDtorDecls.push_back( objPtr );
    524                                                 staticDtorDecls.push_back( dtorCaller );
    525467                                        } else {
    526468                                                stmtsToAddAfter.push_back( ctor );
  • src/InitTweak/FixInit.h

    r73bf8cf2 raea7168  
    2727  /// replace constructor initializers with expression statements
    2828  /// and unwrap basic C-style initializers
    29         void fix( std::list< Declaration * > & translationUnit, const std::string & name, bool inLibrary );
     29        void fix( std::list< Declaration * > & translationUnit );
    3030} // namespace
    3131
  • src/InitTweak/GenInit.cc

    r73bf8cf2 raea7168  
    2626#include "SymTab/Autogen.h"
    2727#include "GenPoly/PolyMutator.h"
    28 #include "GenPoly/DeclMutator.h"
    2928
    3029namespace InitTweak {
     
    5655          public:
    5756                /// create constructor and destructor statements for object declarations.
    58                 /// the actual call statements will be added in after the resolver has run
    59                 /// so that the initializer expression is only removed if a constructor is found
    60                 /// and the same destructor call is inserted in all of the appropriate locations.
     57                /// Destructors are inserted directly into the code, whereas constructors
     58                /// will be added in after the resolver has run so that the initializer expression
     59                /// is only removed if a constructor is found
    6160                static void generateCtorDtor( std::list< Declaration * > &translationUnit );
     61
     62                CtorDtor() : inFunction( false ) {}
    6263
    6364                virtual DeclarationWithType * mutate( ObjectDecl * );
    6465                virtual DeclarationWithType * mutate( FunctionDecl *functionDecl );
    65                 // should not traverse into any of these declarations to find objects
    66                 // that need to be constructed or destructed
    67                 virtual Declaration* mutate( StructDecl *aggregateDecl ) { return aggregateDecl; }
    68                 virtual Declaration* mutate( UnionDecl *aggregateDecl ) { return aggregateDecl; }
    69                 virtual Declaration* mutate( EnumDecl *aggregateDecl ) { return aggregateDecl; }
    70                 virtual Declaration* mutate( TraitDecl *aggregateDecl ) { return aggregateDecl; }
    71                 virtual TypeDecl* mutate( TypeDecl *typeDecl ) { return typeDecl; }
    72                 virtual Declaration* mutate( TypedefDecl *typeDecl ) { return typeDecl; }
    73 
    74                 virtual Type * mutate( FunctionType *funcType ) { return funcType; }
     66                virtual Declaration* mutate( StructDecl *aggregateDecl );
     67                virtual Declaration* mutate( UnionDecl *aggregateDecl );
     68                virtual Declaration* mutate( EnumDecl *aggregateDecl );
     69                virtual Declaration* mutate( TraitDecl *aggregateDecl );
     70                virtual TypeDecl* mutate( TypeDecl *typeDecl );
     71                virtual Declaration* mutate( TypedefDecl *typeDecl );
     72
     73                virtual Type * mutate( FunctionType *funcType );
    7574
    7675          protected:
    77         };
    78 
    79         class HoistArrayDimension : public GenPoly::DeclMutator {
    80           public:
    81                 typedef GenPoly::DeclMutator Parent;
    82 
    83                 /// hoist dimension from array types in object declaration so that it uses a single
    84                 /// const variable of type size_t, so that side effecting array dimensions are only
    85                 /// computed once.
    86                 static void hoistArrayDimension( std::list< Declaration * > & translationUnit );
    87 
    88           private:
    89                 virtual DeclarationWithType * mutate( ObjectDecl * objectDecl );
    90                 virtual DeclarationWithType * mutate( FunctionDecl *functionDecl );
    91                 // should not traverse into any of these declarations to find objects
    92                 // that need to be constructed or destructed
    93                 virtual Declaration* mutate( StructDecl *aggregateDecl ) { return aggregateDecl; }
    94                 virtual Declaration* mutate( UnionDecl *aggregateDecl ) { return aggregateDecl; }
    95                 virtual Declaration* mutate( EnumDecl *aggregateDecl ) { return aggregateDecl; }
    96                 virtual Declaration* mutate( TraitDecl *aggregateDecl ) { return aggregateDecl; }
    97                 virtual TypeDecl* mutate( TypeDecl *typeDecl ) { return typeDecl; }
    98                 virtual Declaration* mutate( TypedefDecl *typeDecl ) { return typeDecl; }
    99 
    100                 virtual Type* mutate( FunctionType *funcType ) { return funcType; }
    101 
    102                 void hoist( Type * type );
    103 
    104                 DeclarationNode::StorageClass storageclass = DeclarationNode::NoStorageClass;
    105                 bool inFunction = false;
     76                bool inFunction;
    10677        };
    10778
    10879        void genInit( std::list< Declaration * > & translationUnit ) {
    10980                ReturnFixer::makeReturnTemp( translationUnit );
    110                 HoistArrayDimension::hoistArrayDimension( translationUnit );
    11181                CtorDtor::generateCtorDtor( translationUnit );
    11282        }
     
    154124        }
    155125
    156         // precompute array dimension expression, because constructor generation may duplicate it,
    157         // which would be incorrect if it is a side-effecting computation.
    158         void HoistArrayDimension::hoistArrayDimension( std::list< Declaration * > & translationUnit ) {
    159                 HoistArrayDimension hoister;
    160                 hoister.mutateDeclarationList( translationUnit );
    161         }
    162 
    163         DeclarationWithType * HoistArrayDimension::mutate( ObjectDecl * objectDecl ) {
    164                 storageclass = objectDecl->get_storageClass();
    165                 DeclarationWithType * temp = Parent::mutate( objectDecl );
    166                 hoist( objectDecl->get_type() );
    167                 storageclass = DeclarationNode::NoStorageClass;
    168                 return temp;
    169         }
    170 
    171         void HoistArrayDimension::hoist( Type * type ) {
    172                 // if in function, generate const size_t var
    173                 static UniqueName dimensionName( "_array_dim" );
    174                 if ( ArrayType * arrayType = dynamic_cast< ArrayType * >( type ) ) {
    175                         if ( ! inFunction ) return;
    176 
    177                         if ( ! arrayType->get_dimension() ) return; // xxx - recursive call to hoist?
    178 
    179                         // don't need to hoist dimension if it's a constexpr - only need to if there's potential
    180                         // for side effects.
    181                         if ( isConstExpr( arrayType->get_dimension() ) ) return;
    182 
    183                         ObjectDecl * arrayDimension = new ObjectDecl( dimensionName.newName(), storageclass, LinkageSpec::C, 0, SymTab::SizeType->clone(), new SingleInit( arrayType->get_dimension() ) );
    184                         arrayDimension->get_type()->set_isConst( true );
    185 
    186                         arrayType->set_dimension( new VariableExpr( arrayDimension ) );
    187                         addDeclaration( arrayDimension );
    188 
    189                         hoist( arrayType->get_base() );
    190                         return;
    191                 }
    192         }
    193 
    194         DeclarationWithType * HoistArrayDimension::mutate( FunctionDecl *functionDecl ) {
    195                 bool oldInFunc = inFunction;
    196                 inFunction = true;
    197                 DeclarationWithType * decl = Parent::mutate( functionDecl );
    198                 inFunction = oldInFunc;
    199                 return decl;
    200         }
    201126
    202127        void CtorDtor::generateCtorDtor( std::list< Declaration * > & translationUnit ) {
     
    215140
    216141        DeclarationWithType * CtorDtor::mutate( ObjectDecl * objDecl ) {
    217                 // hands off if designated, if @=, or if extern
     142                // hands off if designated or if @=
    218143                if ( tryConstruct( objDecl ) ) {
    219                         // call into genImplicitCall from Autogen.h to generate calls to ctor/dtor
    220                         // for each constructable object
    221                         std::list< Statement * > ctor;
    222                         std::list< Statement * > dtor;
    223 
    224                         InitExpander srcParam( objDecl->get_init() );
    225                         InitExpander nullParam( (Initializer *)NULL );
    226                         SymTab::genImplicitCall( srcParam, new VariableExpr( objDecl ), "?{}", back_inserter( ctor ), objDecl );
    227                         SymTab::genImplicitCall( nullParam, new VariableExpr( objDecl ), "^?{}", front_inserter( dtor ), objDecl, false );
    228 
    229                         // Currently genImplicitCall produces a single Statement - a CompoundStmt
    230                         // which  wraps everything that needs to happen. As such, it's technically
    231                         // possible to use a Statement ** in the above calls, but this is inherently
    232                         // unsafe, so instead we take the slightly less efficient route, but will be
    233                         // immediately informed if somehow the above assumption is broken. In this case,
    234                         // we could always wrap the list of statements at this point with a CompoundStmt,
    235                         // but it seems reasonable at the moment for this to be done by genImplicitCall
    236                         // itself. It is possible that genImplicitCall produces no statements (e.g. if
    237                         // an array type does not have a dimension). In this case, it's fine to ignore
    238                         // the object for the purposes of construction.
    239                         assert( ctor.size() == dtor.size() && ctor.size() <= 1 );
    240                         if ( ctor.size() == 1 ) {
    241                                 // need to remember init expression, in case no ctors exist
    242                                 // if ctor does exist, want to use ctor expression instead of init
    243                                 // push this decision to the resolver
    244                                 assert( dynamic_cast< ImplicitCtorDtorStmt * > ( ctor.front() ) && dynamic_cast< ImplicitCtorDtorStmt * > ( dtor.front() ) );
    245                                 objDecl->set_init( new ConstructorInit( ctor.front(), dtor.front(), objDecl->get_init() ) );
     144                        if ( inFunction ) {
     145                                if ( ArrayType * at = dynamic_cast< ArrayType * >( objDecl->get_type() ) ) {
     146                                        // call into makeArrayFunction from validate.cc to generate calls to ctor/dtor for each element of array
     147                                        // TODO: walk initializer and generate appropriate copy ctor if element has initializer
     148                                        std::list< Expression * > args = makeInitList( objDecl->get_init() );
     149                                        if ( args.empty() ) {
     150                                                std::list< Statement * > ctor;
     151                                                std::list< Statement * > dtor;
     152
     153                                                SymTab::makeArrayFunction( NULL, new VariableExpr( objDecl ), at, "?{}", back_inserter( ctor ) );
     154                                                SymTab::makeArrayFunction( NULL, new VariableExpr( objDecl ), at, "^?{}", front_inserter( dtor ), false );
     155
     156                                                // Currently makeArrayFunction produces a single Statement - a CompoundStmt
     157                                                // which  wraps everything that needs to happen. As such, it's technically
     158                                                // possible to use a Statement ** in the above calls, but this is inherently
     159                                                // unsafe, so instead we take the slightly less efficient route, but will be
     160                                                // immediately informed if somehow the above assumption is broken. In this case,
     161                                                // we could always wrap the list of statements at this point with a CompoundStmt,
     162                                                // but it seems reasonable at the moment for this to be done by makeArrayFunction
     163                                                // itself
     164                                                assert( ctor.size() == 1 && dynamic_cast< ImplicitCtorDtorStmt * >( ctor.front() ) );
     165                                                assert( dtor.size() == 1 && dynamic_cast< ImplicitCtorDtorStmt * >( dtor.front() ) );
     166                                                objDecl->set_init( new ConstructorInit( ctor.front(), dtor.front(), objDecl->get_init() ) );
     167                                        } else {
     168                                                // array came with an initializer list: initialize each element
     169                                                // may have more initializers than elements in the array - need to check at each index that
     170                                                // we haven't exceeded size. This requires precomputing the size because it might be a side-effecting
     171                                                // computation.
     172                                                // may have fewer initializers than eleemnts in the array - need to default construct
     173                                                // remaining elements.
     174                                                // might be able to merge this with the case above.
     175                                        }
     176                                } else {
     177                                        // it's sufficient to attempt to call the ctor/dtor for the given object and its initializer
     178                                        Expression * ctor = makeCtorDtorExpr( "?{}", objDecl, makeInitList( objDecl->get_init() ) );
     179                                        Expression * dtor = makeCtorDtorExpr( "^?{}", objDecl, std::list< Expression * >() );
     180
     181                                        // need to remember init expression, in case no ctors exist
     182                                        // if ctor does exist, want to use ctor expression instead of init
     183                                        // push this decision to the resolver
     184                                        ExprStmt * ctorStmt = new ExprStmt( noLabels, ctor );
     185                                        ExprStmt * dtorStmt = new ExprStmt( noLabels, dtor );
     186                                        objDecl->set_init( new ConstructorInit( new ImplicitCtorDtorStmt( ctorStmt ), new ImplicitCtorDtorStmt( dtorStmt ), objDecl->get_init() ) );
     187                                }
    246188                        }
    247189                }
     
    251193        DeclarationWithType * CtorDtor::mutate( FunctionDecl *functionDecl ) {
    252194                // parameters should not be constructed and destructed, so don't mutate FunctionType
     195                bool oldInFunc = inFunction;
    253196                mutateAll( functionDecl->get_oldDecls(), *this );
     197                inFunction = true;
    254198                functionDecl->set_statements( maybeMutate( functionDecl->get_statements(), *this ) );
     199                inFunction = oldInFunc;
    255200                return functionDecl;
    256201        }
     202
     203        // should not traverse into any of these declarations to find objects
     204        // that need to be constructed or destructed
     205        Declaration* CtorDtor::mutate( StructDecl *aggregateDecl ) { return aggregateDecl; }
     206        Declaration* CtorDtor::mutate( UnionDecl *aggregateDecl ) { return aggregateDecl; }
     207        Declaration* CtorDtor::mutate( EnumDecl *aggregateDecl ) { return aggregateDecl; }
     208        Declaration* CtorDtor::mutate( TraitDecl *aggregateDecl ) { return aggregateDecl; }
     209        TypeDecl* CtorDtor::mutate( TypeDecl *typeDecl ) { return typeDecl; }
     210        Declaration* CtorDtor::mutate( TypedefDecl *typeDecl ) { return typeDecl; }
     211        Type* CtorDtor::mutate( FunctionType *funcType ) { return funcType; }
     212
    257213} // namespace InitTweak
    258214
  • src/InitTweak/InitTweak.cc

    r73bf8cf2 raea7168  
    1 #include <algorithm>
    21#include "InitTweak.h"
    32#include "SynTree/Visitor.h"
     
    2120                };
    2221
    23                 class InitFlattener : public Visitor {
     22                class InitExpander : public Visitor {
    2423                        public:
     24                        InitExpander() {}
    2525                        virtual void visit( SingleInit * singleInit );
    2626                        virtual void visit( ListInit * listInit );
     
    2828                };
    2929
    30                 void InitFlattener::visit( SingleInit * singleInit ) {
     30                void InitExpander::visit( SingleInit * singleInit ) {
    3131                        argList.push_back( singleInit->get_value()->clone() );
    3232                }
    3333
    34                 void InitFlattener::visit( ListInit * listInit ) {
    35                         // flatten nested list inits
    36                         std::list<Initializer*>::iterator it = listInit->begin();
    37                         for ( ; it != listInit->end(); ++it ) {
     34                void InitExpander::visit( ListInit * listInit ) {
     35                        // xxx - for now, assume no nested list inits
     36                        std::list<Initializer*>::iterator it = listInit->begin_initializers();
     37                        for ( ; it != listInit->end_initializers(); ++it ) {
    3838                                (*it)->accept( *this );
    3939                        }
     
    4242
    4343        std::list< Expression * > makeInitList( Initializer * init ) {
    44                 InitFlattener flattener;
    45                 maybeAccept( init, flattener );
    46                 return flattener.argList;
     44                InitExpander expander;
     45                maybeAccept( init, expander );
     46                return expander.argList;
    4747        }
    4848
     
    5353        }
    5454
    55         class InitExpander::ExpanderImpl {
    56         public:
    57                 virtual std::list< Expression * > next( std::list< Expression * > & indices ) = 0;
    58                 virtual Statement * buildListInit( UntypedExpr * callExpr, std::list< Expression * > & indices ) = 0;
    59         };
    60 
    61         class InitImpl : public InitExpander::ExpanderImpl {
    62         public:
    63                 InitImpl( Initializer * init ) : init( init ) {}
    64 
    65                 virtual std::list< Expression * > next( std::list< Expression * > & indices ) {
    66                         // this is wrong, but just a placeholder for now
    67                         // if ( ! flattened ) flatten( indices );
    68                         // return ! inits.empty() ? makeInitList( inits.front() ) : std::list< Expression * >();
    69                         return makeInitList( init );
    70                 }
    71 
    72                 virtual Statement * buildListInit( UntypedExpr * callExpr, std::list< Expression * > & indices );
    73         private:
    74                 Initializer * init;
    75         };
    76 
    77         class ExprImpl : public InitExpander::ExpanderImpl {
    78         public:
    79                 ExprImpl( Expression * expr ) : arg( expr ) {}
    80 
    81                 virtual std::list< Expression * > next( std::list< Expression * > & indices ) {
    82                         std::list< Expression * > ret;
    83                         Expression * expr = maybeClone( arg );
    84                         if ( expr ) {
    85                                 for ( std::list< Expression * >::reverse_iterator it = indices.rbegin(); it != indices.rend(); ++it ) {
    86                                         // go through indices and layer on subscript exprs ?[?]
    87                                         ++it;
    88                                         UntypedExpr * subscriptExpr = new UntypedExpr( new NameExpr( "?[?]") );
    89                                         subscriptExpr->get_args().push_back( expr );
    90                                         subscriptExpr->get_args().push_back( (*it)->clone() );
    91                                         expr = subscriptExpr;
    92                                 }
    93                                 ret.push_back( expr );
    94                         }
    95                         return ret;
    96                 }
    97 
    98                 virtual Statement * buildListInit( UntypedExpr * callExpr, std::list< Expression * > & indices );
    99         private:
    100                 Expression * arg;
    101         };
    102 
    103         InitExpander::InitExpander( Initializer * init ) : expander( new InitImpl( init ) ) {}
    104 
    105         InitExpander::InitExpander( Expression * expr ) : expander( new ExprImpl( expr ) ) {}
    106 
    107         std::list< Expression * > InitExpander::operator*() {
    108                 return cur;
    109         }
    110 
    111         InitExpander & InitExpander::operator++() {
    112                 cur = expander->next( indices );
    113                 return *this;
    114         }
    115 
    116         // use array indices list to build switch statement
    117         void InitExpander::addArrayIndex( Expression * index, Expression * dimension ) {
    118                 indices.push_back( index );
    119                 indices.push_back( dimension );
    120         }
    121 
    122         void InitExpander::clearArrayIndices() {
    123                 indices.clear();
    124         }
    125 
    126         namespace {
    127                 template< typename OutIterator >
    128                 void dothething( UntypedExpr * callExpr, Expression * index, Expression * dimension, Initializer * init, OutIterator out ) {
    129                         UntypedExpr * cond = new UntypedExpr( new NameExpr( "?<?") );
    130                         cond->get_args().push_back( index->clone() );
    131                         cond->get_args().push_back( dimension->clone() );
    132 
    133                         std::list< Expression * > args = makeInitList( init );
    134                         callExpr->get_args().splice( callExpr->get_args().end(), args );
    135 
    136                         *out++ = new IfStmt( noLabels, cond, new ExprStmt( noLabels, callExpr ), NULL );
    137 
    138                         UntypedExpr * increment = new UntypedExpr( new NameExpr( "++?" ) );
    139                         increment->get_args().push_back( new AddressExpr( index->clone() ) );
    140                         *out++ = new ExprStmt( noLabels, increment );
    141                 }
    142 
    143                 template< typename OutIterator >
    144                 void build( UntypedExpr * callExpr, InitExpander::IndexList::iterator idx, InitExpander::IndexList::iterator idxEnd, Initializer * init, OutIterator out ) {
    145                         if ( idx == idxEnd ) return;
    146                         Expression * index = *idx++;
    147                         assert( idx != idxEnd );
    148                         Expression * dimension = *idx++;
    149 
    150                         if ( idx == idxEnd ) {
    151                                 if ( ListInit * listInit = dynamic_cast< ListInit * >( init ) ) {
    152                                         for ( Initializer * init : *listInit ) {
    153                                                 dothething( callExpr->clone(), index, dimension, init, out );
    154                                         }
    155                                 } else {
    156                                         dothething( callExpr->clone(), index, dimension, init, out );
    157                                 }
    158                         } else {
    159                                 std::list< Statement * > branches;
    160 
    161                                 unsigned long cond = 0;
    162                                 ListInit * listInit = dynamic_cast< ListInit * >( init );
    163                                 if ( ! listInit ) {
    164                                         // xxx - this shouldn't be an error, but need a way to
    165                                         // terminate without creating output, so should catch this error
    166                                         throw SemanticError( "unbalanced list initializers" );
    167                                 }
    168                                 for ( Initializer * init : *listInit ) {
    169                                         Expression * condition;
    170                                         // check for designations
    171                                         // if ( init-> ) {
    172                                                 condition = new ConstantExpr( Constant::from_ulong( cond ) );
    173                                                 ++cond;
    174                                         // } else {
    175                                         //      condition = // ... take designation
    176                                         //      cond = // ... take designation+1
    177                                         // }
    178                                         std::list< Statement * > stmts;
    179                                         build( callExpr, idx, idxEnd, init, back_inserter( stmts ) );
    180                                         CaseStmt * caseStmt = new CaseStmt( noLabels, condition, stmts );
    181                                         branches.push_back( caseStmt );
    182                                 }
    183                                 *out++ = new SwitchStmt( noLabels, index->clone(), branches );
    184                         }
    185                 }
    186         }
    187 
    188         // if array came with an initializer list: initialize each element
    189         // may have more initializers than elements in the array - need to check at each index that
    190         // we haven't exceeded size.
    191         // may have fewer initializers than elements in the array - need to default construct
    192         // remaining elements.
    193         // To accomplish this, generate switch statement, consuming all of expander's elements
    194         Statement * InitImpl::buildListInit( UntypedExpr * dst, std::list< Expression * > & indices ) {
    195                 if ( ! init ) return NULL;
    196                 std::list< Statement * > results;
    197                 build( dst, indices.begin(), indices.end(), init, back_inserter( results ) );
    198                 assert( results.size() <= 1 );
    199                 if ( results.empty() ) {
    200                         return NULL;
    201                 } else {
    202                         init = NULL; // init was consumed in creating the list init
    203                         return results.front();
    204                 }
    205                 return ! results.empty() ? results.front() : NULL;
    206         }
    207 
    208         Statement * ExprImpl::buildListInit( UntypedExpr * dst, std::list< Expression * > & indices ) {
    209                 return NULL;
    210         }
    211 
    212         Statement * InitExpander::buildListInit( UntypedExpr * dst ) {
    213                 return expander->buildListInit( dst, indices );
    214         }
    215 
    21655        bool tryConstruct( ObjectDecl * objDecl ) {
    21756                return ! LinkageSpec::isBuiltin( objDecl->get_linkage() ) &&
    21857                        (objDecl->get_init() == NULL ||
    21958                                ( objDecl->get_init() != NULL && objDecl->get_init()->get_maybeConstructed() )) &&
    220                         ! isDesignated( objDecl->get_init() )
    221                         && objDecl->get_storageClass() != DeclarationNode::Extern;
    222         }
    223 
    224         class CallFinder : public Visitor {
    225         public:
    226                 typedef Visitor Parent;
    227                 CallFinder( const std::list< std::string > & names ) : names( names ) {}
    228 
    229                 virtual void visit( ApplicationExpr * appExpr ) {
    230                         handleCallExpr( appExpr );
    231                 }
    232 
    233                 virtual void visit( UntypedExpr * untypedExpr ) {
    234                         handleCallExpr( untypedExpr );
    235                 }
    236 
    237                 std::list< Expression * > * matches;
    238         private:
    239                 const std::list< std::string > names;
    240 
    241                 template< typename CallExpr >
    242                 void handleCallExpr( CallExpr * expr ) {
    243                         Parent::visit( expr );
    244                         std::string fname = getFunctionName( expr );
    245                         if ( std::find( names.begin(), names.end(), fname ) != names.end() ) {
    246                                 matches->push_back( expr );
    247                         }
    248                 }
    249         };
    250 
    251         void collectCtorDtorCalls( Statement * stmt, std::list< Expression * > & matches ) {
    252                 static CallFinder finder( std::list< std::string >{ "?{}", "^?{}" } );
    253                 finder.matches = &matches;
    254                 maybeAccept( stmt, finder );
     59                        ! isDesignated( objDecl->get_init() );
    25560        }
    25661
    25762        Expression * getCtorDtorCall( Statement * stmt ) {
    258                 std::list< Expression * > matches;
    259                 collectCtorDtorCalls( stmt, matches );
    260                 assert( matches.size() <= 1 );
    261                 return matches.size() == 1 ? matches.front() : NULL;
    262         }
    263 
    264         namespace {
    265                 VariableExpr * getCalledFunction( ApplicationExpr * appExpr ) {
    266                         assert( appExpr );
    267                         // xxx - it's possible this can be other things, e.g. MemberExpr, so this is insufficient
    268                         return dynamic_cast< VariableExpr * >( appExpr->get_function() );
     63                if ( stmt == NULL ) return NULL;
     64                if ( ExprStmt * exprStmt = dynamic_cast< ExprStmt * >( stmt ) ) {
     65                        return exprStmt->get_expr();
     66                } else if ( CompoundStmt * compoundStmt = dynamic_cast< CompoundStmt * >( stmt ) ) {
     67                        // could also be a compound statement with a loop, in the case of an array
     68                        if( compoundStmt->get_kids().size() == 2 ) {
     69                                // loop variable and loop
     70                                ForStmt * forStmt = dynamic_cast< ForStmt * >( compoundStmt->get_kids().back() );
     71                                assert( forStmt && forStmt->get_body() );
     72                                return getCtorDtorCall( forStmt->get_body() );
     73                        } else if ( compoundStmt->get_kids().size() == 1 ) {
     74                                // should be the call statement, but in any case there's only one option
     75                                return getCtorDtorCall( compoundStmt->get_kids().front() );
     76                        } else {
     77                                assert( false && "too many statements in compoundStmt for getCtorDtorCall" );
     78                        }
     79                } if ( ImplicitCtorDtorStmt * impCtorDtorStmt = dynamic_cast< ImplicitCtorDtorStmt * > ( stmt ) ) {
     80                        return getCtorDtorCall( impCtorDtorStmt->get_callStmt() );
     81                } else {
     82                        // should never get here
     83                        assert( false && "encountered unknown call statement" );
    26984                }
    27085        }
    27186
    272         ApplicationExpr * isIntrinsicCallExpr( Expression * expr ) {
    273                 ApplicationExpr * appExpr = dynamic_cast< ApplicationExpr * >( expr );
    274                 if ( ! appExpr ) return NULL;
    275                 VariableExpr * function = getCalledFunction( appExpr );
     87        bool isInstrinsicSingleArgCallStmt( Statement * stmt ) {
     88                Expression * callExpr = getCtorDtorCall( stmt );
     89                if ( ! callExpr ) return false;
     90                ApplicationExpr * appExpr = dynamic_cast< ApplicationExpr * >( callExpr );
     91                assert( appExpr );
     92                VariableExpr * function = dynamic_cast< VariableExpr * >( appExpr->get_function() );
    27693                assert( function );
    27794                // check for Intrinsic only - don't want to remove all overridable ctor/dtors because autogenerated ctor/dtor
    27895                // will call all member dtors, and some members may have a user defined dtor.
    279                 return function->get_var()->get_linkage() == LinkageSpec::Intrinsic ? appExpr : NULL;
    280         }
    281 
    282         bool isInstrinsicSingleArgCallStmt( Statement * stmt ) {
    283                 std::list< Expression * > callExprs;
    284                 collectCtorDtorCalls( stmt, callExprs );
    285                 // if ( callExprs.empty() ) return false; // xxx - do I still need this check?
    286                 return std::all_of( callExprs.begin(), callExprs.end(), []( Expression * callExpr ){
    287                         if ( ApplicationExpr * appExpr = isIntrinsicCallExpr( callExpr ) ) {
    288                                 assert( ! appExpr->get_function()->get_results().empty() );
    289                                 FunctionType *funcType = GenPoly::getFunctionType( appExpr->get_function()->get_results().front() );
    290                                 assert( funcType );
    291                                 return funcType->get_parameters().size() == 1;
    292                         }
    293                         return false;
    294                 });
     96                FunctionType * funcType = GenPoly::getFunctionType( function->get_var()->get_type() );
     97                assert( funcType );
     98                return function->get_var()->get_linkage() == LinkageSpec::Intrinsic && funcType->get_parameters().size() == 1;
    29599        }
    296100
     
    356160                else return NULL;
    357161        }
    358 
    359         class ConstExprChecker : public Visitor {
    360         public:
    361                 ConstExprChecker() : isConstExpr( true ) {}
    362 
    363                 virtual void visit( ApplicationExpr *applicationExpr ) { isConstExpr = false; }
    364                 virtual void visit( UntypedExpr *untypedExpr ) { isConstExpr = false; }
    365                 virtual void visit( NameExpr *nameExpr ) { isConstExpr = false; }
    366                 virtual void visit( CastExpr *castExpr ) { isConstExpr = false; }
    367                 virtual void visit( LabelAddressExpr *labAddressExpr ) { isConstExpr = false; }
    368                 virtual void visit( UntypedMemberExpr *memberExpr ) { isConstExpr = false; }
    369                 virtual void visit( MemberExpr *memberExpr ) { isConstExpr = false; }
    370                 virtual void visit( VariableExpr *variableExpr ) { isConstExpr = false; }
    371                 virtual void visit( ConstantExpr *constantExpr ) { /* bottom out */ }
    372                 // these might be okay?
    373                 // virtual void visit( SizeofExpr *sizeofExpr );
    374                 // virtual void visit( AlignofExpr *alignofExpr );
    375                 // virtual void visit( UntypedOffsetofExpr *offsetofExpr );
    376                 // virtual void visit( OffsetofExpr *offsetofExpr );
    377                 // virtual void visit( OffsetPackExpr *offsetPackExpr );
    378                 // virtual void visit( AttrExpr *attrExpr );
    379                 // virtual void visit( CommaExpr *commaExpr );
    380                 // virtual void visit( LogicalExpr *logicalExpr );
    381                 // virtual void visit( ConditionalExpr *conditionalExpr );
    382                 virtual void visit( TupleExpr *tupleExpr ) { isConstExpr = false; }
    383                 virtual void visit( SolvedTupleExpr *tupleExpr ) { isConstExpr = false; }
    384                 virtual void visit( TypeExpr *typeExpr ) { isConstExpr = false; }
    385                 virtual void visit( AsmExpr *asmExpr ) { isConstExpr = false; }
    386                 virtual void visit( UntypedValofExpr *valofExpr ) { isConstExpr = false; }
    387                 virtual void visit( CompoundLiteralExpr *compLitExpr ) { isConstExpr = false; }
    388 
    389                 bool isConstExpr;
    390         };
    391 
    392         bool isConstExpr( Expression * expr ) {
    393                 if ( expr ) {
    394                         ConstExprChecker checker;
    395                         expr->accept( checker );
    396                         return checker.isConstExpr;
    397                 }
    398                 return true;
    399         }
    400 
    401         bool isConstExpr( Initializer * init ) {
    402                 if ( init ) {
    403                         ConstExprChecker checker;
    404                         init->accept( checker );
    405                         return checker.isConstExpr;
    406                 } // if
    407                 // for all intents and purposes, no initializer means const expr
    408                 return true;
    409         }
    410 
    411162}
  • src/InitTweak/InitTweak.h

    r73bf8cf2 raea7168  
    2626// helper functions for initialization
    2727namespace InitTweak {
    28         /// transform Initializer into an argument list that can be passed to a call expression
    29         std::list< Expression * > makeInitList( Initializer * init );
     28  /// transform Initializer into an argument list that can be passed to a call expression
     29  std::list< Expression * > makeInitList( Initializer * init );
    3030
    31         /// True if the resolver should try to construct objDecl
    32         bool tryConstruct( ObjectDecl * objDecl );
     31  /// True if the resolver should try to construct objDecl
     32  bool tryConstruct( ObjectDecl * objDecl );
    3333
    34         /// True if the Initializer contains designations
    35         bool isDesignated( Initializer * init );
     34  /// True if the Initializer contains designations
     35  bool isDesignated( Initializer * init );
    3636
    37   /// Non-Null if expr is a call expression whose target function is intrinsic
    38   ApplicationExpr * isIntrinsicCallExpr( Expression * expr );
     37  /// True if stmt is a call statement where the function called is intrinsic and takes one parameter.
     38  /// Intended to be used for default ctor/dtor calls, but might have use elsewhere.
     39  /// Currently has assertions that make it less than fully general.
     40  bool isInstrinsicSingleArgCallStmt( Statement * expr );
    3941
    40         /// True if stmt is a call statement where the function called is intrinsic and takes one parameter.
    41         /// Intended to be used for default ctor/dtor calls, but might have use elsewhere.
    42         /// Currently has assertions that make it less than fully general.
    43         bool isInstrinsicSingleArgCallStmt( Statement * expr );
     42  /// get the Ctor/Dtor call expression from a Statement that looks like a generated ctor/dtor call
     43  Expression * getCtorDtorCall( Statement * stmt );
    4444
    45         /// get all Ctor/Dtor call expressions from a Statement
    46         void collectCtorDtorCalls( Statement * stmt, std::list< Expression * > & matches );
     45  /// returns the name of the function being called
     46  std::string getFunctionName( Expression * expr );
    4747
    48         /// get the Ctor/Dtor call expression from a Statement that looks like a generated ctor/dtor call
    49         Expression * getCtorDtorCall( Statement * stmt );
     48  /// returns the argument to a call expression in position N indexed from 0
     49  Expression *& getCallArg( Expression * callExpr, unsigned int pos );
    5050
    51         /// returns the name of the function being called
    52         std::string getFunctionName( Expression * expr );
     51  /// returns the base type of a PointerType or ArrayType, else returns NULL
     52  Type * getPointerBase( Type * );
    5353
    54         /// returns the argument to a call expression in position N indexed from 0
    55         Expression *& getCallArg( Expression * callExpr, unsigned int pos );
    56 
    57         /// returns the base type of a PointerType or ArrayType, else returns NULL
    58         Type * getPointerBase( Type * );
    59 
    60         /// returns the argument if it is a PointerType or ArrayType, else returns NULL
    61         Type * isPointerType( Type * );
    62 
    63         /// returns true if expr is trivially a compile-time constant
    64         bool isConstExpr( Expression * expr );
    65         bool isConstExpr( Initializer * init );
    66 
    67         class InitExpander {
    68         public:
    69                 // expand by stepping through init to get each list of arguments
    70                 InitExpander( Initializer * init );
    71 
    72                 // always expand to expr
    73                 InitExpander( Expression * expr );
    74 
    75                 // iterator-like interface
    76                 std::list< Expression * > operator*();
    77                 InitExpander & operator++();
    78 
    79                 // builds statement which has the same semantics as a C-style list initializer
    80                 // (for array initializers) using callExpr as the base expression to perform initialization
    81                 Statement * buildListInit( UntypedExpr * callExpr );
    82                 void addArrayIndex( Expression * index, Expression * dimension );
    83                 void clearArrayIndices();
    84 
    85                 class ExpanderImpl;
    86         private:
    87                 std::shared_ptr< ExpanderImpl > expander;
    88                 std::list< Expression * > cur;
    89 
    90                 // invariant: list of size 2N (elements come in pairs [index, dimension])
    91                 typedef std::list< Expression * > IndexList;
    92                 IndexList indices;
    93         };
     54  /// returns the argument if it is a PointerType or ArrayType, else returns NULL
     55  Type * isPointerType( Type * );
    9456} // namespace
    9557
  • src/ResolvExpr/Resolver.cc

    r73bf8cf2 raea7168  
    2424#include "SynTree/Initializer.h"
    2525#include "SymTab/Indexer.h"
    26 #include "SymTab/Autogen.h"
    2726#include "Common/utility.h"
    2827#include "InitTweak/InitTweak.h"
     
    4241
    4342                virtual void visit( ArrayType * at );
    44                 virtual void visit( PointerType * at );
    4543
    4644                virtual void visit( ExprStmt *exprStmt );
     
    5452                virtual void visit( BranchStmt *branchStmt );
    5553                virtual void visit( ReturnStmt *returnStmt );
     54                virtual void visit( ImplicitCtorDtorStmt * impCtorDtorStmt );
    5655
    5756                virtual void visit( SingleInit *singleInit );
     
    6059          private:
    6160        typedef std::list< Initializer * >::iterator InitIterator;
    62 
    63                 template< typename PtrType >
    64                 void handlePtrType( PtrType * type );
    6561
    6662          void resolveAggrInit( AggregateDecl *, InitIterator &, InitIterator & );
     
    196192        }
    197193
    198         template< typename PtrType >
    199         void Resolver::handlePtrType( PtrType * type ) {
    200                 if ( type->get_dimension() ) {
    201                         CastExpr *castExpr = new CastExpr( type->get_dimension(), SymTab::SizeType->clone() );
     194        void Resolver::visit( ArrayType * at ) {
     195                if ( at->get_dimension() ) {
     196                        BasicType arrayLenType = BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt );
     197                        CastExpr *castExpr = new CastExpr( at->get_dimension(), arrayLenType.clone() );
    202198                        Expression *newExpr = findSingleExpression( castExpr, *this );
    203                         delete type->get_dimension();
    204                         type->set_dimension( newExpr );
    205                 }
    206         }
    207 
    208         void Resolver::visit( ArrayType * at ) {
    209                 handlePtrType( at );
     199                        delete at->get_dimension();
     200                        at->set_dimension( newExpr );
     201                }
    210202                Visitor::visit( at );
    211         }
    212 
    213         void Resolver::visit( PointerType * pt ) {
    214                 handlePtrType( pt );
    215                 Visitor::visit( pt );
    216203        }
    217204
     
    435422
    436423        void Resolver::visit( ListInit * listInit ) {
    437                 InitIterator iter = listInit->begin();
    438                 InitIterator end = listInit->end();
     424                InitIterator iter = listInit->begin_initializers();
     425                InitIterator end = listInit->end_initializers();
    439426
    440427                if ( ArrayType * at = dynamic_cast< ArrayType * >( initContext ) ) {
     
    538525                        ctorInit->set_ctor( NULL );
    539526                }
    540                 if ( InitTweak::isInstrinsicSingleArgCallStmt( ctorInit->get_dtor() ) ) {
     527                if ( InitTweak::isInstrinsicSingleArgCallStmt( ctorInit->get_ctor() ) ) {
    541528                        delete ctorInit->get_dtor();
    542529                        ctorInit->set_dtor( NULL );
    543530                }
     531        }
     532
     533        void Resolver::visit( ImplicitCtorDtorStmt * impCtorDtorStmt ) {
     534                // before resolving ctor/dtor, need to remove type qualifiers from the first argument (the object being constructed).
     535                // Do this through a cast expression to greatly simplify the code.
     536                Expression * callExpr = InitTweak::getCtorDtorCall( impCtorDtorStmt );
     537                assert( callExpr );
     538                Expression *& constructee = InitTweak::getCallArg( callExpr, 0 );
     539                Type * type = 0;
     540
     541                // need to find the type of the first argument, which is unfortunately not uniform since array construction
     542                // includes an untyped '+' expression.
     543                if ( UntypedExpr * plusExpr = dynamic_cast< UntypedExpr * >( constructee ) ) {
     544                        // constructee is <array>+<index>
     545                        // get Variable <array>, then get the base type of the VariableExpr - this is the type that needs to be fixed
     546                        Expression * arr = InitTweak::getCallArg( plusExpr, 0 );
     547                        assert( dynamic_cast< VariableExpr * >( arr ) || dynamic_cast< MemberExpr *>( arr ) );
     548                        assert( arr && arr->get_results().size() == 1 );
     549                        type = arr->get_results().front()->clone();
     550                } else {
     551                        // otherwise, constructing a plain object, which means the object's address is being taken.
     552                        // Need to get the type of the VariableExpr object, because the AddressExpr is rebuilt and uses the
     553                        // type of the VariableExpr to do so.
     554                        assert( constructee->get_results().size() == 1 );
     555                        AddressExpr * addrExpr = dynamic_cast< AddressExpr * > ( constructee );
     556                        assert( addrExpr && addrExpr->get_results().size() == 1 );
     557                        type = addrExpr->get_results().front()->clone();
     558                }
     559                // cast to T* with qualifiers removed.
     560                // unfortunately, lvalue is considered a qualifier. For AddressExpr to resolve, its argument
     561                // must have an lvalue qualified type, so remove all qualifiers except lvalue. If we ever
     562                // remove lvalue as a qualifier, this can change to
     563                //   type->get_qualifiers() = Type::Qualifiers();
     564                Type * base = InitTweak::getPointerBase( type );
     565                assert( base );
     566                base->get_qualifiers() -= Type::Qualifiers(true, true, true, false, true, true);
     567                // if pointer has lvalue qualifier, cast won't appear in output
     568                type->set_isLvalue( false );
     569                constructee = new CastExpr( constructee, type );
     570
     571                // finally, resolve the ctor/dtor
     572                impCtorDtorStmt->get_callStmt()->accept( *this );
    544573        }
    545574} // namespace ResolvExpr
  • src/SymTab/Autogen.cc

    r73bf8cf2 raea7168  
    2626
    2727namespace SymTab {
    28         Type * SizeType = 0;
    29 
    3028        class AutogenerateRoutines : public Visitor {
    3129                public:
     
    6159        bool isUnnamedBitfield( ObjectDecl * obj ) {
    6260                return obj != NULL && obj->get_name() == "" && obj->get_bitfieldWidth() != NULL;
     61        }
     62
     63        template< typename OutputIterator >
     64        void makeScalarFunction( Expression *src, ObjectDecl *dstParam, DeclarationWithType *member, std::string fname, OutputIterator out ) {
     65                ObjectDecl *obj = dynamic_cast<ObjectDecl *>( member );
     66                // unnamed bit fields are not copied as they cannot be accessed
     67                if ( isUnnamedBitfield( obj ) ) return;
     68
     69                // want to be able to generate assignment, ctor, and dtor generically,
     70                // so fname is either ?=?, ?{}, or ^?{}
     71                UntypedExpr *fExpr = new UntypedExpr( new NameExpr( fname ) );
     72
     73                UntypedExpr *derefExpr = new UntypedExpr( new NameExpr( "*?" ) );
     74                derefExpr->get_args().push_back( new VariableExpr( dstParam ) );
     75
     76                // do something special for unnamed members
     77                Expression *dstselect = new AddressExpr( new MemberExpr( member, derefExpr ) );
     78                fExpr->get_args().push_back( dstselect );
     79
     80                if ( src ) {
     81                        fExpr->get_args().push_back( src );
     82                }
     83
     84                Statement * callStmt = new ExprStmt( noLabels, fExpr );
     85                if ( (fname == "?{}" || fname == "^?{}") && ( !obj || ( obj && obj->get_bitfieldWidth() == NULL ) ) ) {
     86                        // implicitly generated ctor/dtor calls should be wrapped
     87                        // so that later passes are aware they were generated.
     88                        // xxx - don't mark as an implicit ctor/dtor if obj is a bitfield,
     89                        // because this causes the address to be taken at codegen, which is illegal in C.
     90                        callStmt = new ImplicitCtorDtorStmt( callStmt );
     91                }
     92                *out++ = callStmt;
    6393        }
    6494
     
    189219                }
    190220
    191                 InitTweak::InitExpander srcParam( src );
    192 
    193221                // assign to destination (and return value if generic)
    194                 UntypedExpr *derefExpr = new UntypedExpr( new NameExpr( "*?" ) );
    195                 derefExpr->get_args().push_back( new VariableExpr( dstParam ) );
    196                 Expression *dstselect = new MemberExpr( field, derefExpr );
    197                 genImplicitCall( srcParam, dstselect, func->get_name(), back_inserter( func->get_statements()->get_kids() ), field, forward );
    198 
    199                 if ( isGeneric && returnVal ) {
    200                         UntypedExpr *derefRet = new UntypedExpr( new NameExpr( "*?" ) );
    201                         derefRet->get_args().push_back( new VariableExpr( returnVal ) );
    202                         Expression *retselect = new MemberExpr( field, derefRet );
    203                         genImplicitCall( srcParam, retselect, func->get_name(), back_inserter( func->get_statements()->get_kids() ), field, forward );
     222                if ( ArrayType *array = dynamic_cast< ArrayType * >( field->get_type() ) ) {
     223                        UntypedExpr *derefExpr = new UntypedExpr( new NameExpr( "*?" ) );
     224                        derefExpr->get_args().push_back( new VariableExpr( dstParam ) );
     225                        Expression *dstselect = new MemberExpr( field, derefExpr );
     226
     227                        makeArrayFunction( src, dstselect, array, func->get_name(), back_inserter( func->get_statements()->get_kids() ), forward );
     228                        if ( isGeneric && returnVal ) {
     229                                UntypedExpr *derefRet = new UntypedExpr( new NameExpr( "*?" ) );
     230                                derefRet->get_args().push_back( new VariableExpr( returnVal ) );
     231                                Expression *retselect = new MemberExpr( field, derefRet );
     232
     233                                makeArrayFunction( src, retselect, array, func->get_name(), back_inserter( func->get_statements()->get_kids() ), forward );
     234                        }
     235                } else {
     236                        makeScalarFunction( src, dstParam, field, func->get_name(), back_inserter( func->get_statements()->get_kids() ) );
     237                        if ( isGeneric && returnVal ) makeScalarFunction( src, returnVal, field, func->get_name(), back_inserter( func->get_statements()->get_kids() ) );
    204238                } // if
    205239        }
  • src/SymTab/Autogen.h

    r73bf8cf2 raea7168  
    2222#include "SynTree/Declaration.h"
    2323#include "SynTree/Initializer.h"
    24 #include "InitTweak/InitTweak.h"
    2524
    2625namespace SymTab {
    27         /// Generates assignment operators, constructors, and destructor for aggregate types as required
    28         void autogenerateRoutines( std::list< Declaration * > &translationUnit );
     26  /// Generates assignment operators, constructors, and destructor for aggregate types as required
     27  void autogenerateRoutines( std::list< Declaration * > &translationUnit );
    2928
    30         /// returns true if obj's name is the empty string and it has a bitfield width
    31         bool isUnnamedBitfield( ObjectDecl * obj );
     29  // originally makeArrayAssignment - changed to Function because it is now used for ctors and dtors as well
     30  // admittedly not a great name change. This used to live in Validate.cc, but has been moved so it can be reused elsewhere
    3231
    33         /// size_t type - set when size_t typedef is seen. Useful in a few places,
    34         /// such as in determining array dimension type
    35         extern Type * SizeType;
     32  /// Store in out a loop which calls fname on each element of the array with srcParam and dstParam as arguments.
     33  /// If forward is true, loop goes from 0 to N-1, else N-1 to 0
     34  template< typename OutputIterator >
     35  void makeArrayFunction( Expression *srcParam, Expression *dstParam, ArrayType *array, std::string fname, OutputIterator out, bool forward = true ) {
     36    static UniqueName indexName( "_index" );
    3637
    37         /// inserts into out a generated call expression to function fname with arguments dstParam and srcParam. Intended to be used with generated ?=?, ?{}, and ^?{} calls.
    38         template< typename OutputIterator >
    39         void genCall( InitTweak::InitExpander & srcParam, Expression * dstParam, const std::string & fname, OutputIterator out, Type * type, bool addCast = false, bool forward = true );
     38    // for a flexible array member nothing is done -- user must define own assignment
     39    if ( ! array->get_dimension() ) return;
    4040
    41         /// inserts into out a generated call expression to function fname with arguments dstParam and srcParam. Should only be called with non-array types.
    42         template< typename OutputIterator >
    43         void genScalarCall( InitTweak::InitExpander & srcParam, Expression *dstParam, const std::string & fname, OutputIterator out, Type * type, bool addCast = false ) {
    44                 // want to be able to generate assignment, ctor, and dtor generically,
    45                 // so fname is either ?=?, ?{}, or ^?{}
    46                 UntypedExpr *fExpr = new UntypedExpr( new NameExpr( fname ) );
    47 
    48                 // do something special for unnamed members
    49                 dstParam = new AddressExpr( dstParam );
    50                 if ( addCast ) {
    51                         // cast to T* with qualifiers removed, so that qualified objects can be constructed
    52                         // and destructed with the same functions as non-qualified objects.
    53                         // unfortunately, lvalue is considered a qualifier. For AddressExpr to resolve, its argument
    54                         // must have an lvalue qualified type, so remove all qualifiers except lvalue. If we ever
    55                         // remove lvalue as a qualifier, this can change to
    56                         //   type->get_qualifiers() = Type::Qualifiers();
    57                         assert( type );
    58                         Type * castType = type->clone();
    59                         castType->get_qualifiers() -= Type::Qualifiers(true, true, true, false, true, true);
    60                         castType->set_isLvalue( true ); // xxx - might not need this
    61                         dstParam = new CastExpr( dstParam, new PointerType( Type::Qualifiers(), castType ) );
    62                 }
    63                 fExpr->get_args().push_back( dstParam );
    64 
    65     Statement * listInit = srcParam.buildListInit( fExpr );
    66     if ( listInit ) {
    67       *out++ = listInit;
     41    Expression * begin, * end, * update, * cmp;
     42    if ( forward ) {
     43      // generate: for ( int i = 0; i < 0; ++i )
     44      begin = new NameExpr( "0" );
     45      end = array->get_dimension()->clone();
     46      cmp = new NameExpr( "?<?" );
     47      update = new NameExpr( "++?" );
     48    } else {
     49      // generate: for ( int i = N-1; i >= 0; --i )
     50      begin = new UntypedExpr( new NameExpr( "?-?" ) );
     51      ((UntypedExpr*)begin)->get_args().push_back( array->get_dimension()->clone() );
     52      ((UntypedExpr*)begin)->get_args().push_back( new NameExpr( "1" ) );
     53      end = new NameExpr( "0" );
     54      cmp = new NameExpr( "?>=?" );
     55      update = new NameExpr( "--?" );
    6856    }
    6957
    70     std::list< Expression * > args = *++srcParam;
    71     fExpr->get_args().splice( fExpr->get_args().end(), args );
     58    ObjectDecl *index = new ObjectDecl( indexName.newName(), DeclarationNode::NoStorageClass, LinkageSpec::C, 0, new BasicType( Type::Qualifiers(), BasicType::SignedInt ), NULL );
    7259
    73                 *out++ = new ExprStmt( noLabels, fExpr );
     60    UntypedExpr *init = new UntypedExpr( new NameExpr( "?=?" ) );
     61    init->get_args().push_back( new AddressExpr( new VariableExpr( index ) ) );
     62    init->get_args().push_back( begin );
     63    index->set_init( new SingleInit( init, std::list<Expression*>() ) );
    7464
    75     srcParam.clearArrayIndices();
    76         }
     65    UntypedExpr *cond = new UntypedExpr( cmp );
     66    cond->get_args().push_back( new VariableExpr( index ) );
     67    cond->get_args().push_back( end );
    7768
    78         /// Store in out a loop which calls fname on each element of the array with srcParam and dstParam as arguments.
    79         /// If forward is true, loop goes from 0 to N-1, else N-1 to 0
    80         template< typename OutputIterator >
    81         void genArrayCall( InitTweak::InitExpander & srcParam, Expression *dstParam, const std::string & fname, OutputIterator out, ArrayType *array, bool addCast = false, bool forward = true ) {
    82                 static UniqueName indexName( "_index" );
     69    UntypedExpr *inc = new UntypedExpr( update );
     70    inc->get_args().push_back( new AddressExpr( new VariableExpr( index ) ) );
    8371
    84                 // for a flexible array member nothing is done -- user must define own assignment
    85                 if ( ! array->get_dimension() ) return ;
     72    // want to be able to generate assignment, ctor, and dtor generically,
     73    // so fname is either ?=?, ?{}, or ^?{}
     74    UntypedExpr *fExpr = new UntypedExpr( new NameExpr( fname ) );
    8675
    87                 Expression * begin, * end, * update, * cmp;
    88                 if ( forward ) {
    89                         // generate: for ( int i = 0; i < 0; ++i )
    90                         begin = new NameExpr( "0" );
    91                         end = array->get_dimension()->clone();
    92                         cmp = new NameExpr( "?<?" );
    93                         update = new NameExpr( "++?" );
    94                 } else {
    95                         // generate: for ( int i = N-1; i >= 0; --i )
    96                         begin = new UntypedExpr( new NameExpr( "?-?" ) );
    97                         ((UntypedExpr*)begin)->get_args().push_back( array->get_dimension()->clone() );
    98                         ((UntypedExpr*)begin)->get_args().push_back( new NameExpr( "1" ) );
    99                         end = new NameExpr( "0" );
    100                         cmp = new NameExpr( "?>=?" );
    101                         update = new NameExpr( "--?" );
    102                 }
     76    UntypedExpr *dstIndex = new UntypedExpr( new NameExpr( "?+?" ) );
     77    dstIndex->get_args().push_back( dstParam );
     78    dstIndex->get_args().push_back( new VariableExpr( index ) );
     79    fExpr->get_args().push_back( dstIndex );
    10380
    104                 ObjectDecl *index = new ObjectDecl( indexName.newName(), DeclarationNode::NoStorageClass, LinkageSpec::C, 0, new BasicType( Type::Qualifiers(), BasicType::SignedInt ), NULL );
     81    // srcParam is NULL for default ctor/dtor
     82    if ( srcParam ) {
     83      UntypedExpr *srcIndex = new UntypedExpr( new NameExpr( "?[?]" ) );
     84      srcIndex->get_args().push_back( srcParam );
     85      srcIndex->get_args().push_back( new VariableExpr( index ) );
     86      fExpr->get_args().push_back( srcIndex );
     87    }
    10588
    106                 UntypedExpr *init = new UntypedExpr( new NameExpr( "?=?" ) );
    107                 init->get_args().push_back( new AddressExpr( new VariableExpr( index ) ) );
    108                 init->get_args().push_back( begin );
    109                 index->set_init( new SingleInit( init, std::list<Expression*>() ) );
     89    std::list<Statement *> initList;
     90    CompoundStmt * block = new CompoundStmt( noLabels );
     91    block->get_kids().push_back( new DeclStmt( noLabels, index ) );
     92    block->get_kids().push_back( new ForStmt( noLabels, initList, cond, inc, new ExprStmt( noLabels, fExpr ) ) );
    11093
    111                 UntypedExpr *cond = new UntypedExpr( cmp );
    112                 cond->get_args().push_back( new VariableExpr( index ) );
    113                 cond->get_args().push_back( end );
    114 
    115                 UntypedExpr *inc = new UntypedExpr( update );
    116                 inc->get_args().push_back( new AddressExpr( new VariableExpr( index ) ) );
    117 
    118                 UntypedExpr *dstIndex = new UntypedExpr( new NameExpr( "?[?]" ) );
    119                 dstIndex->get_args().push_back( dstParam );
    120                 dstIndex->get_args().push_back( new VariableExpr( index ) );
    121                 dstParam = dstIndex;
    122 
    123                 // srcParam must keep track of the array indices to build the
    124                 // source parameter and/or array list initializer
    125                 srcParam.addArrayIndex( new VariableExpr( index ), array->get_dimension()->clone() );
    126 
    127                 // if ( srcParam ) {
    128                 //      UntypedExpr *srcIndex = new UntypedExpr( new NameExpr( "?[?]" ) );
    129                 //      srcIndex->get_args().push_back( srcParam );
    130                 //      srcIndex->get_args().push_back( new VariableExpr( index ) );
    131                 //      srcParam = srcIndex;
    132                 // }
    133 
    134                 // for stmt's body, eventually containing call
    135                 CompoundStmt * body = new CompoundStmt( noLabels );
    136                 genCall( srcParam, dstParam, fname, back_inserter( body->get_kids() ), array->get_base(), addCast, forward );
    137 
    138                 // block containing for stmt and index variable
    139                 std::list<Statement *> initList;
    140                 CompoundStmt * block = new CompoundStmt( noLabels );
    141                 block->get_kids().push_back( new DeclStmt( noLabels, index ) );
    142                 block->get_kids().push_back( new ForStmt( noLabels, initList, cond, inc, body ) );
    143 
    144                 *out++ = block;
    145         }
    146 
    147         template< typename OutputIterator >
    148         void genCall( InitTweak::InitExpander &  srcParam, Expression * dstParam, const std::string & fname, OutputIterator out, Type * type, bool addCast, bool forward ) {
    149                 if ( ArrayType * at = dynamic_cast< ArrayType * >( type ) ) {
    150                         genArrayCall( srcParam, dstParam, fname, out, at, addCast, forward );
    151                 } else {
    152                         genScalarCall( srcParam, dstParam, fname, out, type, addCast );
    153                 }
    154         }
    155 
    156         /// inserts into out a generated call expression to function fname with arguments dstParam
    157         /// and srcParam. Intended to be used with generated ?=?, ?{}, and ^?{} calls. decl is the
    158         /// object being constructed. The function wraps constructor and destructor calls in an
    159         /// ImplicitCtorDtorStmt node.
    160         template< typename OutputIterator >
    161         void genImplicitCall( InitTweak::InitExpander &  srcParam, Expression * dstParam, const std::string & fname, OutputIterator out, DeclarationWithType * decl, bool forward = true ) {
    162                 ObjectDecl *obj = dynamic_cast<ObjectDecl *>( decl );
    163                 assert( obj );
    164                 // unnamed bit fields are not copied as they cannot be accessed
    165                 if ( isUnnamedBitfield( obj ) ) return;
    166 
    167                 bool addCast = (fname == "?{}" || fname == "^?{}") && ( !obj || ( obj && obj->get_bitfieldWidth() == NULL ) );
    168                 std::list< Statement * > stmts;
    169                 genCall( srcParam, dstParam, fname, back_inserter( stmts ), obj->get_type(), addCast, forward );
    170 
    171                 // currently genCall should produce at most one element, but if that changes then the next line needs to be updated to grab the statement which contains the call
    172                 assert( stmts.size() <= 1 );
    173     if ( stmts.size() == 1 ) {
    174                 Statement * callStmt = stmts.front();
    175                 if ( addCast ) {
    176                         // implicitly generated ctor/dtor calls should be wrapped
    177                         // so that later passes are aware they were generated.
    178                         // xxx - don't mark as an implicit ctor/dtor if obj is a bitfield,
    179                         // because this causes the address to be taken at codegen, which is illegal in C.
    180                         callStmt = new ImplicitCtorDtorStmt( callStmt );
    181                 }
    182                 *out++ = callStmt;
     94    Statement * stmt = block;
     95    if ( fname == "?{}" || fname == "^?{}" ) {
     96      // implicitly generated ctor/dtor calls should be wrapped
     97      // so that later passes are aware they were generated
     98      stmt = new ImplicitCtorDtorStmt( stmt );
    18399    }
    184         }
     100    *out++ = stmt;
     101  }
    185102} // namespace SymTab
    186103#endif // AUTOGEN_H
  • src/SymTab/FixFunction.cc

    r73bf8cf2 raea7168  
    55// file "LICENCE" distributed with Cforall.
    66//
    7 // FixFunction.cc --
     7// FixFunction.cc -- 
    88//
    99// Author           : Richard C. Bilson
     
    4444
    4545        Type * FixFunction::mutate(ArrayType *arrayType) {
    46                 // need to recursively mutate the base type in order for multi-dimensional arrays to work.
    47                 PointerType *pointerType = new PointerType( arrayType->get_qualifiers(), arrayType->get_base()->clone()->acceptMutator( *this ), maybeClone( arrayType->get_dimension() ), arrayType->get_isVarLen(), arrayType->get_isStatic() );
     46                PointerType *pointerType = new PointerType( arrayType->get_qualifiers(), maybeClone( arrayType->get_base()->clone() ), maybeClone( arrayType->get_dimension() ), arrayType->get_isVarLen(), arrayType->get_isStatic() );
    4847                delete arrayType;
    4948                return pointerType;
  • src/SymTab/Validate.cc

    r73bf8cf2 raea7168  
    174174
    175175                virtual void visit( FunctionDecl *funcDecl );
    176         };
     176};
    177177
    178178        class CompoundLiteral : public GenPoly::DeclMutator {
     
    191191                EliminateTypedef::eliminateTypedef( translationUnit );
    192192                HoistStruct::hoistStruct( translationUnit );
    193                 autogenerateRoutines( translationUnit ); // moved up, used to be below compoundLiteral - currently needs Pass1
    194193                acceptAll( translationUnit, pass1 );
    195194                acceptAll( translationUnit, pass2 );
    196195                ReturnChecker::checkFunctionReturns( translationUnit );
    197                 compoundliteral.mutateDeclarationList( translationUnit );
     196                mutateAll( translationUnit, compoundliteral );
     197                autogenerateRoutines( translationUnit );
    198198                acceptAll( translationUnit, pass3 );
    199199                VerifyCtorDtor::verify( translationUnit );
     
    490490                EliminateTypedef eliminator;
    491491                mutateAll( translationUnit, eliminator );
    492                 if ( eliminator.typedefNames.count( "size_t" ) ) {
    493                         // grab and remember declaration of size_t
    494                         SizeType = eliminator.typedefNames["size_t"].first->get_base()->clone();
    495                 } else {
    496                         // xxx - missing global typedef for size_t - default to long unsigned int, even though that may be wrong
    497                         // eventually should have a warning for this case.
    498                         SizeType = new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt );
    499                 }
    500492                filter( translationUnit, isTypedef, true );
    501 
    502493        }
    503494
     
    527518        Declaration *EliminateTypedef::mutate( TypedefDecl * tyDecl ) {
    528519                Declaration *ret = Mutator::mutate( tyDecl );
    529 
    530520                if ( typedefNames.count( tyDecl->get_name() ) == 1 && typedefNames[ tyDecl->get_name() ].second == scopeLevel ) {
    531521                        // typedef to the same name from the same scope
  • src/SynTree/Expression.cc

    r73bf8cf2 raea7168  
    344344}
    345345
    346 //// is this right? It's cloning the member, but the member is a declaration so probably shouldn't be cloned...
    347346MemberExpr::MemberExpr( const MemberExpr &other ) :
    348                 Expression( other ), member( other.member ), aggregate( maybeClone( other.aggregate ) ) {
     347                Expression( other ), member( maybeClone( other.member ) ), aggregate( maybeClone( other.aggregate ) ) {
    349348}
    350349
    351350MemberExpr::~MemberExpr() {
    352         // delete member;
     351        delete member;
    353352        delete aggregate;
    354353}
  • src/SynTree/Initializer.h

    r73bf8cf2 raea7168  
    9393        std::list<Initializer*> &get_initializers() { return initializers; }
    9494
    95         typedef std::list<Initializer*>::iterator iterator;
    96         iterator begin() { return initializers.begin(); }
    97         iterator end() { return initializers.end(); }
     95        std::list<Initializer*>::iterator begin_initializers() { return initializers.begin(); }
     96        std::list<Initializer*>::iterator end_initializers() { return initializers.end(); }
    9897
    9998        virtual ListInit *clone() const { return new ListInit( *this ); }
  • src/main.cc

    r73bf8cf2 raea7168  
    4242#include "InitTweak/GenInit.h"
    4343#include "InitTweak/FixInit.h"
     44#include "InitTweak/FixGlobalInit.h"
    4445//#include "Explain/GenProlog.h"
    4546//#include "Try/Visit.h"
     
    281282                OPTPRINT( "fixNames" )
    282283                CodeGen::fixNames( translationUnit );
     284                OPTPRINT( "fixGlobalInit" );
     285                InitTweak::fixGlobalInit( translationUnit, filename, libcfap || treep );
    283286                OPTPRINT( "tweakInit" )
    284287                InitTweak::genInit( translationUnit );
     
    301304                }
    302305
     306                OPTPRINT( "fixInit" )
    303307                // fix ObjectDecl - replaces ConstructorInit nodes
    304                 OPTPRINT( "fixInit" )
    305                 InitTweak::fix( translationUnit, filename, libcfap || treep );
     308                InitTweak::fix( translationUnit );
    306309                if ( ctorinitp ) {
    307310                        dump ( translationUnit );
  • src/tests/.expect/64/extension.txt

    r73bf8cf2 raea7168  
    100100    ((void)((__extension__ __a__i_2 , __extension__ __b__i_2) , __extension__ __c__i_2));
    101101}
     102__attribute__ ((constructor(),)) static void _init_extension(void){
     103    int _global_init0;
     104    ((void)((*((int *)(&__a__i_1)))=_global_init0) /* ?{} */);
     105    int _global_init1;
     106    ((void)((*((int *)(&__b__i_1)))=_global_init1) /* ?{} */);
     107    int _global_init2;
     108    ((void)((*((int *)(&__c__i_1)))=_global_init2) /* ?{} */);
     109}
     110__attribute__ ((destructor(),)) static void _destroy_extension(void){
     111    ((void)((*((int *)(&__c__i_1)))) /* ^?{} */);
     112    ((void)((*((int *)(&__b__i_1)))) /* ^?{} */);
     113    ((void)((*((int *)(&__a__i_1)))) /* ^?{} */);
     114}
  • src/tests/init_once.c

    r73bf8cf2 raea7168  
    9292init_once y = x;
    9393
    94 void static_variable() {
    95         static init_once x;
    96 }
    97 
    9894int main() {
    9995        // local variables
     
    183179                }
    184180        }
    185 
    186         // function-scoped static variable
    187         for (int i = 0; i < 10; i++) {
    188                 static_variable();
    189         }
    190181}
    191182
Note: See TracChangeset for help on using the changeset viewer.