Ignore:
Timestamp:
Jul 13, 2017, 2:27:58 PM (4 years ago)
Author:
Rob Schluntz <rschlunt@…>
Branches:
aaron-thesis, arm-eh, cleanup-dtors, deferred_resn, demangler, jacob/cs343-translation, jenkins-sandbox, master, new-ast, new-ast-unique-expr, new-env, no_list, persistent-indexer, resolv-new, with_gc
Children:
65cec25
Parents:
0a81c3f
Message:

Add conversion & cast cost for reference conversions

File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/ResolvExpr/ConversionCost.cc

    r0a81c3f r2463d0e  
    5757                } else if ( dynamic_cast< VoidType* >( dest ) ) {
    5858                        return Cost( 0, 0, 1 );
     59                } else if ( ReferenceType * refType = dynamic_cast< ReferenceType * > ( dest ) ) {
     60                        // std::cerr << "conversionCost: dest is reference" << std::endl;
     61                        return convertToReferenceCost( src, refType, indexer, env );
    5962                } else {
    6063                        ConversionCost converter( dest, indexer, env );
     
    6669                        } // if
    6770                } // if
     71        }
     72
     73        Cost convertToReferenceCost( Type * src, ReferenceType * dest, const SymTab::Indexer & indexer, const TypeEnvironment & env ) {
     74                // std::cerr << "convert to reference cost..." << std::endl;
     75                if ( ReferenceType *srcAsRef = dynamic_cast< ReferenceType * >( src ) ) { // pointer-like conversions between references
     76                        // std::cerr << "converting between references" << std::endl;
     77                        if ( srcAsRef->get_base()->get_qualifiers() <= dest->get_base()->get_qualifiers() && typesCompatibleIgnoreQualifiers( srcAsRef->get_base(), dest->get_base(), indexer, env ) ) {
     78                                return Cost( 0, 0, 1 );
     79                        } else {  // xxx - this discards reference qualifiers from consideration -- reducing qualifiers is a safe conversion; is this right?
     80                                int assignResult = ptrsAssignable( srcAsRef->get_base(), dest->get_base(), env );
     81                                if ( assignResult < 0 ) {
     82                                        return Cost( 0, 0, 1 );
     83                                } else if ( assignResult > 0 ) {
     84                                        return Cost( 1, 0, 0 );
     85                                } // if
     86                        } // if
     87                } else if ( typesCompatibleIgnoreQualifiers( src, dest->get_base(), indexer, env ) ) {
     88                        // std::cerr << "converting compatible base type" << std::endl;
     89                        if ( src->get_lvalue() ) {
     90                                // std::cerr << "lvalue to reference conversion" << std::endl;
     91                                // lvalue-to-reference conversion:  cv lvalue T => cv T &
     92                                if ( src->get_qualifiers() == dest->get_base()->get_qualifiers() ) {
     93                                        return Cost( 0, 0, 1 ); // cost needs to be non-zero to add cast
     94                                } if ( src->get_qualifiers() < dest->get_base()->get_qualifiers() ) {
     95                                        return Cost( 0, 0, 2 ); // cost needs to be higher than previous cast to differentiate adding qualifiers vs. keeping same
     96                                } else {
     97                                        return Cost( 1, 0, 0 );
     98                                }
     99                        } else if ( dest->get_base()->get_const() ) {
     100                                // std::cerr << "rvalue to const ref conversion" << std::endl;
     101                                // rvalue-to-const-reference conversion: T => const T &
     102                                return Cost( 0, 0, 1 );
     103                        } else {
     104                                // std::cerr << "rvalue to non-const reference conversion" << std::endl;
     105                                // rvalue-to-reference conversion: T => T &
     106                                return Cost( 1, 0, 0 );
     107                        }
     108                } else {
     109                        // std::cerr << "attempting to convert from incompatible base type -- fail" << std::endl;
     110                }
     111                return Cost::infinity;
    68112        }
    69113
     
    173217                        if ( pointerType->get_base()->get_qualifiers() <= destAsPtr->get_base()->get_qualifiers() && typesCompatibleIgnoreQualifiers( pointerType->get_base(), destAsPtr->get_base(), indexer, env ) ) {
    174218                                cost = Cost( 0, 0, 1 );
    175                         } else {
     219                        } else {  // xxx - this discards pointer qualifiers from consideration -- reducing qualifiers is a safe conversion; is this right?
    176220                                int assignResult = ptrsAssignable( pointerType->get_base(), destAsPtr->get_base(), env );
    177221                                if ( assignResult < 0 ) {
     
    187231
    188232        void ConversionCost::visit(__attribute((unused)) ArrayType *arrayType) {}
     233
     234        void ConversionCost::visit(ReferenceType *refType) {
     235                // Note: dest can never be a reference, since it would have been caught in an earlier check
     236                assert( ! dynamic_cast< ReferenceType * >( dest ) );
     237                // convert reference to rvalue: cv T1 & => T2
     238                // recursively compute conversion cost from T1 to T2.
     239                // cv can be safely dropped because of 'implicit dereference' behavior.
     240                refType->get_base()->accept( *this );
     241        }
     242
    189243        void ConversionCost::visit(__attribute((unused)) FunctionType *functionType) {}
    190244
     
    208262                static Type::Qualifiers q;
    209263                static BasicType integer( q, BasicType::SignedInt );
    210                 integer.accept( *this );
     264                integer.accept( *this );  // safe if dest >= int
    211265                if ( cost < Cost( 1, 0, 0 ) ) {
    212266                        cost.incSafe();
Note: See TracChangeset for help on using the changeset viewer.