Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/ResolvExpr/ConversionCost.cc

    rc6b4432 r251ce80  
    2121
    2222#include "ResolvExpr/Cost.h"             // for Cost
     23#include "ResolvExpr/TypeEnvironment.h"  // for EqvClass, TypeEnvironment
    2324#include "ResolvExpr/Unify.h"            // for typesCompatibleIgnoreQualifiers
    2425#include "ResolvExpr/PtrsAssignable.hpp" // for ptrsAssignable
     26#include "SymTab/Indexer.h"              // for Indexer
     27#include "SynTree/Declaration.h"         // for TypeDecl, NamedTypeDecl
     28#include "SynTree/Type.h"                // for Type, BasicType, TypeInstType
     29
    2530
    2631namespace ResolvExpr {
     32#if 0
     33        const Cost Cost::zero =      Cost{  0,  0,  0,  0,  0,  0,  0 };
     34        const Cost Cost::infinity =  Cost{ -1, -1, -1, -1, -1,  1, -1 };
     35        const Cost Cost::unsafe =    Cost{  1,  0,  0,  0,  0,  0,  0 };
     36        const Cost Cost::poly =      Cost{  0,  1,  0,  0,  0,  0,  0 };
     37        const Cost Cost::safe =      Cost{  0,  0,  1,  0,  0,  0,  0 };
     38        const Cost Cost::sign =      Cost{  0,  0,  0,  1,  0,  0,  0 };
     39        const Cost Cost::var =       Cost{  0,  0,  0,  0,  1,  0,  0 };
     40        const Cost Cost::spec =      Cost{  0,  0,  0,  0,  0, -1,  0 };
     41        const Cost Cost::reference = Cost{  0,  0,  0,  0,  0,  0,  1 };
     42#endif
    2743
    2844#if 0
     
    3147#define PRINT(x)
    3248#endif
     49
     50        Cost conversionCost( const Type * src, const Type * dest, bool srcIsLvalue,
     51                        const SymTab::Indexer &indexer, const TypeEnvironment &env ) {
     52                if ( const TypeInstType * destAsTypeInst = dynamic_cast< const TypeInstType * >( dest ) ) {
     53                        PRINT( std::cerr << "type inst " << destAsTypeInst->name; )
     54                        if ( const EqvClass * eqvClass = env.lookup( destAsTypeInst->name ) ) {
     55                                if ( eqvClass->type ) {
     56                                        return conversionCost( src, eqvClass->type, srcIsLvalue, indexer, env );
     57                                } else {
     58                                        return Cost::infinity;
     59                                }
     60                        } else if ( const NamedTypeDecl * namedType = indexer.lookupType( destAsTypeInst->name ) ) {
     61                                PRINT( std::cerr << " found" << std::endl; )
     62                                const TypeDecl * type = dynamic_cast< const TypeDecl * >( namedType );
     63                                // all typedefs should be gone by this point
     64                                assert( type );
     65                                if ( type->base ) {
     66                                        return conversionCost( src, type->base, srcIsLvalue, indexer, env )
     67                                                + Cost::safe;
     68                                } // if
     69                        } // if
     70                        PRINT( std::cerr << " not found" << std::endl; )
     71                } // if
     72                PRINT(
     73                        std::cerr << "src is ";
     74                        src->print( std::cerr );
     75                        std::cerr << std::endl << "dest is ";
     76                        dest->print( std::cerr );
     77                        std::cerr << std::endl << "env is" << std::endl;
     78                        env.print( std::cerr, 8 );
     79                )
     80                if ( typesCompatibleIgnoreQualifiers( src, dest, indexer, env ) ) {
     81                        PRINT( std::cerr << "compatible!" << std::endl; )
     82                        return Cost::zero;
     83                } else if ( dynamic_cast< const VoidType * >( dest ) ) {
     84                        return Cost::safe;
     85                } else if ( const ReferenceType * refType = dynamic_cast< const ReferenceType * > ( dest ) ) {
     86                        PRINT( std::cerr << "conversionCost: dest is reference" << std::endl; )
     87                        return convertToReferenceCost( src, refType, srcIsLvalue, indexer, env, [](const Type * const t1, const Type * t2, const SymTab::Indexer &, const TypeEnvironment & env ){
     88                                return ptrsAssignable( t1, t2, env );
     89                        });
     90                } else {
     91                        PassVisitor<ConversionCost> converter(
     92                                dest, srcIsLvalue, indexer, env,
     93                                (Cost (*)(const Type *, const Type *, bool, const SymTab::Indexer&, const TypeEnvironment&))
     94                                        conversionCost );
     95                        src->accept( converter );
     96                        if ( converter.pass.get_cost() == Cost::infinity ) {
     97                                return Cost::infinity;
     98                        } else {
     99                                return converter.pass.get_cost() + Cost::zero;
     100                        } // if
     101                } // if
     102        }
     103
     104        static Cost convertToReferenceCost( const Type * src, const Type * dest, bool srcIsLvalue,
     105                        int diff, const SymTab::Indexer & indexer, const TypeEnvironment & env, PtrsFunction func ) {
     106                PRINT( std::cerr << "convert to reference cost... diff " << diff << " " << src << " / " << dest << std::endl; )
     107                if ( diff > 0 ) {
     108                        // TODO: document this
     109                        Cost cost = convertToReferenceCost(
     110                                strict_dynamic_cast< const ReferenceType * >( src )->base, dest, srcIsLvalue,
     111                                diff-1, indexer, env, func );
     112                        cost.incReference();
     113                        return cost;
     114                } else if ( diff < -1 ) {
     115                        // TODO: document this
     116                        Cost cost = convertToReferenceCost(
     117                                src, strict_dynamic_cast< const ReferenceType * >( dest )->base, srcIsLvalue,
     118                                diff+1, indexer, env, func );
     119                        cost.incReference();
     120                        return cost;
     121                } else if ( diff == 0 ) {
     122                        const ReferenceType * srcAsRef = dynamic_cast< const ReferenceType * >( src );
     123                        const ReferenceType * destAsRef = dynamic_cast< const ReferenceType * >( dest );
     124                        if ( srcAsRef && destAsRef ) { // pointer-like conversions between references
     125                                PRINT( std::cerr << "converting between references" << std::endl; )
     126                                Type::Qualifiers tq1 = srcAsRef->base->tq;
     127                                Type::Qualifiers tq2 = destAsRef->base->tq;
     128                                if ( tq1 <= tq2 && typesCompatibleIgnoreQualifiers( srcAsRef->base, destAsRef->base, indexer, env ) ) {
     129                                        PRINT( std::cerr << " :: compatible and good qualifiers" << std::endl; )
     130                                        if ( tq1 == tq2 ) {
     131                                                // types are the same
     132                                                return Cost::zero;
     133                                        } else {
     134                                                // types are the same, except otherPointer has more qualifiers
     135                                                return Cost::safe;
     136                                        }
     137                                } else {  // xxx - this discards reference qualifiers from consideration -- reducing qualifiers is a safe conversion; is this right?
     138                                        int assignResult = func( srcAsRef->base, destAsRef->base, indexer, env );
     139                                        PRINT( std::cerr << "comparing references: " << assignResult << " " << srcAsRef << " " << destAsRef << std::endl; )
     140                                        if ( assignResult > 0 ) {
     141                                                return Cost::safe;
     142                                        } else if ( assignResult < 0 ) {
     143                                                return Cost::unsafe;
     144                                        } // if
     145                                } // if
     146                        } else {
     147                                PRINT( std::cerr << "reference to rvalue conversion" << std::endl; )
     148                                PassVisitor<ConversionCost> converter(
     149                                        dest, srcIsLvalue, indexer, env,
     150                                        (Cost (*)(const Type *, const Type *, bool, const SymTab::Indexer&, const TypeEnvironment&))
     151                                                conversionCost );
     152                                src->accept( converter );
     153                                return converter.pass.get_cost();
     154                        } // if
     155                } else {
     156                        const ReferenceType * destAsRef = dynamic_cast< const ReferenceType * >( dest );
     157                        assert( diff == -1 && destAsRef );
     158                        PRINT( std::cerr << "dest is: " << dest << " / src is: " << src << std::endl; )
     159                        if ( typesCompatibleIgnoreQualifiers( src, destAsRef->base, indexer, env ) ) {
     160                                PRINT( std::cerr << "converting compatible base type" << std::endl; )
     161                                if ( srcIsLvalue ) {
     162                                        PRINT(
     163                                                std::cerr << "lvalue to reference conversion" << std::endl;
     164                                                std::cerr << src << " => " << destAsRef << std::endl;
     165                                        )
     166                                        // lvalue-to-reference conversion:  cv lvalue T => cv T &
     167                                        if ( src->tq == destAsRef->base->tq ) {
     168                                                return Cost::reference; // cost needs to be non-zero to add cast
     169                                        } if ( src->tq < destAsRef->base->tq ) {
     170                                                return Cost::safe; // cost needs to be higher than previous cast to differentiate adding qualifiers vs. keeping same
     171                                        } else {
     172                                                return Cost::unsafe;
     173                                        } // if
     174                                } else if ( destAsRef->base->get_const() ) {
     175                                        PRINT( std::cerr << "rvalue to const ref conversion" << std::endl; )
     176                                        // rvalue-to-const-reference conversion: T => const T &
     177                                        return Cost::safe;
     178                                } else {
     179                                        PRINT( std::cerr << "rvalue to non-const reference conversion" << std::endl; )
     180                                        // rvalue-to-reference conversion: T => T &
     181                                        return Cost::unsafe;
     182                                } // if
     183                        } // if
     184                        PRINT( std::cerr << "attempting to convert from incompatible base type -- fail" << std::endl; )
     185                }
     186                return Cost::infinity;
     187        }
     188
     189        Cost convertToReferenceCost( const Type * src, const ReferenceType * dest, bool srcIsLvalue,
     190                        const SymTab::Indexer & indexer, const TypeEnvironment & env, PtrsFunction func ) {
     191                int sdepth = src->referenceDepth(), ddepth = dest->referenceDepth();
     192                Cost cost = convertToReferenceCost( src, dest, srcIsLvalue, sdepth-ddepth, indexer, env, func );
     193                PRINT( std::cerr << "convertToReferenceCost result: " << cost << std::endl; )
     194                return cost;
     195        }
     196
     197        ConversionCost::ConversionCost( const Type * dest, bool srcIsLvalue, const SymTab::Indexer &indexer, const TypeEnvironment &env, CostFunction costFunc )
     198                : dest( dest ), srcIsLvalue( srcIsLvalue ), indexer( indexer ), cost( Cost::infinity ), env( env ), costFunc( costFunc ) {
     199        }
    33200
    34201        // GENERATED START, DO NOT EDIT
     
    59226        // GENERATED START, DO NOT EDIT
    60227        // GENERATED BY BasicTypes-gen.cc
    61         static const int costMatrix[ast::BasicType::NUMBER_OF_BASIC_TYPES][ast::BasicType::NUMBER_OF_BASIC_TYPES] = { // path length from root to node
     228        static const int costMatrix[BasicType::NUMBER_OF_BASIC_TYPES][BasicType::NUMBER_OF_BASIC_TYPES] = { // path length from root to node
    62229                /*               B    C   SC   UC   SI  SUI    I   UI   LI  LUI  LLI LLUI   IB  UIB  _FH  _FH   _F  _FC    F   FC  _FX _FXC   FD _FDC    D   DC F80X_FDXC  F80  _FB_FLDC   FB   LD  LDC _FBX_FLDXC */
    63230                /*      B */ {   0,   1,   1,   2,   2,   3,   3,   4,   4,   5,   5,   6,   6,   7,   7,   8,   8,   9,   9,  10,  10,  11,  11,  12,  12,  13,  13,  14,  14,  15,  15,  16,  17,  16,  18,  17, },
     
    101268        // GENERATED END
    102269        static_assert(
    103                 sizeof(costMatrix)/sizeof(costMatrix[0][0]) == ast::BasicType::NUMBER_OF_BASIC_TYPES * ast::BasicType::NUMBER_OF_BASIC_TYPES,
     270                sizeof(costMatrix)/sizeof(costMatrix[0][0]) == BasicType::NUMBER_OF_BASIC_TYPES * BasicType::NUMBER_OF_BASIC_TYPES,
    104271                "Missing row in the cost matrix"
    105272        );
     
    107274        // GENERATED START, DO NOT EDIT
    108275        // GENERATED BY BasicTypes-gen.cc
    109         static const int signMatrix[ast::BasicType::NUMBER_OF_BASIC_TYPES][ast::BasicType::NUMBER_OF_BASIC_TYPES] = { // number of sign changes in safe conversion
     276        static const int signMatrix[BasicType::NUMBER_OF_BASIC_TYPES][BasicType::NUMBER_OF_BASIC_TYPES] = { // number of sign changes in safe conversion
    110277                /*               B    C   SC   UC   SI  SUI    I   UI   LI  LUI  LLI LLUI   IB  UIB  _FH  _FH   _F  _FC    F   FC  _FX _FXC   FD _FDC    D   DC F80X_FDXC  F80  _FB_FLDC   FB   LD  LDC _FBX_FLDXC */
    111278                /*      B */ {   0,   0,   0,   1,   0,   1,   0,   1,   0,   1,   0,   1,   0,   1,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, },
     
    148315        // GENERATED END
    149316        static_assert(
    150                 sizeof(signMatrix)/sizeof(signMatrix[0][0]) == ast::BasicType::NUMBER_OF_BASIC_TYPES * ast::BasicType::NUMBER_OF_BASIC_TYPES,
     317                sizeof(signMatrix)/sizeof(signMatrix[0][0]) == BasicType::NUMBER_OF_BASIC_TYPES * BasicType::NUMBER_OF_BASIC_TYPES,
    151318                "Missing row in the sign matrix"
    152319        );
     320
     321        void ConversionCost::postvisit( const VoidType * ) {
     322                cost = Cost::infinity;
     323        }
     324
     325        // refactor for code resue
     326        void ConversionCost::conversionCostFromBasicToBasic(const BasicType * src, const BasicType * dest) {
     327                int tableResult = costMatrix[ src->kind ][ dest->kind ];
     328                if ( tableResult == -1 ) {
     329                        cost = Cost::unsafe;
     330                } else {
     331                        cost = Cost::zero;
     332                        cost.incSafe( tableResult );
     333                        cost.incSign( signMatrix[ src->kind ][ dest->kind ] );
     334                } // if
     335        } // ConversionCost::conversionCostFromBasicToBasic
     336
     337        void ConversionCost::postvisit(const BasicType * basicType) {
     338                if ( const BasicType * destAsBasic = dynamic_cast< const BasicType * >( dest ) ) {
     339                        conversionCostFromBasicToBasic(basicType, destAsBasic);
     340                } else if ( const EnumInstType * enumInst = dynamic_cast< const EnumInstType * >( dest ) ) {
     341                        const EnumDecl * base_enum = enumInst->baseEnum;
     342                        if ( const Type * base = base_enum->base ) {
     343                                if ( const BasicType * enumBaseAstBasic = dynamic_cast< const BasicType *> (base) ) {
     344                                        conversionCostFromBasicToBasic(basicType, enumBaseAstBasic);
     345                                } else {
     346                                        cost = Cost::infinity;
     347                                } // if
     348                        } else {
     349                                cost = Cost::unsafe;
     350                        } // if
     351                } // if
     352                // no cases for zero_t/one_t because it should not be possible to convert int, etc. to zero_t/one_t.
     353        }
     354
     355        void ConversionCost::postvisit( const PointerType * pointerType ) {
     356                if ( const PointerType * destAsPtr = dynamic_cast< const PointerType * >( dest ) ) {
     357                        PRINT( std::cerr << pointerType << " ===> " << destAsPtr << std::endl; )
     358                        Type::Qualifiers tq1 = pointerType->base->tq;
     359                        Type::Qualifiers tq2 = destAsPtr->base->tq;
     360                        if ( tq1 <= tq2 && typesCompatibleIgnoreQualifiers( pointerType->base, destAsPtr->base, indexer, env ) ) {
     361                                PRINT( std::cerr << " :: compatible and good qualifiers" << std::endl; )
     362                                if ( tq1 == tq2 ) {
     363                                        // types are the same
     364                                        cost = Cost::zero;
     365                                } else {
     366                                        // types are the same, except otherPointer has more qualifiers
     367                                        cost = Cost::safe;
     368                                } // if
     369                        } else {
     370                                int assignResult = ptrsAssignable( pointerType->base, destAsPtr->base, env );
     371                                PRINT( std::cerr << " :: " << assignResult << std::endl; )
     372                                if ( assignResult > 0 && tq1 <= tq2 ) {
     373                                        // xxx - want the case where qualifiers are added to be more expensive than the case where qualifiers are the same. Is 1 safe vs. 2 safe correct?
     374                                        if ( tq1 == tq2 ) {
     375                                                cost = Cost::safe;
     376                                        } else if ( tq1 < tq2 ) {
     377                                                cost = Cost::safe+Cost::safe;
     378                                        }
     379                                } else if ( assignResult < 0 ) {
     380                                        cost = Cost::unsafe;
     381                                } // if
     382                                // assignResult == 0 means Cost::Infinity
     383                        } // if
     384                        // case case for zero_t because it should not be possible to convert pointers to zero_t.
     385                } // if
     386        }
     387
     388        void ConversionCost::postvisit( const ArrayType * ) {}
     389
     390        void ConversionCost::postvisit( const ReferenceType * refType ) {
     391                // Note: dest can never be a reference, since it would have been caught in an earlier check
     392                assert( ! dynamic_cast< const ReferenceType * >( dest ) );
     393                // convert reference to rvalue: cv T1 & => T2
     394                // recursively compute conversion cost from T1 to T2.
     395                // cv can be safely dropped because of 'implicit dereference' behavior.
     396                cost = costFunc( refType->base, dest, srcIsLvalue, indexer, env );
     397                if ( refType->base->tq == dest->tq ) {
     398                        cost.incReference();  // prefer exact qualifiers
     399                } else if ( refType->base->tq < dest->tq ) {
     400                        cost.incSafe(); // then gaining qualifiers
     401                } else {
     402                        cost.incUnsafe(); // lose qualifiers as last resort
     403                }
     404                PRINT( std::cerr << refType << " ==> " << dest << " " << cost << std::endl; )
     405        }
     406
     407        void ConversionCost::postvisit( const FunctionType * ) {}
     408
     409        void ConversionCost::postvisit( const EnumInstType * enumInst) {
     410                const EnumDecl * enumDecl = enumInst -> baseEnum;
     411                if ( const Type * enumType = enumDecl -> base ) { // if it is a typed enum
     412                        cost = costFunc( enumType, dest, srcIsLvalue, indexer, env );
     413                } else {
     414                        static Type::Qualifiers q;
     415                        static BasicType integer( q, BasicType::SignedInt );
     416                        cost = costFunc( &integer, dest, srcIsLvalue, indexer, env );  // safe if dest >= int
     417                } // if
     418                if ( cost < Cost::unsafe ) {
     419                                cost.incSafe();
     420                } // if
     421        }
     422
     423        void ConversionCost::postvisit( const TraitInstType * ) {}
     424
     425        void ConversionCost::postvisit( const TypeInstType * inst ) {
     426                if ( const EqvClass * eqvClass = env.lookup( inst->name ) ) {
     427                        cost = costFunc( eqvClass->type, dest, srcIsLvalue, indexer, env );
     428                } else if ( const TypeInstType * destAsInst = dynamic_cast< const TypeInstType * >( dest ) ) {
     429                        if ( inst->name == destAsInst->name ) {
     430                                cost = Cost::zero;
     431                        }
     432                } else if ( const NamedTypeDecl * namedType = indexer.lookupType( inst->name ) ) {
     433                        const TypeDecl * type = dynamic_cast< const TypeDecl * >( namedType );
     434                        // all typedefs should be gone by this point
     435                        assert( type );
     436                        if ( type->base ) {
     437                                cost = costFunc( type->base, dest, srcIsLvalue, indexer, env ) + Cost::safe;
     438                        } // if
     439                } // if
     440        }
     441
     442        void ConversionCost::postvisit( const TupleType * tupleType ) {
     443                Cost c = Cost::zero;
     444                if ( const TupleType * destAsTuple = dynamic_cast< const TupleType * >( dest ) ) {
     445                        std::list< Type * >::const_iterator srcIt = tupleType->types.begin();
     446                        std::list< Type * >::const_iterator destIt = destAsTuple->types.begin();
     447                        while ( srcIt != tupleType->types.end() && destIt != destAsTuple->types.end() ) {
     448                                Cost newCost = costFunc( * srcIt++, * destIt++, srcIsLvalue, indexer, env );
     449                                if ( newCost == Cost::infinity ) {
     450                                        return;
     451                                } // if
     452                                c += newCost;
     453                        } // while
     454                        if ( destIt != destAsTuple->types.end() ) {
     455                                cost = Cost::infinity;
     456                        } else {
     457                                cost = c;
     458                        } // if
     459                } // if
     460        }
     461
     462        void ConversionCost::postvisit( const VarArgsType * ) {
     463                if ( dynamic_cast< const VarArgsType * >( dest ) ) {
     464                        cost = Cost::zero;
     465                }
     466        }
     467
     468        void ConversionCost::postvisit( const ZeroType * ) {
     469                if ( dynamic_cast< const ZeroType * >( dest ) ) {
     470                        cost = Cost::zero;
     471                } else if ( const BasicType * destAsBasic = dynamic_cast< const BasicType * >( dest ) ) {
     472                        // copied from visit(BasicType *) for signed int, but +1 for safe conversions
     473                        int tableResult = costMatrix[ BasicType::SignedInt ][ destAsBasic->kind ];
     474                        if ( tableResult == -1 ) {
     475                                cost = Cost::unsafe;
     476                        } else {
     477                                cost = Cost::zero;
     478                                cost.incSafe( tableResult + 1 );
     479                                cost.incSign( signMatrix[ BasicType::SignedInt ][ destAsBasic->kind ] );
     480                        } // if
     481                } else if ( dynamic_cast< const PointerType * >( dest ) ) {
     482                        cost = Cost::zero;
     483                        cost.incSafe( maxIntCost + 2 ); // +1 for zero_t -> int, +1 for disambiguation
     484                } // if
     485        }
     486
     487        void ConversionCost::postvisit( const OneType * ) {
     488                if ( dynamic_cast< const OneType * >( dest ) ) {
     489                        cost = Cost::zero;
     490                } else if ( const BasicType * destAsBasic = dynamic_cast< const BasicType * >( dest ) ) {
     491                        // copied from visit(BasicType *) for signed int, but +1 for safe conversions
     492                        int tableResult = costMatrix[ BasicType::SignedInt ][ destAsBasic->kind ];
     493                        if ( tableResult == -1 ) {
     494                                cost = Cost::unsafe;
     495                        } else {
     496                                cost = Cost::zero;
     497                                cost.incSafe( tableResult + 1 );
     498                                cost.incSign( signMatrix[ BasicType::SignedInt ][ destAsBasic->kind ] );
     499                        } // if
     500                } // if
     501        }
    153502
    154503namespace {
     
    353702
    354703        cost = costCalc( refType->base, dst, srcIsLvalue, symtab, env );
    355 
    356         // xxx - should qualifiers be considered in pass-by-value?
    357         /*
    358704        if ( refType->base->qualifiers == dst->qualifiers ) {
    359705                cost.incReference();
     
    363709                cost.incUnsafe();
    364710        }
    365         */
    366         cost.incReference();
    367711}
    368712
     
    448792                        cost.incSign( signMatrix[ ast::BasicType::SignedInt ][ dstAsBasic->kind ] );
    449793                }
    450                 // this has the effect of letting any expr such as x+0, x+1 to be typed
    451                 // the same as x, instead of at least int. are we willing to sacrifice this little
    452                 // bit of coherence with C?
    453                 // TODO: currently this does not work when no zero/one overloads exist. Find a fix for it.
    454                 // cost = Cost::zero;
    455794        } else if ( dynamic_cast< const ast::PointerType * >( dst ) ) {
    456795                cost = Cost::zero;
    457796                // +1 for zero_t ->, +1 for disambiguation
    458797                cost.incSafe( maxIntCost + 2 );
    459                 // assuming 0p is supposed to be used for pointers?
    460798        }
    461799}
     
    466804                cost = Cost::zero;
    467805        } else if ( const ast::BasicType * dstAsBasic =
    468                         dynamic_cast< const ast::BasicType * >( dst ) ) {               
     806                        dynamic_cast< const ast::BasicType * >( dst ) ) {
    469807                int tableResult = costMatrix[ ast::BasicType::SignedInt ][ dstAsBasic->kind ];
    470808                if ( -1 == tableResult ) {
     
    475813                        cost.incSign( signMatrix[ ast::BasicType::SignedInt ][ dstAsBasic->kind ] );
    476814                }
    477                
    478                 // cost = Cost::zero;
    479815        }
    480816}
Note: See TracChangeset for help on using the changeset viewer.