Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/InitTweak/FixGlobalInit.cc

    rf9cebb5 rca35c51  
    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 && ! isIntrinsicSingleArgCallStmt( 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        }
Note: See TracChangeset for help on using the changeset viewer.