Ignore:
Timestamp:
Nov 17, 2017, 10:56:16 AM (6 years ago)
Author:
Rob Schluntz <rschlunt@…>
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:
cdbfab0
Parents:
f5c3b6c (diff), b7f8cb4 (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.
Message:

Merge branch 'master' into fix-bug-51

File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/ResolvExpr/AlternativeFinder.cc

    rf5c3b6c r0fe4e62  
    2222#include <memory>                  // for allocator_traits<>::value_type
    2323#include <utility>                 // for pair
     24#include <vector>                  // for vector
    2425
    2526#include "Alternative.h"           // for AltList, Alternative
     
    333334                tmpCost.incPoly( -tmpCost.get_polyCost() );
    334335                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;
    523407        }
    524408
     
    675559        }
    676560
    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
     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
    685809                if ( targetType && ! targetType->isVoid() && ! funcType->get_returnVals().empty() ) {
    686810                        // attempt to narrow based on expected target type
    687811                        Type * returnType = funcType->get_returnVals().front()->get_type();
    688                         if ( ! unify( returnType, targetType, resultEnv, resultNeed, resultHave, openVars, indexer ) ) {
    689                                 // unification failed, don't pursue this alternative
     812                        if ( ! unify( returnType, targetType, funcEnv, funcNeed, funcHave, funcOpenVars,
     813                                        indexer ) ) {
     814                                // unification failed, don't pursue this function alternative
    690815                                return;
    691816                        }
    692817                }
    693818
    694                 if ( instantiateFunction( funcType->get_parameters(), actualAlt, funcType->get_isVarArgs(), openVars, resultEnv, resultNeed, resultHave, instantiatedActuals ) ) {
     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 ) {
    695887                        ApplicationExpr *appExpr = new ApplicationExpr( func.expr->clone() );
    696                         Alternative newAlt( appExpr, resultEnv, sumCost( instantiatedActuals ) );
    697                         makeExprList( instantiatedActuals, appExpr->get_args() );
     888                        Alternative newAlt( appExpr, result.env, sumCost( result.actuals ) );
     889                        makeExprList( result.actuals, appExpr->get_args() );
    698890                        PRINT(
    699891                                std::cerr << "instantiate function success: " << appExpr << std::endl;
    700892                                std::cerr << "need assertions:" << std::endl;
    701                                 printAssertionSet( resultNeed, std::cerr, 8 );
     893                                printAssertionSet( result.need, std::cerr, 8 );
    702894                        )
    703                         inferParameters( resultNeed, resultHave, newAlt, openVars, out );
     895                        inferParameters( result.need, result.have, newAlt, result.openVars, out );
    704896                }
    705897        }
     
    711903                if ( funcFinder.alternatives.empty() ) return;
    712904
    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 ) );
     905                std::vector< AlternativeFinder > argAlternatives;
     906                findSubExprs( untypedExpr->begin_args(), untypedExpr->end_args(),
     907                        back_inserter( argAlternatives ) );
    718908
    719909                // take care of possible tuple assignments
    720910                // if not tuple assignment, assignment is taken care of as a normal function call
    721                 Tuples::handleTupleAssignment( *this, untypedExpr, possibilities );
     911                Tuples::handleTupleAssignment( *this, untypedExpr, argAlternatives );
    722912
    723913                // find function operators
     
    744934                                                Alternative newFunc( *func );
    745935                                                referenceToRvalueConversion( newFunc.expr );
    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                                                 }
     936                                                makeFunctionAlternatives( newFunc, function, argAlternatives,
     937                                                        std::back_inserter( candidates ) );
    751938                                        }
    752939                                } else if ( TypeInstType *typeInst = dynamic_cast< TypeInstType* >( func->expr->get_result()->stripReferences() ) ) { // handle ftype (e.g. *? on function pointer)
     
    756943                                                        Alternative newFunc( *func );
    757944                                                        referenceToRvalueConversion( newFunc.expr );
    758                                                         for ( std::list< AltList >::iterator actualAlt = possibilities.begin(); actualAlt != possibilities.end(); ++actualAlt ) {
    759                                                                 makeFunctionAlternatives( newFunc, function, *actualAlt, std::back_inserter( candidates ) );
    760                                                         } // for
     945                                                        makeFunctionAlternatives( newFunc, function, argAlternatives,
     946                                                                std::back_inserter( candidates ) );
    761947                                                } // if
    762948                                        } // if
    763949                                }
    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() ) ) {
     950                        } catch ( SemanticError &e ) {
     951                                errors.append( e );
     952                        }
     953                } // 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() ) ) {
    770968                                                        Alternative newFunc( *funcOp );
    771969                                                        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
    781                         } catch ( SemanticError &e ) {
    782                                 errors.append( e );
    783                         }
    784                 } // for
     970                                                        makeFunctionAlternatives( newFunc, function, argAlternatives,
     971                                                                std::back_inserter( candidates ) );
     972                                                }
     973                                        }
     974                                } catch ( SemanticError &e ) {
     975                                        errors.append( e );
     976                                }
     977                        }
     978                }
    785979
    786980                // Implement SFINAE; resolution errors are only errors if there aren't any non-erroneous resolutions
     
    8131007                candidates.splice( candidates.end(), alternatives );
    8141008
    815                 findMinCost( candidates.begin(), candidates.end(), std::back_inserter( alternatives ) );
     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 ) );
    8161012
    8171013                // function may return struct or union value, in which case we need to add alternatives for implicit
    8181014                // conversions to each of the anonymous members, must happen after findMinCost since anon conversions
    8191015                // are never the cheapest expression
    820                 for ( const Alternative & alt : alternatives ) {
     1016                for ( const Alternative & alt : winners ) {
    8211017                        addAnonConversions( alt );
    8221018                }
     1019                alternatives.splice( alternatives.begin(), winners );
    8231020
    8241021                if ( alternatives.empty() && targetType && ! targetType->isVoid() ) {
Note: See TracChangeset for help on using the changeset viewer.