Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/ResolvExpr/AlternativeFinder.cc

    r11094d9 rd06c808  
    2222#include <memory>                  // for allocator_traits<>::value_type
    2323#include <utility>                 // for pair
    24 #include <vector>                  // for vector
    2524
    2625#include "Alternative.h"           // for AltList, Alternative
     
    334333                tmpCost.incPoly( -tmpCost.get_polyCost() );
    335334                if ( tmpCost != Cost::zero ) {
     335                // if ( convCost != Cost::zero ) {
    336336                        Type *newType = formalType->clone();
    337337                        env.apply( newType );
     
    405405///     needAssertions.insert( needAssertions.end(), (*tyvar)->get_assertions().begin(), (*tyvar)->get_assertions().end() );
    406406                }
     407        }
     408
     409        /// instantiate a single argument by matching actuals from [actualIt, actualEnd) against formalType,
     410        /// producing expression(s) in out and their total cost in cost.
     411        template< typename AltIterator, typename OutputIterator >
     412        bool instantiateArgument( Type * formalType, Initializer * defaultValue, AltIterator & actualIt, AltIterator actualEnd, OpenVarSet & openVars, TypeEnvironment & resultEnv, AssertionSet & resultNeed, AssertionSet & resultHave, const SymTab::Indexer & indexer, Cost & cost, OutputIterator out ) {
     413                if ( TupleType * tupleType = dynamic_cast< TupleType * >( formalType ) ) {
     414                        // formalType is a TupleType - group actuals into a TupleExpr whose type unifies with the TupleType
     415                        std::list< Expression * > exprs;
     416                        for ( Type * type : *tupleType ) {
     417                                if ( ! instantiateArgument( type, defaultValue, actualIt, actualEnd, openVars, resultEnv, resultNeed, resultHave, indexer, cost, back_inserter( exprs ) ) ) {
     418                                        deleteAll( exprs );
     419                                        return false;
     420                                }
     421                        }
     422                        *out++ = new TupleExpr( exprs );
     423                } else if ( TypeInstType * ttype = Tuples::isTtype( formalType ) ) {
     424                        // xxx - mixing default arguments with variadic??
     425                        std::list< Expression * > exprs;
     426                        for ( ; actualIt != actualEnd; ++actualIt ) {
     427                                exprs.push_back( actualIt->expr->clone() );
     428                                cost += actualIt->cost;
     429                        }
     430                        Expression * arg = nullptr;
     431                        if ( exprs.size() == 1 && Tuples::isTtype( exprs.front()->get_result() ) ) {
     432                                // the case where a ttype value is passed directly is special, e.g. for argument forwarding purposes
     433                                // xxx - what if passing multiple arguments, last of which is ttype?
     434                                // xxx - what would happen if unify was changed so that unifying tuple types flattened both before unifying lists? then pass in TupleType(ttype) below.
     435                                arg = exprs.front();
     436                        } else {
     437                                arg = new TupleExpr( exprs );
     438                        }
     439                        assert( arg && arg->get_result() );
     440                        if ( ! unify( ttype, arg->get_result(), resultEnv, resultNeed, resultHave, openVars, indexer ) ) {
     441                                return false;
     442                        }
     443                        *out++ = arg;
     444                } else if ( actualIt != actualEnd ) {
     445                        // both actualType and formalType are atomic (non-tuple) types - if they unify
     446                        // then accept actual as an argument, otherwise return false (fail to instantiate argument)
     447                        Expression * actual = actualIt->expr;
     448                        Type * actualType = actual->get_result();
     449
     450                        PRINT(
     451                                std::cerr << "formal type is ";
     452                                formalType->print( std::cerr );
     453                                std::cerr << std::endl << "actual type is ";
     454                                actualType->print( std::cerr );
     455                                std::cerr << std::endl;
     456                        )
     457                        if ( ! unify( formalType, actualType, resultEnv, resultNeed, resultHave, openVars, indexer ) ) {
     458                                // std::cerr << "unify failed" << std::endl;
     459                                return false;
     460                        }
     461                        // move the expression from the alternative to the output iterator
     462                        *out++ = actual;
     463                        actualIt->expr = nullptr;
     464                        cost += actualIt->cost;
     465                        ++actualIt;
     466                } else {
     467                        // End of actuals - Handle default values
     468                        if ( SingleInit *si = dynamic_cast<SingleInit *>( defaultValue )) {
     469                                if ( CastExpr * castExpr = dynamic_cast< CastExpr * >( si->get_value() ) ) {
     470                                        // so far, only constant expressions are accepted as default values
     471                                        if ( ConstantExpr *cnstexpr = dynamic_cast<ConstantExpr *>( castExpr->get_arg() ) ) {
     472                                                if ( Constant *cnst = dynamic_cast<Constant *>( cnstexpr->get_constant() ) ) {
     473                                                        if ( unify( formalType, cnst->get_type(), resultEnv, resultNeed, resultHave, openVars, indexer ) ) {
     474                                                                *out++ = cnstexpr->clone();
     475                                                                return true;
     476                                                        } // if
     477                                                } // if
     478                                        } // if
     479                                }
     480                        } // if
     481                        return false;
     482                } // if
     483                return true;
     484        }
     485
     486        bool AlternativeFinder::instantiateFunction( std::list< DeclarationWithType* >& formals, const AltList &actuals, bool isVarArgs, OpenVarSet& openVars, TypeEnvironment &resultEnv, AssertionSet &resultNeed, AssertionSet &resultHave, AltList & out ) {
     487                simpleCombineEnvironments( actuals.begin(), actuals.end(), resultEnv );
     488                // make sure we don't widen any existing bindings
     489                for ( TypeEnvironment::iterator i = resultEnv.begin(); i != resultEnv.end(); ++i ) {
     490                        i->allowWidening = false;
     491                }
     492                resultEnv.extractOpenVars( openVars );
     493
     494                // flatten actuals so that each actual has an atomic (non-tuple) type
     495                AltList exploded;
     496                Tuples::explode( actuals, indexer, back_inserter( exploded ) );
     497
     498                AltList::iterator actualExpr = exploded.begin();
     499                AltList::iterator actualEnd = exploded.end();
     500                for ( DeclarationWithType * formal : formals ) {
     501                        // match flattened actuals with formal parameters - actuals will be grouped to match
     502                        // with formals as appropriate
     503                        Cost cost = Cost::zero;
     504                        std::list< Expression * > newExprs;
     505                        ObjectDecl * obj = strict_dynamic_cast< ObjectDecl * >( formal );
     506                        if ( ! instantiateArgument( obj->get_type(), obj->get_init(), actualExpr, actualEnd, openVars, resultEnv, resultNeed, resultHave, indexer, cost, back_inserter( newExprs ) ) ) {
     507                                deleteAll( newExprs );
     508                                return false;
     509                        }
     510                        // success - produce argument as a new alternative
     511                        assert( newExprs.size() == 1 );
     512                        out.push_back( Alternative( newExprs.front(), resultEnv, cost ) );
     513                }
     514                if ( actualExpr != actualEnd ) {
     515                        // there are still actuals remaining, but we've run out of formal parameters to match against
     516                        // this is okay only if the function is variadic
     517                        if ( ! isVarArgs ) {
     518                                return false;
     519                        }
     520                        out.splice( out.end(), exploded, actualExpr, actualEnd );
     521                }
     522                return true;
    407523        }
    408524
     
    559675        }
    560676
    561         /// Gets a default value from an initializer, nullptr if not present
    562         ConstantExpr* getDefaultValue( Initializer* init ) {
    563                 if ( SingleInit* si = dynamic_cast<SingleInit*>( init ) ) {
    564                         if ( CastExpr* ce = dynamic_cast<CastExpr*>( si->get_value() ) ) {
    565                                 return dynamic_cast<ConstantExpr*>( ce->get_arg() );
    566                         }
    567                 }
    568                 return nullptr;
    569         }
    570 
    571         /// State to iteratively build a match of parameter expressions to arguments
    572         struct ArgPack {
    573                 AltList actuals;                 ///< Arguments included in this pack
    574                 TypeEnvironment env;             ///< Environment for this pack
    575                 AssertionSet need;               ///< Assertions outstanding for this pack
    576                 AssertionSet have;               ///< Assertions found for this pack
    577                 OpenVarSet openVars;             ///< Open variables for this pack
    578                 unsigned nextArg;                ///< Index of next argument in arguments list
    579                 std::vector<Alternative> expls;  ///< Exploded actuals left over from last match
    580                 unsigned nextExpl;               ///< Index of next exploded alternative to use
    581                 std::vector<unsigned> tupleEls;  /// Number of elements in current tuple element(s)
    582 
    583                 ArgPack(const TypeEnvironment& env, const AssertionSet& need, const AssertionSet& have,
    584                                 const OpenVarSet& openVars)
    585                         : actuals(), env(env), need(need), have(have), openVars(openVars), nextArg(0),
    586                           expls(), nextExpl(0), tupleEls() {}
    587 
    588                 /// Starts a new tuple expression
    589                 void beginTuple() {
    590                         if ( ! tupleEls.empty() ) ++tupleEls.back();
    591                         tupleEls.push_back(0);
    592                 }
    593 
    594                 /// Ends a tuple expression, consolidating the appropriate actuals
    595                 void endTuple() {
    596                         // set up new Tuple alternative
    597                         std::list<Expression*> exprs;
    598                         Cost cost = Cost::zero;
    599 
    600                         // transfer elements into alternative
    601                         for (unsigned i = 0; i < tupleEls.back(); ++i) {
    602                                 exprs.push_front( actuals.back().expr );
    603                                 actuals.back().expr = nullptr;
    604                                 cost += actuals.back().cost;
    605                                 actuals.pop_back();
    606                         }
    607                         tupleEls.pop_back();
    608 
    609                         // build new alternative
    610                         actuals.emplace_back( new TupleExpr( exprs ), this->env, cost );
    611                 }
    612 
    613                 /// Clones and adds an actual, returns this
    614                 ArgPack& withArg( Expression* expr, Cost cost = Cost::zero ) {
    615                         actuals.emplace_back( expr->clone(), this->env, cost );
    616                         if ( ! tupleEls.empty() ) ++tupleEls.back();
    617                         return *this;
    618                 }
    619         };
    620 
    621         /// Instantiates an argument to match a formal, returns false if no results left
    622         bool instantiateArgument( Type* formalType, Initializer* initializer,
    623                         const std::vector< AlternativeFinder >& args,
    624                         std::vector<ArgPack>& results, std::vector<ArgPack>& nextResults,
    625                         const SymTab::Indexer& indexer ) {
    626                 if ( TupleType* tupleType = dynamic_cast<TupleType*>( formalType ) ) {
    627                         // formalType is a TupleType - group actuals into a TupleExpr
    628                         for ( ArgPack& result : results ) { result.beginTuple(); }
    629                         for ( Type* type : *tupleType ) {
    630                                 // xxx - dropping initializer changes behaviour from previous, but seems correct
    631                                 if ( ! instantiateArgument( type, nullptr, args, results, nextResults, indexer ) )
    632                                         return false;
    633                         }
    634                         for ( ArgPack& result : results ) { result.endTuple(); }
    635                         return true;
    636                 } else if ( TypeInstType* ttype = Tuples::isTtype( formalType ) ) {
    637                         // formalType is a ttype, consumes all remaining arguments
    638                         // xxx - mixing default arguments with variadic??
    639                         std::vector<ArgPack> finalResults{};  /// list of completed tuples
    640                         // start tuples
    641                         for ( ArgPack& result : results ) {
    642                                 result.beginTuple();
    643 
    644                                 // use rest of exploded tuple if present
    645                                 while ( result.nextExpl < result.expls.size() ) {
    646                                         const Alternative& actual = result.expls[result.nextExpl];
    647                                         result.env.addActual( actual.env, result.openVars );
    648                                         result.withArg( actual.expr );
    649                                         ++result.nextExpl;
    650                                 }
    651                         }
    652                         // iterate until all results completed
    653                         while ( ! results.empty() ) {
    654                                 // add another argument to results
    655                                 for ( ArgPack& result : results ) {
    656                                         // finish result when out of arguments
    657                                         if ( result.nextArg >= args.size() ) {
    658                                                 Type* argType = result.actuals.back().expr->get_result();
    659                                                 if ( result.tupleEls.back() == 1 && Tuples::isTtype( argType ) ) {
    660                                                         // the case where a ttype value is passed directly is special, e.g. for
    661                                                         // argument forwarding purposes
    662                                                         // xxx - what if passing multiple arguments, last of which is ttype?
    663                                                         // xxx - what would happen if unify was changed so that unifying tuple
    664                                                         // types flattened both before unifying lists? then pass in TupleType
    665                                                         // (ttype) below.
    666                                                         result.tupleEls.pop_back();
    667                                                 } else {
    668                                                         // collapse leftover arguments into tuple
    669                                                         result.endTuple();
    670                                                         argType = result.actuals.back().expr->get_result();
    671                                                 }
    672                                                 // check unification for ttype before adding to final
    673                                                 if ( unify( ttype, argType, result.env, result.need, result.have,
    674                                                                 result.openVars, indexer ) ) {
    675                                                         finalResults.push_back( std::move(result) );
    676                                                 }
    677                                                 continue;
    678                                         }
    679 
    680                                         // add each possible next argument
    681                                         for ( const Alternative& actual : args[result.nextArg] ) {
    682                                                 ArgPack aResult = result;  // copy to clone everything
    683                                                 // add details of actual to result
    684                                                 aResult.env.addActual( actual.env, aResult.openVars );
    685                                                 Cost cost = actual.cost;
    686 
    687                                                 // explode argument
    688                                                 std::vector<Alternative> exploded;
    689                                                 Tuples::explode( actual, indexer, back_inserter( exploded ) );
    690 
    691                                                 // add exploded argument to tuple
    692                                                 for ( Alternative& aActual : exploded ) {
    693                                                         aResult.withArg( aActual.expr, cost );
    694                                                         cost = Cost::zero;
    695                                                 }
    696                                                 ++aResult.nextArg;
    697                                                 nextResults.push_back( std::move(aResult) );
    698                                         }
    699                                 }
    700 
    701                                 // reset for next round
    702                                 results.swap( nextResults );
    703                                 nextResults.clear();
    704                         }
    705                         results.swap( finalResults );
    706                         return ! results.empty();
    707                 }
    708 
    709                 // iterate each current subresult
    710                 for ( unsigned iResult = 0; iResult < results.size(); ++iResult ) {
    711                         ArgPack& result = results[iResult];
    712 
    713                         if ( result.nextExpl < result.expls.size() ) {
    714                                 // use remainder of exploded tuple if present
    715                                 const Alternative& actual = result.expls[result.nextExpl];
    716                                 result.env.addActual( actual.env, result.openVars );
    717                                 Type* actualType = actual.expr->get_result();
    718 
    719                                 PRINT(
    720                                         std::cerr << "formal type is ";
    721                                         formalType->print( std::cerr );
    722                                         std::cerr << std::endl << "actual type is ";
    723                                         actualType->print( std::cerr );
    724                                         std::cerr << std::endl;
    725                                 )
    726 
    727                                 if ( unify( formalType, actualType, result.env, result.need, result.have,
    728                                                 result.openVars, indexer ) ) {
    729                                         ++result.nextExpl;
    730                                         nextResults.push_back( std::move(result.withArg( actual.expr )) );
    731                                 }
    732 
    733                                 continue;
    734                         } else if ( result.nextArg >= args.size() ) {
    735                                 // use default initializers if out of arguments
    736                                 if ( ConstantExpr* cnstExpr = getDefaultValue( initializer ) ) {
    737                                         if ( Constant* cnst = dynamic_cast<Constant*>( cnstExpr->get_constant() ) ) {
    738                                                 if ( unify( formalType, cnst->get_type(), result.env, result.need,
    739                                                                 result.have, result.openVars, indexer ) ) {
    740                                                         nextResults.push_back( std::move(result.withArg( cnstExpr )) );
    741                                                 }
    742                                         }
    743                                 }
    744                                 continue;
    745                         }
    746 
    747                         // Check each possible next argument
    748                         for ( const Alternative& actual : args[result.nextArg] ) {
    749                                 ArgPack aResult = result;  // copy to clone everything
    750                                 // add details of actual to result
    751                                 aResult.env.addActual( actual.env, aResult.openVars );
    752 
    753                                 // explode argument
    754                                 std::vector<Alternative> exploded;
    755                                 Tuples::explode( actual, indexer, back_inserter( exploded ) );
    756                                 if ( exploded.empty() ) {
    757                                         // skip empty tuple arguments
    758                                         ++aResult.nextArg;
    759                                         results.push_back( std::move(aResult) );
    760                                         continue;
    761                                 }
    762 
    763                                 // consider only first exploded actual
    764                                 const Alternative& aActual = exploded.front();
    765                                 Type* actualType = aActual.expr->get_result()->clone();
    766 
    767                                 PRINT(
    768                                         std::cerr << "formal type is ";
    769                                         formalType->print( std::cerr );
    770                                         std::cerr << std::endl << "actual type is ";
    771                                         actualType->print( std::cerr );
    772                                         std::cerr << std::endl;
    773                                 )
    774 
    775                                 // attempt to unify types
    776                                 if ( unify( formalType, actualType, aResult.env, aResult.need, aResult.have, aResult.openVars, indexer ) ) {
    777                                         // add argument
    778                                         aResult.withArg( aActual.expr, actual.cost );
    779                                         ++aResult.nextArg;
    780                                         if ( exploded.size() > 1 ) {
    781                                                 // other parts of tuple left over
    782                                                 aResult.expls = std::move( exploded );
    783                                                 aResult.nextExpl = 1;
    784                                         }
    785                                         nextResults.push_back( std::move(aResult) );
    786                                 }
    787                         }
    788                 }
    789 
    790                 // reset for next parameter
    791                 results.swap( nextResults );
    792                 nextResults.clear();
    793 
    794                 return ! results.empty();
    795         }
    796 
    797         template<typename OutputIterator>
    798         void AlternativeFinder::makeFunctionAlternatives( const Alternative &func,
    799                         FunctionType *funcType, const std::vector< AlternativeFinder > &args,
    800                         OutputIterator out ) {
    801                 OpenVarSet funcOpenVars;
    802                 AssertionSet funcNeed, funcHave;
    803                 TypeEnvironment funcEnv( func.env );
    804                 makeUnifiableVars( funcType, funcOpenVars, funcNeed );
    805                 // add all type variables as open variables now so that those not used in the parameter
    806                 // list are still considered open.
    807                 funcEnv.add( funcType->get_forall() );
    808 
     677        template< typename OutputIterator >
     678        void AlternativeFinder::makeFunctionAlternatives( const Alternative &func, FunctionType *funcType, const AltList &actualAlt, OutputIterator out ) {
     679                OpenVarSet openVars;
     680                AssertionSet resultNeed, resultHave;
     681                TypeEnvironment resultEnv( func.env );
     682                makeUnifiableVars( funcType, openVars, resultNeed );
     683                resultEnv.add( funcType->get_forall() ); // add all type variables as open variables now so that those not used in the parameter list are still considered open
     684                AltList instantiatedActuals; // filled by instantiate function
    809685                if ( targetType && ! targetType->isVoid() && ! funcType->get_returnVals().empty() ) {
    810686                        // attempt to narrow based on expected target type
    811687                        Type * returnType = funcType->get_returnVals().front()->get_type();
    812                         if ( ! unify( returnType, targetType, funcEnv, funcNeed, funcHave, funcOpenVars,
    813                                         indexer ) ) {
    814                                 // unification failed, don't pursue this function alternative
     688                        if ( ! unify( returnType, targetType, resultEnv, resultNeed, resultHave, openVars, indexer ) ) {
     689                                // unification failed, don't pursue this alternative
    815690                                return;
    816691                        }
    817692                }
    818693
    819                 // iteratively build matches, one parameter at a time
    820                 std::vector<ArgPack> results{ ArgPack{ funcEnv, funcNeed, funcHave, funcOpenVars } };
    821                 std::vector<ArgPack> nextResults{};
    822                 for ( DeclarationWithType* formal : funcType->get_parameters() ) {
    823                         ObjectDecl* obj = strict_dynamic_cast< ObjectDecl* >( formal );
    824                         if ( ! instantiateArgument(
    825                                         obj->get_type(), obj->get_init(), args, results, nextResults, indexer ) )
    826                                 return;
    827                 }
    828 
    829                 // filter out results that don't use all the arguments, and aren't variadic
    830                 std::vector<ArgPack> finalResults{};
    831                 if ( funcType->get_isVarArgs() ) {
    832                         for ( ArgPack& result : results ) {
    833                                 // use rest of exploded tuple if present
    834                                 while ( result.nextExpl < result.expls.size() ) {
    835                                         const Alternative& actual = result.expls[result.nextExpl];
    836                                         result.env.addActual( actual.env, result.openVars );
    837                                         result.withArg( actual.expr );
    838                                         ++result.nextExpl;
    839                                 }
    840                         }
    841 
    842                         while ( ! results.empty() ) {
    843                                 // build combinations for all remaining arguments
    844                                 for ( ArgPack& result : results ) {
    845                                         // keep if used all arguments
    846                                         if ( result.nextArg >= args.size() ) {
    847                                                 finalResults.push_back( std::move(result) );
    848                                                 continue;
    849                                         }
    850 
    851                                         // add each possible next argument
    852                                         for ( const Alternative& actual : args[result.nextArg] ) {
    853                                                 ArgPack aResult = result; // copy to clone everything
    854                                                 // add details of actual to result
    855                                                 aResult.env.addActual( actual.env, aResult.openVars );
    856                                                 Cost cost = actual.cost;
    857 
    858                                                 // explode argument
    859                                                 std::vector<Alternative> exploded;
    860                                                 Tuples::explode( actual, indexer, back_inserter( exploded ) );
    861 
    862                                                 // add exploded argument to arg list
    863                                                 for ( Alternative& aActual : exploded ) {
    864                                                         aResult.withArg( aActual.expr, cost );
    865                                                         cost = Cost::zero;
    866                                                 }
    867                                                 ++aResult.nextArg;
    868                                                 nextResults.push_back( std::move(aResult) );
    869                                         }
    870                                 }
    871 
    872                                 // reset for next round
    873                                 results.swap( nextResults );
    874                                 nextResults.clear();
    875                         }
    876                 } else {
    877                         // filter out results that don't use all the arguments
    878                         for ( ArgPack& result : results ) {
    879                                 if ( result.nextExpl >= result.expls.size() && result.nextArg >= args.size() ) {
    880                                         finalResults.push_back( std::move(result) );
    881                                 }
    882                         }
    883                 }
    884 
    885                 // validate matching combos, add to final result list
    886                 for ( ArgPack& result : finalResults ) {
     694                if ( instantiateFunction( funcType->get_parameters(), actualAlt, funcType->get_isVarArgs(), openVars, resultEnv, resultNeed, resultHave, instantiatedActuals ) ) {
    887695                        ApplicationExpr *appExpr = new ApplicationExpr( func.expr->clone() );
    888                         Alternative newAlt( appExpr, result.env, sumCost( result.actuals ) );
    889                         makeExprList( result.actuals, appExpr->get_args() );
     696                        Alternative newAlt( appExpr, resultEnv, sumCost( instantiatedActuals ) );
     697                        makeExprList( instantiatedActuals, appExpr->get_args() );
    890698                        PRINT(
    891699                                std::cerr << "instantiate function success: " << appExpr << std::endl;
    892700                                std::cerr << "need assertions:" << std::endl;
    893                                 printAssertionSet( result.need, std::cerr, 8 );
     701                                printAssertionSet( resultNeed, std::cerr, 8 );
    894702                        )
    895                         inferParameters( result.need, result.have, newAlt, result.openVars, out );
     703                        inferParameters( resultNeed, resultHave, newAlt, openVars, out );
    896704                }
    897705        }
     
    903711                if ( funcFinder.alternatives.empty() ) return;
    904712
    905                 std::vector< AlternativeFinder > argAlternatives;
    906                 findSubExprs( untypedExpr->begin_args(), untypedExpr->end_args(),
    907                         back_inserter( argAlternatives ) );
     713                std::list< AlternativeFinder > argAlternatives;
     714                findSubExprs( untypedExpr->begin_args(), untypedExpr->end_args(), back_inserter( argAlternatives ) );
     715
     716                std::list< AltList > possibilities;
     717                combos( argAlternatives.begin(), argAlternatives.end(), back_inserter( possibilities ) );
    908718
    909719                // take care of possible tuple assignments
    910720                // if not tuple assignment, assignment is taken care of as a normal function call
    911                 Tuples::handleTupleAssignment( *this, untypedExpr, argAlternatives );
     721                Tuples::handleTupleAssignment( *this, untypedExpr, possibilities );
    912722
    913723                // find function operators
     
    934744                                                Alternative newFunc( *func );
    935745                                                referenceToRvalueConversion( newFunc.expr );
    936                                                 makeFunctionAlternatives( newFunc, function, argAlternatives,
    937                                                         std::back_inserter( candidates ) );
     746                                                for ( std::list< AltList >::iterator actualAlt = possibilities.begin(); actualAlt != possibilities.end(); ++actualAlt ) {
     747                                                        // XXX
     748                                                        //Designators::check_alternative( function, *actualAlt );
     749                                                        makeFunctionAlternatives( newFunc, function, *actualAlt, std::back_inserter( candidates ) );
     750                                                }
    938751                                        }
    939752                                } else if ( TypeInstType *typeInst = dynamic_cast< TypeInstType* >( func->expr->get_result()->stripReferences() ) ) { // handle ftype (e.g. *? on function pointer)
     
    943756                                                        Alternative newFunc( *func );
    944757                                                        referenceToRvalueConversion( newFunc.expr );
    945                                                         makeFunctionAlternatives( newFunc, function, argAlternatives,
    946                                                                 std::back_inserter( candidates ) );
     758                                                        for ( std::list< AltList >::iterator actualAlt = possibilities.begin(); actualAlt != possibilities.end(); ++actualAlt ) {
     759                                                                makeFunctionAlternatives( newFunc, function, *actualAlt, std::back_inserter( candidates ) );
     760                                                        } // for
    947761                                                } // if
    948762                                        } // if
    949763                                }
     764
     765                                // try each function operator ?() with the current function alternative and each of the argument combinations
     766                                for ( AltList::iterator funcOp = funcOpFinder.alternatives.begin(); funcOp != funcOpFinder.alternatives.end(); ++funcOp ) {
     767                                        // check if the type is pointer to function
     768                                        if ( PointerType *pointer = dynamic_cast< PointerType* >( funcOp->expr->get_result()->stripReferences() ) ) {
     769                                                if ( FunctionType *function = dynamic_cast< FunctionType* >( pointer->get_base() ) ) {
     770                                                        Alternative newFunc( *funcOp );
     771                                                        referenceToRvalueConversion( newFunc.expr );
     772                                                        for ( std::list< AltList >::iterator actualAlt = possibilities.begin(); actualAlt != possibilities.end(); ++actualAlt ) {
     773                                                                AltList currentAlt;
     774                                                                currentAlt.push_back( *func );
     775                                                                currentAlt.insert( currentAlt.end(), actualAlt->begin(), actualAlt->end() );
     776                                                                makeFunctionAlternatives( newFunc, function, currentAlt, std::back_inserter( candidates ) );
     777                                                        } // for
     778                                                } // if
     779                                        } // if
     780                                } // for
    950781                        } catch ( SemanticError &e ) {
    951782                                errors.append( e );
    952783                        }
    953784                } // for
    954 
    955                 // try each function operator ?() with each function alternative
    956                 if ( ! funcOpFinder.alternatives.empty() ) {
    957                         // add function alternatives to front of argument list
    958                         argAlternatives.insert( argAlternatives.begin(), std::move(funcFinder) );
    959 
    960                         for ( AltList::iterator funcOp = funcOpFinder.alternatives.begin();
    961                                         funcOp != funcOpFinder.alternatives.end(); ++funcOp ) {
    962                                 try {
    963                                         // check if type is a pointer to function
    964                                         if ( PointerType* pointer = dynamic_cast<PointerType*>(
    965                                                         funcOp->expr->get_result()->stripReferences() ) ) {
    966                                                 if ( FunctionType* function =
    967                                                                 dynamic_cast<FunctionType*>( pointer->get_base() ) ) {
    968                                                         Alternative newFunc( *funcOp );
    969                                                         referenceToRvalueConversion( newFunc.expr );
    970                                                         makeFunctionAlternatives( newFunc, function, argAlternatives,
    971                                                                 std::back_inserter( candidates ) );
    972                                                 }
    973                                         }
    974                                 } catch ( SemanticError &e ) {
    975                                         errors.append( e );
    976                                 }
    977                         }
    978                 }
    979785
    980786                // Implement SFINAE; resolution errors are only errors if there aren't any non-erroneous resolutions
     
    1007813                candidates.splice( candidates.end(), alternatives );
    1008814
    1009                 // use a new list so that alternatives are not examined by addAnonConversions twice.
    1010                 AltList winners;
    1011                 findMinCost( candidates.begin(), candidates.end(), std::back_inserter( winners ) );
     815                findMinCost( candidates.begin(), candidates.end(), std::back_inserter( alternatives ) );
    1012816
    1013817                // function may return struct or union value, in which case we need to add alternatives for implicit
    1014818                // conversions to each of the anonymous members, must happen after findMinCost since anon conversions
    1015819                // are never the cheapest expression
    1016                 for ( const Alternative & alt : winners ) {
     820                for ( const Alternative & alt : alternatives ) {
    1017821                        addAnonConversions( alt );
    1018822                }
    1019                 alternatives.splice( alternatives.begin(), winners );
    1020823
    1021824                if ( alternatives.empty() && targetType && ! targetType->isVoid() ) {
Note: See TracChangeset for help on using the changeset viewer.