Changes in src/InitTweak/GenInit.cc [dcd73d1:f0121d7]
- File:
-
- 1 edited
-
src/InitTweak/GenInit.cc (modified) (10 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/InitTweak/GenInit.cc
rdcd73d1 rf0121d7 29 29 #include "GenPoly/DeclMutator.h" 30 30 #include "GenPoly/ScopedSet.h" 31 #include "ResolvExpr/typeops.h" 31 32 32 33 namespace InitTweak { … … 50 51 51 52 protected: 52 std::list<DeclarationWithType*> returnVals;53 FunctionType * ftype; 53 54 UniqueName tempNamer; 54 55 std::string funcName; … … 86 87 87 88 bool isManaged( ObjectDecl * objDecl ) const ; // determine if object is managed 89 bool isManaged( Type * type ) const; // determine if type is managed 88 90 void handleDWT( DeclarationWithType * dwt ); // add type to managed if ctor/dtor 89 91 GenPoly::ScopedSet< std::string > managedTypes; … … 134 136 135 137 Statement *ReturnFixer::mutate( ReturnStmt *returnStmt ) { 136 // update for multiple return values138 std::list< DeclarationWithType * > & returnVals = ftype->get_returnVals(); 137 139 assert( returnVals.size() == 0 || returnVals.size() == 1 ); 138 140 // hands off if the function returns an lvalue - we don't want to allocate a temporary if a variable's address … … 156 158 157 159 DeclarationWithType* ReturnFixer::mutate( FunctionDecl *functionDecl ) { 158 ValueGuard< std::list<DeclarationWithType*> > oldReturnVals( returnVals ); 160 // xxx - need to handle named return values - this pass may need to happen 161 // after resolution? the ordering is tricky because return statements must be 162 // constructed - the simplest way to do that (while also handling multiple 163 // returns) is to structure the returnVals into a tuple, as done here. 164 // however, if the tuple return value is structured before resolution, 165 // it's difficult to resolve named return values, since the name is lost 166 // in conversion to a tuple. this might be easiest to deal with 167 // after reference types are added, as it may then be possible to 168 // uniformly move named return values to the parameter list directly 169 ValueGuard< FunctionType * > oldFtype( ftype ); 159 170 ValueGuard< std::string > oldFuncName( funcName ); 160 171 161 FunctionType * type = functionDecl->get_functionType(); 162 returnVals = type->get_returnVals(); 172 ftype = functionDecl->get_functionType(); 173 std::list< DeclarationWithType * > & retVals = ftype->get_returnVals(); 174 if ( retVals.size() > 1 ) { 175 TupleType * tupleType = safe_dynamic_cast< TupleType * >( ResolvExpr::extractResultType( ftype ) ); 176 ObjectDecl * newRet = new ObjectDecl( tempNamer.newName(), DeclarationNode::NoStorageClass, LinkageSpec::C, 0, tupleType, new ListInit( std::list<Initializer*>(), noDesignators, false ) ); 177 retVals.clear(); 178 retVals.push_back( newRet ); 179 } 163 180 funcName = functionDecl->get_name(); 164 181 DeclarationWithType * decl = Mutator::mutate( functionDecl ); … … 220 237 } 221 238 239 bool CtorDtor::isManaged( Type * type ) const { 240 if ( TupleType * tupleType = dynamic_cast< TupleType * > ( type ) ) { 241 // tuple is also managed if any of its components are managed 242 if ( std::any_of( tupleType->get_types().begin(), tupleType->get_types().end(), [&](Type * type) { return isManaged( type ); }) ) { 243 return true; 244 } 245 } 246 return managedTypes.find( SymTab::Mangler::mangle( type ) ) != managedTypes.end(); 247 } 248 222 249 bool CtorDtor::isManaged( ObjectDecl * objDecl ) const { 223 250 Type * type = objDecl->get_type(); … … 225 252 type = at->get_base(); 226 253 } 227 return managedTypes.find( SymTab::Mangler::mangle( type ) ) != managedTypes.end();254 return isManaged( type ); 228 255 } 229 256 … … 236 263 managedTypes.insert( SymTab::Mangler::mangle( type->get_base() ) ); 237 264 } 265 } 266 267 ConstructorInit * genCtorInit( ObjectDecl * objDecl ) { 268 // call into genImplicitCall from Autogen.h to generate calls to ctor/dtor 269 // for each constructable object 270 std::list< Statement * > ctor; 271 std::list< Statement * > dtor; 272 273 InitExpander srcParam( objDecl->get_init() ); 274 InitExpander nullParam( (Initializer *)NULL ); 275 SymTab::genImplicitCall( srcParam, new VariableExpr( objDecl ), "?{}", back_inserter( ctor ), objDecl ); 276 SymTab::genImplicitCall( nullParam, new VariableExpr( objDecl ), "^?{}", front_inserter( dtor ), objDecl, false ); 277 278 // Currently genImplicitCall produces a single Statement - a CompoundStmt 279 // which wraps everything that needs to happen. As such, it's technically 280 // possible to use a Statement ** in the above calls, but this is inherently 281 // unsafe, so instead we take the slightly less efficient route, but will be 282 // immediately informed if somehow the above assumption is broken. In this case, 283 // we could always wrap the list of statements at this point with a CompoundStmt, 284 // but it seems reasonable at the moment for this to be done by genImplicitCall 285 // itself. It is possible that genImplicitCall produces no statements (e.g. if 286 // an array type does not have a dimension). In this case, it's fine to ignore 287 // the object for the purposes of construction. 288 assert( ctor.size() == dtor.size() && ctor.size() <= 1 ); 289 if ( ctor.size() == 1 ) { 290 // need to remember init expression, in case no ctors exist 291 // if ctor does exist, want to use ctor expression instead of init 292 // push this decision to the resolver 293 assert( dynamic_cast< ImplicitCtorDtorStmt * > ( ctor.front() ) && dynamic_cast< ImplicitCtorDtorStmt * > ( dtor.front() ) ); 294 return new ConstructorInit( ctor.front(), dtor.front(), objDecl->get_init() ); 295 } 296 return nullptr; 238 297 } 239 298 … … 248 307 if ( ! checkInitDepth( objDecl ) ) throw SemanticError( "Managed object's initializer is too deep ", objDecl ); 249 308 250 // call into genImplicitCall from Autogen.h to generate calls to ctor/dtor 251 // for each constructable object 252 std::list< Statement * > ctor; 253 std::list< Statement * > dtor; 254 255 InitExpander srcParam( objDecl->get_init() ); 256 InitExpander nullParam( (Initializer *)NULL ); 257 SymTab::genImplicitCall( srcParam, new VariableExpr( objDecl ), "?{}", back_inserter( ctor ), objDecl ); 258 SymTab::genImplicitCall( nullParam, new VariableExpr( objDecl ), "^?{}", front_inserter( dtor ), objDecl, false ); 259 260 // Currently genImplicitCall produces a single Statement - a CompoundStmt 261 // which wraps everything that needs to happen. As such, it's technically 262 // possible to use a Statement ** in the above calls, but this is inherently 263 // unsafe, so instead we take the slightly less efficient route, but will be 264 // immediately informed if somehow the above assumption is broken. In this case, 265 // we could always wrap the list of statements at this point with a CompoundStmt, 266 // but it seems reasonable at the moment for this to be done by genImplicitCall 267 // itself. It is possible that genImplicitCall produces no statements (e.g. if 268 // an array type does not have a dimension). In this case, it's fine to ignore 269 // the object for the purposes of construction. 270 assert( ctor.size() == dtor.size() && ctor.size() <= 1 ); 271 if ( ctor.size() == 1 ) { 272 // need to remember init expression, in case no ctors exist 273 // if ctor does exist, want to use ctor expression instead of init 274 // push this decision to the resolver 275 assert( dynamic_cast< ImplicitCtorDtorStmt * > ( ctor.front() ) && dynamic_cast< ImplicitCtorDtorStmt * > ( dtor.front() ) ); 276 objDecl->set_init( new ConstructorInit( ctor.front(), dtor.front(), objDecl->get_init() ) ); 277 } 309 objDecl->set_init( genCtorInit( objDecl ) ); 278 310 } 279 311 return Parent::mutate( objDecl ); … … 288 320 managedTypes.beginScope(); 289 321 // go through assertions and recursively add seen ctor/dtors 290 for ( TypeDecl *tyDecl : functionDecl->get_functionType()->get_forall() ) {322 for ( auto & tyDecl : functionDecl->get_functionType()->get_forall() ) { 291 323 for ( DeclarationWithType *& assertion : tyDecl->get_assertions() ) { 292 324 assertion = assertion->acceptMutator( *this );
Note:
See TracChangeset
for help on using the changeset viewer.