Changes in / [31e46b8:ccb447e]


Ignore:
Location:
src
Files:
14 edited

Legend:

Unmodified
Added
Removed
  • src/GenPoly/DeclMutator.h

    r31e46b8 rccb447e  
    2828        class DeclMutator : public Mutator {
    2929        public:
     30                typedef Mutator Parent;
     31
    3032                DeclMutator();
    3133                virtual ~DeclMutator();
    32                
     34
     35                using Parent::mutate;
    3336                virtual CompoundStmt* mutate(CompoundStmt *compoundStmt);
    3437                virtual Statement* mutate(IfStmt *ifStmt);
     
    4245                /// Mutates a list of declarations with this visitor
    4346                void mutateDeclarationList(std::list< Declaration* >& decls);
    44                
     47
    4548                /// Called on entry to a new scope; overriders should call this as a super-class call
    4649                virtual void doBeginScope();
  • src/InitTweak/FixGlobalInit.cc

    r31e46b8 rccb447e  
    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         }
    9148
    9249        void fixGlobalInit( std::list< Declaration * > & translationUnit, const std::string & name, bool inLibrary ) {
     
    14097                std::list< Statement * > & destroyStatements = destroyFunction->get_statements()->get_kids();
    14198
    142                 if ( ! tryConstruct( objDecl ) ) return; // don't construct @= or designated objects
    143                 if ( objDecl->get_storageClass() == DeclarationNode::Extern ) return;
    14499                // C allows you to initialize objects with constant expressions
    145100                // xxx - this is an optimization. Need to first resolve constructors before we decide
     
    147102                // if ( isConstExpr( objDecl->get_init() ) ) return;
    148103
    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 ) );
     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() );
    156107
    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 ) ) );
     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;
    167127                } // if
    168128        }
  • src/InitTweak/FixInit.cc

    r31e46b8 rccb447e  
    1818#include <iterator>
    1919#include <algorithm>
     20#include "InitTweak.h"
    2021#include "FixInit.h"
    21 #include "InitTweak.h"
     22#include "FixGlobalInit.h"
    2223#include "ResolvExpr/Resolver.h"
    2324#include "ResolvExpr/typeops.h"
     
    8384                };
    8485
     86                // debug
    8587                struct printSet {
    8688                        typedef ObjDeclCollector::ObjectSet ObjectSet;
     
    171173        } // namespace
    172174
    173         void fix( std::list< Declaration * > & translationUnit ) {
     175        void fix( std::list< Declaration * > & translationUnit, const std::string & filename, bool inLibrary ) {
     176                // fixes ConstructorInit for global variables. should happen before fixInitializers.
     177                InitTweak::fixGlobalInit( translationUnit, filename, inLibrary );
     178
    174179                InsertImplicitCalls::insert( translationUnit );
    175180                ResolveCopyCtors::resolveImplicitCalls( translationUnit );
  • src/InitTweak/FixInit.h

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

    r31e46b8 rccb447e  
    2626#include "SymTab/Autogen.h"
    2727#include "GenPoly/PolyMutator.h"
     28#include "GenPoly/DeclMutator.h"
    2829
    2930namespace InitTweak {
     
    5556          public:
    5657                /// create constructor and destructor statements for object declarations.
    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
     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.
    6061                static void generateCtorDtor( std::list< Declaration * > &translationUnit );
    61 
    62                 CtorDtor() : inFunction( false ) {}
    6362
    6463                virtual DeclarationWithType * mutate( ObjectDecl * );
    6564                virtual DeclarationWithType * mutate( FunctionDecl *functionDecl );
    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 );
     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; }
    7475
    7576          protected:
    76                 bool inFunction;
     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;
    77106        };
    78107
    79108        void genInit( std::list< Declaration * > & translationUnit ) {
    80109                ReturnFixer::makeReturnTemp( translationUnit );
     110                HoistArrayDimension::hoistArrayDimension( translationUnit );
    81111                CtorDtor::generateCtorDtor( translationUnit );
    82112        }
     
    124154        }
    125155
     156        void HoistArrayDimension::hoistArrayDimension( std::list< Declaration * > & translationUnit ) {
     157                HoistArrayDimension hoister;
     158                hoister.mutateDeclarationList( translationUnit );
     159        }
     160
     161        DeclarationWithType * HoistArrayDimension::mutate( ObjectDecl * objectDecl ) {
     162                storageclass = objectDecl->get_storageClass();
     163                DeclarationWithType * temp = Parent::mutate( objectDecl );
     164                hoist( objectDecl->get_type() );
     165                storageclass = DeclarationNode::NoStorageClass;
     166                return temp;
     167        }
     168
     169        void HoistArrayDimension::hoist( Type * type ) {
     170                // if in function, generate const size_t var
     171                static UniqueName dimensionName( "_array_dim" );
     172                if ( ArrayType * arrayType = dynamic_cast< ArrayType * >( type ) ) {
     173                        if ( ! inFunction ) return;
     174
     175                        if ( ! arrayType->get_dimension() ) return; // xxx - recursive call to hoist?
     176
     177                        // don't need to hoist dimension if it's a constexpr - only need to if there's potential
     178                        // for side effects.
     179                        if ( isConstExpr( arrayType->get_dimension() ) ) return;
     180
     181                        ObjectDecl * arrayDimension = new ObjectDecl( dimensionName.newName(), storageclass, LinkageSpec::C, 0, SymTab::SizeType->clone(), new SingleInit( arrayType->get_dimension() ) );
     182                        arrayDimension->get_type()->set_isConst( true );
     183
     184                        arrayType->set_dimension( new VariableExpr( arrayDimension ) );
     185                        addDeclaration( arrayDimension );
     186
     187                        hoist( arrayType->get_base() );
     188                        return;
     189                }
     190        }
     191
     192        DeclarationWithType * HoistArrayDimension::mutate( FunctionDecl *functionDecl ) {
     193                bool oldInFunc = inFunction;
     194                inFunction = true;
     195                DeclarationWithType * decl = Parent::mutate( functionDecl );
     196                inFunction = oldInFunc;
     197                return decl;
     198        }
    126199
    127200        void CtorDtor::generateCtorDtor( std::list< Declaration * > & translationUnit ) {
     
    140213
    141214        DeclarationWithType * CtorDtor::mutate( ObjectDecl * objDecl ) {
    142                 // hands off if designated or if @=
     215                // hands off if designated, if @=, or if extern
    143216                if ( tryConstruct( objDecl ) ) {
    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() ) );
     217                        if ( ArrayType * at = dynamic_cast< ArrayType * >( objDecl->get_type() ) ) {
     218                                // call into makeArrayFunction from validate.cc to generate calls to ctor/dtor for each element of array
     219                                // TODO: walk initializers and generate appropriate ctor if element has initializer.
     220                                // Initializer could be nested (depends on the depth of the array type on the object)
     221
     222                                std::list< Expression * > args = makeInitList( objDecl->get_init() );
     223                                if ( args.empty() ) {
     224                                        std::list< Statement * > ctor;
     225                                        std::list< Statement * > dtor;
     226
     227                                        SymTab::genImplicitCall( NULL, new VariableExpr( objDecl ), "?{}", back_inserter( ctor ), objDecl );
     228                                        SymTab::genImplicitCall( NULL, new VariableExpr( objDecl ), "^?{}", front_inserter( dtor ), objDecl, false );
     229
     230                                        // Currently genImplicitCall produces a single Statement - a CompoundStmt
     231                                        // which  wraps everything that needs to happen. As such, it's technically
     232                                        // possible to use a Statement ** in the above calls, but this is inherently
     233                                        // unsafe, so instead we take the slightly less efficient route, but will be
     234                                        // immediately informed if somehow the above assumption is broken. In this case,
     235                                        // we could always wrap the list of statements at this point with a CompoundStmt,
     236                                        // but it seems reasonable at the moment for this to be done by genImplicitCall
     237                                        // itself. It is possible that genImplicitCall produces no statements (e.g. if
     238                                        // an array type does not have a dimension). In this case, it's fine to ignore
     239                                        // the object for the purposes of construction.
     240                                        assert( ctor.size() == dtor.size() && ctor.size() <= 1 );
     241                                        if ( ctor.size() == 1 ) {
     242                                                assert( dynamic_cast< ImplicitCtorDtorStmt * > ( ctor.front() ) && dynamic_cast< ImplicitCtorDtorStmt * > ( dtor.front() ) );
    166243                                                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.
    175244                                        }
    176245                                } 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() ) );
     246                                        // array came with an initializer list: initialize each element
     247                                        // may have more initializers than elements in the array - need to check at each index that
     248                                        // we haven't exceeded size. This requires precomputing the size because it might be a side-effecting
     249                                        // computation.
     250                                        // may have fewer initializers than elements in the array - need to default construct
     251                                        // remaining elements.
     252                                        // might be able to merge this with the case above.
     253
    187254                                }
     255                        } else {
     256                                // it's sufficient to attempt to call the ctor/dtor for the given object and its initializer
     257                                Expression * ctor = makeCtorDtorExpr( "?{}", objDecl, makeInitList( objDecl->get_init() ) );
     258                                Expression * dtor = makeCtorDtorExpr( "^?{}", objDecl, std::list< Expression * >() );
     259
     260                                // need to remember init expression, in case no ctors exist
     261                                // if ctor does exist, want to use ctor expression instead of init
     262                                // push this decision to the resolver
     263                                ExprStmt * ctorStmt = new ExprStmt( noLabels, ctor );
     264                                ExprStmt * dtorStmt = new ExprStmt( noLabels, dtor );
     265                                objDecl->set_init( new ConstructorInit( new ImplicitCtorDtorStmt( ctorStmt ), new ImplicitCtorDtorStmt( dtorStmt ), objDecl->get_init() ) );
    188266                        }
    189267                }
     
    193271        DeclarationWithType * CtorDtor::mutate( FunctionDecl *functionDecl ) {
    194272                // parameters should not be constructed and destructed, so don't mutate FunctionType
    195                 bool oldInFunc = inFunction;
    196273                mutateAll( functionDecl->get_oldDecls(), *this );
    197                 inFunction = true;
    198274                functionDecl->set_statements( maybeMutate( functionDecl->get_statements(), *this ) );
    199                 inFunction = oldInFunc;
    200275                return functionDecl;
    201276        }
    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 
    213277} // namespace InitTweak
    214278
  • src/InitTweak/InitTweak.cc

    r31e46b8 rccb447e  
    5757                        (objDecl->get_init() == NULL ||
    5858                                ( objDecl->get_init() != NULL && objDecl->get_init()->get_maybeConstructed() )) &&
    59                         ! isDesignated( objDecl->get_init() );
     59                        ! isDesignated( objDecl->get_init() )
     60                        && objDecl->get_storageClass() != DeclarationNode::Extern;
    6061        }
    6162
     
    160161                else return NULL;
    161162        }
     163
     164        class ConstExprChecker : public Visitor {
     165        public:
     166                ConstExprChecker() : isConstExpr( true ) {}
     167
     168                virtual void visit( ApplicationExpr *applicationExpr ) { isConstExpr = false; }
     169                virtual void visit( UntypedExpr *untypedExpr ) { isConstExpr = false; }
     170                virtual void visit( NameExpr *nameExpr ) { isConstExpr = false; }
     171                virtual void visit( CastExpr *castExpr ) { isConstExpr = false; }
     172                virtual void visit( LabelAddressExpr *labAddressExpr ) { isConstExpr = false; }
     173                virtual void visit( UntypedMemberExpr *memberExpr ) { isConstExpr = false; }
     174                virtual void visit( MemberExpr *memberExpr ) { isConstExpr = false; }
     175                virtual void visit( VariableExpr *variableExpr ) { isConstExpr = false; }
     176                virtual void visit( ConstantExpr *constantExpr ) { /* bottom out */ }
     177                // these might be okay?
     178                // virtual void visit( SizeofExpr *sizeofExpr );
     179                // virtual void visit( AlignofExpr *alignofExpr );
     180                // virtual void visit( UntypedOffsetofExpr *offsetofExpr );
     181                // virtual void visit( OffsetofExpr *offsetofExpr );
     182                // virtual void visit( OffsetPackExpr *offsetPackExpr );
     183                // virtual void visit( AttrExpr *attrExpr );
     184                // virtual void visit( CommaExpr *commaExpr );
     185                // virtual void visit( LogicalExpr *logicalExpr );
     186                // virtual void visit( ConditionalExpr *conditionalExpr );
     187                virtual void visit( TupleExpr *tupleExpr ) { isConstExpr = false; }
     188                virtual void visit( SolvedTupleExpr *tupleExpr ) { isConstExpr = false; }
     189                virtual void visit( TypeExpr *typeExpr ) { isConstExpr = false; }
     190                virtual void visit( AsmExpr *asmExpr ) { isConstExpr = false; }
     191                virtual void visit( UntypedValofExpr *valofExpr ) { isConstExpr = false; }
     192                virtual void visit( CompoundLiteralExpr *compLitExpr ) { isConstExpr = false; }
     193
     194                bool isConstExpr;
     195        };
     196
     197        bool isConstExpr( Expression * expr ) {
     198                if ( expr ) {
     199                        ConstExprChecker checker;
     200                        expr->accept( checker );
     201                        return checker.isConstExpr;
     202                }
     203                return true;
     204        }
     205
     206        bool isConstExpr( Initializer * init ) {
     207                if ( init ) {
     208                        ConstExprChecker checker;
     209                        init->accept( checker );
     210                        return checker.isConstExpr;
     211                } // if
     212                // for all intents and purposes, no initializer means const expr
     213                return true;
     214        }
     215
    162216}
  • src/InitTweak/InitTweak.h

    r31e46b8 rccb447e  
    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   /// 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 );
     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 );
    4141
    42   /// get the Ctor/Dtor call expression from a Statement that looks like a generated ctor/dtor call
    43   Expression * getCtorDtorCall( Statement * stmt );
     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   /// returns the name of the function being called
    46   std::string getFunctionName( Expression * expr );
     45        /// returns the name of the function being called
     46        std::string getFunctionName( Expression * expr );
    4747
    48   /// returns the argument to a call expression in position N indexed from 0
    49   Expression *& getCallArg( Expression * callExpr, unsigned int pos );
     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 base type of a PointerType or ArrayType, else returns NULL
    52   Type * getPointerBase( Type * );
     51        /// returns the base type of a PointerType or ArrayType, else returns NULL
     52        Type * getPointerBase( Type * );
    5353
    54   /// returns the argument if it is a PointerType or ArrayType, else returns NULL
    55   Type * isPointerType( Type * );
     54        /// returns the argument if it is a PointerType or ArrayType, else returns NULL
     55        Type * isPointerType( Type * );
     56
     57        /// returns true if expr is trivially a compile-time constant
     58        bool isConstExpr( Expression * expr );
     59        bool isConstExpr( Initializer * init );
    5660} // namespace
    5761
  • src/ResolvExpr/Resolver.cc

    r31e46b8 rccb447e  
    2424#include "SynTree/Initializer.h"
    2525#include "SymTab/Indexer.h"
     26#include "SymTab/Autogen.h"
    2627#include "Common/utility.h"
    2728#include "InitTweak/InitTweak.h"
     
    4142
    4243                virtual void visit( ArrayType * at );
     44                virtual void visit( PointerType * at );
    4345
    4446                virtual void visit( ExprStmt *exprStmt );
     
    5961          private:
    6062        typedef std::list< Initializer * >::iterator InitIterator;
     63
     64                template< typename PtrType >
     65                void handlePtrType( PtrType * type );
    6166
    6267          void resolveAggrInit( AggregateDecl *, InitIterator &, InitIterator & );
     
    192197        }
    193198
     199        template< typename PtrType >
     200        void Resolver::handlePtrType( PtrType * type ) {
     201                if ( type->get_dimension() ) {
     202                        CastExpr *castExpr = new CastExpr( type->get_dimension(), SymTab::SizeType->clone() );
     203                        Expression *newExpr = findSingleExpression( castExpr, *this );
     204                        delete type->get_dimension();
     205                        type->set_dimension( newExpr );
     206                }
     207        }
     208
    194209        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() );
    198                         Expression *newExpr = findSingleExpression( castExpr, *this );
    199                         delete at->get_dimension();
    200                         at->set_dimension( newExpr );
    201                 }
     210                handlePtrType( at );
    202211                Visitor::visit( at );
     212        }
     213
     214        void Resolver::visit( PointerType * pt ) {
     215                handlePtrType( pt );
     216                Visitor::visit( pt );
    203217        }
    204218
     
    537551                assert( callExpr );
    538552                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                 }
     553
     554                // the first argument will always be &<expr>
     555                AddressExpr * addrExpr = dynamic_cast< AddressExpr * > ( constructee );
     556                assert( addrExpr );
     557
     558                // need to find the type of the first argument. In the case of an array,
     559                // need to remove one ArrayType layer from the type for each subscript expression.
     560                Expression * addressee = addrExpr->get_arg();
     561                int numLayers = 0;
     562                while ( UntypedExpr * untypedExpr = dynamic_cast< UntypedExpr * >( addressee ) ) {
     563                        assert( InitTweak::getFunctionName( untypedExpr ) == "?[?]" );
     564                        addressee = InitTweak::getCallArg( untypedExpr, 0 );
     565                        numLayers++;
     566                }
     567                assert( addressee->get_results().size() == 1 );
     568                Type * type = addressee->get_results().front();
     569                for ( int i = 0; i < numLayers; i++ ) {
     570                        type = InitTweak::getPointerBase( type );
     571                        assert( type && "Expected pointer or array type. May have generated too many ?[?] calls." );
     572                }
     573
    559574                // cast to T* with qualifiers removed.
    560575                // unfortunately, lvalue is considered a qualifier. For AddressExpr to resolve, its argument
     
    562577                // remove lvalue as a qualifier, this can change to
    563578                //   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 );
     579                assert( type );
     580                type = type->clone();
     581                type->get_qualifiers() -= Type::Qualifiers(true, true, true, false, true, true);
     582                type = new PointerType( Type::Qualifiers(), type );
    569583                constructee = new CastExpr( constructee, type );
    570584
  • src/SymTab/Autogen.cc

    r31e46b8 rccb447e  
    2626
    2727namespace SymTab {
     28        Type * SizeType = 0;
     29
    2830        class AutogenerateRoutines : public Visitor {
    2931                public:
     
    5961        bool isUnnamedBitfield( ObjectDecl * obj ) {
    6062                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;
    9363        }
    9464
     
    220190
    221191                // assign to destination (and return value if generic)
    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() ) );
     192                UntypedExpr *derefExpr = new UntypedExpr( new NameExpr( "*?" ) );
     193                derefExpr->get_args().push_back( new VariableExpr( dstParam ) );
     194                Expression *dstselect = new MemberExpr( field, derefExpr );
     195                genImplicitCall( src, dstselect, func->get_name(), back_inserter( func->get_statements()->get_kids() ), field, forward );
     196
     197                if ( isGeneric && returnVal ) {
     198                        UntypedExpr *derefRet = new UntypedExpr( new NameExpr( "*?" ) );
     199                        derefRet->get_args().push_back( new VariableExpr( returnVal ) );
     200                        Expression *retselect = new MemberExpr( field, derefRet );
     201                        genImplicitCall( src, retselect, func->get_name(), back_inserter( func->get_statements()->get_kids() ), field, forward );
    238202                } // if
    239203        }
  • src/SymTab/Autogen.h

    r31e46b8 rccb447e  
    2424
    2525namespace SymTab {
    26   /// Generates assignment operators, constructors, and destructor for aggregate types as required
    27   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 );
    2828
    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
     29        /// returns true if obj's name is the empty string and it has a bitfield width
     30        bool isUnnamedBitfield( ObjectDecl * obj );
    3131
    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" );
     32        /// size_t type - set when size_t typedef is seen. Useful in a few places,
     33        /// such as in determining array dimension type
     34        extern Type * SizeType;
    3735
    38     // for a flexible array member nothing is done -- user must define own assignment
    39     if ( ! array->get_dimension() ) return;
     36        /// inserts into out a generated call expression to function fname with arguments dstParam and srcParam. Intended to be used with generated ?=?, ?{}, and ^?{} calls.
     37        template< typename OutputIterator >
     38        void genCall( Expression * srcParam, Expression * dstParam, const std::string & fname, OutputIterator out, Type * type, bool forward = true );
    4039
    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( "--?" );
     40        /// inserts into out a generated call expression to function fname with arguments dstParam and srcParam. Should only be called with non-array types.
     41        template< typename OutputIterator >
     42        void genScalarCall( Expression *srcParam, Expression *dstParam, const std::string & fname, OutputIterator out ) {
     43                // want to be able to generate assignment, ctor, and dtor generically,
     44                // so fname is either ?=?, ?{}, or ^?{}
     45                UntypedExpr *fExpr = new UntypedExpr( new NameExpr( fname ) );
     46
     47                // do something special for unnamed members
     48                fExpr->get_args().push_back( new AddressExpr( dstParam ) );
     49
     50                if ( srcParam ) {
     51                        fExpr->get_args().push_back( srcParam );
     52                }
     53
     54                *out++ = new ExprStmt( noLabels, fExpr );
     55        }
     56
     57        /// Store in out a loop which calls fname on each element of the array with srcParam and dstParam as arguments.
     58        /// If forward is true, loop goes from 0 to N-1, else N-1 to 0
     59        template< typename OutputIterator >
     60        void genArrayCall( Expression *srcParam, Expression *dstParam, const std::string & fname, OutputIterator out, ArrayType *array, bool forward = true ) {
     61                static UniqueName indexName( "_index" );
     62
     63                // for a flexible array member nothing is done -- user must define own assignment
     64                if ( ! array->get_dimension() ) return ;
     65
     66                Expression * begin, * end, * update, * cmp;
     67                if ( forward ) {
     68                        // generate: for ( int i = 0; i < 0; ++i )
     69                        begin = new NameExpr( "0" );
     70                        end = array->get_dimension()->clone();
     71                        cmp = new NameExpr( "?<?" );
     72                        update = new NameExpr( "++?" );
     73                } else {
     74                        // generate: for ( int i = N-1; i >= 0; --i )
     75                        begin = new UntypedExpr( new NameExpr( "?-?" ) );
     76                        ((UntypedExpr*)begin)->get_args().push_back( array->get_dimension()->clone() );
     77                        ((UntypedExpr*)begin)->get_args().push_back( new NameExpr( "1" ) );
     78                        end = new NameExpr( "0" );
     79                        cmp = new NameExpr( "?>=?" );
     80                        update = new NameExpr( "--?" );
     81                }
     82
     83                ObjectDecl *index = new ObjectDecl( indexName.newName(), DeclarationNode::NoStorageClass, LinkageSpec::C, 0, new BasicType( Type::Qualifiers(), BasicType::SignedInt ), NULL );
     84
     85                UntypedExpr *init = new UntypedExpr( new NameExpr( "?=?" ) );
     86                init->get_args().push_back( new AddressExpr( new VariableExpr( index ) ) );
     87                init->get_args().push_back( begin );
     88                index->set_init( new SingleInit( init, std::list<Expression*>() ) );
     89
     90                UntypedExpr *cond = new UntypedExpr( cmp );
     91                cond->get_args().push_back( new VariableExpr( index ) );
     92                cond->get_args().push_back( end );
     93
     94                UntypedExpr *inc = new UntypedExpr( update );
     95                inc->get_args().push_back( new AddressExpr( new VariableExpr( index ) ) );
     96
     97                UntypedExpr *dstIndex = new UntypedExpr( new NameExpr( "?[?]" ) );
     98                dstIndex->get_args().push_back( dstParam );
     99                dstIndex->get_args().push_back( new VariableExpr( index ) );
     100                dstParam = dstIndex;
     101
     102                // srcParam is NULL for default ctor/dtor
     103                if ( srcParam ) {
     104                        UntypedExpr *srcIndex = new UntypedExpr( new NameExpr( "?[?]" ) );
     105                        srcIndex->get_args().push_back( srcParam );
     106                        srcIndex->get_args().push_back( new VariableExpr( index ) );
     107                        srcParam = srcIndex;
     108                }
     109
     110                // for stmt's body, eventually containing call
     111                CompoundStmt * body = new CompoundStmt( noLabels );
     112                genCall( srcParam, dstParam, fname, back_inserter( body->get_kids() ), array->get_base(), forward );
     113
     114                // block containing for stmt and index variable
     115                std::list<Statement *> initList;
     116                CompoundStmt * block = new CompoundStmt( noLabels );
     117                block->get_kids().push_back( new DeclStmt( noLabels, index ) );
     118                block->get_kids().push_back( new ForStmt( noLabels, initList, cond, inc, body ) );
     119
     120                *out++ = block;
     121        }
     122
     123        template< typename OutputIterator >
     124        void genCall( Expression * srcParam, Expression * dstParam, const std::string & fname, OutputIterator out, Type * type, bool forward ) {
     125                if ( ArrayType * at = dynamic_cast< ArrayType * >( type ) ) {
     126                        genArrayCall( srcParam, dstParam, fname, out, at, forward );
     127                } else {
     128                        genScalarCall( srcParam, dstParam, fname, out );
     129                }
     130        }
     131
     132        /// inserts into out a generated call expression to function fname with arguments dstParam
     133        /// and srcParam. Intended to be used with generated ?=?, ?{}, and ^?{} calls. decl is the
     134        /// object being constructed. The function wraps constructor and destructor calls in an
     135        /// ImplicitCtorDtorStmt node.
     136        template< typename OutputIterator >
     137        void genImplicitCall( Expression * srcParam, Expression * dstParam, const std::string & fname, OutputIterator out, DeclarationWithType * decl, bool forward = true ) {
     138                ObjectDecl *obj = dynamic_cast<ObjectDecl *>( decl );
     139                assert( obj );
     140                // unnamed bit fields are not copied as they cannot be accessed
     141                if ( isUnnamedBitfield( obj ) ) return;
     142
     143                std::list< Statement * > stmts;
     144                genCall( srcParam, dstParam, fname, back_inserter( stmts ), obj->get_type(), forward );
     145
     146                // 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
     147                assert( stmts.size() <= 1 );
     148    if ( stmts.size() == 1 ) {
     149                Statement * callStmt = stmts.front();
     150                if ( (fname == "?{}" || fname == "^?{}") && ( !obj || ( obj && obj->get_bitfieldWidth() == NULL ) ) ) {
     151                        // implicitly generated ctor/dtor calls should be wrapped
     152                        // so that later passes are aware they were generated.
     153                        // xxx - don't mark as an implicit ctor/dtor if obj is a bitfield,
     154                        // because this causes the address to be taken at codegen, which is illegal in C.
     155                        callStmt = new ImplicitCtorDtorStmt( callStmt );
     156                }
     157                *out++ = callStmt;
    56158    }
    57 
    58     ObjectDecl *index = new ObjectDecl( indexName.newName(), DeclarationNode::NoStorageClass, LinkageSpec::C, 0, new BasicType( Type::Qualifiers(), BasicType::SignedInt ), NULL );
    59 
    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*>() ) );
    64 
    65     UntypedExpr *cond = new UntypedExpr( cmp );
    66     cond->get_args().push_back( new VariableExpr( index ) );
    67     cond->get_args().push_back( end );
    68 
    69     UntypedExpr *inc = new UntypedExpr( update );
    70     inc->get_args().push_back( new AddressExpr( new VariableExpr( index ) ) );
    71 
    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 ) );
    75 
    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 );
    80 
    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     }
    88 
    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 ) ) );
    93 
    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 );
    99     }
    100     *out++ = stmt;
    101   }
     159        }
    102160} // namespace SymTab
    103161#endif // AUTOGEN_H
  • src/SymTab/FixFunction.cc

    r31e46b8 rccb447e  
    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                 PointerType *pointerType = new PointerType( arrayType->get_qualifiers(), maybeClone( arrayType->get_base()->clone() ), maybeClone( arrayType->get_dimension() ), arrayType->get_isVarLen(), arrayType->get_isStatic() );
     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() );
    4748                delete arrayType;
    4849                return pointerType;
  • src/SymTab/Validate.cc

    r31e46b8 rccb447e  
    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
    193194                acceptAll( translationUnit, pass1 );
    194195                acceptAll( translationUnit, pass2 );
    195196                ReturnChecker::checkFunctionReturns( translationUnit );
    196                 mutateAll( translationUnit, compoundliteral );
    197                 autogenerateRoutines( translationUnit );
     197                compoundliteral.mutateDeclarationList( 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                }
    492500                filter( translationUnit, isTypedef, true );
     501
    493502        }
    494503
     
    518527        Declaration *EliminateTypedef::mutate( TypedefDecl * tyDecl ) {
    519528                Declaration *ret = Mutator::mutate( tyDecl );
     529
    520530                if ( typedefNames.count( tyDecl->get_name() ) == 1 && typedefNames[ tyDecl->get_name() ].second == scopeLevel ) {
    521531                        // typedef to the same name from the same scope
  • src/main.cc

    r31e46b8 rccb447e  
    4242#include "InitTweak/GenInit.h"
    4343#include "InitTweak/FixInit.h"
    44 #include "InitTweak/FixGlobalInit.h"
    4544//#include "Explain/GenProlog.h"
    4645//#include "Try/Visit.h"
     
    282281                OPTPRINT( "fixNames" )
    283282                CodeGen::fixNames( translationUnit );
    284                 OPTPRINT( "fixGlobalInit" );
    285                 InitTweak::fixGlobalInit( translationUnit, filename, libcfap || treep );
    286283                OPTPRINT( "tweakInit" )
    287284                InitTweak::genInit( translationUnit );
     
    304301                }
    305302
     303                // fix ObjectDecl - replaces ConstructorInit nodes
    306304                OPTPRINT( "fixInit" )
    307                 // fix ObjectDecl - replaces ConstructorInit nodes
    308                 InitTweak::fix( translationUnit );
     305                InitTweak::fix( translationUnit, filename, libcfap || treep );
    309306                if ( ctorinitp ) {
    310307                        dump ( translationUnit );
  • src/tests/.expect/64/extension.txt

    r31e46b8 rccb447e  
    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 }
Note: See TracChangeset for help on using the changeset viewer.