Changeset d3e4d6c for src/ResolvExpr


Ignore:
Timestamp:
Aug 23, 2017, 6:22:07 PM (8 years ago)
Author:
Peter A. Buhr <pabuhr@…>
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:
87e08e24, cb811ac
Parents:
9f07232 (diff), bd37119 (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' of plg2:software/cfa/cfa-cc

Location:
src/ResolvExpr
Files:
12 edited

Legend:

Unmodified
Added
Removed
  • src/ResolvExpr/Alternative.cc

    r9f07232 rd3e4d6c  
    3434                : cost( cost ), cvtCost( cvtCost ), expr( expr ), env( env ) {}
    3535
    36         Alternative::Alternative( const Alternative &other ) {
    37                 initialize( other, *this );
     36        Alternative::Alternative( const Alternative &other ) : cost( other.cost ), cvtCost( other.cvtCost ), expr( maybeClone( other.expr ) ), env( other.env ) {
    3837        }
    3938
    4039        Alternative &Alternative::operator=( const Alternative &other ) {
    4140                if ( &other == this ) return *this;
    42                 initialize( other, *this );
     41                delete expr;
     42                cost = other.cost;
     43                cvtCost = other.cvtCost;
     44                expr = maybeClone( other.expr );
     45                env = other.env;
    4346                return *this;
    4447        }
     
    5760                other.expr = nullptr;
    5861                return *this;
    59         }
    60 
    61         void Alternative::initialize( const Alternative &src, Alternative &dest ) {
    62                 dest.cost = src.cost;
    63                 dest.cvtCost = src.cvtCost;
    64                 dest.expr = maybeClone( src.expr );
    65                 dest.env = src.env;
    6662        }
    6763
  • src/ResolvExpr/Alternative.h

    r9f07232 rd3e4d6c  
    3939                ~Alternative();
    4040
    41                 void initialize( const Alternative &src, Alternative &dest );
    42 
    4341                void print( std::ostream &os, int indent = 0 ) const;
    4442
  • src/ResolvExpr/AlternativeFinder.cc

    r9f07232 rd3e4d6c  
    6767
    6868        Cost sumCost( const AltList &in ) {
    69                 Cost total;
     69                Cost total = Cost::zero;
    7070                for ( AltList::const_iterator i = in.begin(); i != in.end(); ++i ) {
    7171                        total += i->cost;
     
    144144                        expr->get_result()->accept( global_renamer );
    145145                }
    146         }
     146
     147                void referenceToRvalueConversion( Expression *& expr ) {
     148                        if ( dynamic_cast< ReferenceType * >( expr->get_result() ) ) {
     149                                // cast away reference from expr
     150                                expr = new CastExpr( expr, expr->get_result()->stripReferences()->clone() );
     151                        }
     152                }
     153        } // namespace
    147154
    148155        template< typename InputIterator, typename OutputIterator >
     
    186193                        if ( alternatives.begin() == oldBegin ) {
    187194                                std::ostringstream stream;
    188                                 stream << "Can't choose between " << alternatives.size() << " alternatives for expression ";
     195                                AltList winners;
     196                                findMinCost( alternatives.begin(), alternatives.end(), back_inserter( winners ) );
     197                                stream << "Can't choose between " << winners.size() << " alternatives for expression ";
    189198                                expr->print( stream );
    190199                                stream << "Alternatives are:";
    191                                 AltList winners;
    192                                 findMinCost( alternatives.begin(), alternatives.end(), back_inserter( winners ) );
    193200                                printAlts( winners, stream, 8 );
    194201                                throw SemanticError( stream.str() );
     
    213220        void AlternativeFinder::addAnonConversions( const Alternative & alt ) {
    214221                // adds anonymous member interpretations whenever an aggregate value type is seen.
    215                 Expression * expr = alt.expr->clone();
    216                 std::unique_ptr< Expression > manager( expr ); // RAII for expr
    217                 alt.env.apply( expr->get_result() );
    218                 if ( StructInstType *structInst = dynamic_cast< StructInstType* >( expr->get_result() ) ) {
     222                // it's okay for the aggregate expression to have reference type -- cast it to the base type to treat the aggregate as the referenced value
     223                std::unique_ptr<Expression> aggrExpr( alt.expr->clone() );
     224                alt.env.apply( aggrExpr->get_result() );
     225                Type * aggrType = aggrExpr->get_result();
     226                if ( dynamic_cast< ReferenceType * >( aggrType ) ) {
     227                        aggrType = aggrType->stripReferences();
     228                        aggrExpr.reset( new CastExpr( aggrExpr.release(), aggrType->clone() ) );
     229                }
     230
     231                if ( StructInstType *structInst = dynamic_cast< StructInstType* >( aggrExpr->get_result() ) ) {
    219232                        NameExpr nameExpr( "" );
    220                         addAggMembers( structInst, expr, alt.cost+Cost( 0, 0, 1 ), alt.env, &nameExpr );
    221                 } else if ( UnionInstType *unionInst = dynamic_cast< UnionInstType* >( expr->get_result() ) ) {
     233                        addAggMembers( structInst, aggrExpr.get(), alt.cost+Cost::safe, alt.env, &nameExpr );
     234                } else if ( UnionInstType *unionInst = dynamic_cast< UnionInstType* >( aggrExpr->get_result() ) ) {
    222235                        NameExpr nameExpr( "" );
    223                         addAggMembers( unionInst, expr, alt.cost+Cost( 0, 0, 1 ), alt.env, &nameExpr );
     236                        addAggMembers( unionInst, aggrExpr.get(), alt.cost+Cost::safe, alt.env, &nameExpr );
    224237                } // if
    225238        }
     
    228241        void AlternativeFinder::addAggMembers( StructOrUnionType *aggInst, Expression *expr, const Cost &newCost, const TypeEnvironment & env, Expression * member ) {
    229242                // by this point, member must be a name expr
    230                 NameExpr * nameExpr = safe_dynamic_cast< NameExpr * >( member );
     243                NameExpr * nameExpr = dynamic_cast< NameExpr * >( member );
     244                if ( ! nameExpr ) return;
    231245                const std::string & name = nameExpr->get_name();
    232246                std::list< Declaration* > members;
     
    250264                        // during parsing and reusing that information here.
    251265                        std::stringstream ss( constantExpr->get_constant()->get_value() );
    252                         int val;
     266                        int val = 0;
    253267                        std::string tmp;
    254268                        if ( ss >> val && ! (ss >> tmp) ) {
     
    277291                FunctionType *function = safe_dynamic_cast< FunctionType* >( pointer->get_base() );
    278292
    279                 Cost convCost( 0, 0, 0 );
     293                Cost convCost = Cost::zero;
    280294                std::list< DeclarationWithType* >& formals = function->get_parameters();
    281295                std::list< DeclarationWithType* >::iterator formal = formals.begin();
     
    290304                                actualType->print( std::cerr, 8 );
    291305                        )
    292                         Cost actualCost;
     306                        Cost actualCost = Cost::zero;
    293307                        if ( formal == formals.end() ) {
    294308                                if ( function->get_isVarArgs() ) {
    295                                         convCost += Cost( 1, 0, 0 );
     309                                        convCost.incUnsafe();
     310                                        // convert reference-typed expressions to value-typed expressions
     311                                        referenceToRvalueConversion( *actualExpr );
    296312                                        continue;
    297313                                } else {
     
    305321                                std::cerr << std::endl << " to ";
    306322                                formalType->print( std::cerr, 8 );
     323                                std::cerr << std::endl << "environment is: ";
     324                                alt.env.print( std::cerr, 8 );
     325                                std::cerr << std::endl;
    307326                        )
    308327                        Cost newCost = conversionCost( actualType, formalType, indexer, alt.env );
     
    316335                        convCost += newCost;
    317336                        actualCost += newCost;
    318                         if ( actualCost != Cost( 0, 0, 0 ) ) {
     337                        if ( actualCost != Cost::zero ) {
    319338                                Type *newType = formalType->clone();
    320339                                alt.env.apply( newType );
    321340                                *actualExpr = new CastExpr( *actualExpr, newType );
    322341                        }
    323                         convCost += Cost( 0, polyCost( formalType, alt.env, indexer ) + polyCost( actualType, alt.env, indexer ), 0 );
     342                        convCost.incPoly( polyCost( formalType, alt.env, indexer ) + polyCost( actualType, alt.env, indexer ) );
    324343                        ++formal; // can't be in for-loop update because of the continue
    325344                }
     
    343362                        }
    344363                        convCost += newCost;
    345                         convCost += Cost( 0, polyCost( assert->second.formalType, alt.env, indexer ) + polyCost( assert->second.actualType, alt.env, indexer ), 0 );
     364                        convCost.incPoly( polyCost( assert->second.formalType, alt.env, indexer ) + polyCost( assert->second.actualType, alt.env, indexer ) );
    346365                }
    347366
     
    400419                        Expression * actual = actualIt->expr;
    401420                        Type * actualType = actual->get_result();
     421
    402422                        PRINT(
    403423                                std::cerr << "formal type is ";
     
    408428                        )
    409429                        if ( ! unify( formalType, actualType, resultEnv, resultNeed, resultHave, openVars, indexer ) ) {
     430                                // std::cerr << "unify failed" << std::endl;
    410431                                return false;
    411432                        }
     
    452473                        // match flattened actuals with formal parameters - actuals will be grouped to match
    453474                        // with formals as appropriate
    454                         Cost cost;
     475                        Cost cost = Cost::zero;
    455476                        std::list< Expression * > newExprs;
    456477                        ObjectDecl * obj = safe_dynamic_cast< ObjectDecl * >( formal );
     
    613634                AssertionSet newNeed;
    614635                //AssertionParentSet needParents;
     636                PRINT(
     637                        std::cerr << "env is: " << std::endl;
     638                        newAlt.env.print( std::cerr, 0 );
     639                        std::cerr << std::endl;
     640                )
     641
    615642                inferRecursive( need.begin(), need.end(), newAlt, openVars, decls, newNeed, /*needParents,*/ 0, indexer, out );
    616643//      PRINT(
     
    643670                        makeExprList( instantiatedActuals, appExpr->get_args() );
    644671                        PRINT(
     672                                std::cerr << "instantiate function success: " << appExpr << std::endl;
    645673                                std::cerr << "need assertions:" << std::endl;
    646674                                printAssertionSet( resultNeed, std::cerr, 8 );
     
    663691                                UntypedExpr *vexpr = untypedExpr->clone();
    664692                                vexpr->set_result( pt.clone() );
    665                                 alternatives.push_back( Alternative( vexpr, env, Cost()) );
     693                                alternatives.push_back( Alternative( vexpr, env, Cost::zero) );
    666694                                return;
    667695                        }
     
    681709                AltList candidates;
    682710                SemanticError errors;
    683                 for ( AltList::const_iterator func = funcFinder.alternatives.begin(); func != funcFinder.alternatives.end(); ++func ) {
     711                for ( AltList::iterator func = funcFinder.alternatives.begin(); func != funcFinder.alternatives.end(); ++func ) {
    684712                        try {
    685713                                PRINT(
     
    688716                                )
    689717                                // check if the type is pointer to function
    690                                 PointerType *pointer;
    691                                 if ( ( pointer = dynamic_cast< PointerType* >( func->expr->get_result() ) ) ) {
     718                                if ( PointerType *pointer = dynamic_cast< PointerType* >( func->expr->get_result()->stripReferences() ) ) {
    692719                                        if ( FunctionType *function = dynamic_cast< FunctionType* >( pointer->get_base() ) ) {
     720                                                referenceToRvalueConversion( func->expr );
    693721                                                for ( std::list< AltList >::iterator actualAlt = possibilities.begin(); actualAlt != possibilities.end(); ++actualAlt ) {
    694722                                                        // XXX
     
    696724                                                        makeFunctionAlternatives( *func, function, *actualAlt, std::back_inserter( candidates ) );
    697725                                                }
    698                                         } else if ( TypeInstType *typeInst = dynamic_cast< TypeInstType* >( pointer->get_base() ) ) {
    699                                                 EqvClass eqvClass;
    700                                                 if ( func->env.lookup( typeInst->get_name(), eqvClass ) && eqvClass.type ) {
    701                                                         if ( FunctionType *function = dynamic_cast< FunctionType* >( eqvClass.type ) ) {
    702                                                                 for ( std::list< AltList >::iterator actualAlt = possibilities.begin(); actualAlt != possibilities.end(); ++actualAlt ) {
    703                                                                         makeFunctionAlternatives( *func, function, *actualAlt, std::back_inserter( candidates ) );
    704                                                                 } // for
    705                                                         } // if
     726                                        }
     727                                } else if ( TypeInstType *typeInst = dynamic_cast< TypeInstType* >( func->expr->get_result()->stripReferences() ) ) { // handle ftype (e.g. *? on function pointer)
     728                                        referenceToRvalueConversion( func->expr );
     729                                        EqvClass eqvClass;
     730                                        if ( func->env.lookup( typeInst->get_name(), eqvClass ) && eqvClass.type ) {
     731                                                if ( FunctionType *function = dynamic_cast< FunctionType* >( eqvClass.type ) ) {
     732                                                        for ( std::list< AltList >::iterator actualAlt = possibilities.begin(); actualAlt != possibilities.end(); ++actualAlt ) {
     733                                                                makeFunctionAlternatives( *func, function, *actualAlt, std::back_inserter( candidates ) );
     734                                                        } // for
    706735                                                } // if
    707736                                        } // if
     
    722751                                        }
    723752
    724                                         for ( AltList::const_iterator funcOp = funcOpFinder.alternatives.begin(); funcOp != funcOpFinder.alternatives.end(); ++funcOp ) {
     753                                        for ( AltList::iterator funcOp = funcOpFinder.alternatives.begin(); funcOp != funcOpFinder.alternatives.end(); ++funcOp ) {
    725754                                                // check if the type is pointer to function
    726                                                 PointerType *pointer;
    727                                                 if ( ( pointer = dynamic_cast< PointerType* >( funcOp->expr->get_result() ) ) ) {
     755                                                if ( PointerType *pointer = dynamic_cast< PointerType* >( funcOp->expr->get_result()->stripReferences() ) ) {
    728756                                                        if ( FunctionType *function = dynamic_cast< FunctionType* >( pointer->get_base() ) ) {
     757                                                                referenceToRvalueConversion( funcOp->expr );
    729758                                                                for ( std::list< AltList >::iterator actualAlt = possibilities.begin(); actualAlt != possibilities.end(); ++actualAlt ) {
    730759                                                                        AltList currentAlt;
     
    753782                                PointerType *pointer = safe_dynamic_cast< PointerType* >( appExpr->get_function()->get_result() );
    754783                                FunctionType *function = safe_dynamic_cast< FunctionType* >( pointer->get_base() );
    755                                 std::cerr << "Case +++++++++++++" << std::endl;
     784                                std::cerr << "Case +++++++++++++ " << appExpr->get_function() << std::endl;
    756785                                std::cerr << "formals are:" << std::endl;
    757786                                printAll( function->get_parameters(), std::cerr, 8 );
     
    796825        bool isLvalue( Expression *expr ) {
    797826                // xxx - recurse into tuples?
    798                 return expr->has_result() && expr->get_result()->get_lvalue();
     827                return expr->has_result() && ( expr->get_result()->get_lvalue() || dynamic_cast< ReferenceType * >( expr->get_result() ) );
    799828        }
    800829
     
    810839
    811840        Expression * restructureCast( Expression * argExpr, Type * toType ) {
    812                 if ( argExpr->get_result()->size() > 1 && ! toType->isVoid() ) {
    813                         // Argument expression is a tuple and the target type is not void. Cast each member of the tuple
    814                         // to its corresponding target type, producing the tuple of those cast expressions. If there are
    815                         // more components of the tuple than components in the target type, then excess components do not
    816                         // come out in the result expression (but UniqueExprs ensure that side effects will still be done).
    817                         if ( Tuples::maybeImpure( argExpr ) && ! dynamic_cast< UniqueExpr * >( argExpr ) ) {
     841                if ( argExpr->get_result()->size() > 1 && ! toType->isVoid() && ! dynamic_cast<ReferenceType *>( toType ) ) {
     842                        // Argument expression is a tuple and the target type is not void and not a reference type.
     843                        // Cast each member of the tuple to its corresponding target type, producing the tuple of those
     844                        // cast expressions. If there are more components of the tuple than components in the target type,
     845                        // then excess components do not come out in the result expression (but UniqueExprs ensure that
     846                        // side effects will still be done).
     847                        if ( Tuples::maybeImpureIgnoreUnique( argExpr ) ) {
    818848                                // expressions which may contain side effects require a single unique instance of the expression.
    819849                                argExpr = new UniqueExpr( argExpr );
     
    855885                        // that are cast directly.  The candidate is invalid if it has fewer results than there are types to cast
    856886                        // to.
    857                         int discardedValues = (*i).expr->get_result()->size() - castExpr->get_result()->size();
     887                        int discardedValues = i->expr->get_result()->size() - castExpr->get_result()->size();
    858888                        if ( discardedValues < 0 ) continue;
    859889                        // xxx - may need to go into tuple types and extract relevant types and use unifyList. Note that currently, this does not
    860890                        // allow casting a tuple to an atomic type (e.g. (int)([1, 2, 3]))
    861891                        // unification run for side-effects
    862                         unify( castExpr->get_result(), (*i).expr->get_result(), i->env, needAssertions, haveAssertions, openVars, indexer );
    863                         Cost thisCost = castCost( (*i).expr->get_result(), castExpr->get_result(), indexer, i->env );
     892                        unify( castExpr->get_result(), i->expr->get_result(), i->env, needAssertions, haveAssertions, openVars, indexer );
     893                        Cost thisCost = castCost( i->expr->get_result(), castExpr->get_result(), indexer, i->env );
    864894                        if ( thisCost != Cost::infinity ) {
    865895                                // count one safe conversion for each value that is thrown away
    866                                 thisCost += Cost( 0, 0, discardedValues );
     896                                thisCost.incSafe( discardedValues );
    867897
    868898                                candidates.push_back( Alternative( restructureCast( i->expr->clone(), toType ), i->env, i->cost, thisCost ) );
     
    895925                funcFinder.findWithAdjustment( memberExpr->get_aggregate() );
    896926                for ( AltList::const_iterator agg = funcFinder.alternatives.begin(); agg != funcFinder.alternatives.end(); ++agg ) {
    897                         if ( StructInstType *structInst = dynamic_cast< StructInstType* >( agg->expr->get_result() ) ) {
    898                                 addAggMembers( structInst, agg->expr, agg->cost, agg->env, memberExpr->get_member() );
    899                         } else if ( UnionInstType *unionInst = dynamic_cast< UnionInstType* >( agg->expr->get_result() ) ) {
    900                                 addAggMembers( unionInst, agg->expr, agg->cost, agg->env, memberExpr->get_member() );
    901                         } else if ( TupleType * tupleType = dynamic_cast< TupleType * >( agg->expr->get_result() ) ) {
    902                                 addTupleMembers( tupleType, agg->expr, agg->cost, agg->env, memberExpr->get_member() );
     927                        // it's okay for the aggregate expression to have reference type -- cast it to the base type to treat the aggregate as the referenced value
     928                        std::unique_ptr<Expression> aggrExpr( agg->expr->clone() );
     929                        Type * aggrType = aggrExpr->get_result();
     930                        if ( dynamic_cast< ReferenceType * >( aggrType ) ) {
     931                                aggrType = aggrType->stripReferences();
     932                                aggrExpr.reset( new CastExpr( aggrExpr.release(), aggrType->clone() ) );
     933                        }
     934                        // find member of the given type
     935                        if ( StructInstType *structInst = dynamic_cast< StructInstType* >( aggrExpr->get_result() ) ) {
     936                                addAggMembers( structInst, aggrExpr.get(), agg->cost, agg->env, memberExpr->get_member() );
     937                        } else if ( UnionInstType *unionInst = dynamic_cast< UnionInstType* >( aggrExpr->get_result() ) ) {
     938                                addAggMembers( unionInst, aggrExpr.get(), agg->cost, agg->env, memberExpr->get_member() );
     939                        } else if ( TupleType * tupleType = dynamic_cast< TupleType * >( aggrExpr->get_result() ) ) {
     940                                addTupleMembers( tupleType, aggrExpr.get(), agg->cost, agg->env, memberExpr->get_member() );
    903941                        } // if
    904942                } // for
     
    915953                for ( std::list< DeclarationWithType* >::iterator i = declList.begin(); i != declList.end(); ++i ) {
    916954                        VariableExpr newExpr( *i, nameExpr->get_argName() );
    917                         alternatives.push_back( Alternative( newExpr.clone(), env, Cost() ) );
     955                        alternatives.push_back( Alternative( newExpr.clone(), env, Cost::zero ) );
    918956                        PRINT(
    919957                                std::cerr << "decl is ";
     
    955993                        // return the lowest cost alternative for the argument
    956994                        Alternative &choice = winners.front();
     995                        referenceToRvalueConversion( choice.expr );
    957996                        alternatives.push_back( Alternative( new SizeofExpr( choice.expr->clone() ), choice.env, Cost::zero ) );
    958997                } // if
     
    9751014                        // return the lowest cost alternative for the argument
    9761015                        Alternative &choice = winners.front();
     1016                        referenceToRvalueConversion( choice.expr );
    9771017                        alternatives.push_back( Alternative( new AlignofExpr( choice.expr->clone() ), choice.env, Cost::zero ) );
    9781018                } // if
     
    10591099                        for ( std::list< DeclarationWithType* >::iterator i = attrList.begin(); i != attrList.end(); ++i ) {
    10601100                                VariableExpr newExpr( *i );
    1061                                 alternatives.push_back( Alternative( newExpr.clone(), env, Cost() ) );
     1101                                alternatives.push_back( Alternative( newExpr.clone(), env, Cost::zero ) );
    10621102                                renameTypes( alternatives.back().expr );
    10631103                        } // for
     
    12321272                                if ( thisCost != Cost::infinity ) {
    12331273                                        // count one safe conversion for each value that is thrown away
    1234                                         thisCost += Cost( 0, 0, discardedValues );
     1274                                        thisCost.incSafe( discardedValues );
    12351275                                        candidates.push_back( Alternative( new InitExpr( restructureCast( alt.expr->clone(), toType ), initAlt.designation->clone() ), newEnv, alt.cost, thisCost ) );
    12361276                                }
  • src/ResolvExpr/CastCost.cc

    r9f07232 rd3e4d6c  
    4949                                assert( type );
    5050                                if ( type->get_base() ) {
    51                                         return castCost( src, type->get_base(), indexer, env ) + Cost( 0, 0, 1 );
     51                                        return castCost( src, type->get_base(), indexer, env ) + Cost::safe;
    5252                                } // if
    5353                        } // if
    5454                } // if
    5555                if ( typesCompatibleIgnoreQualifiers( src, dest, indexer, env ) ) {
    56                         return Cost( 0, 0, 0 );
     56                        return Cost::zero;
    5757                } else if ( dynamic_cast< VoidType* >( dest ) ) {
    58                         return Cost( 0, 0, 1 );
     58                        return Cost::safe;
     59                } else if ( ReferenceType * refType = dynamic_cast< ReferenceType * > ( dest ) ) {
     60                        return convertToReferenceCost( src, refType, indexer, env );
    5961                } else {
    6062                        CastCost converter( dest, indexer, env );
     
    6466                        } else {
    6567                                // xxx - why are we adding cost 0 here?
    66                                 return converter.get_cost() + Cost( 0, 0, 0 );
     68                                return converter.get_cost() + Cost::zero;
    6769                        } // if
    6870                } // if
     
    7779                if ( destAsPointer && basicType->isInteger() ) {
    7880                        // necessary for, e.g. unsigned long => void*
    79                         cost = Cost( 1, 0, 0 );
     81                        cost = Cost::unsafe;
    8082                } else {
    81                         ConversionCost::visit( basicType );
     83                        cost = conversionCost( basicType, dest, indexer, env );
    8284                } // if
    8385        }
     
    8688                if ( PointerType *destAsPtr = dynamic_cast< PointerType* >( dest ) ) {
    8789                        if ( pointerType->get_qualifiers() <= destAsPtr->get_qualifiers() && typesCompatibleIgnoreQualifiers( pointerType->get_base(), destAsPtr->get_base(), indexer, env ) ) {
    88                                 cost = Cost( 0, 0, 1 );
     90                                cost = Cost::safe;
    8991                        } else {
    9092                                TypeEnvironment newEnv( env );
     
    9395                                int castResult = ptrsCastable( pointerType->get_base(), destAsPtr->get_base(), newEnv, indexer );
    9496                                if ( castResult > 0 ) {
    95                                         cost = Cost( 0, 0, 1 );
     97                                        cost = Cost::safe;
    9698                                } else if ( castResult < 0 ) {
    9799                                        cost = Cost::infinity;
     
    101103                        if ( destAsBasic->isInteger() ) {
    102104                                // necessary for, e.g. void* => unsigned long
    103                                 cost = Cost( 1, 0, 0 );
     105                                cost = Cost::unsafe;
    104106                        } // if
    105107                }
  • src/ResolvExpr/CommonType.cc

    r9f07232 rd3e4d6c  
    2626#include "typeops.h"                     // for isFtype
    2727
    28 
    29 /// #define DEBUG
     28// #define DEBUG
    3029
    3130namespace ResolvExpr {
     
    3938                virtual void visit( PointerType *pointerType );
    4039                virtual void visit( ArrayType *arrayType );
     40                virtual void visit( ReferenceType *refType );
    4141                virtual void visit( FunctionType *functionType );
    4242                virtual void visit( StructInstType *aggregateUseType );
     
    5050                virtual void visit( OneType *oneType );
    5151
    52                 void getCommonWithVoidPointer( PointerType* voidPointer, PointerType* otherPointer );
     52                template< typename Pointer > void getCommonWithVoidPointer( Pointer* voidPointer, Pointer* otherPointer );
     53                template< typename RefType > void handleRefType( RefType *inst, Type *other );
    5354
    5455                Type *result;
     
    6061        };
    6162
     63        Type * handleReference( ReferenceType * refType, Type * other, bool widenFirst, bool widenSecond, const SymTab::Indexer &indexer, TypeEnvironment & env, const OpenVarSet &openVars ) {
     64                Type * result = nullptr, * common = nullptr;
     65                AssertionSet have, need;
     66                OpenVarSet newOpen( openVars );
     67                // need unify to bind type variables
     68                if ( unify( refType->get_base(), other, env, have, need, newOpen, indexer, common ) ) {
     69                        // std::cerr << "unify success" << std::endl;
     70                        if ( widenSecond ) {
     71                                // std::cerr << "widen second" << std::endl;
     72                                if ( widenFirst || other->get_qualifiers() <= refType->get_qualifiers() ) {
     73                                        result = new ReferenceType( refType->get_qualifiers(), common ); // refType->clone();
     74                                        result->get_qualifiers() |= other->get_qualifiers();
     75                                }
     76                        } else if ( widenFirst ) {
     77                                // std::cerr << "widen first" << std::endl;
     78                                if ( widenSecond || refType->get_qualifiers() <= other->get_qualifiers() ) {
     79                                        result = common;
     80                                        result->get_qualifiers() |= refType->get_qualifiers();
     81                                }
     82                        }
     83                } else {
     84                        // std::cerr << "exact unify failed: " << refType << " " << other << std::endl;
     85                }
     86                // std::cerr << "common type of reference [" << refType << "] and non-reference [" << other << "] is [" << result << "]" << std::endl;
     87                return result;
     88        }
     89
    6290        Type *commonType( Type *type1, Type *type2, bool widenFirst, bool widenSecond, const SymTab::Indexer &indexer, TypeEnvironment &env, const OpenVarSet &openVars ) {
    6391                CommonType visitor( type2, widenFirst, widenSecond, indexer, env, openVars );
     92
     93                int depth1 = type1->referenceDepth();
     94                int depth2 = type2->referenceDepth();
     95                if ( depth1 > 0 || depth2 > 0 ) {
     96                        int diff = depth1-depth2;
     97                        // TODO: should it be possible for commonType to generate complicated conversions? I would argue no, only conversions that involve types of the same reference level or a difference of 1 should be allowed.
     98                        if ( diff > 1 || diff < -1 ) return nullptr;
     99
     100                        // special case where one type has a reference depth of 1 larger than the other
     101                        if ( diff > 0 ) {
     102                                return handleReference( safe_dynamic_cast<ReferenceType *>( type1 ), type2, widenFirst, widenSecond, indexer, env, openVars );
     103                        } else if ( diff < 0 ) {
     104                                return handleReference( safe_dynamic_cast<ReferenceType *>( type2 ), type1, widenSecond, widenFirst, indexer, env, openVars );
     105                        }
     106                        // otherwise, both are reference types of the same depth and this is handled by the CommonType visitor.
     107                }
     108
    64109                type1->accept( visitor );
    65110                Type *result = visitor.get_result();
     
    88133                } // if
    89134#ifdef DEBUG
    90                 std::cout << "============= commonType" << std::endl << "type1 is ";
    91                 type1->print( std::cout );
    92                 std::cout << " type2 is ";
    93                 type2->print( std::cout );
     135                std::cerr << "============= commonType" << std::endl << "type1 is ";
     136                type1->print( std::cerr );
     137                std::cerr << " type2 is ";
     138                type2->print( std::cerr );
    94139                if ( result ) {
    95                         std::cout << " common type is ";
    96                         result->print( std::cout );
     140                        std::cerr << " common type is ";
     141                        result->print( std::cerr );
    97142                } else {
    98                         std::cout << " no common type";
    99                 } // if
    100                 std::cout << std::endl;
     143                        std::cerr << " no common type";
     144                } // if
     145                std::cerr << std::endl;
    101146#endif
    102147                return result;
     
    150195        }
    151196
    152         void CommonType::getCommonWithVoidPointer( PointerType* voidPointer, PointerType* otherPointer ) {
     197        template< typename Pointer >
     198        void CommonType::getCommonWithVoidPointer( Pointer* voidPointer, Pointer* otherPointer ) {
    153199                if ( TypeInstType* var = dynamic_cast< TypeInstType* >( otherPointer->get_base() ) ) {
    154200                        OpenVarSet::const_iterator entry = openVars.find( var->get_name() );
     
    165211        void CommonType::visit( PointerType *pointerType ) {
    166212                if ( PointerType *otherPointer = dynamic_cast< PointerType* >( type2 ) ) {
     213                        // std::cerr << "commonType: two pointers: " << pointerType << " / " << otherPointer << std::endl;
    167214                        if ( widenFirst && dynamic_cast< VoidType* >( otherPointer->get_base() ) && ! isFtype(pointerType->get_base()) ) {
    168215                                getCommonWithVoidPointer( otherPointer, pointerType );
     
    171218                        } else if ( ( pointerType->get_base()->get_qualifiers() >= otherPointer->get_base()->get_qualifiers() || widenFirst )
    172219                                           && ( pointerType->get_base()->get_qualifiers() <= otherPointer->get_base()->get_qualifiers() || widenSecond ) ) {
     220                                // std::cerr << "middle case" << std::endl;
    173221                                Type::Qualifiers tq1 = pointerType->get_base()->get_qualifiers(), tq2 = otherPointer->get_base()->get_qualifiers();
    174222                                pointerType->get_base()->get_qualifiers() = Type::Qualifiers();
     
    177225                                OpenVarSet newOpen( openVars );
    178226                                if ( unifyExact( pointerType->get_base(), otherPointer->get_base(), env, have, need, newOpen, indexer ) ) {
     227                                        // std::cerr << "unifyExact success" << std::endl;
    179228                                        if ( tq1 < tq2 ) {
    180229                                                result = pointerType->clone();
     
    184233                                        result->get_qualifiers() = tq1 | tq2;
    185234                                } else {
    186                                         /// std::cout << "place for ptr-to-type" << std::endl;
     235                                        /// std::cerr << "place for ptr-to-type" << std::endl;
    187236                                } // if
    188237                                pointerType->get_base()->get_qualifiers() = tq1;
     
    196245
    197246        void CommonType::visit( __attribute((unused)) ArrayType *arrayType ) {}
     247
     248        void CommonType::visit( ReferenceType *refType ) {
     249                if ( ReferenceType *otherRef = dynamic_cast< ReferenceType* >( type2 ) ) {
     250                        // std::cerr << "commonType: both references: " << refType << " / " << otherRef << std::endl;
     251                        // std::cerr << ( refType->get_base()->get_qualifiers() >= otherRef->get_base()->get_qualifiers() || widenFirst ) << (refType->get_base()->get_qualifiers() <= otherRef->get_base()->get_qualifiers() || widenSecond) << std::endl;
     252                        if ( widenFirst && dynamic_cast< VoidType* >( otherRef->get_base() ) && ! isFtype(refType->get_base()) ) {
     253                                getCommonWithVoidPointer( otherRef, refType );
     254                        } else if ( widenSecond && dynamic_cast< VoidType* >( refType->get_base() ) && ! isFtype(otherRef->get_base()) ) {
     255                                getCommonWithVoidPointer( refType, otherRef );
     256                        } else if ( ( refType->get_base()->get_qualifiers() >= otherRef->get_base()->get_qualifiers() || widenFirst )
     257                                           && ( refType->get_base()->get_qualifiers() <= otherRef->get_base()->get_qualifiers() || widenSecond ) ) {
     258                                // std::cerr << "middle case" << std::endl;
     259                                Type::Qualifiers tq1 = refType->get_base()->get_qualifiers(), tq2 = otherRef->get_base()->get_qualifiers();
     260                                refType->get_base()->get_qualifiers() = Type::Qualifiers();
     261                                otherRef->get_base()->get_qualifiers() = Type::Qualifiers();
     262                                AssertionSet have, need;
     263                                OpenVarSet newOpen( openVars );
     264                                if ( unifyExact( refType->get_base(), otherRef->get_base(), env, have, need, newOpen, indexer ) ) {
     265                                        if ( tq1 < tq2 ) {
     266                                                result = refType->clone();
     267                                        } else {
     268                                                result = otherRef->clone();
     269                                        } // if
     270                                        result->get_qualifiers() = tq1 | tq2;
     271                                } else {
     272                                        /// std::cerr << "place for ptr-to-type" << std::endl;
     273                                } // if
     274                                refType->get_base()->get_qualifiers() = tq1;
     275                                otherRef->get_base()->get_qualifiers() = tq2;
     276                        } // if
     277                } else if ( widenSecond && dynamic_cast< ZeroType* >( type2 ) ) {
     278                        result = refType->clone();
     279                        result->get_qualifiers() |= type2->get_qualifiers();
     280                } // if
     281        }
     282
    198283        void CommonType::visit( __attribute((unused)) FunctionType *functionType ) {}
    199284        void CommonType::visit( __attribute((unused)) StructInstType *aggregateUseType ) {}
     
    203288                if ( dynamic_cast< BasicType * >( type2 ) || dynamic_cast< ZeroType* >( type2 ) || dynamic_cast< OneType* >( type2 ) ) {
    204289                        // reuse BasicType, EnumInstType code by swapping type2 with enumInstType
    205                         Type * temp = type2;
     290                        ValueGuard< Type * > temp( type2 );
    206291                        type2 = enumInstType;
    207                         temp->accept( *this );
    208                         type2 = temp;
     292                        temp.old->accept( *this );
    209293                } // if
    210294        }
  • src/ResolvExpr/ConversionCost.cc

    r9f07232 rd3e4d6c  
    2828
    2929namespace ResolvExpr {
    30         const Cost Cost::zero = Cost( 0, 0, 0 );
    31         const Cost Cost::infinity = Cost( -1, -1, -1 );
     30        const Cost Cost::zero = Cost( 0, 0, 0, 0 );
     31        const Cost Cost::infinity = Cost( -1, -1, -1, -1 );
     32        const Cost Cost::unsafe = Cost( 1, 0, 0, 0 );
     33        const Cost Cost::poly = Cost( 0, 1, 0, 0 );
     34        const Cost Cost::safe = Cost( 0, 0, 1, 0 );
     35        const Cost Cost::reference = Cost( 0, 0, 0, 1 );
     36
     37#if 0
     38#define PRINT(x) x
     39#else
     40#define PRINT(x)
     41#endif
    3242
    3343        Cost conversionCost( Type *src, Type *dest, const SymTab::Indexer &indexer, const TypeEnvironment &env ) {
     
    3545                        EqvClass eqvClass;
    3646                        NamedTypeDecl *namedType;
    37 ///     std::cout << "type inst " << destAsTypeInst->get_name();
     47                        PRINT( std::cerr << "type inst " << destAsTypeInst->get_name(); )
    3848                        if ( env.lookup( destAsTypeInst->get_name(), eqvClass ) ) {
    3949                                if ( eqvClass.type ) {
     
    4353                                }
    4454                        } else if ( ( namedType = indexer.lookupType( destAsTypeInst->get_name() ) ) ) {
    45 ///       std::cout << " found" << std::endl;
     55                                PRINT( std::cerr << " found" << std::endl; )
    4656                                TypeDecl *type = dynamic_cast< TypeDecl* >( namedType );
    4757                                // all typedefs should be gone by this point
    4858                                assert( type );
    4959                                if ( type->get_base() ) {
    50                                         return conversionCost( src, type->get_base(), indexer, env ) + Cost( 0, 0, 1 );
     60                                        return conversionCost( src, type->get_base(), indexer, env ) + Cost::safe;
    5161                                } // if
    5262                        } // if
    53 ///     std::cout << " not found" << std::endl;
    54                 } // if
    55 ///   std::cout << "src is ";
    56 ///   src->print( std::cout );
    57 ///   std::cout << std::endl << "dest is ";
    58 ///   dest->print( std::cout );
    59 ///   std::cout << std::endl << "env is" << std::endl;
    60 ///   env.print( std::cout, 8 );
     63                        PRINT( std::cerr << " not found" << std::endl; )
     64                } // if
     65                PRINT(
     66                        std::cerr << "src is ";
     67                        src->print( std::cerr );
     68                        std::cerr << std::endl << "dest is ";
     69                        dest->print( std::cerr );
     70                        std::cerr << std::endl << "env is" << std::endl;
     71                        env.print( std::cerr, 8 );
     72                )
    6173                if ( typesCompatibleIgnoreQualifiers( src, dest, indexer, env ) ) {
    62 ///     std::cout << "compatible!" << std::endl;
    63                         return Cost( 0, 0, 0 );
     74                        PRINT( std::cerr << "compatible!" << std::endl; )
     75                        return Cost::zero;
    6476                } else if ( dynamic_cast< VoidType* >( dest ) ) {
    65                         return Cost( 0, 0, 1 );
     77                        return Cost::safe;
     78                } else if ( ReferenceType * refType = dynamic_cast< ReferenceType * > ( dest ) ) {
     79                        PRINT( std::cerr << "conversionCost: dest is reference" << std::endl; )
     80                        return convertToReferenceCost( src, refType, indexer, env );
    6681                } else {
    6782                        ConversionCost converter( dest, indexer, env );
     
    7085                                return Cost::infinity;
    7186                        } else {
    72                                 return converter.get_cost() + Cost( 0, 0, 0 );
    73                         } // if
    74                 } // if
     87                                return converter.get_cost() + Cost::zero;
     88                        } // if
     89                } // if
     90        }
     91
     92        Cost convertToReferenceCost( Type * src, Type * dest, int diff, const SymTab::Indexer & indexer, const TypeEnvironment & env ) {
     93                PRINT( std::cerr << "convert to reference cost..." << std::endl; )
     94                if ( diff > 0 ) {
     95                        // TODO: document this
     96                        Cost cost = convertToReferenceCost( safe_dynamic_cast< ReferenceType * >( src )->get_base(), dest, diff-1, indexer, env );
     97                        cost.incReference();
     98                        return cost;
     99                } else if ( diff < -1 ) {
     100                        // TODO: document this
     101                        Cost cost = convertToReferenceCost( src, safe_dynamic_cast< ReferenceType * >( dest )->get_base(), diff+1, indexer, env );
     102                        cost.incReference();
     103                        return cost;
     104                } else if ( diff == 0 ) {
     105                        ReferenceType * srcAsRef = dynamic_cast< ReferenceType * >( src );
     106                        ReferenceType * destAsRef = dynamic_cast< ReferenceType * >( dest );
     107                        if ( srcAsRef && destAsRef ) { // pointer-like conversions between references
     108                                PRINT( std::cerr << "converting between references" << std::endl; )
     109                                if ( srcAsRef->get_base()->get_qualifiers() <= destAsRef->get_base()->get_qualifiers() && typesCompatibleIgnoreQualifiers( srcAsRef->get_base(), destAsRef->get_base(), indexer, env ) ) {
     110                                        return Cost::safe;
     111                                } else {  // xxx - this discards reference qualifiers from consideration -- reducing qualifiers is a safe conversion; is this right?
     112                                        int assignResult = ptrsAssignable( srcAsRef->get_base(), destAsRef->get_base(), env );
     113                                        PRINT( std::cerr << "comparing references: " << assignResult << " " << srcAsRef << " " << destAsRef << std::endl; )
     114                                        if ( assignResult < 0 ) {
     115                                                return Cost::safe;
     116                                        } else if ( assignResult > 0 ) {
     117                                                return Cost::unsafe;
     118                                        } // if
     119                                } // if
     120                        } else {
     121                                PRINT( std::cerr << "reference to rvalue conversion" << std::endl; )
     122                                ConversionCost converter( dest, indexer, env );
     123                                src->accept( converter );
     124                                return converter.get_cost();
     125                        } // if
     126                } else {
     127                        ReferenceType * destAsRef = dynamic_cast< ReferenceType * >( dest );
     128                        assert( diff == -1 && destAsRef );
     129                        if ( typesCompatibleIgnoreQualifiers( src, destAsRef->get_base(), indexer, env ) ) {
     130                                PRINT( std::cerr << "converting compatible base type" << std::endl; )
     131                                if ( src->get_lvalue() ) {
     132                                        PRINT(
     133                                                std::cerr << "lvalue to reference conversion" << std::endl;
     134                                                std::cerr << src << " => " << destAsRef << std::endl;
     135                                        )
     136                                        // lvalue-to-reference conversion:  cv lvalue T => cv T &
     137                                        if ( src->get_qualifiers() == destAsRef->get_base()->get_qualifiers() ) {
     138                                                return Cost::reference; // cost needs to be non-zero to add cast
     139                                        } if ( src->get_qualifiers() < destAsRef->get_base()->get_qualifiers() ) {
     140                                                return Cost::safe; // cost needs to be higher than previous cast to differentiate adding qualifiers vs. keeping same
     141                                        } else {
     142                                                return Cost::unsafe;
     143                                        } // if
     144                                } else if ( destAsRef->get_base()->get_const() ) {
     145                                        PRINT( std::cerr << "rvalue to const ref conversion" << std::endl; )
     146                                        // rvalue-to-const-reference conversion: T => const T &
     147                                        return Cost::safe;
     148                                } else {
     149                                        PRINT( std::cerr << "rvalue to non-const reference conversion" << std::endl; )
     150                                        // rvalue-to-reference conversion: T => T &
     151                                        return Cost::unsafe;
     152                                } // if
     153                        } // if
     154                        PRINT( std::cerr << "attempting to convert from incompatible base type -- fail" << std::endl; )
     155                }
     156                return Cost::infinity;
     157        }
     158
     159        Cost convertToReferenceCost( Type * src, ReferenceType * dest, const SymTab::Indexer & indexer, const TypeEnvironment & env ) {
     160                int sdepth = src->referenceDepth(), ddepth = dest->referenceDepth();
     161                return convertToReferenceCost( src, dest, sdepth-ddepth, indexer, env );
    75162        }
    76163
     
    164251                        int tableResult = costMatrix[ basicType->get_kind() ][ destAsBasic->get_kind() ];
    165252                        if ( tableResult == -1 ) {
    166                                 cost = Cost( 1, 0, 0 );
    167                         } else {
    168                                 cost = Cost( 0, 0, tableResult );
     253                                cost = Cost::unsafe;
     254                        } else {
     255                                cost = Cost::zero;
     256                                cost.incSafe( tableResult );
    169257                        } // if
    170258                } else if ( dynamic_cast< EnumInstType *>( dest ) ) {
    171259                        // xxx - not positive this is correct, but appears to allow casting int => enum
    172                         cost = Cost( 1, 0, 0 );
     260                        cost = Cost::unsafe;
    173261                } else if ( dynamic_cast< ZeroType* >( dest ) != nullptr || dynamic_cast< OneType* >( dest ) != nullptr ) {
    174                         cost = Cost( 1, 0, 0 );
     262                        cost = Cost::unsafe;
    175263                } // if
    176264        }
     
    178266        void ConversionCost::visit(PointerType *pointerType) {
    179267                if ( PointerType *destAsPtr = dynamic_cast< PointerType* >( dest ) ) {
    180                         if ( pointerType->get_base()->get_qualifiers() <= destAsPtr->get_base()->get_qualifiers() && typesCompatibleIgnoreQualifiers( pointerType->get_base(), destAsPtr->get_base(), indexer, env ) ) {
    181                                 cost = Cost( 0, 0, 1 );
    182                         } else {
     268                        PRINT( std::cerr << pointerType << " ===> " << destAsPtr; )
     269                        Type::Qualifiers tq1 = pointerType->get_base()->get_qualifiers();
     270                        Type::Qualifiers tq2 = destAsPtr->get_base()->get_qualifiers();
     271                        if ( tq1 <= tq2 && typesCompatibleIgnoreQualifiers( pointerType->get_base(), destAsPtr->get_base(), indexer, env ) ) {
     272                                if ( tq1 == tq2 ) {
     273                                        // types are the same
     274                                        cost = Cost::zero;
     275                                } else {
     276                                        // types are the same, except otherPointer has more qualifiers
     277                                        PRINT( std::cerr << " :: compatible and good qualifiers" << std::endl; )
     278                                        cost = Cost::safe;
     279                                }
     280                        } else {  // xxx - this discards qualifiers from consideration -- reducing qualifiers is a safe conversion; is this right?
    183281                                int assignResult = ptrsAssignable( pointerType->get_base(), destAsPtr->get_base(), env );
    184                                 if ( assignResult < 0 ) {
    185                                         cost = Cost( 0, 0, 1 );
     282                                PRINT( std::cerr << " :: " << assignResult << std::endl; )
     283                                if ( assignResult < 0 && pointerType->get_base()->get_qualifiers() <= destAsPtr->get_qualifiers() ) {
     284                                        cost = Cost::safe;
    186285                                } else if ( assignResult > 0 ) {
    187                                         cost = Cost( 1, 0, 0 );
     286                                        cost = Cost::unsafe;
    188287                                } // if
     288                                // assignResult == 0 means Cost::Infinity
    189289                        } // if
    190290                } else if ( dynamic_cast< ZeroType* >( dest ) != nullptr || dynamic_cast< OneType* >( dest ) != nullptr ) {
    191                         cost = Cost( 1, 0, 0 );
     291                        cost = Cost::unsafe;
    192292                } // if
    193293        }
    194294
    195295        void ConversionCost::visit(__attribute((unused)) ArrayType *arrayType) {}
     296
     297        void ConversionCost::visit(ReferenceType *refType) {
     298                // Note: dest can never be a reference, since it would have been caught in an earlier check
     299                assert( ! dynamic_cast< ReferenceType * >( dest ) );
     300                // convert reference to rvalue: cv T1 & => T2
     301                // recursively compute conversion cost from T1 to T2.
     302                // cv can be safely dropped because of 'implicit dereference' behavior.
     303                refType->get_base()->accept( *this );
     304                if ( refType->get_base()->get_qualifiers() == dest->get_qualifiers() ) {
     305                        cost.incReference();  // prefer exact qualifiers
     306                } else if ( refType->get_base()->get_qualifiers() < dest->get_qualifiers() ) {
     307                        cost.incSafe(); // then gaining qualifiers
     308                } else {
     309                        cost.incUnsafe(); // lose qualifiers as last resort
     310                }
     311                PRINT( std::cerr << refType << " ==> " << dest << " " << cost << std::endl; )
     312        }
     313
    196314        void ConversionCost::visit(__attribute((unused)) FunctionType *functionType) {}
    197315
     
    215333                static Type::Qualifiers q;
    216334                static BasicType integer( q, BasicType::SignedInt );
    217                 integer.accept( *this );
    218                 if ( cost < Cost( 1, 0, 0 ) ) {
     335                integer.accept( *this );  // safe if dest >= int
     336                if ( cost < Cost::unsafe ) {
    219337                        cost.incSafe();
    220338                } // if
     
    238356                        assert( type );
    239357                        if ( type->get_base() ) {
    240                                 cost = conversionCost( type->get_base(), dest, indexer, env ) + Cost( 0, 0, 1 );
     358                                cost = conversionCost( type->get_base(), dest, indexer, env ) + Cost::safe;
    241359                        } // if
    242360                } // if
     
    244362
    245363        void ConversionCost::visit( __attribute((unused)) TupleType *tupleType) {
    246                 Cost c;
     364                Cost c = Cost::zero;
    247365                if ( TupleType *destAsTuple = dynamic_cast< TupleType* >( dest ) ) {
    248366                        std::list< Type* >::const_iterator srcIt = tupleType->get_types().begin();
     
    276394                        int tableResult = costMatrix[ BasicType::SignedInt ][ destAsBasic->get_kind() ];
    277395                        if ( tableResult == -1 ) {
    278                                 cost = Cost( 1, 0, 0 );
    279                         } else {
    280                                 cost = Cost( 0, 0, tableResult + 1 );
     396                                cost = Cost::unsafe;
     397                        } else {
     398                                cost = Cost::zero;
     399                                cost.incSafe( tableResult + 1 );
    281400                        }
    282401                } else if ( dynamic_cast< PointerType* >( dest ) ) {
    283                         cost = Cost( 0, 0, 1 );
     402                        cost = Cost::safe;
    284403                }
    285404        }
     
    292411                        int tableResult = costMatrix[ BasicType::SignedInt ][ destAsBasic->get_kind() ];
    293412                        if ( tableResult == -1 ) {
    294                                 cost = Cost( 1, 0, 0 );
    295                         } else {
    296                                 cost = Cost( 0, 0, tableResult + 1 );
     413                                cost = Cost::unsafe;
     414                        } else {
     415                                cost = Cost::zero;
     416                                cost.incSafe( tableResult + 1 );
    297417                        }
    298418                }
  • src/ResolvExpr/ConversionCost.h

    r9f07232 rd3e4d6c  
    3737                virtual void visit(PointerType *pointerType);
    3838                virtual void visit(ArrayType *arrayType);
     39                virtual void visit(ReferenceType *refType);
    3940                virtual void visit(FunctionType *functionType);
    4041                virtual void visit(StructInstType *aggregateUseType);
     
    5354                const TypeEnvironment &env;
    5455        };
     56
     57        Cost convertToReferenceCost( Type * src, ReferenceType * dest, const SymTab::Indexer & indexer, const TypeEnvironment & env );
    5558} // namespace ResolvExpr
    5659
  • src/ResolvExpr/Cost.h

    r9f07232 rd3e4d6c  
    55// file "LICENCE" distributed with Cforall.
    66//
    7 // Cost.h -- 
     7// Cost.h --
    88//
    99// Author           : Richard C. Bilson
     
    2020namespace ResolvExpr {
    2121        class Cost {
     22          private:
     23                Cost( int unsafeCost, int polyCost, int safeCost, int referenceCost );
     24
    2225          public:
    23                 Cost();
    24                 Cost( int unsafe, int poly, int safe );
    25  
    26                 void incUnsafe( int inc = 1 );
    27                 void incPoly( int inc = 1 );
    28                 void incSafe( int inc = 1 );
    29  
     26                Cost & incUnsafe( int inc = 1 );
     27                Cost & incPoly( int inc = 1 );
     28                Cost & incSafe( int inc = 1 );
     29                Cost & incReference( int inc = 1 );
     30
    3031                Cost operator+( const Cost &other ) const;
    3132                Cost operator-( const Cost &other ) const;
     
    3536                bool operator!=( const Cost &other ) const;
    3637                friend std::ostream &operator<<( std::ostream &os, const Cost &cost );
    37  
     38
    3839                static const Cost zero;
    3940                static const Cost infinity;
     41
     42                static const Cost unsafe;
     43                static const Cost poly;
     44                static const Cost safe;
     45                static const Cost reference;
    4046          private:
    4147                int compare( const Cost &other ) const;
    4248
    43                 int unsafe;
    44                 int poly;
    45                 int safe;
     49                int unsafeCost;
     50                int polyCost;
     51                int safeCost;
     52                int referenceCost;
    4653        };
    4754
    48         inline Cost::Cost() : unsafe( 0 ), poly( 0 ), safe( 0 ) {}
     55        inline Cost::Cost( int unsafeCost, int polyCost, int safeCost, int referenceCost ) : unsafeCost( unsafeCost ), polyCost( polyCost ), safeCost( safeCost ), referenceCost( referenceCost ) {}
    4956
    50         inline Cost::Cost( int unsafe, int poly, int safe ) : unsafe( unsafe ), poly( poly ), safe( safe ) {}
    51 
    52         inline void Cost::incUnsafe( int inc ) {
    53                 unsafe += inc;
     57        inline Cost & Cost::incUnsafe( int inc ) {
     58                if ( *this == infinity ) return *this;
     59                unsafeCost += inc;
     60                return *this;
    5461        }
    5562
    56         inline void Cost::incPoly( int inc ) {
    57                 poly += inc;
     63        inline Cost & Cost::incPoly( int inc ) {
     64                if ( *this == infinity ) return *this;
     65                polyCost += inc;
     66                return *this;
    5867        }
    5968
    60         inline void Cost::incSafe( int inc ) {
    61                 safe += inc;
     69        inline Cost & Cost::incSafe( int inc ) {
     70                if ( *this == infinity ) return *this;
     71                safeCost += inc;
     72                return *this;
     73        }
     74
     75        inline Cost & Cost::incReference( int inc ) {
     76                if ( *this == infinity ) return *this;
     77                referenceCost += inc;
     78                return *this;
    6279        }
    6380
    6481        inline Cost Cost::operator+( const Cost &other ) const {
    65                 return Cost( unsafe + other.unsafe, poly + other.poly, safe + other.safe );
     82                if ( *this == infinity || other == infinity ) return infinity;
     83                return Cost( unsafeCost + other.unsafeCost, polyCost + other.polyCost, safeCost + other.safeCost, referenceCost + other.referenceCost );
    6684        }
    6785
    6886        inline Cost Cost::operator-( const Cost &other ) const {
    69                 return Cost( unsafe - other.unsafe, poly - other.poly, safe - other.safe );
     87                if ( *this == infinity || other == infinity ) return infinity;
     88                return Cost( unsafeCost - other.unsafeCost, polyCost - other.polyCost, safeCost - other.safeCost, referenceCost - other.referenceCost );
    7089        }
    7190
    7291        inline Cost &Cost::operator+=( const Cost &other ) {
    73                 unsafe += other.unsafe;
    74                 poly += other.poly;
    75                 safe += other.safe;
     92                if ( *this == infinity ) return *this;
     93                if ( other == infinity ) {
     94                        *this = infinity;
     95                        return *this;
     96                }
     97                unsafeCost += other.unsafeCost;
     98                polyCost += other.polyCost;
     99                safeCost += other.safeCost;
     100                referenceCost += other.referenceCost;
    76101                return *this;
    77102        }
    78103
    79104        inline bool Cost::operator<( const Cost &other ) const {
    80             if ( *this == infinity ) return false;
    81             if ( other == infinity ) return true;
    82             if ( unsafe > other.unsafe ) {
     105                if ( *this == infinity ) return false;
     106                if ( other == infinity ) return true;
     107
     108                if ( unsafeCost > other.unsafeCost ) {
    83109                        return false;
    84             } else if ( unsafe < other.unsafe ) {
     110                } else if ( unsafeCost < other.unsafeCost ) {
    85111                        return true;
    86             } else if ( poly > other.poly ) {
     112                } else if ( polyCost > other.polyCost ) {
    87113                        return false;
    88             } else if ( poly < other.poly ) {
     114                } else if ( polyCost < other.polyCost ) {
    89115                        return true;
    90             } else if ( safe > other.safe ) {
     116                } else if ( safeCost > other.safeCost ) {
    91117                        return false;
    92             } else if ( safe < other.safe ) {
     118                } else if ( safeCost < other.safeCost ) {
    93119                        return true;
    94             } else {
     120                } else if ( referenceCost > other.referenceCost ) {
    95121                        return false;
    96             } // if
     122                } else if ( referenceCost < other.referenceCost ) {
     123                        return true;
     124                } else {
     125                        return false;
     126                } // if
    97127        }
    98128
    99129        inline bool Cost::operator==( const Cost &other ) const {
    100                 return unsafe == other.unsafe
    101                         && poly == other.poly
    102                         && safe == other.safe;
     130                return unsafeCost == other.unsafeCost
     131                        && polyCost == other.polyCost
     132                        && safeCost == other.safeCost
     133                        && referenceCost == other.referenceCost;
    103134        }
    104135
     
    108139
    109140        inline std::ostream &operator<<( std::ostream &os, const Cost &cost ) {
    110                 os << "( " << cost.unsafe << ", " << cost.poly << ", " << cost.safe << " )";
     141                os << "( " << cost.unsafeCost << ", " << cost.polyCost << ", " << cost.safeCost << ", " << cost.referenceCost << " )";
    111142                return os;
    112143        }
  • src/ResolvExpr/PtrsAssignable.cc

    r9f07232 rd3e4d6c  
    55// file "LICENCE" distributed with Cforall.
    66//
    7 // PtrsAssignable.cc -- 
     7// PtrsAssignable.cc --
    88//
    99// Author           : Richard C. Bilson
     
    8282        void PtrsAssignable::visit(  __attribute__((unused)) UnionInstType *inst ) {}
    8383
    84         void PtrsAssignable::visit( EnumInstType *inst ) {
    85                 if ( dynamic_cast< EnumInstType* >( inst ) ) {
     84        void PtrsAssignable::visit( EnumInstType * ) {
     85                if ( dynamic_cast< EnumInstType* >( dest ) ) {
    8686                        result = 1;
    87                 } else if ( BasicType *bt = dynamic_cast< BasicType* >( inst ) ) {
     87                } else if ( BasicType *bt = dynamic_cast< BasicType* >( dest ) ) {
    8888                        result = bt->get_kind() == BasicType::SignedInt;
    8989                }
     
    104104        void PtrsAssignable::visit(  __attribute__((unused)) ZeroType *zeroType ) {}
    105105        void PtrsAssignable::visit(  __attribute__((unused)) OneType *oneType ) {}
    106        
     106
    107107} // namespace ResolvExpr
    108108
  • src/ResolvExpr/ResolveTypeof.cc

    r9f07232 rd3e4d6c  
    6565                        assert( newExpr->has_result() && ! newExpr->get_result()->isVoid() );
    6666                        Type *newType = newExpr->get_result();
     67                        newExpr->set_result( nullptr );
    6768                        delete typeofType;
     69                        delete newExpr;
    6870                        return newType;
    6971                } // if
  • src/ResolvExpr/Unify.cc

    r9f07232 rd3e4d6c  
    5353                virtual void visit(PointerType *pointerType);
    5454                virtual void visit(ArrayType *arrayType);
     55                virtual void visit(ReferenceType *refType);
    5556                virtual void visit(FunctionType *functionType);
    5657                virtual void visit(StructInstType *aggregateUseType);
     
    153154
    154155        bool bindVar( TypeInstType *typeInst, Type *other, const TypeDecl::Data & data, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, WidenMode widenMode, const SymTab::Indexer &indexer ) {
     156                // remove references from other, so that type variables can only bind to value types
     157                other = other->stripReferences();
    155158                OpenVarSet::const_iterator tyvar = openVars.find( typeInst->get_name() );
    156159                assert( tyvar != openVars.end() );
     
    387390                                } // if
    388391                        } else {
     392                                common = type1->clone();
     393                                common->get_qualifiers() = tq1 | tq2;
    389394                                result = true;
    390395                        } // if
     
    436441                        markAssertions( haveAssertions, needAssertions, pointerType );
    437442                        markAssertions( haveAssertions, needAssertions, otherPointer );
     443                } // if
     444        }
     445
     446        void Unify::visit(ReferenceType *refType) {
     447                if ( ReferenceType *otherRef = dynamic_cast< ReferenceType* >( type2 ) ) {
     448                        result = unifyExact( refType->get_base(), otherRef->get_base(), env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer );
     449                        markAssertions( haveAssertions, needAssertions, refType );
     450                        markAssertions( haveAssertions, needAssertions, otherRef );
    438451                } // if
    439452        }
  • src/ResolvExpr/typeops.h

    r9f07232 rd3e4d6c  
    6666        Cost castCost( Type *src, Type *dest, const SymTab::Indexer &indexer, const TypeEnvironment &env );
    6767
    68         template< typename SrcIterator, typename DestIterator >
    69         Cost castCostList( SrcIterator srcBegin, SrcIterator srcEnd, DestIterator destBegin, DestIterator destEnd, const SymTab::Indexer &indexer, const TypeEnvironment &env ) {
    70                 Cost ret;
    71                 if ( destBegin == destEnd ) {
    72                         if ( srcBegin == srcEnd ) {
    73                                 return Cost::zero;
    74                         } else {
    75                                 return Cost( 0, 0, 1 );
    76                         } // if
    77                 } // if
    78                 while ( srcBegin != srcEnd && destBegin != destEnd ) {
    79                         Cost thisCost = castCost( *srcBegin++, *destBegin++, indexer, env );
    80                         if ( thisCost == Cost::infinity ) {
    81                                 return Cost::infinity;
    82                         } // if
    83                         ret += thisCost;
    84                 } // while
    85                 if ( srcBegin == srcEnd && destBegin == destEnd ) {
    86                         return ret;
    87                 } else {
    88                         return Cost::infinity;
    89                 } // if
    90         }
    91 
    9268        // in ConversionCost.cc
    9369        Cost conversionCost( Type *src, Type *dest, const SymTab::Indexer &indexer, const TypeEnvironment &env );
    94 
    95         template< typename SrcIterator, typename DestIterator >
    96         Cost conversionCostList( SrcIterator srcBegin, SrcIterator srcEnd, DestIterator destBegin, DestIterator destEnd, const SymTab::Indexer &indexer, const TypeEnvironment &env ) {
    97                 Cost ret;
    98                 while ( srcBegin != srcEnd && destBegin != destEnd ) {
    99                         Cost thisCost = conversionCost( *srcBegin++, *destBegin++, indexer, env );
    100                         if ( thisCost == Cost::infinity ) {
    101                                 return Cost::infinity;
    102                         } // if
    103                         ret += thisCost;
    104                 } // while
    105                 if ( srcBegin == srcEnd && destBegin == destEnd ) {
    106                         return ret;
    107                 } else {
    108                         return Cost::infinity;
    109                 } // if
    110         }
    11170
    11271        // in PtrsAssignable.cc
Note: See TracChangeset for help on using the changeset viewer.