Changes in / [73bf8cf2:aea7168]
- Location:
- src
- Files:
-
- 19 edited
Legend:
- Unmodified
- Added
- Removed
-
src/CodeGen/CodeGenerator.cc
r73bf8cf2 raea7168 271 271 printDesignators( init->get_designators() ); 272 272 output << "{ "; 273 if ( init->begin () == init->end() ) {273 if ( init->begin_initializers() == init->end_initializers() ) { 274 274 // illegal to leave initializer list empty for scalar initializers, but always legal to have 0 275 275 output << "0"; 276 276 } else { 277 genCommaList( init->begin (), init->end() );277 genCommaList( init->begin_initializers(), init->end_initializers() ); 278 278 } 279 279 output << " }"; -
src/GenPoly/DeclMutator.h
r73bf8cf2 raea7168 28 28 class DeclMutator : public Mutator { 29 29 public: 30 typedef Mutator Parent;31 32 30 DeclMutator(); 33 31 virtual ~DeclMutator(); 34 35 using Parent::mutate; 32 36 33 virtual CompoundStmt* mutate(CompoundStmt *compoundStmt); 37 34 virtual Statement* mutate(IfStmt *ifStmt); … … 45 42 /// Mutates a list of declarations with this visitor 46 43 void mutateDeclarationList(std::list< Declaration* >& decls); 47 44 48 45 /// Called on entry to a new scope; overriders should call this as a super-class call 49 46 virtual void doBeginScope(); -
src/GenPoly/Specialize.cc
r73bf8cf2 raea7168 31 31 #include "Common/UniqueName.h" 32 32 #include "Common/utility.h" 33 #include "InitTweak/InitTweak.h"34 33 35 34 namespace GenPoly { … … 185 184 mutateAll( appExpr->get_args(), *this ); 186 185 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 ); 196 192 197 193 return appExpr; -
src/InitTweak/FixGlobalInit.cc
r73bf8cf2 raea7168 46 46 FunctionDecl * destroyFunction; 47 47 }; 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 } 48 91 49 92 void fixGlobalInit( std::list< Declaration * > & translationUnit, const std::string & name, bool inLibrary ) { … … 97 140 std::list< Statement * > & destroyStatements = destroyFunction->get_statements()->get_kids(); 98 141 142 if ( ! tryConstruct( objDecl ) ) return; // don't construct @= or designated objects 143 if ( objDecl->get_storageClass() == DeclarationNode::Extern ) return; 99 144 // C allows you to initialize objects with constant expressions 100 145 // xxx - this is an optimization. Need to first resolve constructors before we decide … … 102 147 // if ( isConstExpr( objDecl->get_init() ) ) return; 103 148 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 ) ); 107 156 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 ) ) ); 127 167 } // if 128 168 } -
src/InitTweak/FixInit.cc
r73bf8cf2 raea7168 18 18 #include <iterator> 19 19 #include <algorithm> 20 #include "FixInit.h" 20 21 #include "InitTweak.h" 21 #include "FixInit.h"22 #include "FixGlobalInit.h"23 22 #include "ResolvExpr/Resolver.h" 24 23 #include "ResolvExpr/typeops.h" … … 84 83 }; 85 84 86 // debug87 85 struct printSet { 88 86 typedef ObjDeclCollector::ObjectSet ObjectSet; … … 161 159 162 160 virtual DeclarationWithType * mutate( ObjectDecl *objDecl ); 163 164 std::list< Declaration * > staticDtorDecls;165 161 }; 166 162 … … 175 171 } // namespace 176 172 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 ) { 181 174 InsertImplicitCalls::insert( translationUnit ); 182 175 ResolveCopyCtors::resolveImplicitCalls( translationUnit ); … … 201 194 void FixInit::fixInitializers( std::list< Declaration * > & translationUnit ) { 202 195 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 ); 220 197 } 221 198 … … 445 422 if ( Statement * ctor = ctorInit->get_ctor() ) { 446 423 if ( objDecl->get_storageClass() == DeclarationNode::Static ) { 447 // originally wanted to take advantage of gcc nested functions, but448 // we get memory errors with this approach. To remedy this, create a449 // global static pointer that is set to refer to the object and make450 // the dtor-caller function global so that.451 //452 424 // 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; 456 433 // } 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 490 436 BasicType * boolType = new BasicType( Type::Qualifiers(), BasicType::Bool ); 491 437 SingleInit * boolInitExpr = new SingleInit( new ConstantExpr( Constant( boolType->clone(), "1" ) ), noDesignators ); … … 493 439 isUninitializedVar->fixUniqueId(); 494 440 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); 501 447 UntypedExpr * callAtexit = new UntypedExpr( new NameExpr( "atexit" ) ); 502 448 callAtexit->get_args().push_back( new VariableExpr( dtorCaller ) ); … … 511 457 std::list< Statement * > & body = initStmts->get_kids(); 512 458 body.push_back( ctor ); 513 body.push_back( new ExprStmt( noLabels, ptrAssign) );459 body.push_back( new DeclStmt( noLabels, dtorCaller ) ); 514 460 body.push_back( new ExprStmt( noLabels, callAtexit ) ); 515 461 body.push_back( new ExprStmt( noLabels, setTrue ) ); … … 519 465 stmtsToAddAfter.push_back( new DeclStmt( noLabels, isUninitializedVar ) ); 520 466 stmtsToAddAfter.push_back( ifStmt ); 521 522 // add pointer and dtor caller decls to list of decls that will be added into global scope523 staticDtorDecls.push_back( objPtr );524 staticDtorDecls.push_back( dtorCaller );525 467 } else { 526 468 stmtsToAddAfter.push_back( ctor ); -
src/InitTweak/FixInit.h
r73bf8cf2 raea7168 27 27 /// replace constructor initializers with expression statements 28 28 /// 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 ); 30 30 } // namespace 31 31 -
src/InitTweak/GenInit.cc
r73bf8cf2 raea7168 26 26 #include "SymTab/Autogen.h" 27 27 #include "GenPoly/PolyMutator.h" 28 #include "GenPoly/DeclMutator.h"29 28 30 29 namespace InitTweak { … … 56 55 public: 57 56 /// create constructor and destructor statements for object declarations. 58 /// the actual call statements will be added in after the resolver has run59 /// so that the initializer expression is only removed if a constructor is found60 /// 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 61 60 static void generateCtorDtor( std::list< Declaration * > &translationUnit ); 61 62 CtorDtor() : inFunction( false ) {} 62 63 63 64 virtual DeclarationWithType * mutate( ObjectDecl * ); 64 65 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 ); 75 74 76 75 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; 106 77 }; 107 78 108 79 void genInit( std::list< Declaration * > & translationUnit ) { 109 80 ReturnFixer::makeReturnTemp( translationUnit ); 110 HoistArrayDimension::hoistArrayDimension( translationUnit );111 81 CtorDtor::generateCtorDtor( translationUnit ); 112 82 } … … 154 124 } 155 125 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 var173 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 potential180 // 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 }201 126 202 127 void CtorDtor::generateCtorDtor( std::list< Declaration * > & translationUnit ) { … … 215 140 216 141 DeclarationWithType * CtorDtor::mutate( ObjectDecl * objDecl ) { 217 // hands off if designated , if @=, or if extern142 // hands off if designated or if @= 218 143 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 } 246 188 } 247 189 } … … 251 193 DeclarationWithType * CtorDtor::mutate( FunctionDecl *functionDecl ) { 252 194 // parameters should not be constructed and destructed, so don't mutate FunctionType 195 bool oldInFunc = inFunction; 253 196 mutateAll( functionDecl->get_oldDecls(), *this ); 197 inFunction = true; 254 198 functionDecl->set_statements( maybeMutate( functionDecl->get_statements(), *this ) ); 199 inFunction = oldInFunc; 255 200 return functionDecl; 256 201 } 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 257 213 } // namespace InitTweak 258 214 -
src/InitTweak/InitTweak.cc
r73bf8cf2 raea7168 1 #include <algorithm>2 1 #include "InitTweak.h" 3 2 #include "SynTree/Visitor.h" … … 21 20 }; 22 21 23 class Init Flattener : public Visitor {22 class InitExpander : public Visitor { 24 23 public: 24 InitExpander() {} 25 25 virtual void visit( SingleInit * singleInit ); 26 26 virtual void visit( ListInit * listInit ); … … 28 28 }; 29 29 30 void Init Flattener::visit( SingleInit * singleInit ) {30 void InitExpander::visit( SingleInit * singleInit ) { 31 31 argList.push_back( singleInit->get_value()->clone() ); 32 32 } 33 33 34 void Init Flattener::visit( ListInit * listInit ) {35 // flattennested list inits36 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 ) { 38 38 (*it)->accept( *this ); 39 39 } … … 42 42 43 43 std::list< Expression * > makeInitList( Initializer * init ) { 44 Init Flattener flattener;45 maybeAccept( init, flattener );46 return flattener.argList;44 InitExpander expander; 45 maybeAccept( init, expander ); 46 return expander.argList; 47 47 } 48 48 … … 53 53 } 54 54 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 now67 // 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 statement117 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 to165 // terminate without creating output, so should catch this error166 throw SemanticError( "unbalanced list initializers" );167 }168 for ( Initializer * init : *listInit ) {169 Expression * condition;170 // check for designations171 // if ( init-> ) {172 condition = new ConstantExpr( Constant::from_ulong( cond ) );173 ++cond;174 // } else {175 // condition = // ... take designation176 // cond = // ... take designation+1177 // }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 element189 // may have more initializers than elements in the array - need to check at each index that190 // we haven't exceeded size.191 // may have fewer initializers than elements in the array - need to default construct192 // remaining elements.193 // To accomplish this, generate switch statement, consuming all of expander's elements194 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 init203 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 216 55 bool tryConstruct( ObjectDecl * objDecl ) { 217 56 return ! LinkageSpec::isBuiltin( objDecl->get_linkage() ) && 218 57 (objDecl->get_init() == NULL || 219 58 ( 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() ); 255 60 } 256 61 257 62 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" ); 269 84 } 270 85 } 271 86 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() ); 276 93 assert( function ); 277 94 // check for Intrinsic only - don't want to remove all overridable ctor/dtors because autogenerated ctor/dtor 278 95 // 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; 295 99 } 296 100 … … 356 160 else return NULL; 357 161 } 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 } // if407 // for all intents and purposes, no initializer means const expr408 return true;409 }410 411 162 } -
src/InitTweak/InitTweak.h
r73bf8cf2 raea7168 26 26 // helper functions for initialization 27 27 namespace InitTweak { 28 29 28 /// transform Initializer into an argument list that can be passed to a call expression 29 std::list< Expression * > makeInitList( Initializer * init ); 30 30 31 32 31 /// True if the resolver should try to construct objDecl 32 bool tryConstruct( ObjectDecl * objDecl ); 33 33 34 35 34 /// True if the Initializer contains designations 35 bool isDesignated( Initializer * init ); 36 36 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 ); 39 41 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 ); 44 44 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 ); 47 47 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 ); 50 50 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 * ); 53 53 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 * ); 94 56 } // namespace 95 57 -
src/ResolvExpr/Resolver.cc
r73bf8cf2 raea7168 24 24 #include "SynTree/Initializer.h" 25 25 #include "SymTab/Indexer.h" 26 #include "SymTab/Autogen.h"27 26 #include "Common/utility.h" 28 27 #include "InitTweak/InitTweak.h" … … 42 41 43 42 virtual void visit( ArrayType * at ); 44 virtual void visit( PointerType * at );45 43 46 44 virtual void visit( ExprStmt *exprStmt ); … … 54 52 virtual void visit( BranchStmt *branchStmt ); 55 53 virtual void visit( ReturnStmt *returnStmt ); 54 virtual void visit( ImplicitCtorDtorStmt * impCtorDtorStmt ); 56 55 57 56 virtual void visit( SingleInit *singleInit ); … … 60 59 private: 61 60 typedef std::list< Initializer * >::iterator InitIterator; 62 63 template< typename PtrType >64 void handlePtrType( PtrType * type );65 61 66 62 void resolveAggrInit( AggregateDecl *, InitIterator &, InitIterator & ); … … 196 192 } 197 193 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() ); 202 198 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 } 210 202 Visitor::visit( at ); 211 }212 213 void Resolver::visit( PointerType * pt ) {214 handlePtrType( pt );215 Visitor::visit( pt );216 203 } 217 204 … … 435 422 436 423 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(); 439 426 440 427 if ( ArrayType * at = dynamic_cast< ArrayType * >( initContext ) ) { … … 538 525 ctorInit->set_ctor( NULL ); 539 526 } 540 if ( InitTweak::isInstrinsicSingleArgCallStmt( ctorInit->get_ dtor() ) ) {527 if ( InitTweak::isInstrinsicSingleArgCallStmt( ctorInit->get_ctor() ) ) { 541 528 delete ctorInit->get_dtor(); 542 529 ctorInit->set_dtor( NULL ); 543 530 } 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 ); 544 573 } 545 574 } // namespace ResolvExpr -
src/SymTab/Autogen.cc
r73bf8cf2 raea7168 26 26 27 27 namespace SymTab { 28 Type * SizeType = 0;29 30 28 class AutogenerateRoutines : public Visitor { 31 29 public: … … 61 59 bool isUnnamedBitfield( ObjectDecl * obj ) { 62 60 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; 63 93 } 64 94 … … 189 219 } 190 220 191 InitTweak::InitExpander srcParam( src );192 193 221 // 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() ) ); 204 238 } // if 205 239 } -
src/SymTab/Autogen.h
r73bf8cf2 raea7168 22 22 #include "SynTree/Declaration.h" 23 23 #include "SynTree/Initializer.h" 24 #include "InitTweak/InitTweak.h"25 24 26 25 namespace SymTab { 27 28 26 /// Generates assignment operators, constructors, and destructor for aggregate types as required 27 void autogenerateRoutines( std::list< Declaration * > &translationUnit ); 29 28 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 32 31 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" ); 36 37 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; 40 40 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( "--?" ); 68 56 } 69 57 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 ); 72 59 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*>() ) ); 74 64 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 ); 77 68 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 ) ) ); 83 71 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 ) ); 86 75 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 ); 103 80 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 } 105 88 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 ) ) ); 110 93 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 ); 183 99 } 184 } 100 *out++ = stmt; 101 } 185 102 } // namespace SymTab 186 103 #endif // AUTOGEN_H -
src/SymTab/FixFunction.cc
r73bf8cf2 raea7168 5 5 // file "LICENCE" distributed with Cforall. 6 6 // 7 // FixFunction.cc -- 7 // FixFunction.cc -- 8 8 // 9 9 // Author : Richard C. Bilson … … 44 44 45 45 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() ); 48 47 delete arrayType; 49 48 return pointerType; -
src/SymTab/Validate.cc
r73bf8cf2 raea7168 174 174 175 175 virtual void visit( FunctionDecl *funcDecl ); 176 176 }; 177 177 178 178 class CompoundLiteral : public GenPoly::DeclMutator { … … 191 191 EliminateTypedef::eliminateTypedef( translationUnit ); 192 192 HoistStruct::hoistStruct( translationUnit ); 193 autogenerateRoutines( translationUnit ); // moved up, used to be below compoundLiteral - currently needs Pass1194 193 acceptAll( translationUnit, pass1 ); 195 194 acceptAll( translationUnit, pass2 ); 196 195 ReturnChecker::checkFunctionReturns( translationUnit ); 197 compoundliteral.mutateDeclarationList( translationUnit ); 196 mutateAll( translationUnit, compoundliteral ); 197 autogenerateRoutines( translationUnit ); 198 198 acceptAll( translationUnit, pass3 ); 199 199 VerifyCtorDtor::verify( translationUnit ); … … 490 490 EliminateTypedef eliminator; 491 491 mutateAll( translationUnit, eliminator ); 492 if ( eliminator.typedefNames.count( "size_t" ) ) {493 // grab and remember declaration of size_t494 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 wrong497 // eventually should have a warning for this case.498 SizeType = new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt );499 }500 492 filter( translationUnit, isTypedef, true ); 501 502 493 } 503 494 … … 527 518 Declaration *EliminateTypedef::mutate( TypedefDecl * tyDecl ) { 528 519 Declaration *ret = Mutator::mutate( tyDecl ); 529 530 520 if ( typedefNames.count( tyDecl->get_name() ) == 1 && typedefNames[ tyDecl->get_name() ].second == scopeLevel ) { 531 521 // typedef to the same name from the same scope -
src/SynTree/Expression.cc
r73bf8cf2 raea7168 344 344 } 345 345 346 //// is this right? It's cloning the member, but the member is a declaration so probably shouldn't be cloned...347 346 MemberExpr::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 ) ) { 349 348 } 350 349 351 350 MemberExpr::~MemberExpr() { 352 //delete member;351 delete member; 353 352 delete aggregate; 354 353 } -
src/SynTree/Initializer.h
r73bf8cf2 raea7168 93 93 std::list<Initializer*> &get_initializers() { return initializers; } 94 94 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(); } 98 97 99 98 virtual ListInit *clone() const { return new ListInit( *this ); } -
src/main.cc
r73bf8cf2 raea7168 42 42 #include "InitTweak/GenInit.h" 43 43 #include "InitTweak/FixInit.h" 44 #include "InitTweak/FixGlobalInit.h" 44 45 //#include "Explain/GenProlog.h" 45 46 //#include "Try/Visit.h" … … 281 282 OPTPRINT( "fixNames" ) 282 283 CodeGen::fixNames( translationUnit ); 284 OPTPRINT( "fixGlobalInit" ); 285 InitTweak::fixGlobalInit( translationUnit, filename, libcfap || treep ); 283 286 OPTPRINT( "tweakInit" ) 284 287 InitTweak::genInit( translationUnit ); … … 301 304 } 302 305 306 OPTPRINT( "fixInit" ) 303 307 // fix ObjectDecl - replaces ConstructorInit nodes 304 OPTPRINT( "fixInit" ) 305 InitTweak::fix( translationUnit, filename, libcfap || treep ); 308 InitTweak::fix( translationUnit ); 306 309 if ( ctorinitp ) { 307 310 dump ( translationUnit ); -
src/tests/.expect/64/extension.txt
r73bf8cf2 raea7168 100 100 ((void)((__extension__ __a__i_2 , __extension__ __b__i_2) , __extension__ __c__i_2)); 101 101 } 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 92 92 init_once y = x; 93 93 94 void static_variable() {95 static init_once x;96 }97 98 94 int main() { 99 95 // local variables … … 183 179 } 184 180 } 185 186 // function-scoped static variable187 for (int i = 0; i < 10; i++) {188 static_variable();189 }190 181 } 191 182
Note:
See TracChangeset
for help on using the changeset viewer.