Changeset 6b224a52 for src/ResolvExpr/AlternativeFinder.cc
- Timestamp:
- Aug 25, 2017, 12:11:53 PM (8 years ago)
- Branches:
- ADT, aaron-thesis, arm-eh, ast-experimental, cleanup-dtors, deferred_resn, demangler, enum, forall-pointer-decay, jacob/cs343-translation, jenkins-sandbox, master, new-ast, new-ast-unique-expr, new-env, no_list, persistent-indexer, pthread-emulation, qualifiedEnum, resolv-new, with_gc
- Children:
- bf7b9da7
- Parents:
- 135b431 (diff), f676b84 (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. - File:
-
- 1 edited
-
src/ResolvExpr/AlternativeFinder.cc (modified) (32 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/ResolvExpr/AlternativeFinder.cc
r135b431 r6b224a52 67 67 68 68 Cost sumCost( const AltList &in ) { 69 Cost total ;69 Cost total = Cost::zero; 70 70 for ( AltList::const_iterator i = in.begin(); i != in.end(); ++i ) { 71 71 total += i->cost; … … 144 144 expr->get_result()->accept( global_renamer ); 145 145 } 146 } 146 147 void referenceToRvalueConversion( Expression *& expr ) { 148 if ( dynamic_cast< ReferenceType * >( expr->get_result() ) ) { 149 // cast away reference from expr 150 expr = new CastExpr( expr, expr->get_result()->stripReferences()->clone() ); 151 } 152 } 153 } // namespace 147 154 148 155 template< typename InputIterator, typename OutputIterator > … … 186 193 if ( alternatives.begin() == oldBegin ) { 187 194 std::ostringstream stream; 188 stream << "Can't choose between " << alternatives.size() << " alternatives for expression "; 195 AltList winners; 196 findMinCost( alternatives.begin(), alternatives.end(), back_inserter( winners ) ); 197 stream << "Can't choose between " << winners.size() << " alternatives for expression "; 189 198 expr->print( stream ); 190 199 stream << "Alternatives are:"; 191 AltList winners;192 findMinCost( alternatives.begin(), alternatives.end(), back_inserter( winners ) );193 200 printAlts( winners, stream, 8 ); 194 201 throw SemanticError( stream.str() ); … … 213 220 void AlternativeFinder::addAnonConversions( const Alternative & alt ) { 214 221 // adds anonymous member interpretations whenever an aggregate value type is seen. 215 Expression * expr = alt.expr->clone(); 216 std::unique_ptr< Expression > manager( expr ); // RAII for expr 217 alt.env.apply( expr->get_result() ); 218 if ( StructInstType *structInst = dynamic_cast< StructInstType* >( expr->get_result() ) ) { 222 // 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 223 std::unique_ptr<Expression> aggrExpr( alt.expr->clone() ); 224 alt.env.apply( aggrExpr->get_result() ); 225 Type * aggrType = aggrExpr->get_result(); 226 if ( dynamic_cast< ReferenceType * >( aggrType ) ) { 227 aggrType = aggrType->stripReferences(); 228 aggrExpr.reset( new CastExpr( aggrExpr.release(), aggrType->clone() ) ); 229 } 230 231 if ( StructInstType *structInst = dynamic_cast< StructInstType* >( aggrExpr->get_result() ) ) { 219 232 NameExpr nameExpr( "" ); 220 addAggMembers( structInst, expr, alt.cost+Cost( 0, 0, 1 ), alt.env, &nameExpr );221 } else if ( UnionInstType *unionInst = dynamic_cast< UnionInstType* >( expr->get_result() ) ) {233 addAggMembers( structInst, aggrExpr.get(), alt.cost+Cost::safe, alt.env, &nameExpr ); 234 } else if ( UnionInstType *unionInst = dynamic_cast< UnionInstType* >( aggrExpr->get_result() ) ) { 222 235 NameExpr nameExpr( "" ); 223 addAggMembers( unionInst, expr, alt.cost+Cost( 0, 0, 1 ), alt.env, &nameExpr );236 addAggMembers( unionInst, aggrExpr.get(), alt.cost+Cost::safe, alt.env, &nameExpr ); 224 237 } // if 225 238 } … … 228 241 void AlternativeFinder::addAggMembers( StructOrUnionType *aggInst, Expression *expr, const Cost &newCost, const TypeEnvironment & env, Expression * member ) { 229 242 // by this point, member must be a name expr 230 NameExpr * nameExpr = safe_dynamic_cast< NameExpr * >( member ); 243 NameExpr * nameExpr = dynamic_cast< NameExpr * >( member ); 244 if ( ! nameExpr ) return; 231 245 const std::string & name = nameExpr->get_name(); 232 246 std::list< Declaration* > members; … … 250 264 // during parsing and reusing that information here. 251 265 std::stringstream ss( constantExpr->get_constant()->get_value() ); 252 int val ;266 int val = 0; 253 267 std::string tmp; 254 268 if ( ss >> val && ! (ss >> tmp) ) { … … 272 286 } 273 287 274 Cost computeConversionCost( Alternative &alt, const SymTab::Indexer &indexer ) { 288 Cost computeConversionCost( Type * actualType, Type * formalType, const SymTab::Indexer &indexer, const TypeEnvironment & env ) { 289 PRINT( 290 std::cerr << std::endl << "converting "; 291 actualType->print( std::cerr, 8 ); 292 std::cerr << std::endl << " to "; 293 formalType->print( std::cerr, 8 ); 294 std::cerr << std::endl << "environment is: "; 295 env.print( std::cerr, 8 ); 296 std::cerr << std::endl; 297 ) 298 Cost convCost = conversionCost( actualType, formalType, indexer, env ); 299 PRINT( 300 std::cerr << std::endl << "cost is" << convCost << std::endl; 301 ) 302 if ( convCost == Cost::infinity ) { 303 return convCost; 304 } 305 convCost.incPoly( polyCost( formalType, env, indexer ) + polyCost( actualType, env, indexer ) ); 306 return convCost; 307 } 308 309 Cost computeExpressionConversionCost( Expression *& actualExpr, Type * formalType, const SymTab::Indexer &indexer, const TypeEnvironment & env ) { 310 Cost convCost = computeConversionCost( actualExpr->result, formalType, indexer, env ); 311 // if ( convCost != Cost::zero ) { 312 313 // xxx - temporary -- ignore poly cost, since this causes some polymorphic functions to be cast, which causes the specialize 314 // pass to try to specialize them, which currently does not work. Once that is fixed, remove the next 3 lines and uncomment the 315 // previous line. 316 Cost tmpCost = convCost; 317 tmpCost.incPoly( -tmpCost.get_polyCost() ); 318 if ( tmpCost != Cost::zero ) { 319 Type *newType = formalType->clone(); 320 env.apply( newType ); 321 actualExpr = new CastExpr( actualExpr, newType ); 322 // xxx - SHOULD be able to resolve this cast, but at the moment pointers are not castable to zero_t, but are implicitly convertible. This is clearly 323 // inconsistent, once this is fixed it should be possible to resolve the cast. 324 // xxx - this isn't working, it appears because type1 (the formal type) is seen as widenable, but it shouldn't be, because this makes the conversion from DT* to DT* since commontype(zero_t, DT*) is DT*, rather than just nothing. 325 326 // AlternativeFinder finder( indexer, env ); 327 // finder.findWithAdjustment( actualExpr ); 328 // assertf( finder.get_alternatives().size() > 0, "Somehow castable expression failed to find alternatives." ); 329 // assertf( finder.get_alternatives().size() == 1, "Somehow got multiple alternatives for known cast expression." ); 330 // Alternative & alt = finder.get_alternatives().front(); 331 // delete actualExpr; 332 // actualExpr = alt.expr->clone(); 333 } 334 return convCost; 335 } 336 337 Cost computeApplicationConversionCost( Alternative &alt, const SymTab::Indexer &indexer ) { 275 338 ApplicationExpr *appExpr = safe_dynamic_cast< ApplicationExpr* >( alt.expr ); 276 339 PointerType *pointer = safe_dynamic_cast< PointerType* >( appExpr->get_function()->get_result() ); 277 340 FunctionType *function = safe_dynamic_cast< FunctionType* >( pointer->get_base() ); 278 341 279 Cost convCost ( 0, 0, 0 );342 Cost convCost = Cost::zero; 280 343 std::list< DeclarationWithType* >& formals = function->get_parameters(); 281 344 std::list< DeclarationWithType* >::iterator formal = formals.begin(); … … 290 353 actualType->print( std::cerr, 8 ); 291 354 ) 292 Cost actualCost;293 355 if ( formal == formals.end() ) { 294 356 if ( function->get_isVarArgs() ) { 295 convCost += Cost( 1, 0, 0 ); 357 convCost.incUnsafe(); 358 // convert reference-typed expressions to value-typed expressions 359 referenceToRvalueConversion( *actualExpr ); 296 360 continue; 297 361 } else { … … 305 369 std::cerr << std::endl << " to "; 306 370 formalType->print( std::cerr, 8 ); 371 std::cerr << std::endl << "environment is: "; 372 alt.env.print( std::cerr, 8 ); 373 std::cerr << std::endl; 307 374 ) 308 Cost newCost = conversionCost( actualType, formalType, indexer, alt.env ); 309 PRINT( 310 std::cerr << std::endl << "cost is" << newCost << std::endl; 311 ) 312 313 if ( newCost == Cost::infinity ) { 314 return newCost; 315 } 316 convCost += newCost; 317 actualCost += newCost; 318 if ( actualCost != Cost( 0, 0, 0 ) ) { 319 Type *newType = formalType->clone(); 320 alt.env.apply( newType ); 321 *actualExpr = new CastExpr( *actualExpr, newType ); 322 } 323 convCost += Cost( 0, polyCost( formalType, alt.env, indexer ) + polyCost( actualType, alt.env, indexer ), 0 ); 375 convCost += computeExpressionConversionCost( *actualExpr, formalType, indexer, alt.env ); 324 376 ++formal; // can't be in for-loop update because of the continue 325 377 } … … 329 381 330 382 for ( InferredParams::const_iterator assert = appExpr->get_inferParams().begin(); assert != appExpr->get_inferParams().end(); ++assert ) { 331 PRINT( 332 std::cerr << std::endl << "converting "; 333 assert->second.actualType->print( std::cerr, 8 ); 334 std::cerr << std::endl << " to "; 335 assert->second.formalType->print( std::cerr, 8 ); 336 ) 337 Cost newCost = conversionCost( assert->second.actualType, assert->second.formalType, indexer, alt.env ); 338 PRINT( 339 std::cerr << std::endl << "cost of conversion is " << newCost << std::endl; 340 ) 341 if ( newCost == Cost::infinity ) { 342 return newCost; 343 } 344 convCost += newCost; 345 convCost += Cost( 0, polyCost( assert->second.formalType, alt.env, indexer ) + polyCost( assert->second.actualType, alt.env, indexer ), 0 ); 383 convCost += computeConversionCost( assert->second.actualType, assert->second.formalType, indexer, alt.env ); 346 384 } 347 385 … … 400 438 Expression * actual = actualIt->expr; 401 439 Type * actualType = actual->get_result(); 440 402 441 PRINT( 403 442 std::cerr << "formal type is "; … … 408 447 ) 409 448 if ( ! unify( formalType, actualType, resultEnv, resultNeed, resultHave, openVars, indexer ) ) { 449 // std::cerr << "unify failed" << std::endl; 410 450 return false; 411 451 } … … 452 492 // match flattened actuals with formal parameters - actuals will be grouped to match 453 493 // with formals as appropriate 454 Cost cost ;494 Cost cost = Cost::zero; 455 495 std::list< Expression * > newExprs; 456 496 ObjectDecl * obj = safe_dynamic_cast< ObjectDecl * >( formal ); … … 613 653 AssertionSet newNeed; 614 654 //AssertionParentSet needParents; 655 PRINT( 656 std::cerr << "env is: " << std::endl; 657 newAlt.env.print( std::cerr, 0 ); 658 std::cerr << std::endl; 659 ) 660 615 661 inferRecursive( need.begin(), need.end(), newAlt, openVars, decls, newNeed, /*needParents,*/ 0, indexer, out ); 616 662 // PRINT( … … 643 689 makeExprList( instantiatedActuals, appExpr->get_args() ); 644 690 PRINT( 691 std::cerr << "instantiate function success: " << appExpr << std::endl; 645 692 std::cerr << "need assertions:" << std::endl; 646 693 printAssertionSet( resultNeed, std::cerr, 8 ); … … 663 710 UntypedExpr *vexpr = untypedExpr->clone(); 664 711 vexpr->set_result( pt.clone() ); 665 alternatives.push_back( Alternative( vexpr, env, Cost ()) );712 alternatives.push_back( Alternative( vexpr, env, Cost::zero) ); 666 713 return; 667 714 } … … 681 728 AltList candidates; 682 729 SemanticError errors; 683 for ( AltList:: const_iterator func = funcFinder.alternatives.begin(); func != funcFinder.alternatives.end(); ++func ) {730 for ( AltList::iterator func = funcFinder.alternatives.begin(); func != funcFinder.alternatives.end(); ++func ) { 684 731 try { 685 732 PRINT( … … 688 735 ) 689 736 // check if the type is pointer to function 690 PointerType *pointer; 691 if ( ( pointer = dynamic_cast< PointerType* >( func->expr->get_result() ) ) ) { 737 if ( PointerType *pointer = dynamic_cast< PointerType* >( func->expr->get_result()->stripReferences() ) ) { 692 738 if ( FunctionType *function = dynamic_cast< FunctionType* >( pointer->get_base() ) ) { 739 referenceToRvalueConversion( func->expr ); 693 740 for ( std::list< AltList >::iterator actualAlt = possibilities.begin(); actualAlt != possibilities.end(); ++actualAlt ) { 694 741 // XXX … … 696 743 makeFunctionAlternatives( *func, function, *actualAlt, std::back_inserter( candidates ) ); 697 744 } 698 } else if ( TypeInstType *typeInst = dynamic_cast< TypeInstType* >( pointer->get_base() ) ) { 699 EqvClass eqvClass; 700 if ( func->env.lookup( typeInst->get_name(), eqvClass ) && eqvClass.type ) { 701 if ( FunctionType *function = dynamic_cast< FunctionType* >( eqvClass.type ) ) { 702 for ( std::list< AltList >::iterator actualAlt = possibilities.begin(); actualAlt != possibilities.end(); ++actualAlt ) { 703 makeFunctionAlternatives( *func, function, *actualAlt, std::back_inserter( candidates ) ); 704 } // for 705 } // if 745 } 746 } else if ( TypeInstType *typeInst = dynamic_cast< TypeInstType* >( func->expr->get_result()->stripReferences() ) ) { // handle ftype (e.g. *? on function pointer) 747 referenceToRvalueConversion( func->expr ); 748 EqvClass eqvClass; 749 if ( func->env.lookup( typeInst->get_name(), eqvClass ) && eqvClass.type ) { 750 if ( FunctionType *function = dynamic_cast< FunctionType* >( eqvClass.type ) ) { 751 for ( std::list< AltList >::iterator actualAlt = possibilities.begin(); actualAlt != possibilities.end(); ++actualAlt ) { 752 makeFunctionAlternatives( *func, function, *actualAlt, std::back_inserter( candidates ) ); 753 } // for 706 754 } // if 707 755 } // if … … 722 770 } 723 771 724 for ( AltList:: const_iterator funcOp = funcOpFinder.alternatives.begin(); funcOp != funcOpFinder.alternatives.end(); ++funcOp ) {772 for ( AltList::iterator funcOp = funcOpFinder.alternatives.begin(); funcOp != funcOpFinder.alternatives.end(); ++funcOp ) { 725 773 // check if the type is pointer to function 726 PointerType *pointer; 727 if ( ( pointer = dynamic_cast< PointerType* >( funcOp->expr->get_result() ) ) ) { 774 if ( PointerType *pointer = dynamic_cast< PointerType* >( funcOp->expr->get_result()->stripReferences() ) ) { 728 775 if ( FunctionType *function = dynamic_cast< FunctionType* >( pointer->get_base() ) ) { 776 referenceToRvalueConversion( funcOp->expr ); 729 777 for ( std::list< AltList >::iterator actualAlt = possibilities.begin(); actualAlt != possibilities.end(); ++actualAlt ) { 730 778 AltList currentAlt; … … 747 795 // compute conversionsion costs 748 796 for ( AltList::iterator withFunc = candidates.begin(); withFunc != candidates.end(); ++withFunc ) { 749 Cost cvtCost = compute ConversionCost( *withFunc, indexer );797 Cost cvtCost = computeApplicationConversionCost( *withFunc, indexer ); 750 798 751 799 PRINT( … … 753 801 PointerType *pointer = safe_dynamic_cast< PointerType* >( appExpr->get_function()->get_result() ); 754 802 FunctionType *function = safe_dynamic_cast< FunctionType* >( pointer->get_base() ); 755 std::cerr << "Case +++++++++++++ "<< std::endl;803 std::cerr << "Case +++++++++++++ " << appExpr->get_function() << std::endl; 756 804 std::cerr << "formals are:" << std::endl; 757 805 printAll( function->get_parameters(), std::cerr, 8 ); … … 796 844 bool isLvalue( Expression *expr ) { 797 845 // xxx - recurse into tuples? 798 return expr->has_result() && expr->get_result()->get_lvalue();846 return expr->has_result() && ( expr->get_result()->get_lvalue() || dynamic_cast< ReferenceType * >( expr->get_result() ) ); 799 847 } 800 848 … … 810 858 811 859 Expression * restructureCast( Expression * argExpr, Type * toType ) { 812 if ( argExpr->get_result()->size() > 1 && ! toType->isVoid() ) { 813 // Argument expression is a tuple and the target type is not void. Cast each member of the tuple 814 // to its corresponding target type, producing the tuple of those cast expressions. If there are 815 // more components of the tuple than components in the target type, then excess components do not 816 // come out in the result expression (but UniqueExprs ensure that side effects will still be done). 817 if ( Tuples::maybeImpure( argExpr ) && ! dynamic_cast< UniqueExpr * >( argExpr ) ) { 860 if ( argExpr->get_result()->size() > 1 && ! toType->isVoid() && ! dynamic_cast<ReferenceType *>( toType ) ) { 861 // Argument expression is a tuple and the target type is not void and not a reference type. 862 // Cast each member of the tuple to its corresponding target type, producing the tuple of those 863 // cast expressions. If there are more components of the tuple than components in the target type, 864 // then excess components do not come out in the result expression (but UniqueExprs ensure that 865 // side effects will still be done). 866 if ( Tuples::maybeImpureIgnoreUnique( argExpr ) ) { 818 867 // expressions which may contain side effects require a single unique instance of the expression. 819 868 argExpr = new UniqueExpr( argExpr ); … … 855 904 // that are cast directly. The candidate is invalid if it has fewer results than there are types to cast 856 905 // to. 857 int discardedValues = (*i).expr->get_result()->size() - castExpr->get_result()->size();906 int discardedValues = i->expr->get_result()->size() - castExpr->get_result()->size(); 858 907 if ( discardedValues < 0 ) continue; 859 908 // xxx - may need to go into tuple types and extract relevant types and use unifyList. Note that currently, this does not 860 909 // allow casting a tuple to an atomic type (e.g. (int)([1, 2, 3])) 861 910 // unification run for side-effects 862 unify( castExpr->get_result(), (*i).expr->get_result(), i->env, needAssertions, haveAssertions, openVars, indexer );863 Cost thisCost = castCost( (*i).expr->get_result(), castExpr->get_result(), indexer, i->env );911 unify( castExpr->get_result(), i->expr->get_result(), i->env, needAssertions, haveAssertions, openVars, indexer ); 912 Cost thisCost = castCost( i->expr->get_result(), castExpr->get_result(), indexer, i->env ); 864 913 if ( thisCost != Cost::infinity ) { 865 914 // count one safe conversion for each value that is thrown away 866 thisCost += Cost( 0, 0, discardedValues ); 867 868 candidates.push_back( Alternative( restructureCast( i->expr->clone(), toType ), i->env, i->cost, thisCost ) ); 915 thisCost.incSafe( discardedValues ); 916 Alternative newAlt( restructureCast( i->expr->clone(), toType ), i->env, i->cost, thisCost ); 917 // xxx - this doesn't work at the moment, since inferParameters requires an ApplicationExpr as the alternative. 918 // Once this works, it should be possible to infer parameters on a cast expression and specialize any function. 919 920 // inferParameters( needAssertions, haveAssertions, newAlt, openVars, back_inserter( candidates ) ); 921 candidates.emplace_back( std::move( newAlt ) ); 869 922 } // if 870 923 } // for … … 895 948 funcFinder.findWithAdjustment( memberExpr->get_aggregate() ); 896 949 for ( AltList::const_iterator agg = funcFinder.alternatives.begin(); agg != funcFinder.alternatives.end(); ++agg ) { 897 if ( StructInstType *structInst = dynamic_cast< StructInstType* >( agg->expr->get_result() ) ) { 898 addAggMembers( structInst, agg->expr, agg->cost, agg->env, memberExpr->get_member() ); 899 } else if ( UnionInstType *unionInst = dynamic_cast< UnionInstType* >( agg->expr->get_result() ) ) { 900 addAggMembers( unionInst, agg->expr, agg->cost, agg->env, memberExpr->get_member() ); 901 } else if ( TupleType * tupleType = dynamic_cast< TupleType * >( agg->expr->get_result() ) ) { 902 addTupleMembers( tupleType, agg->expr, agg->cost, agg->env, memberExpr->get_member() ); 950 // 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 951 std::unique_ptr<Expression> aggrExpr( agg->expr->clone() ); 952 Type * aggrType = aggrExpr->get_result(); 953 if ( dynamic_cast< ReferenceType * >( aggrType ) ) { 954 aggrType = aggrType->stripReferences(); 955 aggrExpr.reset( new CastExpr( aggrExpr.release(), aggrType->clone() ) ); 956 } 957 // find member of the given type 958 if ( StructInstType *structInst = dynamic_cast< StructInstType* >( aggrExpr->get_result() ) ) { 959 addAggMembers( structInst, aggrExpr.get(), agg->cost, agg->env, memberExpr->get_member() ); 960 } else if ( UnionInstType *unionInst = dynamic_cast< UnionInstType* >( aggrExpr->get_result() ) ) { 961 addAggMembers( unionInst, aggrExpr.get(), agg->cost, agg->env, memberExpr->get_member() ); 962 } else if ( TupleType * tupleType = dynamic_cast< TupleType * >( aggrExpr->get_result() ) ) { 963 addTupleMembers( tupleType, aggrExpr.get(), agg->cost, agg->env, memberExpr->get_member() ); 903 964 } // if 904 965 } // for … … 915 976 for ( std::list< DeclarationWithType* >::iterator i = declList.begin(); i != declList.end(); ++i ) { 916 977 VariableExpr newExpr( *i, nameExpr->get_argName() ); 917 alternatives.push_back( Alternative( newExpr.clone(), env, Cost ()) );978 alternatives.push_back( Alternative( newExpr.clone(), env, Cost::zero ) ); 918 979 PRINT( 919 980 std::cerr << "decl is "; … … 955 1016 // return the lowest cost alternative for the argument 956 1017 Alternative &choice = winners.front(); 1018 referenceToRvalueConversion( choice.expr ); 957 1019 alternatives.push_back( Alternative( new SizeofExpr( choice.expr->clone() ), choice.env, Cost::zero ) ); 958 1020 } // if … … 975 1037 // return the lowest cost alternative for the argument 976 1038 Alternative &choice = winners.front(); 1039 referenceToRvalueConversion( choice.expr ); 977 1040 alternatives.push_back( Alternative( new AlignofExpr( choice.expr->clone() ), choice.env, Cost::zero ) ); 978 1041 } // if … … 1059 1122 for ( std::list< DeclarationWithType* >::iterator i = attrList.begin(); i != attrList.end(); ++i ) { 1060 1123 VariableExpr newExpr( *i ); 1061 alternatives.push_back( Alternative( newExpr.clone(), env, Cost ()) );1124 alternatives.push_back( Alternative( newExpr.clone(), env, Cost::zero ) ); 1062 1125 renameTypes( alternatives.back().expr ); 1063 1126 } // for … … 1099 1162 ConditionalExpr *newExpr = new ConditionalExpr( first->expr->clone(), second->expr->clone(), third->expr->clone() ); 1100 1163 newExpr->set_result( commonType ? commonType : second->expr->get_result()->clone() ); 1164 // convert both options to the conditional result type 1165 newAlt.cost += computeExpressionConversionCost( newExpr->arg2, newExpr->result, indexer, newAlt.env ); 1166 newAlt.cost += computeExpressionConversionCost( newExpr->arg3, newExpr->result, indexer, newAlt.env ); 1101 1167 newAlt.expr = newExpr; 1102 1168 inferParameters( needAssertions, haveAssertions, newAlt, openVars, back_inserter( alternatives ) ); … … 1232 1298 if ( thisCost != Cost::infinity ) { 1233 1299 // count one safe conversion for each value that is thrown away 1234 thisCost += Cost( 0, 0,discardedValues );1300 thisCost.incSafe( discardedValues ); 1235 1301 candidates.push_back( Alternative( new InitExpr( restructureCast( alt.expr->clone(), toType ), initAlt.designation->clone() ), newEnv, alt.cost, thisCost ) ); 1236 1302 }
Note:
See TracChangeset
for help on using the changeset viewer.