- File:
-
- 1 edited
-
src/ResolvExpr/AlternativeFinder.cc (modified) (62 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/ResolvExpr/AlternativeFinder.cc
r982f95d rd286cf68 21 21 #include <list> // for _List_iterator, list, _List_const_... 22 22 #include <map> // for _Rb_tree_iterator, map, _Rb_tree_c... 23 #include <memory> // for allocator_traits<>::value_type 23 #include <memory> // for allocator_traits<>::value_type, unique_ptr 24 24 #include <utility> // for pair 25 25 #include <vector> // for vector … … 35 35 #include "ResolveTypeof.h" // for resolveTypeof 36 36 #include "Resolver.h" // for resolveStmtExpr 37 #include "Common/GC.h" // for new_static_root38 37 #include "SymTab/Indexer.h" // for Indexer 39 38 #include "SymTab/Mangler.h" // for Mangler … … 98 97 void postvisit( InitExpr * initExpr ); 99 98 void postvisit( DeletedExpr * delExpr ); 99 void postvisit( GenericExpr * genExpr ); 100 100 101 101 /// Adds alternatives for anonymous members … … 166 166 candidate->env.apply( newType ); 167 167 mangleName = SymTab::Mangler::mangle( newType ); 168 delete newType; 168 169 } 169 170 std::map< std::string, PruneStruct >::iterator mapPlace = selected.find( mangleName ); … … 175 176 selected[ mangleName ] = current; 176 177 } else if ( candidate->cost == mapPlace->second.candidate->cost ) { 177 PRINT( 178 std::cerr << "marking ambiguous" << std::endl; 179 ) 180 mapPlace->second.isAmbiguous = true; 178 // if one of the candidates contains a deleted identifier, can pick the other, since 179 // deleted expressions should not be ambiguous if there is another option that is at least as good 180 if ( findDeletedExpr( candidate->expr ) ) { 181 // do nothing 182 PRINT( std::cerr << "candidate is deleted" << std::endl; ) 183 } else if ( findDeletedExpr( mapPlace->second.candidate->expr ) ) { 184 PRINT( std::cerr << "current is deleted" << std::endl; ) 185 selected[ mangleName ] = current; 186 } else { 187 PRINT( 188 std::cerr << "marking ambiguous" << std::endl; 189 ) 190 mapPlace->second.isAmbiguous = true; 191 } 181 192 } else { 182 193 PRINT( … … 233 244 } 234 245 235 void AlternativeFinder::find( Expression *expr, ResolvMode mode) {246 void AlternativeFinder::find( Expression *expr, bool adjust, bool prune, bool failFast ) { 236 247 PassVisitor<Finder> finder( *this ); 237 248 expr->accept( finder ); 238 if ( mode.failFast && alternatives.empty() ) {249 if ( failFast && alternatives.empty() ) { 239 250 PRINT( 240 251 std::cerr << "No reasonable alternatives for expression " << expr << std::endl; … … 242 253 SemanticError( expr, "No reasonable alternatives for expression " ); 243 254 } 244 if ( mode.prune ) {255 if ( prune ) { 245 256 auto oldsize = alternatives.size(); 246 257 PRINT( … … 250 261 AltList pruned; 251 262 pruneAlternatives( alternatives.begin(), alternatives.end(), back_inserter( pruned ) ); 252 if ( mode.failFast && pruned.empty() ) {263 if ( failFast && pruned.empty() ) { 253 264 std::ostringstream stream; 254 265 AltList winners; … … 269 280 } 270 281 // adjust types after pruning so that types substituted by pruneAlternatives are correctly adjusted 271 if ( mode.adjust) {272 for ( Alternative& i : alternatives) {273 adjustExprType( i .expr->result, i.env, indexer );282 for ( AltList::iterator i = alternatives.begin(); i != alternatives.end(); ++i ) { 283 if ( adjust ) { 284 adjustExprType( i->expr->get_result(), i->env, indexer ); 274 285 } 275 286 } … … 283 294 284 295 void AlternativeFinder::findWithAdjustment( Expression *expr ) { 285 find( expr, ResolvMode::withAdjustment());296 find( expr, true ); 286 297 } 287 298 288 299 void AlternativeFinder::findWithoutPrune( Expression * expr ) { 289 find( expr, ResolvMode::withoutPrune());300 find( expr, true, false ); 290 301 } 291 302 292 303 void AlternativeFinder::maybeFind( Expression * expr ) { 293 find( expr, ResolvMode::withoutFailFast());304 find( expr, true, true, false ); 294 305 } 295 306 … … 297 308 // adds anonymous member interpretations whenever an aggregate value type is seen. 298 309 // it's okay for the aggregate expression to have reference type -- cast it to the base type to treat the aggregate as the referenced value 299 Expression* aggrExpr = alt.expr->clone();300 alt.env.apply( aggrExpr-> get_result());301 Type * aggrType = aggrExpr-> get_result();310 std::unique_ptr<Expression> aggrExpr( alt.expr->clone() ); 311 alt.env.apply( aggrExpr->result ); 312 Type * aggrType = aggrExpr->result; 302 313 if ( dynamic_cast< ReferenceType * >( aggrType ) ) { 303 314 aggrType = aggrType->stripReferences(); 304 aggrExpr = new CastExpr{ aggrExpr, aggrType->clone() };305 } 306 307 if ( StructInstType *structInst = dynamic_cast< StructInstType* >( aggrExpr-> get_result()) ) {308 addAggMembers( structInst, aggrExpr , alt.cost+Cost::safe, alt.env, "" );309 } else if ( UnionInstType *unionInst = dynamic_cast< UnionInstType* >( aggrExpr-> get_result()) ) {310 addAggMembers( unionInst, aggrExpr , alt.cost+Cost::safe, alt.env, "" );315 aggrExpr.reset( new CastExpr( aggrExpr.release(), aggrType->clone() ) ); 316 } 317 318 if ( StructInstType *structInst = dynamic_cast< StructInstType* >( aggrExpr->result ) ) { 319 addAggMembers( structInst, aggrExpr.get(), alt.cost+Cost::safe, alt.env, "" ); 320 } else if ( UnionInstType *unionInst = dynamic_cast< UnionInstType* >( aggrExpr->result ) ) { 321 addAggMembers( unionInst, aggrExpr.get(), alt.cost+Cost::safe, alt.env, "" ); 311 322 } // if 312 323 } … … 317 328 aggInst->lookup( name, members ); 318 329 319 for ( std::list< Declaration* >::const_iterator i = members.begin(); i != members.end(); ++i ) { 320 if ( DeclarationWithType *dwt = dynamic_cast< DeclarationWithType* >( *i ) ) { 321 alternatives.push_back( Alternative( new MemberExpr( dwt, expr->clone() ), env, newCost ) ); 322 renameTypes( alternatives.back().expr ); 323 addAnonConversions( alternatives.back() ); // add anonymous member interpretations whenever an aggregate value type is seen as a member expression. 330 for ( Declaration * decl : members ) { 331 if ( DeclarationWithType *dwt = dynamic_cast< DeclarationWithType* >( decl ) ) { 332 // addAnonAlternatives uses vector::push_back, which invalidates references to existing elements, so 333 // can't construct in place and use vector::back 334 Alternative newAlt( new MemberExpr( dwt, expr->clone() ), env, newCost ); 335 renameTypes( newAlt.expr ); 336 addAnonConversions( newAlt ); // add anonymous member interpretations whenever an aggregate value type is seen as a member expression. 337 alternatives.push_back( std::move(newAlt) ); 324 338 } else { 325 339 assert( false ); … … 331 345 if ( ConstantExpr * constantExpr = dynamic_cast< ConstantExpr * >( member ) ) { 332 346 // get the value of the constant expression as an int, must be between 0 and the length of the tuple type to have meaning 333 // xxx - this should be improved by memoizing the value of constant exprs 334 // during parsing and reusing that information here. 335 std::stringstream ss( constantExpr->get_constant()->get_value() ); 336 int val = 0; 347 auto val = constantExpr->intValue(); 337 348 std::string tmp; 338 if ( ss >> val && ! (ss >> tmp) ) { 339 if ( val >= 0 && (unsigned int)val < tupleType->size() ) { 340 alternatives.push_back( Alternative( new TupleIndexExpr( expr, val ), env, newCost ) ); 341 } // if 349 if ( val >= 0 && (unsigned long long)val < tupleType->size() ) { 350 alternatives.push_back( Alternative( new TupleIndexExpr( expr->clone(), val ), env, newCost ) ); 342 351 } // if 343 } else if ( NameExpr * nameExpr = dynamic_cast< NameExpr * >( member ) ) {344 // xxx - temporary hack until 0/1 are int constants345 if ( nameExpr->get_name() == "0" || nameExpr->get_name() == "1" ) {346 std::stringstream ss( nameExpr->get_name() );347 int val;348 ss >> val;349 alternatives.push_back( Alternative( new TupleIndexExpr( expr, val ), env, newCost ) );350 }351 352 } // if 352 353 } 353 354 354 355 void AlternativeFinder::Finder::postvisit( ApplicationExpr *applicationExpr ) { 355 alternatives.push_back( Alternative( applicationExpr , env, Cost::zero ) );356 alternatives.push_back( Alternative( applicationExpr->clone(), env, Cost::zero ) ); 356 357 } 357 358 … … 435 436 return Cost::infinity; 436 437 } 438 } 439 if ( DefaultArgExpr * def = dynamic_cast< DefaultArgExpr * >( *actualExpr ) ) { 440 // default arguments should be free - don't include conversion cost. 441 // Unwrap them here because they are not relevant to the rest of the system. 442 *actualExpr = def->expr; 443 ++formal; 444 continue; 437 445 } 438 446 Type * formalType = (*formal)->get_type(); … … 552 560 553 561 Expression *varExpr = data.combine( newerAlt.cvtCost ); 562 delete varExpr->get_result(); 554 563 varExpr->set_result( adjType->clone() ); 555 564 PRINT( … … 565 574 inferParameters = (*inferParameters)[ id ].inferParams.get(); 566 575 } 567 568 (*inferParameters)[ curDecl->get_uniqueId() ] = ParamEntry( candidate->get_uniqueId(), adjType , curDecl->get_type(), varExpr );576 // XXX: this is a memory leak, but adjType can't be deleted because it might contain assertions 577 (*inferParameters)[ curDecl->get_uniqueId() ] = ParamEntry( candidate->get_uniqueId(), adjType->clone(), curDecl->get_type()->clone(), varExpr ); 569 578 inferRecursive( begin, end, newerAlt, newOpenVars, newDecls, newerNeed, level, indexer, out ); 579 } else { 580 delete adjType; 570 581 } 571 582 } … … 604 615 ConstantExpr* getDefaultValue( Initializer* init ) { 605 616 if ( SingleInit* si = dynamic_cast<SingleInit*>( init ) ) { 606 if ( CastExpr* ce = dynamic_cast<CastExpr*>( si->get_value() ) ) { 607 return dynamic_cast<ConstantExpr*>( ce->get_arg() ); 617 if ( CastExpr* ce = dynamic_cast<CastExpr*>( si->value ) ) { 618 return dynamic_cast<ConstantExpr*>( ce->arg ); 619 } else { 620 return dynamic_cast<ConstantExpr*>( si->value ); 608 621 } 609 622 } … … 614 627 struct ArgPack { 615 628 std::size_t parent; ///< Index of parent pack 616 Expression* expr;///< The argument stored here629 std::unique_ptr<Expression> expr; ///< The argument stored here 617 630 Cost cost; ///< The cost of this argument 618 631 TypeEnvironment env; ///< Environment for this pack … … 626 639 627 640 ArgPack() 628 : parent(0), expr( nullptr), cost(Cost::zero), env(), need(), have(), openVars(),629 nextArg(0),tupleStart(0), nextExpl(0), explAlt(0) {}641 : parent(0), expr(), cost(Cost::zero), env(), need(), have(), openVars(), nextArg(0), 642 tupleStart(0), nextExpl(0), explAlt(0) {} 630 643 631 644 ArgPack(const TypeEnvironment& env, const AssertionSet& need, const AssertionSet& have, 632 645 const OpenVarSet& openVars) 633 : parent(0), expr( nullptr), cost(Cost::zero), env(env), need(need), have(have),646 : parent(0), expr(), cost(Cost::zero), env(env), need(need), have(have), 634 647 openVars(openVars), nextArg(0), tupleStart(0), nextExpl(0), explAlt(0) {} 635 648 … … 638 651 unsigned tupleStart = 0, Cost cost = Cost::zero, unsigned nextExpl = 0, 639 652 unsigned explAlt = 0 ) 640 : parent(parent), expr(expr ), cost(cost), env(move(env)), need(move(need)),653 : parent(parent), expr(expr->clone()), cost(cost), env(move(env)), need(move(need)), 641 654 have(move(have)), openVars(move(openVars)), nextArg(nextArg), tupleStart(tupleStart), 642 655 nextExpl(nextExpl), explAlt(explAlt) {} … … 644 657 ArgPack(const ArgPack& o, TypeEnvironment&& env, AssertionSet&& need, AssertionSet&& have, 645 658 OpenVarSet&& openVars, unsigned nextArg, Cost added ) 646 : parent(o.parent), expr(o.expr ), cost(o.cost + added), env(move(env)),647 need(move(need)), have(move(have)), openVars(move(openVars)), nextArg(nextArg),648 tupleStart(o.tupleStart), nextExpl(0), explAlt(0) {}659 : parent(o.parent), expr(o.expr ? o.expr->clone() : nullptr), cost(o.cost + added), 660 env(move(env)), need(move(need)), have(move(have)), openVars(move(openVars)), 661 nextArg(nextArg), tupleStart(o.tupleStart), nextExpl(0), explAlt(0) {} 649 662 650 663 /// true iff this pack is in the middle of an exploded argument … … 661 674 std::list<Expression*> exprs; 662 675 const ArgPack* pack = this; 663 if ( expr ) { exprs.push_front( expr ); }676 if ( expr ) { exprs.push_front( expr.release() ); } 664 677 while ( pack->tupleStart == 0 ) { 665 678 pack = &packs[pack->parent]; 666 exprs.push_front( pack->expr );679 exprs.push_front( pack->expr->clone() ); 667 680 cost += pack->cost; 668 681 } 669 682 // reset pack to appropriate tuple 670 expr = new TupleExpr{ exprs };683 expr.reset( new TupleExpr( exprs ) ); 671 684 tupleStart = pack->tupleStart - 1; 672 685 parent = pack->parent; … … 721 734 722 735 results.emplace_back( 723 i, expl.exprs[results[i].nextExpl] , copy(results[i].env),736 i, expl.exprs[results[i].nextExpl].get(), copy(results[i].env), 724 737 copy(results[i].need), copy(results[i].have), 725 738 copy(results[i].openVars), nextArg, nTuples, Cost::zero, nextExpl, … … 742 755 newResult.parent = i; 743 756 std::list<Expression*> emptyList; 744 newResult.expr = new TupleExpr{ emptyList };757 newResult.expr.reset( new TupleExpr( emptyList ) ); 745 758 argType = newResult.expr->get_result(); 746 759 } else { … … 749 762 newResult.cost = results[i].cost; 750 763 newResult.tupleStart = results[i].tupleStart; 751 newResult.expr = results[i].expr;764 newResult.expr.reset( results[i].expr->clone() ); 752 765 argType = newResult.expr->get_result(); 753 766 … … 799 812 // add new result 800 813 results.emplace_back( 801 i, expl.exprs.front() , move(env), copy(results[i].need),814 i, expl.exprs.front().get(), move(env), copy(results[i].need), 802 815 copy(results[i].have), move(openVars), nextArg + 1, 803 816 nTuples, expl.cost, expl.exprs.size() == 1 ? 0 : 1, j ); … … 825 838 if ( results[i].hasExpl() ) { 826 839 const ExplodedActual& expl = results[i].getExpl( args ); 827 Expression* expr = expl.exprs[results[i].nextExpl] ;840 Expression* expr = expl.exprs[results[i].nextExpl].get(); 828 841 829 842 TypeEnvironment env = results[i].env; … … 866 879 indexer ) ) { 867 880 results.emplace_back( 868 i, cnstExpr, move(env), move(need), move(have),881 i, new DefaultArgExpr( cnstExpr ), move(env), move(need), move(have), 869 882 move(openVars), nextArg, nTuples ); 870 883 } … … 896 909 897 910 // consider only first exploded actual 898 Expression* expr = expl.exprs.front() ;911 Expression* expr = expl.exprs.front().get(); 899 912 Type* actualType = expr->result->clone(); 900 913 … … 924 937 925 938 template<typename OutputIterator> 926 void AlternativeFinder::Finder::validateFunctionAlternative( const Alternative &func, 927 ArgPack& result,const std::vector<ArgPack>& results, OutputIterator out ) {928 ApplicationExpr *appExpr = new ApplicationExpr( func.expr );939 void AlternativeFinder::Finder::validateFunctionAlternative( const Alternative &func, ArgPack& result, 940 const std::vector<ArgPack>& results, OutputIterator out ) { 941 ApplicationExpr *appExpr = new ApplicationExpr( func.expr->clone() ); 929 942 // sum cost and accumulate actuals 930 943 std::list<Expression*>& args = appExpr->args; … … 932 945 const ArgPack* pack = &result; 933 946 while ( pack->expr ) { 934 args.push_front( pack->expr );947 args.push_front( pack->expr->clone() ); 935 948 cost += pack->cost; 936 949 pack = &results[pack->parent]; … … 999 1012 1000 1013 results.emplace_back( 1001 i, expl.exprs[results[i].nextExpl] , copy(results[i].env),1014 i, expl.exprs[results[i].nextExpl].get(), copy(results[i].env), 1002 1015 copy(results[i].need), copy(results[i].have), 1003 1016 copy(results[i].openVars), nextArg, 0, Cost::zero, nextExpl, … … 1035 1048 // add new result 1036 1049 results.emplace_back( 1037 i, expl.exprs.front() , move(env), copy(results[i].need),1050 i, expl.exprs.front().get(), move(env), copy(results[i].need), 1038 1051 copy(results[i].have), move(openVars), nextArg + 1, 0, 1039 1052 expl.cost, expl.exprs.size() == 1 ? 0 : 1, j ); … … 1058 1071 funcFinder.findWithAdjustment( untypedExpr->function ); 1059 1072 // if there are no function alternatives, then proceeding is a waste of time. 1073 // xxx - findWithAdjustment throws, so this check and others like it shouldn't be necessary. 1060 1074 if ( funcFinder.alternatives.empty() ) return; 1061 1075 … … 1069 1083 1070 1084 // find function operators 1071 static auto *opExpr = new_static_root<NameExpr>( "?()" );1085 static NameExpr *opExpr = new NameExpr( "?()" ); 1072 1086 AlternativeFinder funcOpFinder( indexer, env ); 1073 1087 // it's ok if there aren't any defined function ops … … 1085 1099 argExpansions.emplace_back(); 1086 1100 auto& argE = argExpansions.back(); 1087 argE.reserve( arg.alternatives.size() );1101 // argE.reserve( arg.alternatives.size() ); 1088 1102 1089 1103 for ( const Alternative& actual : arg ) { … … 1101 1115 ) 1102 1116 // check if the type is pointer to function 1103 if ( PointerType *pointer = dynamic_cast< PointerType* >( func->expr-> get_result()->stripReferences() ) ) {1104 if ( FunctionType *function = dynamic_cast< FunctionType* >( pointer-> get_base()) ) {1117 if ( PointerType *pointer = dynamic_cast< PointerType* >( func->expr->result->stripReferences() ) ) { 1118 if ( FunctionType *function = dynamic_cast< FunctionType* >( pointer->base ) ) { 1105 1119 Alternative newFunc( *func ); 1106 1120 referenceToRvalueConversion( newFunc.expr, newFunc.cost ); … … 1108 1122 std::back_inserter( candidates ) ); 1109 1123 } 1110 } else if ( TypeInstType *typeInst = dynamic_cast< TypeInstType* >( func->expr-> get_result()->stripReferences() ) ) { // handle ftype (e.g. *? on function pointer)1111 if ( ClassRef eqvClass = func->env.lookup( typeInst->get_name()) ) {1112 if ( FunctionType *function = dynamic_cast< FunctionType* >( eqvClass .get_bound().type ) ) {1124 } else if ( TypeInstType *typeInst = dynamic_cast< TypeInstType* >( func->expr->result->stripReferences() ) ) { // handle ftype (e.g. *? on function pointer) 1125 if ( const EqvClass *eqvClass = func->env.lookup( typeInst->name ) ) { 1126 if ( FunctionType *function = dynamic_cast< FunctionType* >( eqvClass->type ) ) { 1113 1127 Alternative newFunc( *func ); 1114 1128 referenceToRvalueConversion( newFunc.expr, newFunc.cost ); … … 1138 1152 // check if type is a pointer to function 1139 1153 if ( PointerType* pointer = dynamic_cast<PointerType*>( 1140 funcOp->expr-> get_result()->stripReferences() ) ) {1154 funcOp->expr->result->stripReferences() ) ) { 1141 1155 if ( FunctionType* function = 1142 dynamic_cast<FunctionType*>( pointer-> get_base()) ) {1156 dynamic_cast<FunctionType*>( pointer->base ) ) { 1143 1157 Alternative newFunc( *funcOp ); 1144 1158 referenceToRvalueConversion( newFunc.expr, newFunc.cost ); … … 1162 1176 PRINT( 1163 1177 ApplicationExpr *appExpr = strict_dynamic_cast< ApplicationExpr* >( withFunc.expr ); 1164 PointerType *pointer = strict_dynamic_cast< PointerType* >( appExpr-> get_function()->get_result());1165 FunctionType *function = strict_dynamic_cast< FunctionType* >( pointer-> get_base());1166 std::cerr << "Case +++++++++++++ " << appExpr-> get_function()<< std::endl;1178 PointerType *pointer = strict_dynamic_cast< PointerType* >( appExpr->function->result ); 1179 FunctionType *function = strict_dynamic_cast< FunctionType* >( pointer->base ); 1180 std::cerr << "Case +++++++++++++ " << appExpr->function << std::endl; 1167 1181 std::cerr << "formals are:" << std::endl; 1168 printAll( function-> get_parameters(), std::cerr, 8 );1182 printAll( function->parameters, std::cerr, 8 ); 1169 1183 std::cerr << "actuals are:" << std::endl; 1170 printAll( appExpr-> get_args(), std::cerr, 8 );1184 printAll( appExpr->args, std::cerr, 8 ); 1171 1185 std::cerr << "bindings are:" << std::endl; 1172 1186 withFunc.env.print( std::cerr, 8 ); … … 1209 1223 bool isLvalue( Expression *expr ) { 1210 1224 // xxx - recurse into tuples? 1211 return expr->result && ( expr-> get_result()->get_lvalue() || dynamic_cast< ReferenceType * >( expr->get_result()) );1225 return expr->result && ( expr->result->get_lvalue() || dynamic_cast< ReferenceType * >( expr->result ) ); 1212 1226 } 1213 1227 … … 1218 1232 if ( isLvalue( alt.expr ) ) { 1219 1233 alternatives.push_back( 1220 Alternative{ new AddressExpr( alt.expr ), alt.env, alt.cost } );1234 Alternative{ new AddressExpr( alt.expr->clone() ), alt.env, alt.cost } ); 1221 1235 } // if 1222 1236 } // for … … 1224 1238 1225 1239 void AlternativeFinder::Finder::postvisit( LabelAddressExpr * expr ) { 1226 alternatives.push_back( Alternative{ expr , env, Cost::zero } );1240 alternatives.push_back( Alternative{ expr->clone(), env, Cost::zero } ); 1227 1241 } 1228 1242 … … 1244 1258 componentExprs.push_back( restructureCast( idx, toType->getComponent( i ), isGenerated ) ); 1245 1259 } 1260 delete argExpr; 1246 1261 assert( componentExprs.size() > 0 ); 1247 1262 // produce the tuple of casts … … 1319 1334 for ( Alternative & alt : finder.alternatives ) { 1320 1335 alternatives.push_back( Alternative( 1321 new VirtualCastExpr( alt.expr , castExpr->get_result()->clone() ),1336 new VirtualCastExpr( alt.expr->clone(), castExpr->get_result()->clone() ), 1322 1337 alt.env, alt.cost ) ); 1323 1338 } … … 1341 1356 Expression * aggrExpr = agg->expr->clone(); 1342 1357 referenceToRvalueConversion( aggrExpr, cost ); 1358 std::unique_ptr<Expression> guard( aggrExpr ); 1343 1359 1344 1360 // find member of the given type … … 1354 1370 1355 1371 void AlternativeFinder::Finder::postvisit( MemberExpr *memberExpr ) { 1356 alternatives.push_back( Alternative( memberExpr , env, Cost::zero ) );1372 alternatives.push_back( Alternative( memberExpr->clone(), env, Cost::zero ) ); 1357 1373 } 1358 1374 … … 1364 1380 Cost cost = Cost::zero; 1365 1381 Expression * newExpr = data.combine( cost ); 1366 alternatives.push_back( Alternative( newExpr, env, Cost::zero, cost ) ); 1382 1383 // addAnonAlternatives uses vector::push_back, which invalidates references to existing elements, so 1384 // can't construct in place and use vector::back 1385 Alternative newAlt( newExpr, env, Cost::zero, cost ); 1367 1386 PRINT( 1368 1387 std::cerr << "decl is "; … … 1373 1392 std::cerr << std::endl; 1374 1393 ) 1375 renameTypes( alternatives.back().expr ); 1376 addAnonConversions( alternatives.back() ); // add anonymous member interpretations whenever an aggregate value type is seen as a name expression. 1394 renameTypes( newAlt.expr ); 1395 addAnonConversions( newAlt ); // add anonymous member interpretations whenever an aggregate value type is seen as a name expression. 1396 alternatives.push_back( std::move(newAlt) ); 1377 1397 } // for 1378 1398 } … … 1385 1405 1386 1406 void AlternativeFinder::Finder::postvisit( ConstantExpr *constantExpr ) { 1387 alternatives.push_back( Alternative( constantExpr , env, Cost::zero ) );1407 alternatives.push_back( Alternative( constantExpr->clone(), env, Cost::zero ) ); 1388 1408 } 1389 1409 … … 1405 1425 Alternative &choice = winners.front(); 1406 1426 referenceToRvalueConversion( choice.expr, choice.cost ); 1407 alternatives.push_back( Alternative( new SizeofExpr( choice.expr ), choice.env, Cost::zero ) );1427 alternatives.push_back( Alternative( new SizeofExpr( choice.expr->clone() ), choice.env, Cost::zero ) ); 1408 1428 } // if 1409 1429 } … … 1426 1446 Alternative &choice = winners.front(); 1427 1447 referenceToRvalueConversion( choice.expr, choice.cost ); 1428 alternatives.push_back( Alternative( new AlignofExpr( choice.expr ), choice.env, Cost::zero ) );1448 alternatives.push_back( Alternative( new AlignofExpr( choice.expr->clone() ), choice.env, Cost::zero ) ); 1429 1449 } // if 1430 1450 } … … 1455 1475 1456 1476 void AlternativeFinder::Finder::postvisit( OffsetofExpr *offsetofExpr ) { 1457 alternatives.push_back( Alternative( offsetofExpr , env, Cost::zero ) );1477 alternatives.push_back( Alternative( offsetofExpr->clone(), env, Cost::zero ) ); 1458 1478 } 1459 1479 1460 1480 void AlternativeFinder::Finder::postvisit( OffsetPackExpr *offsetPackExpr ) { 1461 alternatives.push_back( Alternative( offsetPackExpr , env, Cost::zero ) );1481 alternatives.push_back( Alternative( offsetPackExpr->clone(), env, Cost::zero ) ); 1462 1482 } 1463 1483 … … 1537 1557 compositeEnv.simpleCombine( second.env ); 1538 1558 1539 LogicalExpr *newExpr = new LogicalExpr( first.expr , second.expr, logicalExpr->get_isAnd() );1559 LogicalExpr *newExpr = new LogicalExpr( first.expr->clone(), second.expr->clone(), logicalExpr->get_isAnd() ); 1540 1560 alternatives.push_back( Alternative( newExpr, compositeEnv, first.cost + second.cost ) ); 1541 1561 } … … 1570 1590 Type* commonType = nullptr; 1571 1591 if ( unify( second.expr->result, third.expr->result, newAlt.env, needAssertions, haveAssertions, openVars, indexer, commonType ) ) { 1572 ConditionalExpr *newExpr = new ConditionalExpr( first.expr , second.expr, third.expr);1592 ConditionalExpr *newExpr = new ConditionalExpr( first.expr->clone(), second.expr->clone(), third.expr->clone() ); 1573 1593 newExpr->result = commonType ? commonType : second.expr->result->clone(); 1574 1594 // convert both options to the conditional result type … … 1589 1609 secondFinder.findWithAdjustment( commaExpr->get_arg2() ); 1590 1610 for ( const Alternative & alt : secondFinder.alternatives ) { 1591 alternatives.push_back( Alternative( new CommaExpr( newFirstArg , alt.expr), alt.env, alt.cost ) );1611 alternatives.push_back( Alternative( new CommaExpr( newFirstArg->clone(), alt.expr->clone() ), alt.env, alt.cost ) ); 1592 1612 } // for 1613 delete newFirstArg; 1593 1614 } 1594 1615 … … 1611 1632 Type* commonType = nullptr; 1612 1633 if ( unify( first.expr->result, second.expr->result, newAlt.env, needAssertions, haveAssertions, openVars, indexer, commonType ) ) { 1613 RangeExpr * newExpr = new RangeExpr( first.expr , second.expr);1634 RangeExpr * newExpr = new RangeExpr( first.expr->clone(), second.expr->clone() ); 1614 1635 newExpr->result = commonType ? commonType : first.expr->result->clone(); 1615 1636 newAlt.expr = newExpr; … … 1639 1660 1640 1661 void AlternativeFinder::Finder::postvisit( TupleExpr *tupleExpr ) { 1641 alternatives.push_back( Alternative( tupleExpr , env, Cost::zero ) );1662 alternatives.push_back( Alternative( tupleExpr->clone(), env, Cost::zero ) ); 1642 1663 } 1643 1664 1644 1665 void AlternativeFinder::Finder::postvisit( ImplicitCopyCtorExpr * impCpCtorExpr ) { 1645 alternatives.push_back( Alternative( impCpCtorExpr , env, Cost::zero ) );1666 alternatives.push_back( Alternative( impCpCtorExpr->clone(), env, Cost::zero ) ); 1646 1667 } 1647 1668 … … 1652 1673 finder.findWithoutPrune( ctorExpr->get_callExpr() ); 1653 1674 for ( Alternative & alt : finder.alternatives ) { 1654 alternatives.push_back( Alternative( new ConstructorExpr( alt.expr ), alt.env, alt.cost ) );1675 alternatives.push_back( Alternative( new ConstructorExpr( alt.expr->clone() ), alt.env, alt.cost ) ); 1655 1676 } 1656 1677 } 1657 1678 1658 1679 void AlternativeFinder::Finder::postvisit( TupleIndexExpr *tupleExpr ) { 1659 alternatives.push_back( Alternative( tupleExpr , env, Cost::zero ) );1680 alternatives.push_back( Alternative( tupleExpr->clone(), env, Cost::zero ) ); 1660 1681 } 1661 1682 1662 1683 void AlternativeFinder::Finder::postvisit( TupleAssignExpr *tupleAssignExpr ) { 1663 alternatives.push_back( Alternative( tupleAssignExpr , env, Cost::zero ) );1684 alternatives.push_back( Alternative( tupleAssignExpr->clone(), env, Cost::zero ) ); 1664 1685 } 1665 1686 … … 1669 1690 for ( Alternative & alt : finder.alternatives ) { 1670 1691 // ensure that the id is passed on to the UniqueExpr alternative so that the expressions are "linked" 1671 UniqueExpr * newUnqExpr = new UniqueExpr( alt.expr , unqExpr->get_id() );1692 UniqueExpr * newUnqExpr = new UniqueExpr( alt.expr->clone(), unqExpr->get_id() ); 1672 1693 alternatives.push_back( Alternative( newUnqExpr, alt.env, alt.cost ) ); 1673 1694 } … … 1720 1741 // count one safe conversion for each value that is thrown away 1721 1742 thisCost.incSafe( discardedValues ); 1722 Alternative newAlt( new InitExpr( restructureCast( alt.expr , toType, true ), initAlt.designation), newEnv, alt.cost, thisCost );1743 Alternative newAlt( new InitExpr( restructureCast( alt.expr->clone(), toType, true ), initAlt.designation->clone() ), newEnv, alt.cost, thisCost ); 1723 1744 inferParameters( needAssertions, haveAssertions, newAlt, openVars, back_inserter( candidates ) ); 1724 1745 } … … 1741 1762 assertf( false, "AlternativeFinder should never see a DeletedExpr." ); 1742 1763 } 1764 1765 void AlternativeFinder::Finder::postvisit( GenericExpr * ) { 1766 assertf( false, "_Generic is not yet supported." ); 1767 } 1743 1768 } // namespace ResolvExpr 1744 1769
Note:
See TracChangeset
for help on using the changeset viewer.