Changes in / [c2c6177:452747a]


Ignore:
Location:
src
Files:
8 edited

Legend:

Unmodified
Added
Removed
  • src/GenPoly/InstantiateGeneric.cc

    rc2c6177 r452747a  
    2727#include "Common/utility.h"            // for deleteAll, cloneAll
    2828#include "GenPoly.h"                   // for isPolyType, typesPolyCompatible
     29#include "ResolvExpr/typeops.h"
    2930#include "ScopedSet.h"                 // for ScopedSet, ScopedSet<>::iterator
    3031#include "ScrubTyVars.h"               // for ScrubTyVars
     
    151152                return gt;
    152153        }
     154
     155        /// Add cast to dtype-static member expressions so that type information is not lost in GenericInstantiator
     156        struct FixDtypeStatic final {
     157                Expression * postmutate( MemberExpr * memberExpr );
     158
     159                template<typename AggrInst>
     160                Expression * fixMemberExpr( AggrInst * inst, MemberExpr * memberExpr );
     161        };
    153162
    154163        /// Mutator pass that replaces concrete instantiations of generic types with actual struct declarations, scoped appropriately
     
    198207
    199208        void instantiateGeneric( std::list< Declaration* > &translationUnit ) {
     209                PassVisitor<FixDtypeStatic> fixer;
    200210                PassVisitor<GenericInstantiator> instantiator;
     211
     212                mutateAll( translationUnit, fixer );
    201213                mutateAll( translationUnit, instantiator );
     214        }
     215
     216        bool isDtypeStatic( const std::list< TypeDecl* >& baseParams ) {
     217                return std::all_of( baseParams.begin(), baseParams.end(), []( TypeDecl * td ) { return ! td->isComplete(); } );
    202218        }
    203219
     
    479495        }
    480496
     497        template< typename AggrInst >
     498        Expression * FixDtypeStatic::fixMemberExpr( AggrInst * inst, MemberExpr * memberExpr ) {
     499                // need to cast dtype-static member expressions to their actual type before that type is erased.
     500                auto & baseParams = *inst->get_baseParameters();
     501                if ( isDtypeStatic( baseParams ) ) {
     502                        if ( ! ResolvExpr::typesCompatible( memberExpr->result, memberExpr->member->get_type(), SymTab::Indexer() ) ) {
     503                                // type of member and type of expression differ, so add cast to actual type
     504                                return new CastExpr( memberExpr, memberExpr->result->clone() );
     505                        }
     506                }
     507                return memberExpr;
     508        }
     509
     510        Expression * FixDtypeStatic::postmutate( MemberExpr * memberExpr ) {
     511                Type * aggrType = memberExpr->aggregate->result;
     512                if ( isGenericType( aggrType ) ) {
     513                        if ( StructInstType * inst = dynamic_cast< StructInstType * >( aggrType ) ) {
     514                                return fixMemberExpr( inst, memberExpr );
     515                        } else if ( UnionInstType * inst = dynamic_cast< UnionInstType * >( aggrType ) ) {
     516                                return fixMemberExpr( inst, memberExpr );
     517                        }
     518                }
     519                return memberExpr;
     520        }
     521
    481522} // namespace GenPoly
    482523
  • src/ResolvExpr/AlternativeFinder.cc

    rc2c6177 r452747a  
    578578        /// State to iteratively build a match of parameter expressions to arguments
    579579        struct ArgPack {
    580                 std::size_t parent;                ///< Index of parent pack 
     580                std::size_t parent;                ///< Index of parent pack
    581581                std::unique_ptr<Expression> expr;  ///< The argument stored here
    582582                Cost cost;                         ///< The cost of this argument
     
    593593                        : parent(0), expr(), cost(Cost::zero), env(), need(), have(), openVars(), nextArg(0),
    594594                          tupleStart(0), expls() {}
    595                
    596                 ArgPack(const TypeEnvironment& env, const AssertionSet& need, const AssertionSet& have, 
     595
     596                ArgPack(const TypeEnvironment& env, const AssertionSet& need, const AssertionSet& have,
    597597                                const OpenVarSet& openVars)
    598                         : parent(0), expr(), cost(Cost::zero), env(env), need(need), have(have), 
     598                        : parent(0), expr(), cost(Cost::zero), env(env), need(need), have(have),
    599599                          openVars(openVars), nextArg(0), tupleStart(0), expls() {}
    600                
    601                 ArgPack(std::size_t parent, Expression* expr, TypeEnvironment&& env, AssertionSet&& need, 
    602                                 AssertionSet&& have, OpenVarSet&& openVars, unsigned nextArg, 
    603                                 unsigned tupleStart = 0, Cost cost = Cost::zero, 
     600
     601                ArgPack(std::size_t parent, Expression* expr, TypeEnvironment&& env, AssertionSet&& need,
     602                                AssertionSet&& have, OpenVarSet&& openVars, unsigned nextArg,
     603                                unsigned tupleStart = 0, Cost cost = Cost::zero,
    604604                                std::vector<Alternative>&& expls = std::vector<Alternative>{} )
    605                         : parent(parent), expr(expr->clone()), cost(cost), env(move(env)), need(move(need)), 
     605                        : parent(parent), expr(expr->clone()), cost(cost), env(move(env)), need(move(need)),
    606606                          have(move(have)), openVars(move(openVars)), nextArg(nextArg), tupleStart(tupleStart),
    607607                          expls(move(expls)) {}
    608                
    609                 ArgPack(const ArgPack& o, TypeEnvironment&& env, AssertionSet&& need, AssertionSet&& have, 
     608
     609                ArgPack(const ArgPack& o, TypeEnvironment&& env, AssertionSet&& need, AssertionSet&& have,
    610610                                OpenVarSet&& openVars, unsigned nextArg, Cost added )
    611                         : parent(o.parent), expr(o.expr ? o.expr->clone() : nullptr), cost(o.cost + added), 
    612                           env(move(env)), need(move(need)), have(move(have)), openVars(move(openVars)), 
     611                        : parent(o.parent), expr(o.expr ? o.expr->clone() : nullptr), cost(o.cost + added),
     612                          env(move(env)), need(move(need)), have(move(have)), openVars(move(openVars)),
    613613                          nextArg(nextArg), tupleStart(o.tupleStart), expls() {}
    614                          
     614
    615615
    616616                // ArgPack(const ArgPack& o)
    617                 //      : parent(o.parent), expr(o.expr ? o.expr->clone() : nullptr), env(o.env), 
    618                 //        need(o.need), have(o.have), openVars(o.openVars), nextArg(o.nextArg), 
     617                //      : parent(o.parent), expr(o.expr ? o.expr->clone() : nullptr), env(o.env),
     618                //        need(o.need), have(o.have), openVars(o.openVars), nextArg(o.nextArg),
    619619                //        tupleStart(o.tupleStart), expls(o.expls) {}
    620620
    621621                // ArgPack(ArgPack&&) = default;
    622                
     622
    623623                /// Ends a tuple expression, consolidating the appropriate actuals
    624624                void endTuple( const std::vector<ArgPack>& packs ) {
     
    640640
    641641        /// Instantiates an argument to match a formal, returns false if no results left
    642         bool instantiateArgument( Type* formalType, Initializer* initializer, 
    643                         const std::vector< AlternativeFinder >& args, std::vector<ArgPack>& results, 
     642        bool instantiateArgument( Type* formalType, Initializer* initializer,
     643                        const std::vector< AlternativeFinder >& args, std::vector<ArgPack>& results,
    644644                        std::size_t& genStart, const SymTab::Indexer& indexer, unsigned nTuples = 0 ) {
    645645                if ( TupleType* tupleType = dynamic_cast<TupleType*>( formalType ) ) {
     
    648648                        for ( Type* type : *tupleType ) {
    649649                                // xxx - dropping initializer changes behaviour from previous, but seems correct
    650                                 if ( ! instantiateArgument( 
    651                                                 type, nullptr, args, results, genStart, indexer, nTuples ) ) 
     650                                if ( ! instantiateArgument(
     651                                                type, nullptr, args, results, genStart, indexer, nTuples ) )
    652652                                        return false;
    653653                                nTuples = 0;
     
    676676                                        if ( ! results[i].expls.empty() ) {
    677677                                                const Alternative& actual = results[i].expls.front();
    678                                                
     678
    679679                                                TypeEnvironment env = results[i].env;
    680680                                                OpenVarSet openVars = results[i].openVars;
     
    682682                                                env.addActual( actual.env, openVars );
    683683
    684                                                 std::vector<Alternative> newExpls( 
     684                                                std::vector<Alternative> newExpls(
    685685                                                        std::next( results[i].expls.begin() ), results[i].expls.end() );
    686686                                                results.emplace_back(
    687                                                         i, actual.expr, move(env), copy(results[i].need), 
    688                                                         copy(results[i].have), move(openVars), results[i].nextArg, nTuples, 
     687                                                        i, actual.expr, move(env), copy(results[i].need),
     688                                                        copy(results[i].have), move(openVars), results[i].nextArg, nTuples,
    689689                                                        Cost::zero, move(newExpls) );
    690                                                
     690
    691691                                                continue;
    692692                                        }
    693                                        
     693
    694694                                        // finish result when out of arguments
    695695                                        if ( results[i].nextArg >= args.size() ) {
    696                                                 ArgPack newResult{ 
    697                                                         results[i].env, results[i].need, results[i].have, 
     696                                                ArgPack newResult{
     697                                                        results[i].env, results[i].need, results[i].have,
    698698                                                        results[i].openVars };
    699699                                                newResult.nextArg = results[i].nextArg;
     
    715715
    716716                                                        if ( results[i].tupleStart > 0 && Tuples::isTtype( argType ) ) {
    717                                                                 // the case where a ttype value is passed directly is special, 
     717                                                                // the case where a ttype value is passed directly is special,
    718718                                                                // e.g. for argument forwarding purposes
    719                                                                 // xxx - what if passing multiple arguments, last of which is 
     719                                                                // xxx - what if passing multiple arguments, last of which is
    720720                                                                //       ttype?
    721                                                                 // xxx - what would happen if unify was changed so that unifying 
    722                                                                 //       tuple 
    723                                                                 // types flattened both before unifying lists? then pass in 
     721                                                                // xxx - what would happen if unify was changed so that unifying
     722                                                                //       tuple
     723                                                                // types flattened both before unifying lists? then pass in
    724724                                                                // TupleType (ttype) below.
    725725                                                                --newResult.tupleStart;
     
    732732
    733733                                                // check unification for ttype before adding to final
    734                                                 if ( unify( ttype, argType, newResult.env, newResult.need, newResult.have, 
     734                                                if ( unify( ttype, argType, newResult.env, newResult.need, newResult.have,
    735735                                                                newResult.openVars, indexer ) ) {
    736736                                                        finalResults.push_back( move(newResult) );
    737737                                                }
    738                                                
     738
    739739                                                continue;
    740740                                        }
     
    755755                                                        // skip empty tuple arguments by (near-)cloning parent into next gen
    756756                                                        results.emplace_back(
    757                                                                 results[i], move(env), copy(results[i].need), 
     757                                                                results[i], move(env), copy(results[i].need),
    758758                                                                copy(results[i].have), move(openVars), j + 1, actual.cost );
    759                                                        
     759
    760760                                                        continue;
    761761                                                }
     
    769769                                                // add new result
    770770                                                results.emplace_back(
    771                                                         i, exploded.front().expr, move(env), copy(results[i].need), 
    772                                                         copy(results[i].have), move(openVars), results[i].nextArg + 1, 
     771                                                        i, exploded.front().expr, move(env), copy(results[i].need),
     772                                                        copy(results[i].have), move(openVars), results[i].nextArg + 1,
    773773                                                        nTuples, actual.cost, move(newExpls) );
    774774                                        }
     
    793793                        if ( ! results[i].expls.empty() ) {
    794794                                const Alternative& actual = results[i].expls.front();
    795                                
     795
    796796                                TypeEnvironment env = results[i].env;
    797797                                AssertionSet need = results[i].need, have = results[i].have;
     
    808808                                        std::cerr << std::endl;
    809809                                )
    810                                
     810
    811811                                if ( unify( formalType, actualType, env, need, have, openVars, indexer ) ) {
    812                                         std::vector<Alternative> newExpls( 
     812                                        std::vector<Alternative> newExpls(
    813813                                                std::next( results[i].expls.begin() ), results[i].expls.end() );
    814                                         results.emplace_back( 
    815                                                 i, actual.expr, move(env), move(need), move(have), move(openVars), 
     814                                        results.emplace_back(
     815                                                i, actual.expr, move(env), move(need), move(have), move(openVars),
    816816                                                results[i].nextArg, nTuples, Cost::zero, move(newExpls) );;
    817817                                }
     
    819819                                continue;
    820820                        }
    821                        
     821
    822822                        // use default initializers if out of arguments
    823823                        if ( results[i].nextArg >= args.size() ) {
     
    828828                                                OpenVarSet openVars = results[i].openVars;
    829829
    830                                                 if ( unify( formalType, cnst->get_type(), env, need, have, openVars, 
     830                                                if ( unify( formalType, cnst->get_type(), env, need, have, openVars,
    831831                                                                indexer ) ) {
    832832                                                        results.emplace_back(
    833                                                                 i, cnstExpr, move(env), move(need), move(have), 
     833                                                                i, cnstExpr, move(env), move(need), move(have),
    834834                                                                move(openVars), results[i].nextArg, nTuples );
    835835                                                }
     
    849849
    850850                                env.addActual( actual.env, openVars );
    851                                
     851
    852852                                // explode argument
    853853                                std::vector<Alternative> exploded;
     
    856856                                        // skip empty tuple arguments by (near-)cloning parent into next gen
    857857                                        results.emplace_back(
    858                                                 results[i], move(env), move(need), move(have), move(openVars), j + 1, 
     858                                                results[i], move(env), move(need), move(have), move(openVars), j + 1,
    859859                                                actual.cost );
    860860
     
    892892                // reset for next parameter
    893893                genStart = genEnd;
    894                
     894
    895895                return genEnd != results.size();
    896896        }
    897897
    898898        template<typename OutputIterator>
    899         void AlternativeFinder::validateFunctionAlternative( const Alternative &func, ArgPack& result, 
     899        void AlternativeFinder::validateFunctionAlternative( const Alternative &func, ArgPack& result,
    900900                        const std::vector<ArgPack>& results, OutputIterator out ) {
    901901                ApplicationExpr *appExpr = new ApplicationExpr( func.expr->clone() );
     
    948948                for ( DeclarationWithType* formal : funcType->get_parameters() ) {
    949949                        ObjectDecl* obj = strict_dynamic_cast< ObjectDecl* >( formal );
    950                         if ( ! instantiateArgument( 
     950                        if ( ! instantiateArgument(
    951951                                        obj->get_type(), obj->get_init(), args, results, genStart, indexer ) )
    952952                                return;
     
    964964                                        if ( ! results[i].expls.empty() ) {
    965965                                                const Alternative& actual = results[i].expls.front();
    966                                                
     966
    967967                                                TypeEnvironment env = results[i].env;
    968968                                                OpenVarSet openVars = results[i].openVars;
     
    970970                                                env.addActual( actual.env, openVars );
    971971
    972                                                 std::vector<Alternative> newExpls( 
     972                                                std::vector<Alternative> newExpls(
    973973                                                        std::next( results[i].expls.begin() ), results[i].expls.end() );
    974974                                                results.emplace_back(
    975                                                         i, actual.expr, move(env), copy(results[i].need), 
    976                                                         copy(results[i].have), move(openVars), results[i].nextArg, 0, 
     975                                                        i, actual.expr, move(env), copy(results[i].need),
     976                                                        copy(results[i].have), move(openVars), results[i].nextArg, 0,
    977977                                                        Cost::zero, move(newExpls) );
    978                                                
     978
    979979                                                continue;
    980980                                        }
     
    10011001                                                if ( exploded.empty() ) {
    10021002                                                        // skip empty tuple arguments by (near-)cloning parent into next gen
    1003                                                         results.emplace_back( 
    1004                                                                 results[i], move(env), copy(results[i].need), 
     1003                                                        results.emplace_back(
     1004                                                                results[i], move(env), copy(results[i].need),
    10051005                                                                copy(results[i].have), move(openVars), j + 1, actual.cost );
    10061006                                                        continue;
     
    10151015                                                // add new result
    10161016                                                results.emplace_back(
    1017                                                         i, exploded.front().expr, move(env), copy(results[i].need), 
    1018                                                         copy(results[i].have), move(openVars), j + 1, 0, 
     1017                                                        i, exploded.front().expr, move(env), copy(results[i].need),
     1018                                                        copy(results[i].have), move(openVars), j + 1, 0,
    10191019                                                        actual.cost, move(newExpls) );
    10201020                                        }
     
    11471147                findMinCost( candidates.begin(), candidates.end(), std::back_inserter( winners ) );
    11481148
    1149                 // function may return struct or union value, in which case we need to add alternatives 
    1150                 // for implicitconversions to each of the anonymous members, must happen after findMinCost 
     1149                // function may return struct or union value, in which case we need to add alternatives
     1150                // for implicitconversions to each of the anonymous members, must happen after findMinCost
    11511151                // since anon conversions are never the cheapest expression
    11521152                for ( const Alternative & alt : winners ) {
     
    11791179                for ( Alternative& alt : finder.alternatives ) {
    11801180                        if ( isLvalue( alt.expr ) ) {
    1181                                 alternatives.push_back( 
     1181                                alternatives.push_back(
    11821182                                        Alternative{ new AddressExpr( alt.expr->clone() ), alt.env, alt.cost } );
    11831183                        } // if
     
    12281228
    12291229                AltList candidates;
    1230                 for ( Alternative& alt : finder.alternatives ) {
     1230                for ( Alternative & alt : finder.alternatives ) {
    12311231                        AssertionSet needAssertions, haveAssertions;
    12321232                        OpenVarSet openVars;
     
    12411241                        // allow casting a tuple to an atomic type (e.g. (int)([1, 2, 3]))
    12421242                        // unification run for side-effects
    1243                         unify( castExpr->get_result(), alt.expr->get_result(), alt.env, needAssertions, 
     1243                        unify( castExpr->get_result(), alt.expr->get_result(), alt.env, needAssertions,
    12441244                                haveAssertions, openVars, indexer );
    1245                         Cost thisCost = castCost( alt.expr->get_result(), castExpr->get_result(), indexer, 
     1245                        Cost thisCost = castCost( alt.expr->get_result(), castExpr->get_result(), indexer,
    12461246                                alt.env );
     1247                        PRINT(
     1248                                std::cerr << "working on cast with result: " << castExpr->result << std::endl;
     1249                                std::cerr << "and expr type: " << alt.expr->result << std::endl;
     1250                                std::cerr << "env: " << alt.env << std::endl;
     1251                        )
    12471252                        if ( thisCost != Cost::infinity ) {
     1253                                PRINT(
     1254                                        std::cerr << "has finite cost." << std::endl;
     1255                                )
    12481256                                // count one safe conversion for each value that is thrown away
    12491257                                thisCost.incSafe( discardedValues );
    1250                                 Alternative newAlt( restructureCast( alt.expr->clone(), toType ), alt.env, 
     1258                                Alternative newAlt( restructureCast( alt.expr->clone(), toType ), alt.env,
    12511259                                        alt.cost, thisCost );
    1252                                 inferParameters( needAssertions, haveAssertions, newAlt, openVars, 
     1260                                inferParameters( needAssertions, haveAssertions, newAlt, openVars,
    12531261                                        back_inserter( candidates ) );
    12541262                        } // if
     
    15391547        void AlternativeFinder::visit( UntypedTupleExpr *tupleExpr ) {
    15401548                std::vector< AlternativeFinder > subExprAlternatives;
    1541                 findSubExprs( tupleExpr->get_exprs().begin(), tupleExpr->get_exprs().end(), 
     1549                findSubExprs( tupleExpr->get_exprs().begin(), tupleExpr->get_exprs().end(),
    15421550                        back_inserter( subExprAlternatives ) );
    15431551                std::vector< AltList > possibilities;
    1544                 combos( subExprAlternatives.begin(), subExprAlternatives.end(), 
     1552                combos( subExprAlternatives.begin(), subExprAlternatives.end(),
    15451553                        back_inserter( possibilities ) );
    15461554                for ( const AltList& alts : possibilities ) {
     
    15501558                        TypeEnvironment compositeEnv;
    15511559                        simpleCombineEnvironments( alts.begin(), alts.end(), compositeEnv );
    1552                         alternatives.push_back( 
     1560                        alternatives.push_back(
    15531561                                Alternative{ new TupleExpr( exprs ), compositeEnv, sumCost( alts ) } );
    15541562                } // for
  • src/ResolvExpr/AlternativeFinder.h

    rc2c6177 r452747a  
    3131
    3232namespace ResolvExpr {
    33         class ArgPack;
    34        
     33        struct ArgPack;
     34
    3535        class AlternativeFinder : public Visitor {
    3636          public:
     
    3838
    3939                AlternativeFinder( const AlternativeFinder& o )
    40                         : indexer(o.indexer), alternatives(o.alternatives), env(o.env), 
     40                        : indexer(o.indexer), alternatives(o.alternatives), env(o.env),
    4141                          targetType(o.targetType) {}
    42                
     42
    4343                AlternativeFinder( AlternativeFinder&& o )
    44                         : indexer(o.indexer), alternatives(std::move(o.alternatives)), env(o.env), 
     44                        : indexer(o.indexer), alternatives(std::move(o.alternatives)), env(o.env),
    4545                          targetType(o.targetType) {}
    46                
     46
    4747                AlternativeFinder& operator= ( const AlternativeFinder& o ) {
    4848                        if (&o == this) return *this;
    49                        
     49
    5050                        // horrific nasty hack to rebind references...
    5151                        alternatives.~AltList();
     
    5656                AlternativeFinder& operator= ( AlternativeFinder&& o ) {
    5757                        if (&o == this) return *this;
    58                        
     58
    5959                        // horrific nasty hack to rebind references...
    6060                        alternatives.~AltList();
  • src/ResolvExpr/TypeEnvironment.cc

    rc2c6177 r452747a  
    212212        }
    213213
     214        std::ostream & operator<<( std::ostream & out, const TypeEnvironment & env ) {
     215                env.print( out );
     216                return out;
     217        }
    214218} // namespace ResolvExpr
    215219
  • src/ResolvExpr/TypeEnvironment.h

    rc2c6177 r452747a  
    8686                TypeEnvironment *clone() const { return new TypeEnvironment( *this ); }
    8787
    88                 /// Iteratively adds the environment of a new actual (with allowWidening = false), 
     88                /// Iteratively adds the environment of a new actual (with allowWidening = false),
    8989                /// and extracts open variables.
    9090                void addActual( const TypeEnvironment& actualEnv, OpenVarSet& openVars );
     
    114114                return sub.applyFree( type );
    115115        }
     116
     117        std::ostream & operator<<( std::ostream & out, const TypeEnvironment & env );
    116118} // namespace ResolvExpr
    117119
  • src/SymTab/Autogen.h

    rc2c6177 r452747a  
    5656        /// inserts into out a generated call expression to function fname with arguments dstParam and srcParam. Intended to be used with generated ?=?, ?{}, and ^?{} calls.
    5757        template< typename OutputIterator >
    58         Statement * genCall( InitTweak::InitExpander & srcParam, Expression * dstParam, const std::string & fname, OutputIterator out, Type * type, bool addCast = false, bool forward = true );
     58        Statement * genCall( InitTweak::InitExpander & srcParam, Expression * dstParam, const std::string & fname, OutputIterator out, Type * type, Type * addCast = nullptr, bool forward = true );
    5959
    6060        /// inserts into out a generated call expression to function fname with arguments dstParam and srcParam. Should only be called with non-array types.
    6161        /// optionally returns a statement which must be inserted prior to the containing loop, if there is one
    6262        template< typename OutputIterator >
    63         Statement * genScalarCall( InitTweak::InitExpander & srcParam, Expression * dstParam, std::string fname, OutputIterator out, Type * type, bool addCast = false ) {
     63        Statement * genScalarCall( InitTweak::InitExpander & srcParam, Expression * dstParam, std::string fname, OutputIterator out, Type * type, Type * addCast = nullptr ) {
    6464                bool isReferenceCtorDtor = false;
    6565                if ( dynamic_cast< ReferenceType * >( type ) && CodeGen::isCtorDtor( fname ) ) {
     
    6868                        fname = "?=?";
    6969                        dstParam = new AddressExpr( dstParam );
    70                         addCast = false;
     70                        addCast = nullptr;
    7171                        isReferenceCtorDtor = true;
    7272                }
     
    8383                        // remove lvalue as a qualifier, this can change to
    8484                        //   type->get_qualifiers() = Type::Qualifiers();
    85                         assert( type );
    86                         Type * castType = type->clone();
     85                        Type * castType = addCast->clone();
    8786                        castType->get_qualifiers() -= Type::Qualifiers( Type::Lvalue | Type::Const | Type::Volatile | Type::Restrict | Type::Atomic );
    8887                        // castType->set_lvalue( true ); // xxx - might not need this
     
    115114        /// If forward is true, loop goes from 0 to N-1, else N-1 to 0
    116115        template< typename OutputIterator >
    117         void genArrayCall( InitTweak::InitExpander & srcParam, Expression *dstParam, const std::string & fname, OutputIterator out, ArrayType *array, bool addCast = false, bool forward = true ) {
     116        void genArrayCall( InitTweak::InitExpander & srcParam, Expression *dstParam, const std::string & fname, OutputIterator out, ArrayType *array, Type * addCast = nullptr, bool forward = true ) {
    118117                static UniqueName indexName( "_index" );
    119118
    120119                // for a flexible array member nothing is done -- user must define own assignment
    121                 if ( ! array->get_dimension() ) return ;
     120                if ( ! array->get_dimension() ) return;
     121
     122                if ( addCast ) {
     123                        // peel off array layer from cast
     124                        ArrayType * at = strict_dynamic_cast< ArrayType * >( addCast );
     125                        addCast = at->base;
     126                }
    122127
    123128                Expression * begin, * end, * update, * cmp;
     
    171176
    172177        template< typename OutputIterator >
    173         Statement * genCall( InitTweak::InitExpander & srcParam, Expression * dstParam, const std::string & fname, OutputIterator out, Type * type, bool addCast, bool forward ) {
     178        Statement * genCall( InitTweak::InitExpander & srcParam, Expression * dstParam, const std::string & fname, OutputIterator out, Type * type, Type * addCast, bool forward ) {
    174179                if ( ArrayType * at = dynamic_cast< ArrayType * >( type ) ) {
    175180                        genArrayCall( srcParam, dstParam, fname, out, at, addCast, forward );
     
    191196                if ( isUnnamedBitfield( obj ) ) return;
    192197
    193                 bool addCast = (fname == "?{}" || fname == "^?{}") && ( !obj || ( obj && ! obj->get_bitfieldWidth() ) );
     198                Type * addCast = nullptr;
     199                if ( (fname == "?{}" || fname == "^?{}") && ( !obj || ( obj && ! obj->get_bitfieldWidth() ) ) ) {
     200                        assert( dstParam->result );
     201                        addCast = dstParam->result;
     202                }
    194203                std::list< Statement * > stmts;
    195204                genCall( srcParam, dstParam, fname, back_inserter( stmts ), obj->type, addCast, forward );
  • src/SymTab/Validate.cc

    rc2c6177 r452747a  
    124124
    125125        /// Associates forward declarations of aggregates with their definitions
    126         struct LinkReferenceToTypes final : public WithIndexer {
     126        struct LinkReferenceToTypes final : public WithIndexer, public WithGuards {
    127127                LinkReferenceToTypes( const Indexer *indexer );
    128128                void postvisit( TypeInstType *typeInst );
     
    137137                void postvisit( UnionDecl *unionDecl );
    138138                void postvisit( TraitDecl * traitDecl );
     139
     140                void previsit( StructDecl *structDecl );
     141                void previsit( UnionDecl *unionDecl );
     142
     143                void renameGenericParams( std::list< TypeDecl * > & params );
    139144
    140145          private:
     
    147152                ForwardStructsType forwardStructs;
    148153                ForwardUnionsType forwardUnions;
     154                /// true if currently in a generic type body, so that type parameter instances can be renamed appropriately
     155                bool inGeneric = false;
    149156        };
    150157
     
    561568        }
    562569
     570        void LinkReferenceToTypes::renameGenericParams( std::list< TypeDecl * > & params ) {
     571                // rename generic type parameters uniquely so that they do not conflict with user-defined function forall parameters, e.g.
     572                //   forall(otype T)
     573                //   struct Box {
     574                //     T x;
     575                //   };
     576                //   forall(otype T)
     577                //   void f(Box(T) b) {
     578                //     ...
     579                //   }
     580                // The T in Box and the T in f are different, so internally the naming must reflect that.
     581                GuardValue( inGeneric );
     582                inGeneric = ! params.empty();
     583                for ( TypeDecl * td : params ) {
     584                        td->name = "__" + td->name + "_generic_";
     585                }
     586        }
     587
     588        void LinkReferenceToTypes::previsit( StructDecl * structDecl ) {
     589                renameGenericParams( structDecl->parameters );
     590        }
     591
     592        void LinkReferenceToTypes::previsit( UnionDecl * unionDecl ) {
     593                renameGenericParams( unionDecl->parameters );
     594        }
     595
    563596        void LinkReferenceToTypes::postvisit( StructDecl *structDecl ) {
    564597                // visit struct members first so that the types of self-referencing members are updated properly
     
    588621
    589622        void LinkReferenceToTypes::postvisit( TypeInstType *typeInst ) {
     623                // ensure generic parameter instances are renamed like the base type
     624                if ( inGeneric && typeInst->baseType ) typeInst->name = typeInst->baseType->name;
    590625                if ( NamedTypeDecl *namedTypeDecl = local_indexer->lookupType( typeInst->get_name() ) ) {
    591626                        if ( TypeDecl *typeDecl = dynamic_cast< TypeDecl * >( namedTypeDecl ) ) {
  • src/SynTree/Expression.cc

    rc2c6177 r452747a  
    324324                        return makeSub( refType->get_base() );
    325325                } else if ( StructInstType * aggInst = dynamic_cast< StructInstType * >( t ) ) {
    326                         return TypeSubstitution( aggInst->get_baseParameters()->begin(), aggInst->get_baseParameters()->end(), aggInst->get_parameters().begin() );
     326                        return TypeSubstitution( aggInst->get_baseParameters()->begin(), aggInst->get_baseParameters()->end(), aggInst->parameters.begin() );
    327327                } else if ( UnionInstType * aggInst = dynamic_cast< UnionInstType * >( t ) ) {
    328                         return TypeSubstitution( aggInst->get_baseParameters()->begin(), aggInst->get_baseParameters()->end(), aggInst->get_parameters().begin() );
     328                        return TypeSubstitution( aggInst->get_baseParameters()->begin(), aggInst->get_baseParameters()->end(), aggInst->parameters.begin() );
    329329                } else {
    330330                        assertf( false, "makeSub expects struct or union type for aggregate, but got: %s", toString( t ).c_str() );
Note: See TracChangeset for help on using the changeset viewer.