Changeset 7416d46a for src/ResolvExpr
- Timestamp:
- Jan 30, 2018, 3:54:32 PM (8 years ago)
- 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, stuck-waitfor-destruct, with_gc
- Children:
- 633a642
- Parents:
- f792cb8 (diff), 42be3c3 (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. - Location:
- src/ResolvExpr
- Files:
-
- 1 deleted
- 13 edited
-
AlternativeFinder.cc (modified) (40 diffs)
-
AlternativeFinder.h (modified) (2 diffs)
-
CastCost.cc (modified) (4 diffs)
-
CommonType.cc (modified) (10 diffs)
-
ConversionCost.cc (modified) (22 diffs)
-
ConversionCost.h (modified) (3 diffs)
-
CurrentObject.cc (modified) (4 diffs)
-
PtrsAssignable.cc (modified) (6 diffs)
-
PtrsCastable.cc (modified) (7 diffs)
-
RenameVars.cc (modified) (2 diffs)
-
RenameVars.h (modified) (1 diff)
-
Resolver.cc (modified) (6 diffs)
-
TypeMap.h (deleted)
-
Unify.cc (modified) (10 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/ResolvExpr/AlternativeFinder.cc
rf792cb8 r7416d46a 60 60 61 61 namespace ResolvExpr { 62 struct AlternativeFinder::Finder : public WithShortCircuiting { 63 Finder( AlternativeFinder & altFinder ) : altFinder( altFinder ), indexer( altFinder.indexer ), alternatives( altFinder.alternatives ), env( altFinder.env ), targetType( altFinder.targetType ) {} 64 65 void previsit( BaseSyntaxNode * ) { visit_children = false; } 66 67 void postvisit( ApplicationExpr * applicationExpr ); 68 void postvisit( UntypedExpr * untypedExpr ); 69 void postvisit( AddressExpr * addressExpr ); 70 void postvisit( LabelAddressExpr * labelExpr ); 71 void postvisit( CastExpr * castExpr ); 72 void postvisit( VirtualCastExpr * castExpr ); 73 void postvisit( UntypedMemberExpr * memberExpr ); 74 void postvisit( MemberExpr * memberExpr ); 75 void postvisit( NameExpr * variableExpr ); 76 void postvisit( VariableExpr * variableExpr ); 77 void postvisit( ConstantExpr * constantExpr ); 78 void postvisit( SizeofExpr * sizeofExpr ); 79 void postvisit( AlignofExpr * alignofExpr ); 80 void postvisit( UntypedOffsetofExpr * offsetofExpr ); 81 void postvisit( OffsetofExpr * offsetofExpr ); 82 void postvisit( OffsetPackExpr * offsetPackExpr ); 83 void postvisit( AttrExpr * attrExpr ); 84 void postvisit( LogicalExpr * logicalExpr ); 85 void postvisit( ConditionalExpr * conditionalExpr ); 86 void postvisit( CommaExpr * commaExpr ); 87 void postvisit( ImplicitCopyCtorExpr * impCpCtorExpr ); 88 void postvisit( ConstructorExpr * ctorExpr ); 89 void postvisit( RangeExpr * rangeExpr ); 90 void postvisit( UntypedTupleExpr * tupleExpr ); 91 void postvisit( TupleExpr * tupleExpr ); 92 void postvisit( TupleIndexExpr * tupleExpr ); 93 void postvisit( TupleAssignExpr * tupleExpr ); 94 void postvisit( UniqueExpr * unqExpr ); 95 void postvisit( StmtExpr * stmtExpr ); 96 void postvisit( UntypedInitExpr * initExpr ); 97 98 /// Adds alternatives for anonymous members 99 void addAnonConversions( const Alternative & alt ); 100 /// Adds alternatives for member expressions, given the aggregate, conversion cost for that aggregate, and name of the member 101 template< typename StructOrUnionType > void addAggMembers( StructOrUnionType *aggInst, Expression *expr, const Cost &newCost, const TypeEnvironment & env, Expression * member ); 102 /// Adds alternatives for member expressions where the left side has tuple type 103 void addTupleMembers( TupleType * tupleType, Expression *expr, const Cost &newCost, const TypeEnvironment & env, Expression * member ); 104 /// Adds alternatives for offsetof expressions, given the base type and name of the member 105 template< typename StructOrUnionType > void addOffsetof( StructOrUnionType *aggInst, const std::string &name ); 106 /// Takes a final result and checks if its assertions can be satisfied 107 template<typename OutputIterator> 108 void validateFunctionAlternative( const Alternative &func, ArgPack& result, const std::vector<ArgPack>& results, OutputIterator out ); 109 /// Finds matching alternatives for a function, given a set of arguments 110 template<typename OutputIterator> 111 void makeFunctionAlternatives( const Alternative &func, FunctionType *funcType, const ExplodedArgs& args, OutputIterator out ); 112 /// Checks if assertion parameters match for a new alternative 113 template< typename OutputIterator > 114 void inferParameters( const AssertionSet &need, AssertionSet &have, const Alternative &newAlt, OpenVarSet &openVars, OutputIterator out ); 115 private: 116 AlternativeFinder & altFinder; 117 const SymTab::Indexer &indexer; 118 AltList & alternatives; 119 const TypeEnvironment &env; 120 Type *& targetType; 121 }; 122 62 123 Expression *resolveInVoidContext( Expression *expr, const SymTab::Indexer &indexer, TypeEnvironment &env ) { 63 124 CastExpr *castToVoid = new CastExpr( expr ); … … 152 213 153 214 void renameTypes( Expression *expr ) { 154 expr->get_result()->accept( global_renamer);215 renameTyVars( expr->result ); 155 216 } 156 217 } // namespace … … 185 246 186 247 void AlternativeFinder::find( Expression *expr, bool adjust, bool prune, bool failFast ) { 187 expr->accept( *this ); 248 PassVisitor<Finder> finder( *this ); 249 expr->accept( finder ); 188 250 if ( failFast && alternatives.empty() ) { 189 251 PRINT( … … 244 306 } 245 307 246 void AlternativeFinder:: addAnonConversions( const Alternative & alt ) {308 void AlternativeFinder::Finder::addAnonConversions( const Alternative & alt ) { 247 309 // adds anonymous member interpretations whenever an aggregate value type is seen. 248 310 // 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 … … 265 327 266 328 template< typename StructOrUnionType > 267 void AlternativeFinder:: addAggMembers( StructOrUnionType *aggInst, Expression *expr, const Cost &newCost, const TypeEnvironment & env, Expression * member ) {329 void AlternativeFinder::Finder::addAggMembers( StructOrUnionType *aggInst, Expression *expr, const Cost &newCost, const TypeEnvironment & env, Expression * member ) { 268 330 // by this point, member must be a name expr 269 331 NameExpr * nameExpr = dynamic_cast< NameExpr * >( member ); … … 284 346 } 285 347 286 void AlternativeFinder:: addTupleMembers( TupleType * tupleType, Expression *expr, const Cost &newCost, const TypeEnvironment & env, Expression * member ) {348 void AlternativeFinder::Finder::addTupleMembers( TupleType * tupleType, Expression *expr, const Cost &newCost, const TypeEnvironment & env, Expression * member ) { 287 349 if ( ConstantExpr * constantExpr = dynamic_cast< ConstantExpr * >( member ) ) { 288 350 // get the value of the constant expression as an int, must be between 0 and the length of the tuple type to have meaning … … 308 370 } 309 371 310 void AlternativeFinder:: visit( ApplicationExpr *applicationExpr ) {372 void AlternativeFinder::Finder::postvisit( ApplicationExpr *applicationExpr ) { 311 373 alternatives.push_back( Alternative( applicationExpr->clone(), env, Cost::zero ) ); 312 374 } … … 485 547 Type *adjType = candidate->get_type()->clone(); 486 548 adjustExprType( adjType, newEnv, indexer ); 487 adjType->accept( global_renamer);549 renameTyVars( adjType ); 488 550 PRINT( 489 551 std::cerr << "unifying "; … … 541 603 542 604 template< typename OutputIterator > 543 void AlternativeFinder:: inferParameters( const AssertionSet &need, AssertionSet &have, const Alternative &newAlt, OpenVarSet &openVars, OutputIterator out ) {605 void AlternativeFinder::Finder::inferParameters( const AssertionSet &need, AssertionSet &have, const Alternative &newAlt, OpenVarSet &openVars, OutputIterator out ) { 544 606 // PRINT( 545 607 // std::cerr << "inferParameters: assertions needed are" << std::endl; … … 595 657 596 658 ArgPack() 597 : parent(0), expr(), cost(Cost::zero), env(), need(), have(), openVars(), nextArg(0), 659 : parent(0), expr(), cost(Cost::zero), env(), need(), have(), openVars(), nextArg(0), 598 660 tupleStart(0), nextExpl(0), explAlt(0) {} 599 661 … … 706 768 707 769 if ( nTuples > 0 || ! results[i].expr ) { 708 // first iteration or no expression to clone, 770 // first iteration or no expression to clone, 709 771 // push empty tuple expression 710 772 newResult.parent = i; … … 892 954 893 955 template<typename OutputIterator> 894 void AlternativeFinder:: validateFunctionAlternative( const Alternative &func, ArgPack& result,956 void AlternativeFinder::Finder::validateFunctionAlternative( const Alternative &func, ArgPack& result, 895 957 const std::vector<ArgPack>& results, OutputIterator out ) { 896 958 ApplicationExpr *appExpr = new ApplicationExpr( func.expr->clone() ); … … 915 977 916 978 template<typename OutputIterator> 917 void AlternativeFinder:: makeFunctionAlternatives( const Alternative &func,979 void AlternativeFinder::Finder::makeFunctionAlternatives( const Alternative &func, 918 980 FunctionType *funcType, const ExplodedArgs &args, OutputIterator out ) { 919 981 OpenVarSet funcOpenVars; … … 1022 1084 } 1023 1085 1024 void AlternativeFinder:: visit( UntypedExpr *untypedExpr ) {1086 void AlternativeFinder::Finder::postvisit( UntypedExpr *untypedExpr ) { 1025 1087 AlternativeFinder funcFinder( indexer, env ); 1026 1088 funcFinder.findWithAdjustment( untypedExpr->get_function() ); … … 1029 1091 1030 1092 std::vector< AlternativeFinder > argAlternatives; 1031 findSubExprs( untypedExpr->begin_args(), untypedExpr->end_args(),1093 altFinder.findSubExprs( untypedExpr->begin_args(), untypedExpr->end_args(), 1032 1094 back_inserter( argAlternatives ) ); 1033 1095 1034 1096 // take care of possible tuple assignments 1035 1097 // if not tuple assignment, assignment is taken care of as a normal function call 1036 Tuples::handleTupleAssignment( *this, untypedExpr, argAlternatives );1098 Tuples::handleTupleAssignment( altFinder, untypedExpr, argAlternatives ); 1037 1099 1038 1100 // find function operators … … 1172 1234 // fix this issue in a more robust way. 1173 1235 targetType = nullptr; 1174 visit( untypedExpr );1236 postvisit( untypedExpr ); 1175 1237 } 1176 1238 } … … 1181 1243 } 1182 1244 1183 void AlternativeFinder:: visit( AddressExpr *addressExpr ) {1245 void AlternativeFinder::Finder::postvisit( AddressExpr *addressExpr ) { 1184 1246 AlternativeFinder finder( indexer, env ); 1185 1247 finder.find( addressExpr->get_arg() ); … … 1192 1254 } 1193 1255 1194 void AlternativeFinder:: visit( LabelAddressExpr * expr ) {1256 void AlternativeFinder::Finder::postvisit( LabelAddressExpr * expr ) { 1195 1257 alternatives.push_back( Alternative{ expr->clone(), env, Cost::zero } ); 1196 1258 } … … 1223 1285 } 1224 1286 1225 void AlternativeFinder:: visit( CastExpr *castExpr ) {1287 void AlternativeFinder::Finder::postvisit( CastExpr *castExpr ) { 1226 1288 Type *& toType = castExpr->get_result(); 1227 1289 assert( toType ); … … 1278 1340 } 1279 1341 1280 void AlternativeFinder:: visit( VirtualCastExpr * castExpr ) {1342 void AlternativeFinder::Finder::postvisit( VirtualCastExpr * castExpr ) { 1281 1343 assertf( castExpr->get_result(), "Implicate virtual cast targets not yet supported." ); 1282 1344 AlternativeFinder finder( indexer, env ); … … 1290 1352 } 1291 1353 1292 void AlternativeFinder:: visit( UntypedMemberExpr *memberExpr ) {1354 void AlternativeFinder::Finder::postvisit( UntypedMemberExpr *memberExpr ) { 1293 1355 AlternativeFinder funcFinder( indexer, env ); 1294 1356 funcFinder.findWithAdjustment( memberExpr->get_aggregate() ); … … 1312 1374 } 1313 1375 1314 void AlternativeFinder:: visit( MemberExpr *memberExpr ) {1376 void AlternativeFinder::Finder::postvisit( MemberExpr *memberExpr ) { 1315 1377 alternatives.push_back( Alternative( memberExpr->clone(), env, Cost::zero ) ); 1316 1378 } 1317 1379 1318 void AlternativeFinder:: visit( NameExpr *nameExpr ) {1380 void AlternativeFinder::Finder::postvisit( NameExpr *nameExpr ) { 1319 1381 std::list< SymTab::Indexer::IdData > declList; 1320 1382 indexer.lookupId( nameExpr->get_name(), declList ); … … 1337 1399 } 1338 1400 1339 void AlternativeFinder:: visit( VariableExpr *variableExpr ) {1401 void AlternativeFinder::Finder::postvisit( VariableExpr *variableExpr ) { 1340 1402 // not sufficient to clone here, because variable's type may have changed 1341 1403 // since the VariableExpr was originally created. … … 1343 1405 } 1344 1406 1345 void AlternativeFinder:: visit( ConstantExpr *constantExpr ) {1407 void AlternativeFinder::Finder::postvisit( ConstantExpr *constantExpr ) { 1346 1408 alternatives.push_back( Alternative( constantExpr->clone(), env, Cost::zero ) ); 1347 1409 } 1348 1410 1349 void AlternativeFinder:: visit( SizeofExpr *sizeofExpr ) {1411 void AlternativeFinder::Finder::postvisit( SizeofExpr *sizeofExpr ) { 1350 1412 if ( sizeofExpr->get_isType() ) { 1351 1413 Type * newType = sizeofExpr->get_type()->clone(); … … 1368 1430 } 1369 1431 1370 void AlternativeFinder:: visit( AlignofExpr *alignofExpr ) {1432 void AlternativeFinder::Finder::postvisit( AlignofExpr *alignofExpr ) { 1371 1433 if ( alignofExpr->get_isType() ) { 1372 1434 Type * newType = alignofExpr->get_type()->clone(); … … 1390 1452 1391 1453 template< typename StructOrUnionType > 1392 void AlternativeFinder:: addOffsetof( StructOrUnionType *aggInst, const std::string &name ) {1454 void AlternativeFinder::Finder::addOffsetof( StructOrUnionType *aggInst, const std::string &name ) { 1393 1455 std::list< Declaration* > members; 1394 1456 aggInst->lookup( name, members ); … … 1403 1465 } 1404 1466 1405 void AlternativeFinder:: visit( UntypedOffsetofExpr *offsetofExpr ) {1467 void AlternativeFinder::Finder::postvisit( UntypedOffsetofExpr *offsetofExpr ) { 1406 1468 AlternativeFinder funcFinder( indexer, env ); 1407 1469 // xxx - resolveTypeof? … … 1413 1475 } 1414 1476 1415 void AlternativeFinder:: visit( OffsetofExpr *offsetofExpr ) {1477 void AlternativeFinder::Finder::postvisit( OffsetofExpr *offsetofExpr ) { 1416 1478 alternatives.push_back( Alternative( offsetofExpr->clone(), env, Cost::zero ) ); 1417 1479 } 1418 1480 1419 void AlternativeFinder:: visit( OffsetPackExpr *offsetPackExpr ) {1481 void AlternativeFinder::Finder::postvisit( OffsetPackExpr *offsetPackExpr ) { 1420 1482 alternatives.push_back( Alternative( offsetPackExpr->clone(), env, Cost::zero ) ); 1421 1483 } … … 1444 1506 } 1445 1507 1446 void AlternativeFinder:: visit( AttrExpr *attrExpr ) {1508 void AlternativeFinder::Finder::postvisit( AttrExpr *attrExpr ) { 1447 1509 // assume no 'pointer-to-attribute' 1448 1510 NameExpr *nameExpr = dynamic_cast< NameExpr* >( attrExpr->get_attr() ); … … 1458 1520 if ( function->get_parameters().size() == 1 ) { 1459 1521 if ( attrExpr->get_isType() ) { 1460 resolveAttr( data, function, attrExpr->get_type(), env, *this);1522 resolveAttr( data, function, attrExpr->get_type(), env, altFinder); 1461 1523 } else { 1462 1524 AlternativeFinder finder( indexer, env ); … … 1464 1526 for ( AltList::iterator choice = finder.alternatives.begin(); choice != finder.alternatives.end(); ++choice ) { 1465 1527 if ( choice->expr->get_result()->size() == 1 ) { 1466 resolveAttr(data, function, choice->expr->get_result(), choice->env, *this);1528 resolveAttr(data, function, choice->expr->get_result(), choice->env, altFinder ); 1467 1529 } // fi 1468 1530 } // for … … 1479 1541 } 1480 1542 1481 void AlternativeFinder:: visit( LogicalExpr *logicalExpr ) {1543 void AlternativeFinder::Finder::postvisit( LogicalExpr *logicalExpr ) { 1482 1544 AlternativeFinder firstFinder( indexer, env ); 1483 1545 firstFinder.findWithAdjustment( logicalExpr->get_arg1() ); 1546 if ( firstFinder.alternatives.empty() ) return; 1547 AlternativeFinder secondFinder( indexer, env ); 1548 secondFinder.findWithAdjustment( logicalExpr->get_arg2() ); 1549 if ( secondFinder.alternatives.empty() ) return; 1484 1550 for ( AltList::const_iterator first = firstFinder.alternatives.begin(); first != firstFinder.alternatives.end(); ++first ) { 1485 AlternativeFinder secondFinder( indexer, first->env );1486 secondFinder.findWithAdjustment( logicalExpr->get_arg2() );1487 1551 for ( AltList::const_iterator second = secondFinder.alternatives.begin(); second != secondFinder.alternatives.end(); ++second ) { 1552 TypeEnvironment compositeEnv; 1553 compositeEnv.simpleCombine( first->env ); 1554 compositeEnv.simpleCombine( second->env ); 1555 1488 1556 LogicalExpr *newExpr = new LogicalExpr( first->expr->clone(), second->expr->clone(), logicalExpr->get_isAnd() ); 1489 alternatives.push_back( Alternative( newExpr, second->env, first->cost + second->cost ) );1490 } 1491 } 1492 } 1493 1494 void AlternativeFinder:: visit( ConditionalExpr *conditionalExpr ) {1557 alternatives.push_back( Alternative( newExpr, compositeEnv, first->cost + second->cost ) ); 1558 } 1559 } 1560 } 1561 1562 void AlternativeFinder::Finder::postvisit( ConditionalExpr *conditionalExpr ) { 1495 1563 // find alternatives for condition 1496 1564 AlternativeFinder firstFinder( indexer, env ); 1497 1565 firstFinder.findWithAdjustment( conditionalExpr->get_arg1() ); 1566 if ( firstFinder.alternatives.empty() ) return; 1567 // find alternatives for true expression 1568 AlternativeFinder secondFinder( indexer, env ); 1569 secondFinder.findWithAdjustment( conditionalExpr->get_arg2() ); 1570 if ( secondFinder.alternatives.empty() ) return; 1571 // find alterantives for false expression 1572 AlternativeFinder thirdFinder( indexer, env ); 1573 thirdFinder.findWithAdjustment( conditionalExpr->get_arg3() ); 1574 if ( thirdFinder.alternatives.empty() ) return; 1498 1575 for ( AltList::const_iterator first = firstFinder.alternatives.begin(); first != firstFinder.alternatives.end(); ++first ) { 1499 // find alternatives for true expression1500 AlternativeFinder secondFinder( indexer, first->env );1501 secondFinder.findWithAdjustment( conditionalExpr->get_arg2() );1502 1576 for ( AltList::const_iterator second = secondFinder.alternatives.begin(); second != secondFinder.alternatives.end(); ++second ) { 1503 // find alterantives for false expression1504 AlternativeFinder thirdFinder( indexer, second->env );1505 thirdFinder.findWithAdjustment( conditionalExpr->get_arg3() );1506 1577 for ( AltList::const_iterator third = thirdFinder.alternatives.begin(); third != thirdFinder.alternatives.end(); ++third ) { 1578 TypeEnvironment compositeEnv; 1579 compositeEnv.simpleCombine( first->env ); 1580 compositeEnv.simpleCombine( second->env ); 1581 compositeEnv.simpleCombine( third->env ); 1582 1507 1583 // unify true and false types, then infer parameters to produce new alternatives 1508 1584 OpenVarSet openVars; 1509 1585 AssertionSet needAssertions, haveAssertions; 1510 Alternative newAlt( 0, third->env, first->cost + second->cost + third->cost );1586 Alternative newAlt( 0, compositeEnv, first->cost + second->cost + third->cost ); 1511 1587 Type* commonType = nullptr; 1512 1588 if ( unify( second->expr->get_result(), third->expr->get_result(), newAlt.env, needAssertions, haveAssertions, openVars, indexer, commonType ) ) { … … 1524 1600 } 1525 1601 1526 void AlternativeFinder:: visit( CommaExpr *commaExpr ) {1602 void AlternativeFinder::Finder::postvisit( CommaExpr *commaExpr ) { 1527 1603 TypeEnvironment newEnv( env ); 1528 1604 Expression *newFirstArg = resolveInVoidContext( commaExpr->get_arg1(), indexer, newEnv ); … … 1535 1611 } 1536 1612 1537 void AlternativeFinder:: visit( RangeExpr * rangeExpr ) {1613 void AlternativeFinder::Finder::postvisit( RangeExpr * rangeExpr ) { 1538 1614 // resolve low and high, accept alternatives whose low and high types unify 1539 1615 AlternativeFinder firstFinder( indexer, env ); 1540 1616 firstFinder.findWithAdjustment( rangeExpr->get_low() ); 1617 if ( firstFinder.alternatives.empty() ) return; 1618 AlternativeFinder secondFinder( indexer, env ); 1619 secondFinder.findWithAdjustment( rangeExpr->get_high() ); 1620 if ( secondFinder.alternatives.empty() ) return; 1541 1621 for ( AltList::const_iterator first = firstFinder.alternatives.begin(); first != firstFinder.alternatives.end(); ++first ) { 1542 AlternativeFinder secondFinder( indexer, first->env );1543 secondFinder.findWithAdjustment( rangeExpr->get_high() );1544 1622 for ( AltList::const_iterator second = secondFinder.alternatives.begin(); second != secondFinder.alternatives.end(); ++second ) { 1623 TypeEnvironment compositeEnv; 1624 compositeEnv.simpleCombine( first->env ); 1625 compositeEnv.simpleCombine( second->env ); 1545 1626 OpenVarSet openVars; 1546 1627 AssertionSet needAssertions, haveAssertions; 1547 Alternative newAlt( 0, second->env, first->cost + second->cost );1628 Alternative newAlt( 0, compositeEnv, first->cost + second->cost ); 1548 1629 Type* commonType = nullptr; 1549 1630 if ( unify( first->expr->get_result(), second->expr->get_result(), newAlt.env, needAssertions, haveAssertions, openVars, indexer, commonType ) ) { … … 1557 1638 } 1558 1639 1559 void AlternativeFinder:: visit( UntypedTupleExpr *tupleExpr ) {1640 void AlternativeFinder::Finder::postvisit( UntypedTupleExpr *tupleExpr ) { 1560 1641 std::vector< AlternativeFinder > subExprAlternatives; 1561 findSubExprs( tupleExpr->get_exprs().begin(), tupleExpr->get_exprs().end(),1642 altFinder.findSubExprs( tupleExpr->get_exprs().begin(), tupleExpr->get_exprs().end(), 1562 1643 back_inserter( subExprAlternatives ) ); 1563 1644 std::vector< AltList > possibilities; … … 1575 1656 } 1576 1657 1577 void AlternativeFinder:: visit( TupleExpr *tupleExpr ) {1658 void AlternativeFinder::Finder::postvisit( TupleExpr *tupleExpr ) { 1578 1659 alternatives.push_back( Alternative( tupleExpr->clone(), env, Cost::zero ) ); 1579 1660 } 1580 1661 1581 void AlternativeFinder:: visit( ImplicitCopyCtorExpr * impCpCtorExpr ) {1662 void AlternativeFinder::Finder::postvisit( ImplicitCopyCtorExpr * impCpCtorExpr ) { 1582 1663 alternatives.push_back( Alternative( impCpCtorExpr->clone(), env, Cost::zero ) ); 1583 1664 } 1584 1665 1585 void AlternativeFinder:: visit( ConstructorExpr * ctorExpr ) {1666 void AlternativeFinder::Finder::postvisit( ConstructorExpr * ctorExpr ) { 1586 1667 AlternativeFinder finder( indexer, env ); 1587 1668 // don't prune here, since it's guaranteed all alternatives will have the same type … … 1593 1674 } 1594 1675 1595 void AlternativeFinder:: visit( TupleIndexExpr *tupleExpr ) {1676 void AlternativeFinder::Finder::postvisit( TupleIndexExpr *tupleExpr ) { 1596 1677 alternatives.push_back( Alternative( tupleExpr->clone(), env, Cost::zero ) ); 1597 1678 } 1598 1679 1599 void AlternativeFinder:: visit( TupleAssignExpr *tupleAssignExpr ) {1680 void AlternativeFinder::Finder::postvisit( TupleAssignExpr *tupleAssignExpr ) { 1600 1681 alternatives.push_back( Alternative( tupleAssignExpr->clone(), env, Cost::zero ) ); 1601 1682 } 1602 1683 1603 void AlternativeFinder:: visit( UniqueExpr *unqExpr ) {1684 void AlternativeFinder::Finder::postvisit( UniqueExpr *unqExpr ) { 1604 1685 AlternativeFinder finder( indexer, env ); 1605 1686 finder.findWithAdjustment( unqExpr->get_expr() ); … … 1611 1692 } 1612 1693 1613 void AlternativeFinder:: visit( StmtExpr *stmtExpr ) {1694 void AlternativeFinder::Finder::postvisit( StmtExpr *stmtExpr ) { 1614 1695 StmtExpr * newStmtExpr = stmtExpr->clone(); 1615 1696 ResolvExpr::resolveStmtExpr( newStmtExpr, indexer ); … … 1618 1699 } 1619 1700 1620 void AlternativeFinder:: visit( UntypedInitExpr *initExpr ) {1701 void AlternativeFinder::Finder::postvisit( UntypedInitExpr *initExpr ) { 1621 1702 // handle each option like a cast 1622 1703 AltList candidates; 1623 PRINT( std::cerr << "untyped init expr: " << initExpr << std::endl; ) 1704 PRINT( 1705 std::cerr << "untyped init expr: " << initExpr << std::endl; 1706 ) 1624 1707 // O(N^2) checks of d-types with e-types 1625 1708 for ( InitAlternative & initAlt : initExpr->get_initAlts() ) { … … 1637 1720 AssertionSet needAssertions, haveAssertions; 1638 1721 OpenVarSet openVars; // find things in env that don't have a "representative type" and claim those are open vars? 1639 PRINT( std::cerr << " @ " << toType << " " << initAlt.designation << std::endl; ) 1722 PRINT( 1723 std::cerr << " @ " << toType << " " << initAlt.designation << std::endl; 1724 ) 1640 1725 // It's possible that a cast can throw away some values in a multiply-valued expression. (An example is a 1641 1726 // cast-to-void, which casts from one value to zero.) Figure out the prefix of the subexpression results -
src/ResolvExpr/AlternativeFinder.h
rf792cb8 r7416d46a 38 38 using ExplodedArgs = std::vector< std::vector< ExplodedActual > >; 39 39 40 class AlternativeFinder : public Visitor{40 class AlternativeFinder { 41 41 public: 42 42 AlternativeFinder( const SymTab::Indexer &indexer, const TypeEnvironment &env ); … … 94 94 void findSubExprs( InputIterator begin, InputIterator end, OutputIterator out ); 95 95 private: 96 virtual void visit( ApplicationExpr *applicationExpr ); 97 virtual void visit( UntypedExpr *untypedExpr ); 98 virtual void visit( AddressExpr *addressExpr ); 99 virtual void visit( LabelAddressExpr *labelExpr ); 100 virtual void visit( CastExpr *castExpr ); 101 virtual void visit( VirtualCastExpr *castExpr ); 102 virtual void visit( UntypedMemberExpr *memberExpr ); 103 virtual void visit( MemberExpr *memberExpr ); 104 virtual void visit( NameExpr *variableExpr ); 105 virtual void visit( VariableExpr *variableExpr ); 106 virtual void visit( ConstantExpr *constantExpr ); 107 virtual void visit( SizeofExpr *sizeofExpr ); 108 virtual void visit( AlignofExpr *alignofExpr ); 109 virtual void visit( UntypedOffsetofExpr *offsetofExpr ); 110 virtual void visit( OffsetofExpr *offsetofExpr ); 111 virtual void visit( OffsetPackExpr *offsetPackExpr ); 112 virtual void visit( AttrExpr *attrExpr ); 113 virtual void visit( LogicalExpr *logicalExpr ); 114 virtual void visit( ConditionalExpr *conditionalExpr ); 115 virtual void visit( CommaExpr *commaExpr ); 116 virtual void visit( ImplicitCopyCtorExpr * impCpCtorExpr ); 117 virtual void visit( ConstructorExpr * ctorExpr ); 118 virtual void visit( RangeExpr * rangeExpr ); 119 virtual void visit( UntypedTupleExpr *tupleExpr ); 120 virtual void visit( TupleExpr *tupleExpr ); 121 virtual void visit( TupleIndexExpr *tupleExpr ); 122 virtual void visit( TupleAssignExpr *tupleExpr ); 123 virtual void visit( UniqueExpr *unqExpr ); 124 virtual void visit( StmtExpr *stmtExpr ); 125 virtual void visit( UntypedInitExpr *initExpr ); 126 127 /// Adds alternatives for anonymous members 128 void addAnonConversions( const Alternative & alt ); 129 /// Adds alternatives for member expressions, given the aggregate, conversion cost for that aggregate, and name of the member 130 template< typename StructOrUnionType > void addAggMembers( StructOrUnionType *aggInst, Expression *expr, const Cost &newCost, const TypeEnvironment & env, Expression * member ); 131 /// Adds alternatives for member expressions where the left side has tuple type 132 void addTupleMembers( TupleType * tupleType, Expression *expr, const Cost &newCost, const TypeEnvironment & env, Expression * member ); 133 /// Adds alternatives for offsetof expressions, given the base type and name of the member 134 template< typename StructOrUnionType > void addOffsetof( StructOrUnionType *aggInst, const std::string &name ); 135 /// Takes a final result and checks if its assertions can be satisfied 136 template<typename OutputIterator> 137 void validateFunctionAlternative( const Alternative &func, ArgPack& result, const std::vector<ArgPack>& results, OutputIterator out ); 138 /// Finds matching alternatives for a function, given a set of arguments 139 template<typename OutputIterator> 140 void makeFunctionAlternatives( const Alternative &func, FunctionType *funcType, const ExplodedArgs& args, OutputIterator out ); 141 /// Checks if assertion parameters match for a new alternative 142 template< typename OutputIterator > 143 void inferParameters( const AssertionSet &need, AssertionSet &have, const Alternative &newAlt, OpenVarSet &openVars, OutputIterator out ); 144 96 struct Finder; 145 97 const SymTab::Indexer &indexer; 146 98 AltList alternatives; -
src/ResolvExpr/CastCost.cc
rf792cb8 r7416d46a 31 31 32 32 namespace ResolvExpr { 33 classCastCost : public ConversionCost {33 struct CastCost : public ConversionCost { 34 34 public: 35 CastCost( Type *dest, const SymTab::Indexer &indexer, const TypeEnvironment &env );35 CastCost( Type *dest, const SymTab::Indexer &indexer, const TypeEnvironment &env, CostFunction costFunc ); 36 36 37 virtual void visit( BasicType *basicType ); 38 virtual void visit( PointerType *pointerType ); 37 using ConversionCost::previsit; 38 using ConversionCost::postvisit; 39 void postvisit( BasicType * basicType ); 40 void postvisit( PointerType * pointerType ); 39 41 }; 40 42 … … 52 54 // all typedefs should be gone by this point 53 55 TypeDecl *type = strict_dynamic_cast< TypeDecl* >( namedType ); 54 if ( type-> get_base()) {55 return castCost( src, type-> get_base(), indexer, env ) + Cost::safe;56 if ( type->base ) { 57 return castCost( src, type->base, indexer, env ) + Cost::safe; 56 58 } // if 57 59 } // if … … 74 76 } else if ( ReferenceType * refType = dynamic_cast< ReferenceType * > ( dest ) ) { 75 77 PRINT( std::cerr << "conversionCost: dest is reference" << std::endl; ) 76 return convertToReferenceCost( src, refType, indexer, env, [](Type * t1, Type * t2, const TypeEnvironment & env, const SymTab::Indexer & indexer) {78 return convertToReferenceCost( src, refType, indexer, env, [](Type * t1, Type * t2, const SymTab::Indexer & indexer, const TypeEnvironment & env ) { 77 79 return ptrsCastable( t1, t2, env, indexer ); 78 80 }); 79 81 } else { 80 CastCost converter( dest, indexer, env);82 PassVisitor<CastCost> converter( dest, indexer, env, castCost ); 81 83 src->accept( converter ); 82 if ( converter. get_cost() == Cost::infinity ) {84 if ( converter.pass.get_cost() == Cost::infinity ) { 83 85 return Cost::infinity; 84 86 } else { 85 87 // xxx - why are we adding cost 0 here? 86 return converter. get_cost() + Cost::zero;88 return converter.pass.get_cost() + Cost::zero; 87 89 } // if 88 90 } // if 89 91 } 90 92 91 CastCost::CastCost( Type *dest, const SymTab::Indexer &indexer, const TypeEnvironment &env )92 : ConversionCost( dest, indexer, env ) {93 CastCost::CastCost( Type *dest, const SymTab::Indexer &indexer, const TypeEnvironment &env, CostFunction costFunc ) 94 : ConversionCost( dest, indexer, env, costFunc ) { 93 95 } 94 96 95 void CastCost:: visit( BasicType *basicType ) {97 void CastCost::postvisit( BasicType *basicType ) { 96 98 PointerType *destAsPointer = dynamic_cast< PointerType* >( dest ); 97 99 if ( destAsPointer && basicType->isInteger() ) { … … 103 105 } 104 106 105 void CastCost:: visit( PointerType *pointerType ) {107 void CastCost::postvisit( PointerType *pointerType ) { 106 108 if ( PointerType *destAsPtr = dynamic_cast< PointerType* >( dest ) ) { 107 if ( pointerType->get_qualifiers() <= destAsPtr->get_qualifiers() && typesCompatibleIgnoreQualifiers( pointerType-> get_base(), destAsPtr->get_base(), indexer, env ) ) {109 if ( pointerType->get_qualifiers() <= destAsPtr->get_qualifiers() && typesCompatibleIgnoreQualifiers( pointerType->base, destAsPtr->base, indexer, env ) ) { 108 110 cost = Cost::safe; 109 111 } else { 110 112 TypeEnvironment newEnv( env ); 111 newEnv.add( pointerType-> get_forall());112 newEnv.add( pointerType-> get_base()->get_forall());113 int castResult = ptrsCastable( pointerType-> get_base(), destAsPtr->get_base(), newEnv, indexer );113 newEnv.add( pointerType->forall ); 114 newEnv.add( pointerType->base->forall ); 115 int castResult = ptrsCastable( pointerType->base, destAsPtr->base, newEnv, indexer ); 114 116 if ( castResult > 0 ) { 115 117 cost = Cost::safe; -
src/ResolvExpr/CommonType.cc
rf792cb8 r7416d46a 18 18 #include <utility> // for pair 19 19 20 #include "Common/PassVisitor.h" 20 21 #include "ResolvExpr/TypeEnvironment.h" // for OpenVarSet, AssertionSet 21 22 #include "SymTab/Indexer.h" // for Indexer … … 29 30 30 31 namespace ResolvExpr { 31 class CommonType : public Visitor { 32 public: 32 struct CommonType : public WithShortCircuiting { 33 33 CommonType( Type *type2, bool widenFirst, bool widenSecond, const SymTab::Indexer &indexer, TypeEnvironment &env, const OpenVarSet &openVars ); 34 34 Type *get_result() const { return result; } 35 36 void previsit( BaseSyntaxNode * ) { visit_children = false; } 37 38 void postvisit( VoidType * voidType ); 39 void postvisit( BasicType * basicType ); 40 void postvisit( PointerType * pointerType ); 41 void postvisit( ArrayType * arrayType ); 42 void postvisit( ReferenceType * refType ); 43 void postvisit( FunctionType * functionType ); 44 void postvisit( StructInstType * aggregateUseType ); 45 void postvisit( UnionInstType * aggregateUseType ); 46 void postvisit( EnumInstType * aggregateUseType ); 47 void postvisit( TraitInstType * aggregateUseType ); 48 void postvisit( TypeInstType * aggregateUseType ); 49 void postvisit( TupleType * tupleType ); 50 void postvisit( VarArgsType * varArgsType ); 51 void postvisit( ZeroType * zeroType ); 52 void postvisit( OneType * oneType ); 53 35 54 private: 36 virtual void visit( VoidType *voidType );37 virtual void visit( BasicType *basicType );38 virtual void visit( PointerType *pointerType );39 virtual void visit( ArrayType *arrayType );40 virtual void visit( ReferenceType *refType );41 virtual void visit( FunctionType *functionType );42 virtual void visit( StructInstType *aggregateUseType );43 virtual void visit( UnionInstType *aggregateUseType );44 virtual void visit( EnumInstType *aggregateUseType );45 virtual void visit( TraitInstType *aggregateUseType );46 virtual void visit( TypeInstType *aggregateUseType );47 virtual void visit( TupleType *tupleType );48 virtual void visit( VarArgsType *varArgsType );49 virtual void visit( ZeroType *zeroType );50 virtual void visit( OneType *oneType );51 52 55 template< typename Pointer > void getCommonWithVoidPointer( Pointer* voidPointer, Pointer* otherPointer ); 53 56 template< typename RefType > void handleRefType( RefType *inst, Type *other ); … … 80 83 81 84 Type *commonType( Type *type1, Type *type2, bool widenFirst, bool widenSecond, const SymTab::Indexer &indexer, TypeEnvironment &env, const OpenVarSet &openVars ) { 82 CommonTypevisitor( type2, widenFirst, widenSecond, indexer, env, openVars );85 PassVisitor<CommonType> visitor( type2, widenFirst, widenSecond, indexer, env, openVars ); 83 86 84 87 int depth1 = type1->referenceDepth(); … … 116 119 117 120 type1->accept( visitor ); 118 Type *result = visitor. get_result();121 Type *result = visitor.pass.get_result(); 119 122 if ( ! result ) { 120 123 // this appears to be handling for opaque type declarations … … 188 191 } 189 192 190 void CommonType:: visit( VoidType * ) {}191 192 void CommonType:: visit( BasicType *basicType ) {193 void CommonType::postvisit( VoidType * ) {} 194 195 void CommonType::postvisit( BasicType *basicType ) { 193 196 if ( BasicType *otherBasic = dynamic_cast< BasicType* >( type2 ) ) { 194 197 BasicType::Kind newType = combinedType[ basicType->get_kind() ][ otherBasic->get_kind() ]; … … 219 222 } 220 223 221 void CommonType:: visit( PointerType *pointerType ) {224 void CommonType::postvisit( PointerType *pointerType ) { 222 225 if ( PointerType *otherPointer = dynamic_cast< PointerType* >( type2 ) ) { 223 226 // std::cerr << "commonType: two pointers: " << pointerType << " / " << otherPointer << std::endl; … … 254 257 } 255 258 256 void CommonType:: visit( ArrayType * ) {}257 258 void CommonType:: visit( ReferenceType *refType ) {259 void CommonType::postvisit( ArrayType * ) {} 260 261 void CommonType::postvisit( ReferenceType *refType ) { 259 262 if ( ReferenceType *otherRef = dynamic_cast< ReferenceType* >( type2 ) ) { 260 263 // std::cerr << "commonType: both references: " << refType << " / " << otherRef << std::endl; … … 291 294 } 292 295 293 void CommonType:: visit( FunctionType * ) {}294 void CommonType:: visit( StructInstType * ) {}295 void CommonType:: visit( UnionInstType * ) {}296 297 void CommonType:: visit( EnumInstType *enumInstType ) {296 void CommonType::postvisit( FunctionType * ) {} 297 void CommonType::postvisit( StructInstType * ) {} 298 void CommonType::postvisit( UnionInstType * ) {} 299 300 void CommonType::postvisit( EnumInstType *enumInstType ) { 298 301 if ( dynamic_cast< BasicType * >( type2 ) || dynamic_cast< ZeroType* >( type2 ) || dynamic_cast< OneType* >( type2 ) ) { 299 302 // reuse BasicType, EnumInstType code by swapping type2 with enumInstType 300 ValueGuard< Type * > temp( type2 ); 301 type2 = enumInstType; 302 temp.old->accept( *this ); 303 } // if 304 } 305 306 void CommonType::visit( TraitInstType * ) { 307 } 308 309 void CommonType::visit( TypeInstType *inst ) { 303 result = commonType( type2, enumInstType, widenSecond, widenFirst, indexer, env, openVars ); 304 } // if 305 } 306 307 void CommonType::postvisit( TraitInstType * ) { 308 } 309 310 void CommonType::postvisit( TypeInstType *inst ) { 310 311 if ( widenFirst ) { 311 312 NamedTypeDecl *nt = indexer.lookupType( inst->get_name() ); … … 329 330 } 330 331 331 void CommonType:: visit( TupleType * ) {}332 void CommonType:: visit( VarArgsType * ) {}333 334 void CommonType:: visit( ZeroType *zeroType ) {332 void CommonType::postvisit( TupleType * ) {} 333 void CommonType::postvisit( VarArgsType * ) {} 334 335 void CommonType::postvisit( ZeroType *zeroType ) { 335 336 if ( widenFirst ) { 336 337 if ( dynamic_cast< BasicType* >( type2 ) || dynamic_cast< PointerType* >( type2 ) || dynamic_cast< EnumInstType* >( type2 ) ) { … … 346 347 } 347 348 348 void CommonType:: visit( OneType *oneType ) {349 void CommonType::postvisit( OneType *oneType ) { 349 350 if ( widenFirst ) { 350 351 if ( dynamic_cast< BasicType* >( type2 ) || dynamic_cast< EnumInstType* >( type2 ) ) { -
src/ResolvExpr/ConversionCost.cc
rf792cb8 r7416d46a 44 44 EqvClass eqvClass; 45 45 NamedTypeDecl *namedType; 46 PRINT( std::cerr << "type inst " << destAsTypeInst-> get_name(); )47 if ( env.lookup( destAsTypeInst-> get_name(), eqvClass ) ) {46 PRINT( std::cerr << "type inst " << destAsTypeInst->name; ) 47 if ( env.lookup( destAsTypeInst->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-> get_name()) ) ) {53 } else if ( ( namedType = indexer.lookupType( destAsTypeInst->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-> get_base()) {59 return conversionCost( src, type-> get_base(), indexer, env ) + Cost::safe;58 if ( type->base ) { 59 return conversionCost( src, type->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 TypeEnvironment & env, const SymTab::Indexer &){79 return convertToReferenceCost( src, refType, indexer, env, [](Type * t1, Type * t2, const SymTab::Indexer &, const TypeEnvironment & env ){ 80 80 return ptrsAssignable( t1, t2, env ); 81 81 }); 82 82 } else { 83 ConversionCost converter( dest, indexer, env);83 PassVisitor<ConversionCost> converter( dest, indexer, env, conversionCost ); 84 84 src->accept( converter ); 85 if ( converter. get_cost() == Cost::infinity ) {85 if ( converter.pass.get_cost() == Cost::infinity ) { 86 86 return Cost::infinity; 87 87 } else { 88 return converter. get_cost() + Cost::zero;88 return converter.pass.get_cost() + Cost::zero; 89 89 } // if 90 90 } // if … … 95 95 if ( diff > 0 ) { 96 96 // TODO: document this 97 Cost cost = convertToReferenceCost( strict_dynamic_cast< ReferenceType * >( src )-> get_base(), dest, diff-1, indexer, env, func );97 Cost cost = convertToReferenceCost( strict_dynamic_cast< ReferenceType * >( src )->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 )-> get_base(), diff+1, indexer, env, func );102 Cost cost = convertToReferenceCost( src, strict_dynamic_cast< ReferenceType * >( dest )->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-> get_base()->get_qualifiers();111 Type::Qualifiers tq2 = destAsRef-> get_base()->get_qualifiers();112 if ( tq1 <= tq2 && typesCompatibleIgnoreQualifiers( srcAsRef-> get_base(), destAsRef->get_base(), indexer, env ) ) {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 113 PRINT( std::cerr << " :: compatible and good qualifiers" << std::endl; ) 114 114 if ( tq1 == tq2 ) { … … 120 120 } 121 121 } else { // xxx - this discards reference qualifiers from consideration -- reducing qualifiers is a safe conversion; is this right? 122 int assignResult = func( srcAsRef-> get_base(), destAsRef->get_base(), env, indexer);122 int assignResult = func( srcAsRef->base, destAsRef->base, indexer, env ); 123 123 PRINT( std::cerr << "comparing references: " << assignResult << " " << srcAsRef << " " << destAsRef << std::endl; ) 124 124 if ( assignResult > 0 ) { … … 130 130 } else { 131 131 PRINT( std::cerr << "reference to rvalue conversion" << std::endl; ) 132 ConversionCost converter( dest, indexer, env);132 PassVisitor<ConversionCost> converter( dest, indexer, env, conversionCost ); 133 133 src->accept( converter ); 134 return converter. get_cost();134 return converter.pass.get_cost(); 135 135 } // if 136 136 } else { … … 138 138 assert( diff == -1 && destAsRef ); 139 139 PRINT( std::cerr << "dest is: " << dest << " / src is: " << src << std::endl; ) 140 if ( typesCompatibleIgnoreQualifiers( src, destAsRef-> get_base(), indexer, env ) ) {140 if ( typesCompatibleIgnoreQualifiers( src, destAsRef->base, indexer, env ) ) { 141 141 PRINT( std::cerr << "converting compatible base type" << std::endl; ) 142 142 if ( src->get_lvalue() ) { … … 146 146 ) 147 147 // lvalue-to-reference conversion: cv lvalue T => cv T & 148 if ( src->get_qualifiers() == destAsRef-> get_base()->get_qualifiers() ) {148 if ( src->get_qualifiers() == destAsRef->base->get_qualifiers() ) { 149 149 return Cost::reference; // cost needs to be non-zero to add cast 150 } if ( src->get_qualifiers() < destAsRef-> get_base()->get_qualifiers() ) {150 } if ( src->get_qualifiers() < destAsRef->base->get_qualifiers() ) { 151 151 return Cost::safe; // cost needs to be higher than previous cast to differentiate adding qualifiers vs. keeping same 152 152 } else { 153 153 return Cost::unsafe; 154 154 } // if 155 } else if ( destAsRef-> get_base()->get_const() ) {155 } else if ( destAsRef->base->get_const() ) { 156 156 PRINT( std::cerr << "rvalue to const ref conversion" << std::endl; ) 157 157 // rvalue-to-const-reference conversion: T => const T & … … 173 173 } 174 174 175 ConversionCost::ConversionCost( Type *dest, const SymTab::Indexer &indexer, const TypeEnvironment &env )176 : dest( dest ), indexer( indexer ), cost( Cost::infinity ), env( env ) {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 ) { 177 177 } 178 178 … … 257 257 }; 258 258 259 void ConversionCost:: visit( VoidType * ) {259 void ConversionCost::postvisit( VoidType * ) { 260 260 cost = Cost::infinity; 261 261 } 262 262 263 void ConversionCost:: visit(BasicType *basicType) {263 void ConversionCost::postvisit(BasicType *basicType) { 264 264 if ( BasicType *destAsBasic = dynamic_cast< BasicType* >( dest ) ) { 265 265 int tableResult = costMatrix[ basicType->get_kind() ][ destAsBasic->get_kind() ]; … … 278 278 } 279 279 280 void ConversionCost:: visit( PointerType * pointerType ) {280 void ConversionCost::postvisit( PointerType * pointerType ) { 281 281 if ( PointerType *destAsPtr = dynamic_cast< PointerType* >( dest ) ) { 282 282 PRINT( std::cerr << pointerType << " ===> " << destAsPtr << std::endl; ) 283 Type::Qualifiers tq1 = pointerType-> get_base()->get_qualifiers();284 Type::Qualifiers tq2 = destAsPtr-> get_base()->get_qualifiers();285 if ( tq1 <= tq2 && typesCompatibleIgnoreQualifiers( pointerType-> get_base(), destAsPtr->get_base(), indexer, env ) ) {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 286 PRINT( std::cerr << " :: compatible and good qualifiers" << std::endl; ) 287 287 if ( tq1 == tq2 ) { … … 312 312 } 313 313 314 void ConversionCost:: visit( ArrayType * ) {}315 316 void ConversionCost:: visit( ReferenceType * refType ) {314 void ConversionCost::postvisit( ArrayType * ) {} 315 316 void ConversionCost::postvisit( ReferenceType * refType ) { 317 317 // Note: dest can never be a reference, since it would have been caught in an earlier check 318 318 assert( ! dynamic_cast< ReferenceType * >( dest ) ); … … 320 320 // recursively compute conversion cost from T1 to T2. 321 321 // cv can be safely dropped because of 'implicit dereference' behavior. 322 refType->base->accept( *this);322 cost = costFunc( refType->base, dest, indexer, env ); 323 323 if ( refType->base->get_qualifiers() == dest->get_qualifiers() ) { 324 324 cost.incReference(); // prefer exact qualifiers … … 331 331 } 332 332 333 void ConversionCost:: visit( FunctionType * ) {}334 335 void ConversionCost:: visit( StructInstType * inst ) {333 void ConversionCost::postvisit( FunctionType * ) {} 334 335 void ConversionCost::postvisit( StructInstType * inst ) { 336 336 if ( StructInstType *destAsInst = dynamic_cast< StructInstType* >( dest ) ) { 337 337 if ( inst->name == destAsInst->name ) { … … 341 341 } 342 342 343 void ConversionCost:: visit( UnionInstType * inst ) {343 void ConversionCost::postvisit( UnionInstType * inst ) { 344 344 if ( UnionInstType *destAsInst = dynamic_cast< UnionInstType* >( dest ) ) { 345 345 if ( inst->name == destAsInst->name ) { … … 349 349 } 350 350 351 void ConversionCost:: visit( EnumInstType * ) {351 void ConversionCost::postvisit( EnumInstType * ) { 352 352 static Type::Qualifiers q; 353 353 static BasicType integer( q, BasicType::SignedInt ); 354 integer.accept( *this); // safe if dest >= int354 cost = costFunc( &integer, dest, indexer, env ); // safe if dest >= int 355 355 if ( cost < Cost::unsafe ) { 356 356 cost.incSafe(); … … 358 358 } 359 359 360 void ConversionCost:: visit( TraitInstType * ) {}361 362 void ConversionCost:: visit( TypeInstType *inst ) {360 void ConversionCost::postvisit( TraitInstType * ) {} 361 362 void ConversionCost::postvisit( TypeInstType *inst ) { 363 363 EqvClass eqvClass; 364 364 NamedTypeDecl *namedType; 365 if ( env.lookup( inst-> get_name(), eqvClass ) ) {366 cost = co nversionCost( eqvClass.type, dest, indexer, env );365 if ( env.lookup( inst->name, eqvClass ) ) { 366 cost = costFunc( eqvClass.type, dest, indexer, env ); 367 367 } else if ( TypeInstType *destAsInst = dynamic_cast< TypeInstType* >( dest ) ) { 368 if ( inst-> get_name() == destAsInst->get_name()) {368 if ( inst->name == destAsInst->name ) { 369 369 cost = Cost::zero; 370 370 } 371 } else if ( ( namedType = indexer.lookupType( inst-> get_name()) ) ) {371 } else if ( ( namedType = indexer.lookupType( inst->name ) ) ) { 372 372 TypeDecl *type = dynamic_cast< TypeDecl* >( namedType ); 373 373 // all typedefs should be gone by this point 374 374 assert( type ); 375 if ( type-> get_base()) {376 cost = co nversionCost( type->get_base(), dest, indexer, env ) + Cost::safe;377 } // if 378 } // if 379 } 380 381 void ConversionCost:: visit( TupleType * tupleType ) {375 if ( type->base ) { 376 cost = costFunc( type->base, dest, indexer, env ) + Cost::safe; 377 } // if 378 } // if 379 } 380 381 void ConversionCost::postvisit( TupleType * tupleType ) { 382 382 Cost c = Cost::zero; 383 383 if ( TupleType * destAsTuple = dynamic_cast< TupleType * >( dest ) ) { 384 std::list< Type * >::const_iterator srcIt = tupleType-> get_types().begin();385 std::list< Type * >::const_iterator destIt = destAsTuple-> get_types().begin();386 while ( srcIt != tupleType-> get_types().end() && destIt != destAsTuple->get_types().end() ) {387 Cost newCost = co nversionCost( *srcIt++, *destIt++, indexer, env );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 = costFunc( *srcIt++, *destIt++, indexer, env ); 388 388 if ( newCost == Cost::infinity ) { 389 389 return; … … 391 391 c += newCost; 392 392 } // while 393 if ( destIt != destAsTuple-> get_types().end() ) {393 if ( destIt != destAsTuple->types.end() ) { 394 394 cost = Cost::infinity; 395 395 } else { … … 399 399 } 400 400 401 void ConversionCost:: visit( VarArgsType * ) {401 void ConversionCost::postvisit( VarArgsType * ) { 402 402 if ( dynamic_cast< VarArgsType* >( dest ) ) { 403 403 cost = Cost::zero; … … 405 405 } 406 406 407 void ConversionCost:: visit( ZeroType * ) {407 void ConversionCost::postvisit( ZeroType * ) { 408 408 if ( dynamic_cast< ZeroType * >( dest ) ) { 409 409 cost = Cost::zero; … … 422 422 } 423 423 424 void ConversionCost:: visit( OneType * ) {424 void ConversionCost::postvisit( OneType * ) { 425 425 if ( dynamic_cast< OneType * >( dest ) ) { 426 426 cost = Cost::zero; -
src/ResolvExpr/ConversionCost.h
rf792cb8 r7416d46a 19 19 20 20 #include "Cost.h" // for Cost 21 22 #include "Common/PassVisitor.h" 21 23 #include "SynTree/Visitor.h" // for Visitor 22 24 #include "SynTree/SynTree.h" // for Visitor Nodes … … 29 31 class TypeEnvironment; 30 32 31 class ConversionCost : public Visitor { 33 typedef std::function<Cost(Type *, Type *, const SymTab::Indexer &, const TypeEnvironment &)> CostFunction; 34 struct ConversionCost : public WithShortCircuiting { 32 35 public: 33 ConversionCost( Type *dest, const SymTab::Indexer &indexer, const TypeEnvironment &env );36 ConversionCost( Type *dest, const SymTab::Indexer &indexer, const TypeEnvironment &env, CostFunction ); 34 37 35 38 Cost get_cost() const { return cost; } 36 39 37 virtual void visit(VoidType *voidType); 38 virtual void visit(BasicType *basicType); 39 virtual void visit(PointerType *pointerType); 40 virtual void visit(ArrayType *arrayType); 41 virtual void visit(ReferenceType *refType); 42 virtual void visit(FunctionType *functionType); 43 virtual void visit(StructInstType *aggregateUseType); 44 virtual void visit(UnionInstType *aggregateUseType); 45 virtual void visit(EnumInstType *aggregateUseType); 46 virtual void visit(TraitInstType *aggregateUseType); 47 virtual void visit(TypeInstType *aggregateUseType); 48 virtual void visit(TupleType *tupleType); 49 virtual void visit(VarArgsType *varArgsType); 50 virtual void visit(ZeroType *zeroType); 51 virtual void visit(OneType *oneType); 40 void previsit( BaseSyntaxNode * ) { visit_children = false; } 41 42 void postvisit( VoidType * voidType ); 43 void postvisit( BasicType * basicType ); 44 void postvisit( PointerType * pointerType ); 45 void postvisit( ArrayType * arrayType ); 46 void postvisit( ReferenceType * refType ); 47 void postvisit( FunctionType * functionType ); 48 void postvisit( StructInstType * aggregateUseType ); 49 void postvisit( UnionInstType * aggregateUseType ); 50 void postvisit( EnumInstType * aggregateUseType ); 51 void postvisit( TraitInstType * aggregateUseType ); 52 void postvisit( TypeInstType * aggregateUseType ); 53 void postvisit( TupleType * tupleType ); 54 void postvisit( VarArgsType * varArgsType ); 55 void postvisit( ZeroType * zeroType ); 56 void postvisit( OneType * oneType ); 52 57 protected: 53 58 Type *dest; … … 55 60 Cost cost; 56 61 const TypeEnvironment &env; 62 CostFunction costFunc; 57 63 }; 58 64 59 typedef std::function<int(Type *, Type *, const TypeEnvironment &, const SymTab::Indexer&)> PtrsFunction;65 typedef std::function<int(Type *, Type *, const SymTab::Indexer &, const TypeEnvironment &)> PtrsFunction; 60 66 Cost convertToReferenceCost( Type * src, ReferenceType * dest, const SymTab::Indexer & indexer, const TypeEnvironment & env, PtrsFunction func ); 61 67 } // namespace ResolvExpr -
src/ResolvExpr/CurrentObject.cc
rf792cb8 r7416d46a 62 62 virtual ~MemberIterator() {} 63 63 64 /// walks the current object using the given designators as a guide 64 65 virtual void setPosition( std::list< Expression * > & designators ) = 0; 66 67 /// retrieve the list of possible Type/Designaton pairs for the current position in the currect object 65 68 virtual std::list<InitAlternative> operator*() const = 0; 69 70 /// true if the iterator is not currently at the end 66 71 virtual operator bool() const = 0; 72 73 /// moves the iterator by one member in the current object 67 74 virtual MemberIterator & bigStep() = 0; 75 76 /// moves the iterator by one member in the current subobject 68 77 virtual MemberIterator & smallStep() = 0; 78 79 /// the type of the current object 69 80 virtual Type * getType() = 0; 81 82 /// the type of the current subobject 70 83 virtual Type * getNext() = 0; 71 84 85 /// printing for debug 72 86 virtual void print( std::ostream & out, Indenter indent ) const = 0; 73 87 88 /// helper for operator*; aggregates must add designator to each init alternative, but 89 /// adding designators in operator* creates duplicates. 74 90 virtual std::list<InitAlternative> first() const = 0; // should be protected 75 91 }; … … 354 370 } 355 371 } 356 // if ( curMember == std::next( decl->get_members().begin(), 1 ) ) { // xxx - this never triggers because curMember is incremented immediately on construction 357 if ( atbegin ) { // xxx - this never triggers because curMember is incremented immediately on construction 372 if ( atbegin ) { 358 373 // xxx - what about case of empty struct?? 359 374 // only add self if at the very beginning of the structure … … 389 404 return *this; 390 405 } 391 virtual std::list<InitAlternative> first() const { return std::list<InitAlternative>{}; }392 406 }; 393 407 … … 443 457 return new UnionIterator( uit ); 444 458 } else { 445 assertf( dynamic_cast< TypeInstType * >( type ), "some other reftotype");459 assertf( dynamic_cast< EnumInstType * >( type ) || dynamic_cast< TypeInstType * >( type ), "Encountered unhandled ReferenceToType in createMemberIterator: %s", toString( type ).c_str() ); 446 460 return new SimpleIterator( type ); 447 461 } -
src/ResolvExpr/PtrsAssignable.cc
rf792cb8 r7416d46a 14 14 // 15 15 16 #include "Common/PassVisitor.h" 16 17 #include "ResolvExpr/TypeEnvironment.h" // for EqvClass, TypeEnvironment 17 18 #include "SynTree/Type.h" // for TypeInstType, Type, BasicType … … 20 21 21 22 namespace ResolvExpr { 22 class PtrsAssignable : public Visitor { 23 public: 23 struct PtrsAssignable : public WithShortCircuiting { 24 24 PtrsAssignable( Type *dest, const TypeEnvironment &env ); 25 25 26 26 int get_result() const { return result; } 27 27 28 virtual void visit( VoidType *voidType ); 29 virtual void visit( BasicType *basicType ); 30 virtual void visit( PointerType *pointerType ); 31 virtual void visit( ArrayType *arrayType ); 32 virtual void visit( FunctionType *functionType ); 33 virtual void visit( StructInstType *inst ); 34 virtual void visit( UnionInstType *inst ); 35 virtual void visit( EnumInstType *inst ); 36 virtual void visit( TraitInstType *inst ); 37 virtual void visit( TypeInstType *inst ); 38 virtual void visit( TupleType *tupleType ); 39 virtual void visit( VarArgsType *varArgsType ); 40 virtual void visit( ZeroType *zeroType ); 41 virtual void visit( OneType *oneType ); 28 void previsit( Type * ) { visit_children = false; } 29 30 void postvisit( VoidType * voidType ); 31 void postvisit( BasicType * basicType ); 32 void postvisit( PointerType * pointerType ); 33 void postvisit( ArrayType * arrayType ); 34 void postvisit( FunctionType * functionType ); 35 void postvisit( StructInstType * inst ); 36 void postvisit( UnionInstType * inst ); 37 void postvisit( EnumInstType * inst ); 38 void postvisit( TraitInstType * inst ); 39 void postvisit( TypeInstType * inst ); 40 void postvisit( TupleType * tupleType ); 41 void postvisit( VarArgsType * varArgsType ); 42 void postvisit( ZeroType * zeroType ); 43 void postvisit( OneType * oneType ); 42 44 private: 43 45 Type *dest; … … 59 61 return -1; 60 62 } else { 61 P trsAssignableptrs( dest, env );63 PassVisitor<PtrsAssignable> ptrs( dest, env ); 62 64 src->accept( ptrs ); 63 return ptrs. get_result();65 return ptrs.pass.get_result(); 64 66 } // if 65 67 } … … 67 69 PtrsAssignable::PtrsAssignable( Type *dest, const TypeEnvironment &env ) : dest( dest ), result( 0 ), env( env ) {} 68 70 69 void PtrsAssignable:: visit( VoidType * ) {71 void PtrsAssignable::postvisit( VoidType * ) { 70 72 // T * = void * is disallowed - this is a change from C, where any 71 73 // void * can be assigned or passed to a non-void pointer without a cast. 72 74 } 73 75 74 void PtrsAssignable:: visit( __attribute__((unused)) BasicType *basicType ) {}75 void PtrsAssignable:: visit( __attribute__((unused)) PointerType *pointerType ) {}76 void PtrsAssignable:: visit( __attribute__((unused)) ArrayType *arrayType ) {}77 void PtrsAssignable:: visit( __attribute__((unused)) FunctionType *functionType ) {}76 void PtrsAssignable::postvisit( __attribute__((unused)) BasicType *basicType ) {} 77 void PtrsAssignable::postvisit( __attribute__((unused)) PointerType *pointerType ) {} 78 void PtrsAssignable::postvisit( __attribute__((unused)) ArrayType *arrayType ) {} 79 void PtrsAssignable::postvisit( __attribute__((unused)) FunctionType *functionType ) {} 78 80 79 void PtrsAssignable:: visit( __attribute__((unused)) StructInstType *inst ) {}80 void PtrsAssignable:: visit( __attribute__((unused)) UnionInstType *inst ) {}81 void PtrsAssignable::postvisit( __attribute__((unused)) StructInstType *inst ) {} 82 void PtrsAssignable::postvisit( __attribute__((unused)) UnionInstType *inst ) {} 81 83 82 void PtrsAssignable:: visit( EnumInstType * ) {84 void PtrsAssignable::postvisit( EnumInstType * ) { 83 85 if ( dynamic_cast< BasicType* >( dest ) ) { 84 86 // int * = E *, etc. is safe. This isn't technically correct, as each … … 91 93 } 92 94 93 void PtrsAssignable:: visit( __attribute__((unused)) TraitInstType *inst ) {}94 void PtrsAssignable:: visit( TypeInstType *inst ) {95 void PtrsAssignable::postvisit( __attribute__((unused)) TraitInstType *inst ) {} 96 void PtrsAssignable::postvisit( TypeInstType *inst ) { 95 97 EqvClass eqvClass; 96 98 if ( env.lookup( inst->get_name(), eqvClass ) && eqvClass.type ) { … … 100 102 } 101 103 102 void PtrsAssignable:: visit( __attribute__((unused)) TupleType *tupleType ) {}103 void PtrsAssignable:: visit( __attribute__((unused)) VarArgsType *varArgsType ) {}104 void PtrsAssignable:: visit( __attribute__((unused)) ZeroType *zeroType ) {}105 void PtrsAssignable:: visit( __attribute__((unused)) OneType *oneType ) {}104 void PtrsAssignable::postvisit( __attribute__((unused)) TupleType *tupleType ) {} 105 void PtrsAssignable::postvisit( __attribute__((unused)) VarArgsType *varArgsType ) {} 106 void PtrsAssignable::postvisit( __attribute__((unused)) ZeroType *zeroType ) {} 107 void PtrsAssignable::postvisit( __attribute__((unused)) OneType *oneType ) {} 106 108 107 109 } // namespace ResolvExpr -
src/ResolvExpr/PtrsCastable.cc
rf792cb8 r7416d46a 14 14 // 15 15 16 #include "Common/PassVisitor.h" 16 17 #include "ResolvExpr/TypeEnvironment.h" // for EqvClass, TypeEnvironment 17 18 #include "SymTab/Indexer.h" // for Indexer … … 21 22 #include "typeops.h" // for ptrsAssignable 22 23 23 24 24 namespace ResolvExpr { 25 class PtrsCastable : public Visitor{25 struct PtrsCastable : public WithShortCircuiting { 26 26 public: 27 27 PtrsCastable( Type *dest, const TypeEnvironment &env, const SymTab::Indexer &indexer ); … … 29 29 int get_result() const { return result; } 30 30 31 virtual void visit(VoidType *voidType); 32 virtual void visit(BasicType *basicType); 33 virtual void visit(PointerType *pointerType); 34 virtual void visit(ArrayType *arrayType); 35 virtual void visit(FunctionType *functionType); 36 virtual void visit(StructInstType *inst); 37 virtual void visit(UnionInstType *inst); 38 virtual void visit(EnumInstType *inst); 39 virtual void visit(TraitInstType *inst); 40 virtual void visit(TypeInstType *inst); 41 virtual void visit(TupleType *tupleType); 42 virtual void visit(VarArgsType *varArgsType); 43 virtual void visit(ZeroType *zeroType); 44 virtual void visit(OneType *oneType); 31 void previsit( Type * ) { visit_children = false; } 32 33 void postvisit( VoidType * voidType ); 34 void postvisit( BasicType * basicType ); 35 void postvisit( PointerType * pointerType ); 36 void postvisit( ArrayType * arrayType ); 37 void postvisit( FunctionType * functionType ); 38 void postvisit( StructInstType * inst ); 39 void postvisit( UnionInstType * inst ); 40 void postvisit( EnumInstType * inst ); 41 void postvisit( TraitInstType * inst ); 42 void postvisit( TypeInstType * inst ); 43 void postvisit( TupleType * tupleType ); 44 void postvisit( VarArgsType * varArgsType ); 45 void postvisit( ZeroType * zeroType ); 46 void postvisit( OneType * oneType ); 45 47 private: 46 48 Type *dest; … … 79 81 EqvClass eqvClass; 80 82 if ( env.lookup( destAsTypeInst->get_name(), eqvClass ) ) { 83 // xxx - should this be ptrsCastable? 81 84 return ptrsAssignable( src, eqvClass.type, env ); 82 85 } // if … … 85 88 return objectCast( src, env, indexer ); 86 89 } else { 87 P trsCastableptrs( dest, env, indexer );90 PassVisitor<PtrsCastable> ptrs( dest, env, indexer ); 88 91 src->accept( ptrs ); 89 return ptrs. get_result();92 return ptrs.pass.get_result(); 90 93 } // if 91 94 } … … 95 98 } 96 99 97 void PtrsCastable:: visit( VoidType * ) {100 void PtrsCastable::postvisit( VoidType * ) { 98 101 result = objectCast( dest, env, indexer ); 99 102 } 100 103 101 void PtrsCastable:: visit( BasicType * ) {104 void PtrsCastable::postvisit( BasicType * ) { 102 105 result = objectCast( dest, env, indexer ); 103 106 } 104 107 105 void PtrsCastable:: visit( PointerType * ) {108 void PtrsCastable::postvisit( PointerType * ) { 106 109 result = objectCast( dest, env, indexer ); 107 110 } 108 111 109 void PtrsCastable:: visit( ArrayType * ) {112 void PtrsCastable::postvisit( ArrayType * ) { 110 113 result = objectCast( dest, env, indexer ); 111 114 } 112 115 113 void PtrsCastable:: visit( FunctionType * ) {116 void PtrsCastable::postvisit( FunctionType * ) { 114 117 // result = -1; 115 118 result = functionCast( dest, env, indexer ); 116 119 } 117 120 118 void PtrsCastable:: visit( StructInstType * ) {121 void PtrsCastable::postvisit( StructInstType * ) { 119 122 result = objectCast( dest, env, indexer ); 120 123 } 121 124 122 void PtrsCastable:: visit( UnionInstType * ) {125 void PtrsCastable::postvisit( UnionInstType * ) { 123 126 result = objectCast( dest, env, indexer ); 124 127 } 125 128 126 void PtrsCastable:: visit( EnumInstType * ) {129 void PtrsCastable::postvisit( EnumInstType * ) { 127 130 if ( dynamic_cast< EnumInstType* >( dest ) ) { 128 131 result = 1; … … 138 141 } 139 142 140 void PtrsCastable:: visit( TraitInstType * ) {}143 void PtrsCastable::postvisit( TraitInstType * ) {} 141 144 142 void PtrsCastable:: visit(TypeInstType *inst) {145 void PtrsCastable::postvisit(TypeInstType *inst) { 143 146 //result = objectCast( inst, env, indexer ) > 0 && objectCast( dest, env, indexer ) > 0 ? 1 : -1; 144 147 result = objectCast( inst, env, indexer ) == objectCast( dest, env, indexer ) ? 1 : -1; 145 148 } 146 149 147 void PtrsCastable:: visit( TupleType * ) {150 void PtrsCastable::postvisit( TupleType * ) { 148 151 result = objectCast( dest, env, indexer ); 149 152 } 150 153 151 void PtrsCastable:: visit( VarArgsType * ) {154 void PtrsCastable::postvisit( VarArgsType * ) { 152 155 result = objectCast( dest, env, indexer ); 153 156 } 154 157 155 void PtrsCastable:: visit( ZeroType * ) {158 void PtrsCastable::postvisit( ZeroType * ) { 156 159 result = objectCast( dest, env, indexer ); 157 160 } 158 161 159 void PtrsCastable:: visit( OneType * ) {162 void PtrsCastable::postvisit( OneType * ) { 160 163 result = objectCast( dest, env, indexer ); 161 164 } -
src/ResolvExpr/RenameVars.cc
rf792cb8 r7416d46a 19 19 #include <utility> // for pair 20 20 21 #include "Common/PassVisitor.h" 21 22 #include "Common/SemanticError.h" // for SemanticError 22 23 #include "RenameVars.h" … … 27 28 28 29 namespace ResolvExpr { 29 RenameVars global_renamer; 30 namespace { 31 struct RenameVars { 32 RenameVars(); 33 void reset(); 30 34 31 RenameVars::RenameVars() : level( 0 ), resetCount( 0 ) { 32 mapStack.push_front( std::map< std::string, std::string >() ); 35 void previsit( TypeInstType * instType ); 36 void previsit( Type * ); 37 void postvisit( Type * ); 38 39 private: 40 int level, resetCount; 41 std::list< std::map< std::string, std::string > > mapStack; 42 }; 43 44 PassVisitor<RenameVars> global_renamer; 45 } // namespace 46 47 void renameTyVars( Type * t ) { 48 t->accept( global_renamer ); 33 49 } 34 50 35 void RenameVars::reset() { 36 level = 0; 37 resetCount++; 51 void resetTyVarRenaming() { 52 global_renamer.pass.reset(); 38 53 } 39 54 40 void RenameVars::visit( VoidType *voidType ){41 typeBefore( voidType );42 typeAfter( voidType);43 }55 namespace { 56 RenameVars::RenameVars() : level( 0 ), resetCount( 0 ) { 57 mapStack.push_front( std::map< std::string, std::string >() ); 58 } 44 59 45 void RenameVars::visit( BasicType *basicType) {46 typeBefore( basicType );47 typeAfter( basicType );48 }60 void RenameVars::reset() { 61 level = 0; 62 resetCount++; 63 } 49 64 50 void RenameVars::visit( PointerType *pointerType ) { 51 typeBefore( pointerType ); 52 maybeAccept( pointerType->get_base(), *this ); 53 typeAfter( pointerType ); 54 } 65 void RenameVars::previsit( TypeInstType * instType ) { 66 previsit( (Type *)instType ); 67 std::map< std::string, std::string >::const_iterator i = mapStack.front().find( instType->name ); 68 if ( i != mapStack.front().end() ) { 69 instType->name = i->second; 70 } // if 71 } 55 72 56 void RenameVars::visit( ArrayType *arrayType ) { 57 typeBefore( arrayType ); 58 maybeAccept( arrayType->get_dimension(), *this ); 59 maybeAccept( arrayType->get_base(), *this ); 60 typeAfter( arrayType ); 61 } 73 void RenameVars::previsit( Type * type ) { 74 if ( ! type->forall.empty() ) { 75 // copies current name mapping into new mapping 76 mapStack.push_front( mapStack.front() ); 77 // renames all "forall" type names to `_${level}_${name}' 78 for ( auto td : type->forall ) { 79 std::ostringstream output; 80 output << "_" << resetCount << "_" << level << "_" << td->name; 81 std::string newname( output.str() ); 82 mapStack.front()[ td->get_name() ] = newname; 83 td->name = newname; 84 // ditto for assertion names, the next level in 85 level++; 86 // acceptAll( td->assertions, *this ); 87 } // for 88 } // if 89 } 62 90 63 void RenameVars::visit( FunctionType *functionType ) { 64 typeBefore( functionType ); 65 acceptAll( functionType->get_returnVals(), *this ); 66 acceptAll( functionType->get_parameters(), *this ); 67 typeAfter( functionType ); 68 } 69 70 void RenameVars::visit( StructInstType *aggregateUseType ) { 71 typeBefore( aggregateUseType ); 72 acceptAll( aggregateUseType->get_parameters(), *this ); 73 typeAfter( aggregateUseType ); 74 } 75 76 void RenameVars::visit( UnionInstType *aggregateUseType ) { 77 typeBefore( aggregateUseType ); 78 acceptAll( aggregateUseType->get_parameters(), *this ); 79 typeAfter( aggregateUseType ); 80 } 81 82 void RenameVars::visit( EnumInstType *aggregateUseType ) { 83 typeBefore( aggregateUseType ); 84 acceptAll( aggregateUseType->get_parameters(), *this ); 85 typeAfter( aggregateUseType ); 86 } 87 88 void RenameVars::visit( TraitInstType *aggregateUseType ) { 89 typeBefore( aggregateUseType ); 90 acceptAll( aggregateUseType->get_parameters(), *this ); 91 typeAfter( aggregateUseType ); 92 } 93 94 void RenameVars::visit( TypeInstType *instType ) { 95 typeBefore( instType ); 96 std::map< std::string, std::string >::const_iterator i = mapStack.front().find( instType->get_name() ); 97 if ( i != mapStack.front().end() ) { 98 instType->set_name( i->second ); 99 } else { 100 } // if 101 acceptAll( instType->get_parameters(), *this ); 102 typeAfter( instType ); 103 } 104 105 void RenameVars::visit( TupleType *tupleType ) { 106 typeBefore( tupleType ); 107 acceptAll( tupleType->get_types(), *this ); 108 typeAfter( tupleType ); 109 } 110 111 void RenameVars::visit( VarArgsType *varArgsType ) { 112 typeBefore( varArgsType ); 113 typeAfter( varArgsType ); 114 } 115 116 void RenameVars::visit( ZeroType *zeroType ) { 117 typeBefore( zeroType ); 118 typeAfter( zeroType ); 119 } 120 121 void RenameVars::visit( OneType *oneType ) { 122 typeBefore( oneType ); 123 typeAfter( oneType ); 124 } 125 126 void RenameVars::typeBefore( Type *type ) { 127 if ( ! type->get_forall().empty() ) { 128 // copies current name mapping into new mapping 129 mapStack.push_front( mapStack.front() ); 130 // renames all "forall" type names to `_${level}_${name}' 131 for ( Type::ForallList::iterator i = type->get_forall().begin(); i != type->get_forall().end(); ++i ) { 132 std::ostringstream output; 133 output << "_" << resetCount << "_" << level << "_" << (*i)->get_name(); 134 std::string newname( output.str() ); 135 mapStack.front()[ (*i)->get_name() ] = newname; 136 (*i)->set_name( newname ); 137 // ditto for assertion names, the next level in 138 level++; 139 acceptAll( (*i)->get_assertions(), *this ); 140 } // for 141 } // if 142 } 143 144 void RenameVars::typeAfter( Type *type ) { 145 // clears name mapping added by typeBefore() 146 if ( ! type->get_forall().empty() ) { 147 mapStack.pop_front(); 148 } // if 149 } 150 91 void RenameVars::postvisit( Type * type ) { 92 // clears name mapping added by typeBefore() 93 if ( ! type->forall.empty() ) { 94 mapStack.pop_front(); 95 } // if 96 } 97 } // namespace 151 98 } // namespace ResolvExpr 152 99 -
src/ResolvExpr/RenameVars.h
rf792cb8 r7416d46a 24 24 25 25 namespace ResolvExpr { 26 /// Provides a consistent renaming of forall type names in a hierarchy by prefixing them with a unique "level" ID 27 void renameTyVars( Type * ); 26 28 27 /// Provides a consistent renaming of forall type names in a hierarchy by prefixing them with a unique "level" ID 28 class RenameVars : public Visitor { 29 public: 30 RenameVars(); 31 void reset(); 32 private: 33 virtual void visit( VoidType *basicType ); 34 virtual void visit( BasicType *basicType ); 35 virtual void visit( PointerType *pointerType ); 36 virtual void visit( ArrayType *arrayType ); 37 virtual void visit( FunctionType *functionType ); 38 virtual void visit( StructInstType *aggregateUseType ); 39 virtual void visit( UnionInstType *aggregateUseType ); 40 virtual void visit( EnumInstType *aggregateUseType ); 41 virtual void visit( TraitInstType *aggregateUseType ); 42 virtual void visit( TypeInstType *aggregateUseType ); 43 virtual void visit( TupleType *tupleType ); 44 virtual void visit( VarArgsType *varArgsType ); 45 virtual void visit( ZeroType *zeroType ); 46 virtual void visit( OneType *oneType ); 47 48 void typeBefore( Type *type ); 49 void typeAfter( Type *type ); 50 int level, resetCount; 51 std::list< std::map< std::string, std::string > > mapStack; 52 }; 53 54 extern RenameVars global_renamer; 29 /// resets internal state of renamer to avoid overflow 30 void resetTyVarRenaming(); 55 31 } // namespace ResolvExpr 56 32 -
src/ResolvExpr/Resolver.cc
rf792cb8 r7416d46a 132 132 133 133 void findVoidExpression( Expression *& untyped, const SymTab::Indexer &indexer ) { 134 global_renamer.reset();134 resetTyVarRenaming(); 135 135 TypeEnvironment env; 136 136 Expression *newExpr = resolveInVoidContext( untyped, indexer, env ); … … 155 155 } // if 156 156 #endif 157 assertf( finder.get_alternatives().size() == 1, "findSingleExpression: must have exactly one alternative at the end .");157 assertf( finder.get_alternatives().size() == 1, "findSingleExpression: must have exactly one alternative at the end: (%zd) %s", finder.get_alternatives().size(), toString( untyped ).c_str() ); 158 158 Alternative &choice = finder.get_alternatives().front(); 159 159 Expression *newExpr = choice.expr->clone(); … … 171 171 172 172 namespace { 173 /// resolve `untyped` to the expression whose type satisfies `pred` with the lowest cost; kindStr is used for providing better error messages 174 template<typename Pred> 175 void findKindExpression(Expression *& untyped, const SymTab::Indexer & indexer, const std::string & kindStr, Pred pred) { 176 TypeEnvironment env; 177 AlternativeFinder finder( indexer, env ); 178 finder.findWithAdjustment( untyped ); 179 180 AltList candidates; 181 for ( Alternative & alt : finder.get_alternatives() ) { 182 if ( pred( alt.expr->result ) ) { 183 candidates.push_back( std::move( alt ) ); 184 } 185 } 186 187 // choose the lowest cost expression among the candidates 188 AltList winners; 189 findMinCost( candidates.begin(), candidates.end(), back_inserter( winners ) ); 190 if ( winners.size() == 0 ) { 191 throw SemanticError( "No reasonable alternatives for " + kindStr + " expression: ", untyped ); 192 } else if ( winners.size() != 1 ) { 193 std::ostringstream stream; 194 stream << "Cannot choose between " << winners.size() << " alternatives for " + kindStr + " expression\n"; 195 untyped->print( stream ); 196 stream << "Alternatives are:\n"; 197 printAlts( winners, stream, 1 ); 198 throw SemanticError( stream.str() ); 199 } 200 201 // there is one unambiguous interpretation - move the expression into the with statement 202 Alternative & alt = winners.front(); 203 finishExpr( alt.expr, alt.env, untyped->env ); 204 delete untyped; 205 untyped = alt.expr; 206 alt.expr = nullptr; 207 } 208 173 209 bool isIntegralType( Type *type ) { 174 210 if ( dynamic_cast< EnumInstType * >( type ) ) { … … 184 220 185 221 void findIntegralExpression( Expression *& untyped, const SymTab::Indexer &indexer ) { 186 TypeEnvironment env; 187 AlternativeFinder finder( indexer, env ); 188 finder.find( untyped ); 189 #if 0 190 if ( finder.get_alternatives().size() != 1 ) { 191 std::cout << "untyped expr is "; 192 untyped->print( std::cout ); 193 std::cout << std::endl << "alternatives are:"; 194 for ( std::list< Alternative >::const_iterator i = finder.get_alternatives().begin(); i != finder.get_alternatives().end(); ++i ) { 195 i->print( std::cout ); 196 } // for 197 } // if 198 #endif 199 Expression *newExpr = 0; 200 const TypeEnvironment *newEnv = 0; 201 for ( AltList::const_iterator i = finder.get_alternatives().begin(); i != finder.get_alternatives().end(); ++i ) { 202 if ( i->expr->get_result()->size() == 1 && isIntegralType( i->expr->get_result() ) ) { 203 if ( newExpr ) { 204 throw SemanticError( "Too many interpretations for case control expression", untyped ); 205 } else { 206 newExpr = i->expr->clone(); 207 newEnv = &i->env; 208 } // if 209 } // if 210 } // for 211 if ( ! newExpr ) { 212 throw SemanticError( "No interpretations for case control expression", untyped ); 213 } // if 214 finishExpr( newExpr, *newEnv, untyped->env ); 215 delete untyped; 216 untyped = newExpr; 217 } 218 222 findKindExpression( untyped, indexer, "condition", isIntegralType ); 223 } 219 224 } 220 225 … … 311 316 312 317 void Resolver::previsit( IfStmt *ifStmt ) { 313 find SingleExpression( ifStmt->condition, indexer );318 findIntegralExpression( ifStmt->condition, indexer ); 314 319 } 315 320 316 321 void Resolver::previsit( WhileStmt *whileStmt ) { 317 find SingleExpression( whileStmt->condition, indexer );322 findIntegralExpression( whileStmt->condition, indexer ); 318 323 } 319 324 320 325 void Resolver::previsit( ForStmt *forStmt ) { 321 326 if ( forStmt->condition ) { 322 find SingleExpression( forStmt->condition, indexer );327 findIntegralExpression( forStmt->condition, indexer ); 323 328 } // if 324 329 … … 579 584 } 580 585 586 581 587 void Resolver::previsit( WithStmt * withStmt ) { 582 588 for ( Expression *& expr : withStmt->exprs ) { 583 TypeEnvironment env;584 AlternativeFinder finder( indexer, env );585 finder.findWithAdjustment( expr );586 587 589 // only struct- and union-typed expressions are viable candidates 588 AltList candidates; 589 for ( Alternative & alt : finder.get_alternatives() ) { 590 if ( isStructOrUnion( alt.expr->result ) ) { 591 candidates.push_back( std::move( alt ) ); 592 } 593 } 594 595 // choose the lowest cost expression among the candidates 596 AltList winners; 597 findMinCost( candidates.begin(), candidates.end(), back_inserter( winners ) ); 598 if ( winners.size() == 0 ) { 599 throw SemanticError( "No reasonable alternatives for with statement expression: ", expr ); 600 } else if ( winners.size() != 1 ) { 601 std::ostringstream stream; 602 stream << "Cannot choose between " << winners.size() << " alternatives for with statement expression\n"; 603 expr->print( stream ); 604 stream << "Alternatives are:\n"; 605 printAlts( winners, stream, 1 ); 606 throw SemanticError( stream.str() ); 607 } 608 609 // there is one unambiguous interpretation - move the expression into the with statement 610 Alternative & alt = winners.front(); 611 finishExpr( alt.expr, alt.env, expr->env ); 612 delete expr; 613 expr = alt.expr; 614 alt.expr = nullptr; 590 findKindExpression( expr, indexer, "with statement", isStructOrUnion ); 615 591 616 592 // if with expression might be impure, create a temporary so that it is evaluated once -
src/ResolvExpr/Unify.cc
rf792cb8 r7416d46a 44 44 namespace ResolvExpr { 45 45 46 class Unify : public Visitor { 47 public: 46 struct Unify : public WithShortCircuiting { 48 47 Unify( Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, WidenMode widenMode, const SymTab::Indexer &indexer ); 49 48 50 49 bool get_result() const { return result; } 50 51 void previsit( BaseSyntaxNode * ) { visit_children = false; } 52 53 void postvisit( VoidType * voidType ); 54 void postvisit( BasicType * basicType ); 55 void postvisit( PointerType * pointerType ); 56 void postvisit( ArrayType * arrayType ); 57 void postvisit( ReferenceType * refType ); 58 void postvisit( FunctionType * functionType ); 59 void postvisit( StructInstType * aggregateUseType ); 60 void postvisit( UnionInstType * aggregateUseType ); 61 void postvisit( EnumInstType * aggregateUseType ); 62 void postvisit( TraitInstType * aggregateUseType ); 63 void postvisit( TypeInstType * aggregateUseType ); 64 void postvisit( TupleType * tupleType ); 65 void postvisit( VarArgsType * varArgsType ); 66 void postvisit( ZeroType * zeroType ); 67 void postvisit( OneType * oneType ); 68 51 69 private: 52 virtual void visit(VoidType *voidType);53 virtual void visit(BasicType *basicType);54 virtual void visit(PointerType *pointerType);55 virtual void visit(ArrayType *arrayType);56 virtual void visit(ReferenceType *refType);57 virtual void visit(FunctionType *functionType);58 virtual void visit(StructInstType *aggregateUseType);59 virtual void visit(UnionInstType *aggregateUseType);60 virtual void visit(EnumInstType *aggregateUseType);61 virtual void visit(TraitInstType *aggregateUseType);62 virtual void visit(TypeInstType *aggregateUseType);63 virtual void visit(TupleType *tupleType);64 virtual void visit(VarArgsType *varArgsType);65 virtual void visit(ZeroType *zeroType);66 virtual void visit(OneType *oneType);67 68 70 template< typename RefType > void handleRefType( RefType *inst, Type *other ); 69 71 template< typename RefType > void handleGenericRefType( RefType *inst, Type *other ); … … 325 327 result = bindVar( var2, type1, entry2->second, env, needAssertions, haveAssertions, openVars, widenMode, indexer ); 326 328 } else { 327 Unifycomparator( type2, env, needAssertions, haveAssertions, openVars, widenMode, indexer );329 PassVisitor<Unify> comparator( type2, env, needAssertions, haveAssertions, openVars, widenMode, indexer ); 328 330 type1->accept( comparator ); 329 result = comparator. get_result();331 result = comparator.pass.get_result(); 330 332 } // if 331 333 #ifdef DEBUG … … 404 406 } 405 407 406 void Unify:: visit( __attribute__((unused)) VoidType *voidType) {408 void Unify::postvisit( __attribute__((unused)) VoidType *voidType) { 407 409 result = dynamic_cast< VoidType* >( type2 ); 408 410 } 409 411 410 void Unify:: visit(BasicType *basicType) {412 void Unify::postvisit(BasicType *basicType) { 411 413 if ( BasicType *otherBasic = dynamic_cast< BasicType* >( type2 ) ) { 412 414 result = basicType->get_kind() == otherBasic->get_kind(); … … 436 438 } 437 439 438 void Unify:: visit(PointerType *pointerType) {440 void Unify::postvisit(PointerType *pointerType) { 439 441 if ( PointerType *otherPointer = dynamic_cast< PointerType* >( type2 ) ) { 440 442 result = unifyExact( pointerType->get_base(), otherPointer->get_base(), env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer ); … … 444 446 } 445 447 446 void Unify:: visit(ReferenceType *refType) {448 void Unify::postvisit(ReferenceType *refType) { 447 449 if ( ReferenceType *otherRef = dynamic_cast< ReferenceType* >( type2 ) ) { 448 450 result = unifyExact( refType->get_base(), otherRef->get_base(), env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer ); … … 452 454 } 453 455 454 void Unify:: visit(ArrayType *arrayType) {456 void Unify::postvisit(ArrayType *arrayType) { 455 457 ArrayType *otherArray = dynamic_cast< ArrayType* >( type2 ); 456 458 // to unify, array types must both be VLA or both not VLA … … 567 569 } 568 570 569 void Unify:: visit(FunctionType *functionType) {571 void Unify::postvisit(FunctionType *functionType) { 570 572 FunctionType *otherFunction = dynamic_cast< FunctionType* >( type2 ); 571 573 if ( otherFunction && functionType->get_isVarArgs() == otherFunction->get_isVarArgs() ) { … … 669 671 } 670 672 671 void Unify:: visit(StructInstType *structInst) {673 void Unify::postvisit(StructInstType *structInst) { 672 674 handleGenericRefType( structInst, type2 ); 673 675 } 674 676 675 void Unify:: visit(UnionInstType *unionInst) {677 void Unify::postvisit(UnionInstType *unionInst) { 676 678 handleGenericRefType( unionInst, type2 ); 677 679 } 678 680 679 void Unify:: visit(EnumInstType *enumInst) {681 void Unify::postvisit(EnumInstType *enumInst) { 680 682 handleRefType( enumInst, type2 ); 681 683 } 682 684 683 void Unify:: visit(TraitInstType *contextInst) {685 void Unify::postvisit(TraitInstType *contextInst) { 684 686 handleRefType( contextInst, type2 ); 685 687 } 686 688 687 void Unify:: visit(TypeInstType *typeInst) {689 void Unify::postvisit(TypeInstType *typeInst) { 688 690 assert( openVars.find( typeInst->get_name() ) == openVars.end() ); 689 691 TypeInstType *otherInst = dynamic_cast< TypeInstType* >( type2 ); … … 740 742 } 741 743 742 void Unify:: visit(TupleType *tupleType) {744 void Unify::postvisit(TupleType *tupleType) { 743 745 if ( TupleType *otherTuple = dynamic_cast< TupleType* >( type2 ) ) { 744 746 std::unique_ptr<TupleType> flat1( tupleType->clone() ); … … 757 759 } 758 760 759 void Unify:: visit( __attribute__((unused)) VarArgsType *varArgsType ) {761 void Unify::postvisit( __attribute__((unused)) VarArgsType *varArgsType ) { 760 762 result = dynamic_cast< VarArgsType* >( type2 ); 761 763 } 762 764 763 void Unify:: visit( __attribute__((unused)) ZeroType *zeroType ) {765 void Unify::postvisit( __attribute__((unused)) ZeroType *zeroType ) { 764 766 result = dynamic_cast< ZeroType* >( type2 ); 765 767 } 766 768 767 void Unify:: visit( __attribute__((unused)) OneType *oneType ) {769 void Unify::postvisit( __attribute__((unused)) OneType *oneType ) { 768 770 result = dynamic_cast< OneType* >( type2 ); 769 771 }
Note:
See TracChangeset
for help on using the changeset viewer.