Changeset 90152a4 for src/InitTweak
- Timestamp:
- Aug 27, 2018, 4:40:34 PM (6 years ago)
- Branches:
- ADT, arm-eh, ast-experimental, cleanup-dtors, enum, forall-pointer-decay, jacob/cs343-translation, jenkins-sandbox, master, new-ast, new-ast-unique-expr, pthread-emulation, qualifiedEnum
- Children:
- b7c89aa
- Parents:
- f9feab8 (diff), 305581d (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the(diff)
links above to see all the changes relative to each parent. - Location:
- src/InitTweak
- Files:
-
- 6 edited
Legend:
- Unmodified
- Added
- Removed
-
src/InitTweak/FixGlobalInit.cc
rf9feab8 r90152a4 21 21 22 22 #include "Common/PassVisitor.h" 23 #include "Common/SemanticError.h" // for SemanticError24 23 #include "Common/UniqueName.h" // for UniqueName 25 24 #include "InitTweak.h" // for isIntrinsicSingleArgCallStmt … … 38 37 class GlobalFixer : public WithShortCircuiting { 39 38 public: 40 GlobalFixer( const std::string & name,bool inLibrary );39 GlobalFixer( bool inLibrary ); 41 40 42 41 void previsit( ObjectDecl *objDecl ); … … 53 52 }; 54 53 55 void fixGlobalInit( std::list< Declaration * > & translationUnit, const std::string & name,bool inLibrary ) {56 PassVisitor<GlobalFixer> visitor( name,inLibrary );54 void fixGlobalInit( std::list< Declaration * > & translationUnit, bool inLibrary ) { 55 PassVisitor<GlobalFixer> visitor( inLibrary ); 57 56 acceptAll( translationUnit, visitor ); 58 57 GlobalFixer & fixer = visitor.pass; … … 71 70 } 72 71 73 std::string globalFunctionName( const std::string & name ) { 74 // get basename 75 std::string ret = name.substr( 0, name.find( '.' ) ); 76 // replace invalid characters with _ 77 static std::string invalid = "/-"; 78 replace_if( ret.begin(), ret.end(), []( char c ) { return invalid.find(c) != std::string::npos; }, '_' ); 79 return ret; 80 } 81 82 GlobalFixer::GlobalFixer( const std::string & name, bool inLibrary ) : tempNamer( "_global_init" ) { 83 std::string fixedName = globalFunctionName( name ); 72 GlobalFixer::GlobalFixer( bool inLibrary ) : tempNamer( "_global_init" ) { 84 73 std::list< Expression * > ctorParameters; 85 74 std::list< Expression * > dtorParameters; … … 91 80 // for library code are run before constructors and destructors for user code, 92 81 // specify a priority when building the library. Priorities 0-100 are reserved by gcc. 93 ctorParameters.push_back( new ConstantExpr( Constant::from_int( 102 ) ) ); 94 dtorParameters.push_back( new ConstantExpr( Constant::from_int( 102 ) ) ); 82 // Priorities 101-200 are reserved by cfa, so use priority 200 for CFA library globals, 83 // allowing room for overriding with a higher priority. 84 ctorParameters.push_back( new ConstantExpr( Constant::from_int( 200 ) ) ); 85 dtorParameters.push_back( new ConstantExpr( Constant::from_int( 200 ) ) ); 95 86 } 96 initFunction = new FunctionDecl( "_ init_" + fixedName, Type::StorageClasses( Type::Static ), LinkageSpec::C, new FunctionType( Type::Qualifiers(), false ), new CompoundStmt() );87 initFunction = new FunctionDecl( "__global_init__", Type::StorageClasses( Type::Static ), LinkageSpec::C, new FunctionType( Type::Qualifiers(), false ), new CompoundStmt() ); 97 88 initFunction->get_attributes().push_back( new Attribute( "constructor", ctorParameters ) ); 98 destroyFunction = new FunctionDecl( "_ destroy_" + fixedName, Type::StorageClasses( Type::Static ), LinkageSpec::C, new FunctionType( Type::Qualifiers(), false ), new CompoundStmt() );89 destroyFunction = new FunctionDecl( "__global_destroy__", Type::StorageClasses( Type::Static ), LinkageSpec::C, new FunctionType( Type::Qualifiers(), false ), new CompoundStmt() ); 99 90 destroyFunction->get_attributes().push_back( new Attribute( "destructor", dtorParameters ) ); 100 91 } … … 111 102 if ( ConstructorInit * ctorInit = dynamic_cast< ConstructorInit * >( objDecl->get_init() ) ) { 112 103 // a decision should have been made by the resolver, so ctor and init are not both non-NULL 113 assert( ! ctorInit-> get_ctor() || ! ctorInit->get_init());104 assert( ! ctorInit->ctor || ! ctorInit->init ); 114 105 115 Statement * dtor = ctorInit-> get_dtor();106 Statement * dtor = ctorInit->dtor; 116 107 if ( dtor && ! isIntrinsicSingleArgCallStmt( dtor ) ) { 117 108 // don't need to call intrinsic dtor, because it does nothing, but 118 109 // non-intrinsic dtors must be called 119 110 destroyStatements.push_front( dtor ); 120 ctorInit-> set_dtor( NULL );111 ctorInit->dtor = nullptr; 121 112 } // if 122 if ( Statement * ctor = ctorInit-> get_ctor()) {113 if ( Statement * ctor = ctorInit->ctor ) { 123 114 initStatements.push_back( ctor ); 124 objDecl-> set_init( NULL );125 ctorInit-> set_ctor( NULL );126 } else if ( Initializer * init = ctorInit-> get_init()) {127 objDecl-> set_init( init );128 ctorInit-> set_init( NULL );115 objDecl->init = nullptr; 116 ctorInit->ctor = nullptr; 117 } else if ( Initializer * init = ctorInit->init ) { 118 objDecl->init = init; 119 ctorInit->init = nullptr; 129 120 } else { 130 121 // no constructor and no initializer, which is okay 131 objDecl-> set_init( NULL );122 objDecl->init = nullptr; 132 123 } // if 133 124 delete ctorInit; -
src/InitTweak/FixGlobalInit.h
rf9feab8 r90152a4 22 22 23 23 namespace InitTweak { 24 /// Moves global initialization into an _init function that is unique to the translation unit. 25 /// Sets the priority of the initialization function depending on whether the initialization 26 /// function is for library code. 27 void fixGlobalInit( std::list< Declaration * > & translationUnit, const std::string & name, bool inLibrary ); 28 29 /// Apply transformations to a file name to get a valid C identifier which will be used as 30 /// the name of the generated initializer function. 31 std::string globalFunctionName( const std::string & name ); 24 /// Moves global initialization into an _init function that is unique to the translation unit. 25 /// Sets the priority of the initialization function depending on whether the initialization 26 /// function is for library code. 27 void fixGlobalInit( std::list< Declaration * > & translationUnit, bool inLibrary ); 32 28 } // namespace 33 29 -
src/InitTweak/FixInit.cc
rf9feab8 r90152a4 5 5 // file "LICENCE" distributed with Cforall. 6 6 // 7 // FixInit. h--7 // FixInit.cc -- 8 8 // 9 9 // Author : Rob Schluntz … … 54 54 #include "SynTree/Type.h" // for Type, Type::StorageClasses 55 55 #include "SynTree/TypeSubstitution.h" // for TypeSubstitution, operator<< 56 #include "SynTree/ VarExprReplacer.h" // for VarExprReplacer56 #include "SynTree/DeclReplacer.h" // for DeclReplacer 57 57 #include "SynTree/Visitor.h" // for acceptAll, maybeAccept 58 58 … … 68 68 namespace { 69 69 typedef std::unordered_map< int, int > UnqCount; 70 71 struct SelfAssignChecker { 72 void previsit( ApplicationExpr * appExpr ); 73 }; 70 74 71 75 struct InsertImplicitCalls : public WithTypeSubstitution { … … 180 184 }; 181 185 182 class FixCopyCtors final : public WithStmtsToAdd, public WithShortCircuiting, public WithVisitorRef<FixCopyCtors> {186 class FixCopyCtors final : public WithStmtsToAdd, public WithShortCircuiting, public WithVisitorRef<FixCopyCtors>, public WithTypeSubstitution { 183 187 public: 184 188 FixCopyCtors( UnqCount & unqCount ) : unqCount( unqCount ){} … … 194 198 }; 195 199 196 struct GenStructMemberCalls final : public WithGuards, public WithShortCircuiting, public WithIndexer {200 struct GenStructMemberCalls final : public WithGuards, public WithShortCircuiting, public WithIndexer, public WithVisitorRef<GenStructMemberCalls> { 197 201 /// generate default/copy ctor and dtor calls for user-defined struct ctor/dtors 198 202 /// for any member that is missing a corresponding ctor/dtor call. … … 200 204 static void generate( std::list< Declaration * > & translationUnit ); 201 205 202 void previsit( StructDecl * structDecl ); 203 204 void previsit( FunctionDecl * funcDecl ); 205 void postvisit( FunctionDecl * funcDecl ); 206 207 void previsit( MemberExpr * memberExpr ); 208 void previsit( ApplicationExpr * appExpr ); 209 210 SemanticError errors; 206 void premutate( StructDecl * structDecl ); 207 208 void premutate( FunctionDecl * funcDecl ); 209 DeclarationWithType * postmutate( FunctionDecl * funcDecl ); 210 211 void premutate( MemberExpr * memberExpr ); 212 void premutate( ApplicationExpr * appExpr ); 213 214 /// Note: this post mutate used to be in a separate visitor. If this pass breaks, one place to examine is whether it is 215 /// okay for this part of the recursion to occur alongside the rest. 216 Expression * postmutate( UntypedExpr * expr ); 217 218 SemanticErrorException errors; 211 219 private: 212 220 template< typename... Params > … … 225 233 }; 226 234 227 // very simple resolver-like mutator class - used to228 // resolve UntypedExprs that are found within newly229 // generated constructor/destructor calls230 class MutatingResolver final : public Mutator {231 public:232 MutatingResolver( SymTab::Indexer & indexer ) : indexer( indexer ) {}233 234 using Mutator::mutate;235 virtual DeclarationWithType* mutate( ObjectDecl *objectDecl ) override;236 virtual Expression* mutate( UntypedExpr *untypedExpr ) override;237 238 private:239 SymTab::Indexer & indexer;240 };241 242 235 struct FixCtorExprs final : public WithDeclsToAdd, public WithIndexer { 243 236 /// expands ConstructorExpr nodes into comma expressions, using a temporary for the first argument … … 248 241 } // namespace 249 242 250 void fix( std::list< Declaration * > & translationUnit, const std::string & filename, bool inLibrary ) { 243 void fix( std::list< Declaration * > & translationUnit, bool inLibrary ) { 244 PassVisitor<SelfAssignChecker> checker; 245 acceptAll( translationUnit, checker ); 246 251 247 // fixes ConstructorInit for global variables. should happen before fixInitializers. 252 InitTweak::fixGlobalInit( translationUnit, filename,inLibrary );248 InitTweak::fixGlobalInit( translationUnit, inLibrary ); 253 249 254 250 UnqCount unqCount; … … 290 286 // can't use mutateAll, because need to insert declarations at top-level 291 287 // can't use DeclMutator, because sometimes need to insert IfStmt, etc. 292 SemanticError errors;288 SemanticErrorException errors; 293 289 for ( std::list< Declaration * >::iterator i = translationUnit.begin(); i != translationUnit.end(); ++i ) { 294 290 try { 295 291 maybeMutate( *i, fixer ); 296 292 translationUnit.splice( i, fixer.pass.staticDtorDecls ); 297 } catch( SemanticError &e ) { 298 e.set_location( (*i)->location ); 293 } catch( SemanticErrorException &e ) { 299 294 errors.append( e ); 300 295 } // try … … 318 313 void GenStructMemberCalls::generate( std::list< Declaration * > & translationUnit ) { 319 314 PassVisitor<GenStructMemberCalls> warner; 320 acceptAll( translationUnit, warner );315 mutateAll( translationUnit, warner ); 321 316 } 322 317 … … 324 319 PassVisitor<FixCtorExprs> fixer; 325 320 mutateAll( translationUnit, fixer ); 321 } 322 323 namespace { 324 // Relatively simple structural comparison for expressions, needed to determine 325 // if two expressions are "the same" (used to determine if self assignment occurs) 326 struct StructuralChecker { 327 Expression * stripCasts( Expression * expr ) { 328 // this might be too permissive. It's possible that only particular casts are relevant. 329 while ( CastExpr * cast = dynamic_cast< CastExpr * >( expr ) ) { 330 expr = cast->arg; 331 } 332 return expr; 333 } 334 335 void previsit( Expression * ) { 336 // anything else does not qualify 337 isSimilar = false; 338 } 339 340 template<typename T> 341 T * cast( Expression * node ) { 342 // all expressions need to ignore casts, so this bit has been factored out 343 return dynamic_cast< T * >( stripCasts( node ) ); 344 } 345 346 // ignore casts 347 void previsit( CastExpr * ) {} 348 349 void previsit( MemberExpr * memExpr ) { 350 if ( MemberExpr * otherMember = cast< MemberExpr >( other ) ) { 351 if ( otherMember->member == memExpr->member ) { 352 other = otherMember->aggregate; 353 return; 354 } 355 } 356 isSimilar = false; 357 } 358 359 void previsit( VariableExpr * varExpr ) { 360 if ( VariableExpr * otherVar = cast< VariableExpr >( other ) ) { 361 if ( otherVar->var == varExpr->var ) { 362 return; 363 } 364 } 365 isSimilar = false; 366 } 367 368 void previsit( AddressExpr * ) { 369 if ( AddressExpr * addrExpr = cast< AddressExpr >( other ) ) { 370 other = addrExpr->arg; 371 return; 372 } 373 isSimilar = false; 374 } 375 376 Expression * other = nullptr; 377 bool isSimilar = true; 378 }; 379 380 bool structurallySimilar( Expression * e1, Expression * e2 ) { 381 PassVisitor<StructuralChecker> checker; 382 checker.pass.other = e2; 383 e1->accept( checker ); 384 return checker.pass.isSimilar; 385 } 386 } 387 388 void SelfAssignChecker::previsit( ApplicationExpr * appExpr ) { 389 DeclarationWithType * function = getFunction( appExpr ); 390 if ( function->name == "?=?" ) { // doesn't use isAssignment, because ?+=?, etc. should not count as self-assignment 391 if ( appExpr->args.size() == 2 ) { 392 // check for structural similarity (same variable use, ignore casts, etc. - but does not look too deeply, anything looking like a function is off limits) 393 if ( structurallySimilar( appExpr->args.front(), appExpr->args.back() ) ) { 394 SemanticWarning( appExpr->location, Warning::SelfAssignment, toCString( appExpr->args.front() ) ); 395 } 396 } 397 } 326 398 } 327 399 … … 368 440 // arrays are not copy constructed, so this should always be an ExprStmt 369 441 ImplicitCtorDtorStmt * stmt = genCtorDtor( fname, var, cpArg ); 370 ExprStmt * exprStmt = strict_dynamic_cast< ExprStmt * >( stmt->get_callStmt() ); 442 assertf( stmt, "ResolveCopyCtors: genCtorDtor returned nullptr: %s / %s / %s", fname.c_str(), toString( var ).c_str(), toString( cpArg ).c_str() ); 443 ExprStmt * exprStmt = strict_dynamic_cast< ExprStmt * >( stmt->callStmt ); 371 444 Expression * resolved = exprStmt->expr; 372 445 exprStmt->expr = nullptr; // take ownership of expr … … 378 451 ResolvExpr::findVoidExpression( resolved, indexer ); 379 452 assert( resolved ); 380 if ( resolved-> get_env()) {453 if ( resolved->env ) { 381 454 // Extract useful information and discard new environments. Keeping them causes problems in PolyMutator passes. 382 env->add( *resolved-> get_env());383 delete resolved-> get_env();384 resolved-> set_env( nullptr );455 env->add( *resolved->env ); 456 delete resolved->env; 457 resolved->env = nullptr; 385 458 } // if 386 459 delete stmt; 460 if ( TupleAssignExpr * assign = dynamic_cast< TupleAssignExpr * >( resolved ) ) { 461 // fix newly generated StmtExpr 462 postvisit( assign->stmtExpr ); 463 } 387 464 return resolved; 388 465 } … … 478 555 static UniqueName retNamer("_tmp_stmtexpr_ret"); 479 556 480 // create variable that will hold the result of the stmt expr481 557 result = result->clone(); 482 558 env->apply( result ); 559 if ( ! InitTweak::isConstructable( result ) ) { 560 delete result; 561 return; 562 } 563 564 // create variable that will hold the result of the stmt expr 483 565 ObjectDecl * ret = ObjectDecl::newObject( retNamer.newName(), result, nullptr ); 484 ret-> get_type()->set_const( false );485 stmtExpr-> get_returnDecls().push_front( ret );566 ret->type->set_const( false ); 567 stmtExpr->returnDecls.push_front( ret ); 486 568 487 569 // must have a non-empty body, otherwise it wouldn't have a result 488 CompoundStmt * body = stmtExpr-> get_statements();570 CompoundStmt * body = stmtExpr->statements; 489 571 assert( ! body->get_kids().empty() ); 490 572 // must be an ExprStmt, otherwise it wouldn't have a result 491 573 ExprStmt * last = strict_dynamic_cast< ExprStmt * >( body->get_kids().back() ); 492 last-> set_expr( makeCtorDtor( "?{}", ret, last->get_expr()) );493 494 stmtExpr-> get_dtors().push_front( makeCtorDtor( "^?{}", ret ) );574 last->expr = makeCtorDtor( "?{}", ret, last->get_expr() ); 575 576 stmtExpr->dtors.push_front( makeCtorDtor( "^?{}", ret ) ); 495 577 } // if 496 578 } … … 555 637 // add destructors after current statement 556 638 for ( Expression * dtor : dtors ) { 639 // take relevant bindings from environment 640 assert( ! dtor->env ); 641 dtor->env = maybeClone( env ); 557 642 stmtsToAddAfter.push_back( new ExprStmt( dtor ) ); 558 643 } // for … … 593 678 // to the outer context, rather than inside of the statement expression. 594 679 visit_children = false; 595 std::list< Statement * > & stmts = stmtExpr-> get_statements()->get_kids();680 std::list< Statement * > & stmts = stmtExpr->statements->get_kids(); 596 681 for ( Statement *& stmt : stmts ) { 597 682 stmt = stmt->acceptMutator( *visitor ); 598 683 } // for 599 assert( stmtExpr-> get_result());600 Type * result = stmtExpr-> get_result();684 assert( stmtExpr->result ); 685 Type * result = stmtExpr->result; 601 686 if ( ! result->isVoid() ) { 602 for ( ObjectDecl * obj : stmtExpr-> get_returnDecls()) {687 for ( ObjectDecl * obj : stmtExpr->returnDecls ) { 603 688 stmtsToAddBefore.push_back( new DeclStmt( obj ) ); 604 689 } // for 605 690 // add destructors after current statement 606 for ( Expression * dtor : stmtExpr-> get_dtors()) {691 for ( Expression * dtor : stmtExpr->dtors ) { 607 692 stmtsToAddAfter.push_back( new ExprStmt( dtor ) ); 608 693 } // for 609 694 // must have a non-empty body, otherwise it wouldn't have a result 610 695 assert( ! stmts.empty() ); 611 assert( ! stmtExpr->get_returnDecls().empty() ); 612 stmts.push_back( new ExprStmt( new VariableExpr( stmtExpr->get_returnDecls().front() ) ) ); 613 stmtExpr->get_returnDecls().clear(); 614 stmtExpr->get_dtors().clear(); 615 } 616 assert( stmtExpr->get_returnDecls().empty() ); 617 assert( stmtExpr->get_dtors().empty() ); 696 assertf( ! stmtExpr->returnDecls.empty() || stmtExpr->dtors.empty(), "StmtExpr returns non-void, but no return decls: %s", toString( stmtExpr ).c_str() ); 697 // if there is a return decl, add a use as the last statement; will not have return decl on non-constructable returns 698 if ( ! stmtExpr->returnDecls.empty() ) { 699 stmts.push_back( new ExprStmt( new VariableExpr( stmtExpr->returnDecls.front() ) ) ); 700 } 701 stmtExpr->returnDecls.clear(); 702 stmtExpr->dtors.clear(); 703 } 704 assert( stmtExpr->returnDecls.empty() ); 705 assert( stmtExpr->dtors.empty() ); 618 706 } 619 707 … … 692 780 replacement = new CastExpr( replacement, base->clone() ); 693 781 } 694 VarExprReplacer::replace( dtor, { std::make_pair( objDecl, replacement ) } );695 dtorFunc->statements->push_back( dtor);782 DeclReplacer::replace( dtor, { std::make_pair( objDecl, replacement ) } ); 783 dtorFunc->statements->push_back( strict_dynamic_cast<Statement *>( dtor ) ); 696 784 697 785 return dtorFunc; … … 905 993 ) 906 994 if ( ! diff.empty() ) { 907 throw SemanticError( std::string("jump to label '") + stmt->get_target().get_name() + "' crosses initialization of " + (*diff.begin())->get_name() + " ", stmt);995 SemanticError( stmt, std::string("jump to label '") + stmt->get_target().get_name() + "' crosses initialization of " + (*diff.begin())->get_name() + " " ); 908 996 } // if 909 997 } … … 931 1019 } 932 1020 933 void GenStructMemberCalls::pre visit( StructDecl * structDecl ) {1021 void GenStructMemberCalls::premutate( StructDecl * structDecl ) { 934 1022 if ( ! dtorStruct && structDecl->name == "__Destructor" ) { 935 1023 dtorStruct = structDecl; … … 937 1025 } 938 1026 939 void GenStructMemberCalls::pre visit( FunctionDecl * funcDecl ) {1027 void GenStructMemberCalls::premutate( FunctionDecl * funcDecl ) { 940 1028 GuardValue( function ); 941 1029 GuardValue( unhandled ); … … 944 1032 GuardValue( isCtor ); 945 1033 GuardValue( structDecl ); 946 errors = SemanticError (); // clear previous errors1034 errors = SemanticErrorException(); // clear previous errors 947 1035 948 1036 // need to start with fresh sets … … 977 1065 } 978 1066 979 void GenStructMemberCalls::postvisit( FunctionDecl * funcDecl ) {1067 DeclarationWithType * GenStructMemberCalls::postmutate( FunctionDecl * funcDecl ) { 980 1068 // remove the unhandled objects from usedUninit, because a call is inserted 981 1069 // to handle them - only objects that are later constructed are used uninitialized. … … 1031 1119 Statement * callStmt = stmt.front(); 1032 1120 1033 MutatingResolver resolver( indexer );1034 1121 try { 1035 callStmt->acceptMutator( resolver );1122 callStmt->acceptMutator( *visitor ); 1036 1123 if ( isCtor ) { 1037 1124 function->statements->push_front( callStmt ); … … 1061 1148 function->statements->kids.splice( function->statements->kids.begin(), stmtsToAdd ); 1062 1149 } 1063 } catch ( SemanticError & error ) {1150 } catch ( SemanticErrorException & error ) { 1064 1151 emit( funcDecl->location, "in ", CodeGen::genPrettyType( function->get_functionType(), function->get_name() ), ", field ", field->get_name(), " not explicitly ", isCtor ? "constructed" : "destructed", " and no ", isCtor ? "default constructor" : "destructor", " found" ); 1065 1152 } … … 1070 1157 throw errors; 1071 1158 } 1159 return funcDecl; 1072 1160 } 1073 1161 … … 1095 1183 } 1096 1184 1097 void GenStructMemberCalls::pre visit( ApplicationExpr * appExpr ) {1185 void GenStructMemberCalls::premutate( ApplicationExpr * appExpr ) { 1098 1186 if ( ! checkWarnings( function ) ) { 1099 1187 visit_children = false; … … 1102 1190 1103 1191 std::string fname = getFunctionName( appExpr ); 1104 if ( fname == function-> get_name()) {1192 if ( fname == function->name ) { 1105 1193 // call to same kind of function 1106 Expression * firstParam = appExpr-> get_args().front();1194 Expression * firstParam = appExpr->args.front(); 1107 1195 1108 1196 if ( isThisExpression( firstParam, thisParam ) ) { … … 1113 1201 // if first parameter is a member expression on the this parameter, 1114 1202 // then remove the member from unhandled set. 1115 if ( isThisExpression( memberExpr-> get_aggregate(), thisParam ) ) {1116 unhandled.erase( memberExpr-> get_member());1203 if ( isThisExpression( memberExpr->aggregate, thisParam ) ) { 1204 unhandled.erase( memberExpr->member ); 1117 1205 } 1118 1206 } … … 1120 1208 } 1121 1209 1122 void GenStructMemberCalls::pre visit( MemberExpr * memberExpr ) {1210 void GenStructMemberCalls::premutate( MemberExpr * memberExpr ) { 1123 1211 if ( ! checkWarnings( function ) || ! isCtor ) { 1124 1212 visit_children = false; … … 1136 1224 template< typename Visitor, typename... Params > 1137 1225 void error( Visitor & v, CodeLocation loc, const Params &... params ) { 1138 SemanticError err( toString( params... ) ); 1139 err.set_location( loc ); 1226 SemanticErrorException err( loc, toString( params... ) ); 1140 1227 v.errors.append( err ); 1141 1228 } … … 1148 1235 } 1149 1236 1150 DeclarationWithType * MutatingResolver::mutate( ObjectDecl * objectDecl ) { 1151 // add object to the indexer assumes that there will be no name collisions 1152 // in generated code. If this changes, add mutate methods for entities with 1153 // scope and call {enter,leave}Scope explicitly. 1154 indexer.addId( objectDecl ); 1155 return objectDecl; 1156 } 1157 1158 Expression * MutatingResolver::mutate( UntypedExpr * untypedExpr ) { 1237 Expression * GenStructMemberCalls::postmutate( UntypedExpr * untypedExpr ) { 1159 1238 Expression * newExpr = untypedExpr; 1160 1239 ResolvExpr::findVoidExpression( newExpr, indexer ); -
src/InitTweak/FixInit.h
rf9feab8 r90152a4 24 24 /// replace constructor initializers with expression statements 25 25 /// and unwrap basic C-style initializers 26 void fix( std::list< Declaration * > & translationUnit, const std::string & name,bool inLibrary );26 void fix( std::list< Declaration * > & translationUnit, bool inLibrary ); 27 27 } // namespace 28 28 -
src/InitTweak/GenInit.cc
rf9feab8 r90152a4 30 30 #include "InitTweak.h" // for isConstExpr, InitExpander, checkIn... 31 31 #include "Parser/LinkageSpec.h" // for isOverridable, C 32 #include "ResolvExpr/Resolver.h" 32 33 #include "SymTab/Autogen.h" // for genImplicitCall, SizeType 33 34 #include "SymTab/Mangler.h" // for Mangler … … 40 41 #include "SynTree/Type.h" // for Type, ArrayType, Type::Qualifiers 41 42 #include "SynTree/Visitor.h" // for acceptAll, maybeAccept 43 #include "Tuples/Tuples.h" // for maybeImpure 42 44 43 45 namespace InitTweak { … … 89 91 }; 90 92 91 struct HoistArrayDimension final : public WithDeclsToAdd, public WithShortCircuiting, public WithGuards {93 struct HoistArrayDimension final : public WithDeclsToAdd, public WithShortCircuiting, public WithGuards, public WithIndexer { 92 94 /// hoist dimension from array types in object declaration so that it uses a single 93 95 /// const variable of type size_t, so that side effecting array dimensions are only … … 104 106 void premutate( FunctionType * ) { visit_children = false; } 105 107 108 // need this so that enumerators are added to the indexer, due to premutate(AggregateDecl *) 109 void premutate( EnumDecl * ) {} 110 106 111 void hoist( Type * type ); 107 112 … … 135 140 if ( varExpr->var == retVal ) return; 136 141 } 137 stmtsToAddBefore.push_back( genCtorDtor( "?{}", retVal, returnStmt->get_expr() ) ); 142 Statement * stmt = genCtorDtor( "?{}", retVal, returnStmt->expr ); 143 assertf( stmt, "ReturnFixer: genCtorDtor returned nullptr: %s / %s", toString( retVal ).c_str(), toString( returnStmt->expr ).c_str() ); 144 stmtsToAddBefore.push_back( stmt ); 138 145 139 146 // return the retVal object … … 178 185 if ( ! arrayType->get_dimension() ) return; // xxx - recursive call to hoist? 179 186 180 // don't need to hoist dimension if it's a constexpr - only need to if there's potential for side effects. 181 if ( isConstExpr( arrayType->get_dimension() ) ) return; 187 // need to resolve array dimensions in order to accurately determine if constexpr 188 ResolvExpr::findSingleExpression( arrayType->dimension, SymTab::SizeType->clone(), indexer ); 189 // array is variable-length when the dimension is not constexpr 190 arrayType->isVarLen = ! isConstExpr( arrayType->dimension ); 191 // don't need to hoist dimension if it's definitely pure - only need to if there's potential for side effects. 192 if ( ! Tuples::maybeImpure( arrayType->dimension ) ) return; 182 193 183 194 ObjectDecl * arrayDimension = new ObjectDecl( dimensionName.newName(), storageClasses, LinkageSpec::C, 0, SymTab::SizeType->clone(), new SingleInit( arrayType->get_dimension() ) ); … … 194 205 void HoistArrayDimension::premutate( FunctionDecl * ) { 195 206 GuardValue( inFunction ); 207 inFunction = true; 196 208 } 197 209 … … 220 232 Type * type = objDecl->get_type(); 221 233 while ( ArrayType * at = dynamic_cast< ArrayType * >( type ) ) { 234 // must always construct VLAs with an initializer, since this is an error in C 235 if ( at->isVarLen && objDecl->init ) return true; 222 236 type = at->get_base(); 223 237 } … … 303 317 if ( tryConstruct( objDecl ) && ( managedTypes.isManaged( objDecl ) || ((! inFunction || objDecl->get_storageClasses().is_static ) && ! isConstExpr( objDecl->get_init() ) ) ) ) { 304 318 // constructed objects cannot be designated 305 if ( isDesignated( objDecl->get_init() ) ) throw SemanticError( "Cannot include designations in the initializer for a managed Object. If this is really what you want, then initialize with @=.\n", objDecl);319 if ( isDesignated( objDecl->get_init() ) ) SemanticError( objDecl, "Cannot include designations in the initializer for a managed Object. If this is really what you want, then initialize with @=.\n" ); 306 320 // constructed objects should not have initializers nested too deeply 307 if ( ! checkInitDepth( objDecl ) ) throw SemanticError( "Managed object's initializer is too deep ", objDecl);321 if ( ! checkInitDepth( objDecl ) ) SemanticError( objDecl, "Managed object's initializer is too deep " ); 308 322 309 323 objDecl->set_init( genCtorInit( objDecl ) ); -
src/InitTweak/InitTweak.cc
rf9feab8 r90152a4 225 225 // xxx - this shouldn't be an error, but need a way to 226 226 // terminate without creating output, so should catch this error 227 throw SemanticError("unbalanced list initializers" );227 SemanticError( init->location, "unbalanced list initializers" ); 228 228 } 229 229 … … 296 296 ObjectDecl * objDecl = dynamic_cast< ObjectDecl * >( dwt ); 297 297 if ( ! objDecl ) return false; 298 return ! LinkageSpec::isBuiltin( objDecl->get_linkage() ) && 299 (objDecl->get_init() == nullptr || 298 return (objDecl->get_init() == nullptr || 300 299 ( objDecl->get_init() != nullptr && objDecl->get_init()->get_maybeConstructed() )) 301 300 && ! objDecl->get_storageClasses().is_extern … … 409 408 return allofCtorDtor( stmt, []( Expression * callExpr ){ 410 409 if ( ApplicationExpr * appExpr = isIntrinsicCallExpr( callExpr ) ) { 411 FunctionType *funcType = GenPoly::getFunctionType( appExpr-> get_function()->get_result());410 FunctionType *funcType = GenPoly::getFunctionType( appExpr->function->result ); 412 411 assert( funcType ); 413 412 return funcType->get_parameters().size() == 1; … … 529 528 } 530 529 if ( dynamic_cast< ReferenceType * >( dst->result ) ) { 531 dst = new AddressExpr( dst ); 530 for (int depth = dst->result->referenceDepth(); depth > 0; depth--) { 531 dst = new AddressExpr( dst ); 532 } 532 533 } else { 533 534 dst = new CastExpr( dst, new ReferenceType( noQualifiers, dst->result->clone() ) ); 534 535 } 535 536 if ( dynamic_cast< ReferenceType * >( src->result ) ) { 536 src = new CastExpr( src, new ReferenceType( noQualifiers, src->result->stripReferences()->clone() ) ); 537 for (int depth = src->result->referenceDepth(); depth > 0; depth--) { 538 src = new AddressExpr( src ); 539 } 540 // src = new CastExpr( src, new ReferenceType( noQualifiers, src->result->stripReferences()->clone() ) ); 537 541 } 538 542 return new ApplicationExpr( VariableExpr::functionPointer( assign ), { dst, src } ); … … 564 568 void previsit( ConstantExpr * ) {} 565 569 570 void previsit( VariableExpr * varExpr ) { 571 visit_children = false; 572 573 if ( EnumInstType * inst = dynamic_cast< EnumInstType * >( varExpr->result ) ) { 574 long long int value; 575 if ( inst->baseEnum->valueOf( varExpr->var, value ) ) { 576 // enumerators are const expr 577 return; 578 } 579 } 580 isConstExpr = false; 581 } 582 566 583 bool isConstExpr = true; 567 584 };
Note: See TracChangeset
for help on using the changeset viewer.