- File:
-
- 1 edited
-
src/ResolvExpr/ConversionCost.cc (modified) (22 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/ResolvExpr/ConversionCost.cc
rbd0b6b62 rb0837e4 44 44 EqvClass eqvClass; 45 45 NamedTypeDecl *namedType; 46 PRINT( std::cerr << "type inst " << destAsTypeInst-> name; )47 if ( env.lookup( destAsTypeInst-> name, eqvClass ) ) {46 PRINT( std::cerr << "type inst " << destAsTypeInst->get_name(); ) 47 if ( env.lookup( destAsTypeInst->get_name(), eqvClass ) ) { 48 48 if ( eqvClass.type ) { 49 49 return conversionCost( src, eqvClass.type, indexer, env ); … … 51 51 return Cost::infinity; 52 52 } 53 } else if ( ( namedType = indexer.lookupType( destAsTypeInst-> name) ) ) {53 } else if ( ( namedType = indexer.lookupType( destAsTypeInst->get_name() ) ) ) { 54 54 PRINT( std::cerr << " found" << std::endl; ) 55 55 TypeDecl *type = dynamic_cast< TypeDecl* >( namedType ); 56 56 // all typedefs should be gone by this point 57 57 assert( type ); 58 if ( type-> base) {59 return conversionCost( src, type-> base, indexer, env ) + Cost::safe;58 if ( type->get_base() ) { 59 return conversionCost( src, type->get_base(), indexer, env ) + Cost::safe; 60 60 } // if 61 61 } // if … … 77 77 } else if ( ReferenceType * refType = dynamic_cast< ReferenceType * > ( dest ) ) { 78 78 PRINT( std::cerr << "conversionCost: dest is reference" << std::endl; ) 79 return convertToReferenceCost( src, refType, indexer, env, [](Type * t1, Type * t2, const SymTab::Indexer &, const TypeEnvironment & env){79 return convertToReferenceCost( src, refType, indexer, env, [](Type * t1, Type * t2, const TypeEnvironment & env, const SymTab::Indexer &){ 80 80 return ptrsAssignable( t1, t2, env ); 81 81 }); 82 82 } else { 83 PassVisitor<ConversionCost> converter( dest, indexer, env, conversionCost);83 ConversionCost converter( dest, indexer, env ); 84 84 src->accept( converter ); 85 if ( converter. pass.get_cost() == Cost::infinity ) {85 if ( converter.get_cost() == Cost::infinity ) { 86 86 return Cost::infinity; 87 87 } else { 88 return converter. pass.get_cost() + Cost::zero;88 return converter.get_cost() + Cost::zero; 89 89 } // if 90 90 } // if … … 92 92 93 93 Cost convertToReferenceCost( Type * src, Type * dest, int diff, const SymTab::Indexer & indexer, const TypeEnvironment & env, PtrsFunction func ) { 94 PRINT( std::cerr << "convert to reference cost... diff " << diff << " " << src << " / " << dest <<std::endl; )94 PRINT( std::cerr << "convert to reference cost... diff " << diff << std::endl; ) 95 95 if ( diff > 0 ) { 96 96 // TODO: document this 97 Cost cost = convertToReferenceCost( strict_dynamic_cast< ReferenceType * >( src )-> base, dest, diff-1, indexer, env, func );97 Cost cost = convertToReferenceCost( strict_dynamic_cast< ReferenceType * >( src )->get_base(), dest, diff-1, indexer, env, func ); 98 98 cost.incReference(); 99 99 return cost; 100 100 } else if ( diff < -1 ) { 101 101 // TODO: document this 102 Cost cost = convertToReferenceCost( src, strict_dynamic_cast< ReferenceType * >( dest )-> base, diff+1, indexer, env, func );102 Cost cost = convertToReferenceCost( src, strict_dynamic_cast< ReferenceType * >( dest )->get_base(), diff+1, indexer, env, func ); 103 103 cost.incReference(); 104 104 return cost; … … 108 108 if ( srcAsRef && destAsRef ) { // pointer-like conversions between references 109 109 PRINT( std::cerr << "converting between references" << std::endl; ) 110 Type::Qualifiers tq1 = srcAsRef->base->get_qualifiers(); 111 Type::Qualifiers tq2 = destAsRef->base->get_qualifiers(); 112 if ( tq1 <= tq2 && typesCompatibleIgnoreQualifiers( srcAsRef->base, destAsRef->base, indexer, env ) ) { 113 PRINT( std::cerr << " :: compatible and good qualifiers" << std::endl; ) 114 if ( tq1 == tq2 ) { 115 // types are the same 116 return Cost::zero; 117 } else { 118 // types are the same, except otherPointer has more qualifiers 119 return Cost::safe; 120 } 110 if ( srcAsRef->get_base()->get_qualifiers() <= destAsRef->get_base()->get_qualifiers() && typesCompatibleIgnoreQualifiers( srcAsRef->get_base(), destAsRef->get_base(), indexer, env ) ) { 111 return Cost::safe; 121 112 } else { // xxx - this discards reference qualifiers from consideration -- reducing qualifiers is a safe conversion; is this right? 122 int assignResult = func( srcAsRef-> base, destAsRef->base, indexer, env);113 int assignResult = func( srcAsRef->get_base(), destAsRef->get_base(), env, indexer ); 123 114 PRINT( std::cerr << "comparing references: " << assignResult << " " << srcAsRef << " " << destAsRef << std::endl; ) 124 115 if ( assignResult > 0 ) { … … 130 121 } else { 131 122 PRINT( std::cerr << "reference to rvalue conversion" << std::endl; ) 132 PassVisitor<ConversionCost> converter( dest, indexer, env, conversionCost);123 ConversionCost converter( dest, indexer, env ); 133 124 src->accept( converter ); 134 return converter. pass.get_cost();125 return converter.get_cost(); 135 126 } // if 136 127 } else { … … 138 129 assert( diff == -1 && destAsRef ); 139 130 PRINT( std::cerr << "dest is: " << dest << " / src is: " << src << std::endl; ) 140 if ( typesCompatibleIgnoreQualifiers( src, destAsRef-> base, indexer, env ) ) {131 if ( typesCompatibleIgnoreQualifiers( src, destAsRef->get_base(), indexer, env ) ) { 141 132 PRINT( std::cerr << "converting compatible base type" << std::endl; ) 142 133 if ( src->get_lvalue() ) { … … 146 137 ) 147 138 // lvalue-to-reference conversion: cv lvalue T => cv T & 148 if ( src->get_qualifiers() == destAsRef-> base->get_qualifiers() ) {139 if ( src->get_qualifiers() == destAsRef->get_base()->get_qualifiers() ) { 149 140 return Cost::reference; // cost needs to be non-zero to add cast 150 } if ( src->get_qualifiers() < destAsRef-> base->get_qualifiers() ) {141 } if ( src->get_qualifiers() < destAsRef->get_base()->get_qualifiers() ) { 151 142 return Cost::safe; // cost needs to be higher than previous cast to differentiate adding qualifiers vs. keeping same 152 143 } else { 153 144 return Cost::unsafe; 154 145 } // if 155 } else if ( destAsRef-> base->get_const() ) {146 } else if ( destAsRef->get_base()->get_const() ) { 156 147 PRINT( std::cerr << "rvalue to const ref conversion" << std::endl; ) 157 148 // rvalue-to-const-reference conversion: T => const T & … … 173 164 } 174 165 175 ConversionCost::ConversionCost( Type *dest, const SymTab::Indexer &indexer, const TypeEnvironment &env , CostFunction costFunc)176 : dest( dest ), indexer( indexer ), cost( Cost::infinity ), env( env ) , costFunc( costFunc ){166 ConversionCost::ConversionCost( Type *dest, const SymTab::Indexer &indexer, const TypeEnvironment &env ) 167 : dest( dest ), indexer( indexer ), cost( Cost::infinity ), env( env ) { 177 168 } 178 169 … … 257 248 }; 258 249 259 void ConversionCost:: postvisit( VoidType *) {250 void ConversionCost::visit( __attribute((unused)) VoidType *voidType ) { 260 251 cost = Cost::infinity; 261 252 } 262 253 263 void ConversionCost:: postvisit(BasicType *basicType) {254 void ConversionCost::visit(BasicType *basicType) { 264 255 if ( BasicType *destAsBasic = dynamic_cast< BasicType* >( dest ) ) { 265 256 int tableResult = costMatrix[ basicType->get_kind() ][ destAsBasic->get_kind() ]; … … 278 269 } 279 270 280 void ConversionCost:: postvisit( PointerType * pointerType ) {271 void ConversionCost::visit( PointerType * pointerType ) { 281 272 if ( PointerType *destAsPtr = dynamic_cast< PointerType* >( dest ) ) { 282 PRINT( std::cerr << pointerType << " ===> " << destAsPtr << std::endl; ) 283 Type::Qualifiers tq1 = pointerType->base->get_qualifiers(); 284 Type::Qualifiers tq2 = destAsPtr->base->get_qualifiers(); 285 if ( tq1 <= tq2 && typesCompatibleIgnoreQualifiers( pointerType->base, destAsPtr->base, indexer, env ) ) { 286 PRINT( std::cerr << " :: compatible and good qualifiers" << std::endl; ) 273 PRINT( std::cerr << pointerType << " ===> " << destAsPtr; ) 274 Type::Qualifiers tq1 = pointerType->get_base()->get_qualifiers(); 275 Type::Qualifiers tq2 = destAsPtr->get_base()->get_qualifiers(); 276 if ( tq1 <= tq2 && typesCompatibleIgnoreQualifiers( pointerType->get_base(), destAsPtr->get_base(), indexer, env ) ) { 287 277 if ( tq1 == tq2 ) { 288 278 // types are the same … … 290 280 } else { 291 281 // types are the same, except otherPointer has more qualifiers 282 PRINT( std::cerr << " :: compatible and good qualifiers" << std::endl; ) 292 283 cost = Cost::safe; 293 284 } 294 } else { 285 } else { // xxx - this discards qualifiers from consideration -- reducing qualifiers is a safe conversion; is this right? 295 286 int assignResult = ptrsAssignable( pointerType->base, destAsPtr->base, env ); 296 287 PRINT( std::cerr << " :: " << assignResult << std::endl; ) 297 if ( assignResult > 0 && tq1 <= tq2 ) { 298 // 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? 299 if ( tq1 == tq2 ) { 300 cost = Cost::safe; 301 } else if ( tq1 < tq2 ) { 302 cost = Cost::safe+Cost::safe; 303 } 288 if ( assignResult > 0 && pointerType->get_base()->get_qualifiers() <= destAsPtr->get_qualifiers() ) { 289 cost = Cost::safe; 304 290 } else if ( assignResult < 0 ) { 305 291 cost = Cost::unsafe; … … 312 298 } 313 299 314 void ConversionCost:: postvisit( ArrayType * ) {}315 316 void ConversionCost:: postvisit( ReferenceType * refType ) {300 void ConversionCost::visit( ArrayType * ) {} 301 302 void ConversionCost::visit( ReferenceType * refType ) { 317 303 // Note: dest can never be a reference, since it would have been caught in an earlier check 318 304 assert( ! dynamic_cast< ReferenceType * >( dest ) ); … … 320 306 // recursively compute conversion cost from T1 to T2. 321 307 // cv can be safely dropped because of 'implicit dereference' behavior. 322 cost = costFunc( refType->base, dest, indexer, env);308 refType->base->accept( *this ); 323 309 if ( refType->base->get_qualifiers() == dest->get_qualifiers() ) { 324 310 cost.incReference(); // prefer exact qualifiers … … 331 317 } 332 318 333 void ConversionCost:: postvisit( FunctionType * ) {}334 335 void ConversionCost:: postvisit( StructInstType * inst ) {319 void ConversionCost::visit( FunctionType * ) {} 320 321 void ConversionCost::visit( StructInstType * inst ) { 336 322 if ( StructInstType *destAsInst = dynamic_cast< StructInstType* >( dest ) ) { 337 323 if ( inst->name == destAsInst->name ) { … … 341 327 } 342 328 343 void ConversionCost:: postvisit( UnionInstType * inst ) {329 void ConversionCost::visit( UnionInstType * inst ) { 344 330 if ( UnionInstType *destAsInst = dynamic_cast< UnionInstType* >( dest ) ) { 345 331 if ( inst->name == destAsInst->name ) { … … 349 335 } 350 336 351 void ConversionCost:: postvisit( EnumInstType * ) {337 void ConversionCost::visit( EnumInstType * ) { 352 338 static Type::Qualifiers q; 353 339 static BasicType integer( q, BasicType::SignedInt ); 354 cost = costFunc( &integer, dest, indexer, env); // safe if dest >= int340 integer.accept( *this ); // safe if dest >= int 355 341 if ( cost < Cost::unsafe ) { 356 342 cost.incSafe(); … … 358 344 } 359 345 360 void ConversionCost:: postvisit( TraitInstType * ) {}361 362 void ConversionCost:: postvisit( TypeInstType *inst ) {346 void ConversionCost::visit( TraitInstType * ) {} 347 348 void ConversionCost::visit( TypeInstType *inst ) { 363 349 EqvClass eqvClass; 364 350 NamedTypeDecl *namedType; 365 if ( env.lookup( inst-> name, eqvClass ) ) {366 cost = co stFunc( eqvClass.type, dest, indexer, env );351 if ( env.lookup( inst->get_name(), eqvClass ) ) { 352 cost = conversionCost( eqvClass.type, dest, indexer, env ); 367 353 } else if ( TypeInstType *destAsInst = dynamic_cast< TypeInstType* >( dest ) ) { 368 if ( inst-> name == destAsInst->name) {354 if ( inst->get_name() == destAsInst->get_name() ) { 369 355 cost = Cost::zero; 370 356 } 371 } else if ( ( namedType = indexer.lookupType( inst-> name) ) ) {357 } else if ( ( namedType = indexer.lookupType( inst->get_name() ) ) ) { 372 358 TypeDecl *type = dynamic_cast< TypeDecl* >( namedType ); 373 359 // all typedefs should be gone by this point 374 360 assert( type ); 375 if ( type-> base) {376 cost = co stFunc( type->base, dest, indexer, env ) + Cost::safe;377 } // if 378 } // if 379 } 380 381 void ConversionCost:: postvisit( TupleType * tupleType ) {361 if ( type->get_base() ) { 362 cost = conversionCost( type->get_base(), dest, indexer, env ) + Cost::safe; 363 } // if 364 } // if 365 } 366 367 void ConversionCost::visit( TupleType * tupleType ) { 382 368 Cost c = Cost::zero; 383 369 if ( TupleType * destAsTuple = dynamic_cast< TupleType * >( dest ) ) { 384 std::list< Type * >::const_iterator srcIt = tupleType-> types.begin();385 std::list< Type * >::const_iterator destIt = destAsTuple-> types.begin();386 while ( srcIt != tupleType-> types.end() && destIt != destAsTuple->types.end() ) {387 Cost newCost = co stFunc( *srcIt++, *destIt++, indexer, env );370 std::list< Type * >::const_iterator srcIt = tupleType->get_types().begin(); 371 std::list< Type * >::const_iterator destIt = destAsTuple->get_types().begin(); 372 while ( srcIt != tupleType->get_types().end() && destIt != destAsTuple->get_types().end() ) { 373 Cost newCost = conversionCost( *srcIt++, *destIt++, indexer, env ); 388 374 if ( newCost == Cost::infinity ) { 389 375 return; … … 391 377 c += newCost; 392 378 } // while 393 if ( destIt != destAsTuple-> types.end() ) {379 if ( destIt != destAsTuple->get_types().end() ) { 394 380 cost = Cost::infinity; 395 381 } else { … … 399 385 } 400 386 401 void ConversionCost:: postvisit( VarArgsType * ) {387 void ConversionCost::visit( VarArgsType * ) { 402 388 if ( dynamic_cast< VarArgsType* >( dest ) ) { 403 389 cost = Cost::zero; … … 405 391 } 406 392 407 void ConversionCost:: postvisit( ZeroType * ) {393 void ConversionCost::visit( ZeroType * ) { 408 394 if ( dynamic_cast< ZeroType * >( dest ) ) { 409 395 cost = Cost::zero; … … 422 408 } 423 409 424 void ConversionCost:: postvisit( OneType * ) {410 void ConversionCost::visit( OneType * ) { 425 411 if ( dynamic_cast< OneType * >( dest ) ) { 426 412 cost = Cost::zero;
Note:
See TracChangeset
for help on using the changeset viewer.