Changes in src/SymTab/Validate.cc [44547b0:5408b59]
- File:
-
- 1 edited
-
src/SymTab/Validate.cc (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/SymTab/Validate.cc
r44547b0 r5408b59 47 47 #include <utility> // for pair 48 48 49 #include "AST/Chain.hpp" 50 #include "AST/Decl.hpp" 51 #include "AST/Node.hpp" 52 #include "AST/Pass.hpp" 53 #include "AST/SymbolTable.hpp" 54 #include "AST/Type.hpp" 55 #include "AST/TypeSubstitution.hpp" 49 56 #include "CodeGen/CodeGenerator.h" // for genName 50 57 #include "CodeGen/OperatorTable.h" // for isCtorDtor, isCtorDtorAssign … … 1319 1326 } 1320 1327 1328 namespace { 1329 /// Replaces enum types by int, and function/array types in function parameter and return 1330 /// lists by appropriate pointers 1331 /* 1332 struct EnumAndPointerDecay_new { 1333 const ast::EnumDecl * previsit( const ast::EnumDecl * enumDecl ) { 1334 // set the type of each member of the enumeration to be EnumConstant 1335 for ( unsigned i = 0; i < enumDecl->members.size(); ++i ) { 1336 // build new version of object with EnumConstant 1337 ast::ptr< ast::ObjectDecl > obj = 1338 enumDecl->members[i].strict_as< ast::ObjectDecl >(); 1339 obj.get_and_mutate()->type = 1340 new ast::EnumInstType{ enumDecl->name, ast::CV::Const }; 1341 1342 // set into decl 1343 ast::EnumDecl * mut = mutate( enumDecl ); 1344 mut->members[i] = obj.get(); 1345 enumDecl = mut; 1346 } 1347 return enumDecl; 1348 } 1349 1350 static const ast::FunctionType * fixFunctionList( 1351 const ast::FunctionType * func, 1352 std::vector< ast::ptr< ast::DeclWithType > > ast::FunctionType::* field, 1353 ast::ArgumentFlag isVarArgs = ast::FixedArgs 1354 ) { 1355 const auto & dwts = func->* field; 1356 unsigned nvals = dwts.size(); 1357 bool hasVoid = false; 1358 for ( unsigned i = 0; i < nvals; ++i ) { 1359 func = ast::mutate_field_index( func, field, i, fixFunction( dwts[i], hasVoid ) ); 1360 } 1361 1362 // the only case in which "void" is valid is where it is the only one in the list 1363 if ( hasVoid && ( nvals > 1 || isVarArgs ) ) { 1364 SemanticError( 1365 dwts.front()->location, func, "invalid type void in function type" ); 1366 } 1367 1368 // one void is the only thing in the list, remove it 1369 if ( hasVoid ) { 1370 func = ast::mutate_field( 1371 func, field, std::vector< ast::ptr< ast::DeclWithType > >{} ); 1372 } 1373 1374 return func; 1375 } 1376 1377 const ast::FunctionType * previsit( const ast::FunctionType * func ) { 1378 func = fixFunctionList( func, &ast::FunctionType::params, func->isVarArgs ); 1379 return fixFunctionList( func, &ast::FunctionType::returns ); 1380 } 1381 }; 1382 1383 /// expand assertions from a trait instance, performing appropriate type variable substitutions 1384 void expandAssertions( 1385 const ast::TraitInstType * inst, std::vector< ast::ptr< ast::DeclWithType > > & out 1386 ) { 1387 assertf( inst->base, "Trait instance not linked to base trait: %s", toCString( inst ) ); 1388 1389 // build list of trait members, substituting trait decl parameters for instance parameters 1390 ast::TypeSubstitution sub{ 1391 inst->base->params.begin(), inst->base->params.end(), inst->params.begin() }; 1392 // deliberately take ast::ptr by-value to ensure this does not mutate inst->base 1393 for ( ast::ptr< ast::Decl > decl : inst->base->members ) { 1394 auto member = decl.strict_as< ast::DeclWithType >(); 1395 sub.apply( member ); 1396 out.emplace_back( member ); 1397 } 1398 } 1399 1400 /// Associates forward declarations of aggregates with their definitions 1401 class LinkReferenceToTypes_new final 1402 : public ast::WithSymbolTable, public ast::WithGuards, public 1403 ast::WithVisitorRef<LinkReferenceToTypes_new>, public ast::WithShortCircuiting { 1404 1405 // these maps of uses of forward declarations of types need to have the actual type 1406 // declaration switched in * after * they have been traversed. To enable this in the 1407 // ast::Pass framework, any node that needs to be so mutated has mutate() called on it 1408 // before it is placed in the map, properly updating its parents in the usual traversal, 1409 // then can have the actual mutation applied later 1410 using ForwardEnumsType = std::unordered_multimap< std::string, ast::EnumInstType * >; 1411 using ForwardStructsType = std::unordered_multimap< std::string, ast::StructInstType * >; 1412 using ForwardUnionsType = std::unordered_multimap< std::string, ast::UnionInstType * >; 1413 1414 const CodeLocation & location; 1415 const ast::SymbolTable * localSymtab; 1416 1417 ForwardEnumsType forwardEnums; 1418 ForwardStructsType forwardStructs; 1419 ForwardUnionsType forwardUnions; 1420 1421 /// true if currently in a generic type body, so that type parameter instances can be 1422 /// renamed appropriately 1423 bool inGeneric = false; 1424 1425 public: 1426 /// contstruct using running symbol table 1427 LinkReferenceToTypes_new( const CodeLocation & loc ) 1428 : location( loc ), localSymtab( &symtab ) {} 1429 1430 /// construct using provided symbol table 1431 LinkReferenceToTypes_new( const CodeLocation & loc, const ast::SymbolTable & syms ) 1432 : location( loc ), localSymtab( &syms ) {} 1433 1434 const ast::Type * postvisit( const ast::TypeInstType * typeInst ) { 1435 // ensure generic parameter instances are renamed like the base type 1436 if ( inGeneric && typeInst->base ) { 1437 typeInst = ast::mutate_field( 1438 typeInst, &ast::TypeInstType::name, typeInst->base->name ); 1439 } 1440 1441 if ( 1442 auto typeDecl = dynamic_cast< const ast::TypeDecl * >( 1443 localSymtab->lookupType( typeInst->name ) ) 1444 ) { 1445 typeInst = ast::mutate_field( typeInst, &ast::TypeInstType::kind, typeDecl->kind ); 1446 } 1447 1448 return typeInst; 1449 } 1450 1451 const ast::Type * postvisit( const ast::EnumInstType * inst ) { 1452 const ast::EnumDecl * decl = localSymtab->lookupEnum( inst->name ); 1453 // not a semantic error if the enum is not found, just an implicit forward declaration 1454 if ( decl ) { 1455 inst = ast::mutate_field( inst, &ast::EnumInstType::base, decl ); 1456 } 1457 if ( ! decl || ! decl->body ) { 1458 // forward declaration 1459 auto mut = mutate( inst ); 1460 forwardEnums.emplace( inst->name, mut ); 1461 inst = mut; 1462 } 1463 return inst; 1464 } 1465 1466 void checkGenericParameters( const ast::BaseInstType * inst ) { 1467 for ( const ast::Expr * param : inst->params ) { 1468 if ( ! dynamic_cast< const ast::TypeExpr * >( param ) ) { 1469 SemanticError( 1470 location, inst, "Expression parameters for generic types are currently " 1471 "unsupported: " ); 1472 } 1473 } 1474 } 1475 1476 const ast::StructInstType * postvisit( const ast::StructInstType * inst ) { 1477 const ast::StructDecl * decl = localSymtab->lookupStruct( inst->name ); 1478 // not a semantic error if the struct is not found, just an implicit forward declaration 1479 if ( decl ) { 1480 inst = ast::mutate_field( inst, &ast::StructInstType::base, decl ); 1481 } 1482 if ( ! decl || ! decl->body ) { 1483 // forward declaration 1484 auto mut = mutate( inst ); 1485 forwardStructs.emplace( inst->name, mut ); 1486 inst = mut; 1487 } 1488 checkGenericParameters( inst ); 1489 return inst; 1490 } 1491 1492 const ast::UnionInstType * postvisit( const ast::UnionInstType * inst ) { 1493 const ast::UnionDecl * decl = localSymtab->lookupUnion( inst->name ); 1494 // not a semantic error if the struct is not found, just an implicit forward declaration 1495 if ( decl ) { 1496 inst = ast::mutate_field( inst, &ast::UnionInstType::base, decl ); 1497 } 1498 if ( ! decl || ! decl->body ) { 1499 // forward declaration 1500 auto mut = mutate( inst ); 1501 forwardUnions.emplace( inst->name, mut ); 1502 inst = mut; 1503 } 1504 checkGenericParameters( inst ); 1505 return inst; 1506 } 1507 1508 const ast::Type * postvisit( const ast::TraitInstType * traitInst ) { 1509 // handle other traits 1510 const ast::TraitDecl * traitDecl = localSymtab->lookupTrait( traitInst->name ); 1511 if ( ! traitDecl ) { 1512 SemanticError( location, "use of undeclared trait " + traitInst->name ); 1513 } 1514 if ( traitDecl->params.size() != traitInst->params.size() ) { 1515 SemanticError( location, traitInst, "incorrect number of trait parameters: " ); 1516 } 1517 traitInst = ast::mutate_field( traitInst, &ast::TraitInstType::base, traitDecl ); 1518 1519 // need to carry over the "sized" status of each decl in the instance 1520 for ( unsigned i = 0; i < traitDecl->params.size(); ++i ) { 1521 auto expr = traitInst->params[i].as< ast::TypeExpr >(); 1522 if ( ! expr ) { 1523 SemanticError( 1524 traitInst->params[i].get(), "Expression parameters for trait instances " 1525 "are currently unsupported: " ); 1526 } 1527 1528 if ( auto inst = expr->type.as< ast::TypeInstType >() ) { 1529 if ( traitDecl->params[i]->sized && ! inst->base->sized ) { 1530 // traitInst = ast::mutate_field_index( 1531 // traitInst, &ast::TraitInstType::params, i, 1532 // ... 1533 // ); 1534 ast::TraitInstType * mut = ast::mutate( traitInst ); 1535 ast::chain_mutate( mut->params[i] ) 1536 ( &ast::TypeExpr::type ) 1537 ( &ast::TypeInstType::base )->sized = true; 1538 traitInst = mut; 1539 } 1540 } 1541 } 1542 1543 return traitInst; 1544 } 1545 1546 void previsit( const ast::QualifiedType * ) { visit_children = false; } 1547 1548 const ast::Type * postvisit( const ast::QualifiedType * qualType ) { 1549 // linking only makes sense for the "oldest ancestor" of the qualified type 1550 return ast::mutate_field( 1551 qualType, &ast::QualifiedType::parent, qualType->parent->accept( * visitor ) ); 1552 } 1553 1554 const ast::Decl * postvisit( const ast::EnumDecl * enumDecl ) { 1555 // visit enum members first so that the types of self-referencing members are updated 1556 // properly 1557 if ( ! enumDecl->body ) return enumDecl; 1558 1559 // update forward declarations to point here 1560 auto fwds = forwardEnums.equal_range( enumDecl->name ); 1561 if ( fwds.first != fwds.second ) { 1562 auto inst = fwds.first; 1563 do { 1564 // forward decl is stored * mutably * in map, can thus be updated 1565 inst->second->base = enumDecl; 1566 } while ( ++inst != fwds.second ); 1567 forwardEnums.erase( fwds.first, fwds.second ); 1568 } 1569 1570 // ensure that enumerator initializers are properly set 1571 for ( unsigned i = 0; i < enumDecl->members.size(); ++i ) { 1572 auto field = enumDecl->members[i].strict_as< ast::ObjectDecl >(); 1573 if ( field->init ) { 1574 // need to resolve enumerator initializers early so that other passes that 1575 // determine if an expression is constexpr have appropriate information 1576 auto init = field->init.strict_as< ast::SingleInit >(); 1577 1578 enumDecl = ast::mutate_field_index( 1579 enumDecl, &ast::EnumDecl::members, i, 1580 ast::mutate_field( field, &ast::ObjectDecl::init, 1581 ast::mutate_field( init, &ast::SingleInit::value, 1582 ResolvExpr::findSingleExpression( 1583 init->value, new ast::BasicType{ ast::BasicType::SignedInt }, 1584 symtab ) ) ) ); 1585 } 1586 } 1587 1588 return enumDecl; 1589 } 1590 1591 /// rename generic type parameters uniquely so that they do not conflict with user defined 1592 /// function forall parameters, e.g. the T in Box and the T in f, below 1593 /// forall(otype T) 1594 /// struct Box { 1595 /// T x; 1596 /// }; 1597 /// forall(otype T) 1598 /// void f(Box(T) b) { 1599 /// ... 1600 /// } 1601 template< typename AggrDecl > 1602 const AggrDecl * renameGenericParams( const AggrDecl * aggr ) { 1603 GuardValue( inGeneric ); 1604 inGeneric = ! aggr->params.empty(); 1605 1606 for ( unsigned i = 0; i < aggr->params.size(); ++i ) { 1607 const ast::TypeDecl * td = aggr->params[i]; 1608 1609 aggr = ast::mutate_field_index( 1610 aggr, &AggrDecl::params, i, 1611 ast::mutate_field( td, &ast::TypeDecl::name, "__" + td->name + "_generic_" ) ); 1612 } 1613 return aggr; 1614 } 1615 1616 const ast::StructDecl * previsit( const ast::StructDecl * structDecl ) { 1617 return renameGenericParams( structDecl ); 1618 } 1619 1620 void postvisit( const ast::StructDecl * structDecl ) { 1621 // visit struct members first so that the types of self-referencing members are 1622 // updated properly 1623 if ( ! structDecl->body ) return; 1624 1625 // update forward declarations to point here 1626 auto fwds = forwardStructs.equal_range( structDecl->name ); 1627 if ( fwds.first != fwds.second ) { 1628 auto inst = fwds.first; 1629 do { 1630 // forward decl is stored * mutably * in map, can thus be updated 1631 inst->second->base = structDecl; 1632 } while ( ++inst != fwds.second ); 1633 forwardStructs.erase( fwds.first, fwds.second ); 1634 } 1635 } 1636 1637 const ast::UnionDecl * previsit( const ast::UnionDecl * unionDecl ) { 1638 return renameGenericParams( unionDecl ); 1639 } 1640 1641 void postvisit( const ast::UnionDecl * unionDecl ) { 1642 // visit union members first so that the types of self-referencing members are updated 1643 // properly 1644 if ( ! unionDecl->body ) return; 1645 1646 // update forward declarations to point here 1647 auto fwds = forwardUnions.equal_range( unionDecl->name ); 1648 if ( fwds.first != fwds.second ) { 1649 auto inst = fwds.first; 1650 do { 1651 // forward decl is stored * mutably * in map, can thus be updated 1652 inst->second->base = unionDecl; 1653 } while ( ++inst != fwds.second ); 1654 forwardUnions.erase( fwds.first, fwds.second ); 1655 } 1656 } 1657 1658 const ast::Decl * postvisit( const ast::TraitDecl * traitDecl ) { 1659 // set the "sized" status for the special "sized" trait 1660 if ( traitDecl->name == "sized" ) { 1661 assertf( traitDecl->params.size() == 1, "Built-in trait 'sized' has incorrect " 1662 "number of parameters: %zd", traitDecl->params.size() ); 1663 1664 traitDecl = ast::mutate_field_index( 1665 traitDecl, &ast::TraitDecl::params, 0, 1666 ast::mutate_field( 1667 traitDecl->params.front().get(), &ast::TypeDecl::sized, true ) ); 1668 } 1669 1670 // move assertions from type parameters into the body of the trait 1671 std::vector< ast::ptr< ast::DeclWithType > > added; 1672 for ( const ast::TypeDecl * td : traitDecl->params ) { 1673 for ( const ast::DeclWithType * assn : td->assertions ) { 1674 auto inst = dynamic_cast< const ast::TraitInstType * >( assn->get_type() ); 1675 if ( inst ) { 1676 expandAssertions( inst, added ); 1677 } else { 1678 added.emplace_back( assn ); 1679 } 1680 } 1681 } 1682 if ( ! added.empty() ) { 1683 auto mut = mutate( traitDecl ); 1684 for ( const ast::DeclWithType * decl : added ) { 1685 mut->members.emplace_back( decl ); 1686 } 1687 traitDecl = mut; 1688 } 1689 1690 return traitDecl; 1691 } 1692 }; 1693 1694 /// Replaces array and function types in forall lists by appropriate pointer type and assigns 1695 /// each object and function declaration a unique ID 1696 class ForallPointerDecay_new { 1697 const CodeLocation & location; 1698 public: 1699 ForallPointerDecay_new( const CodeLocation & loc ) : location( loc ) {} 1700 1701 const ast::ObjectDecl * previsit( const ast::ObjectDecl * obj ) { 1702 // ensure that operator names only apply to functions or function pointers 1703 if ( 1704 CodeGen::isOperator( obj->name ) 1705 && ! dynamic_cast< const ast::FunctionType * >( obj->type->stripDeclarator() ) 1706 ) { 1707 SemanticError( obj->location, toCString( "operator ", obj->name.c_str(), " is not " 1708 "a function or function pointer." ) ); 1709 } 1710 1711 // ensure object has unique ID 1712 if ( obj->uniqueId ) return obj; 1713 auto mut = mutate( obj ); 1714 mut->fixUniqueId(); 1715 return mut; 1716 } 1717 1718 const ast::FunctionDecl * previsit( const ast::FunctionDecl * func ) { 1719 // ensure function has unique ID 1720 if ( func->uniqueId ) return func; 1721 auto mut = mutate( func ); 1722 mut->fixUniqueId(); 1723 return mut; 1724 } 1725 1726 /// Fix up assertions -- flattens assertion lists, removing all trait instances 1727 template< typename node_t, typename parent_t > 1728 static const node_t * forallFixer( 1729 const CodeLocation & loc, const node_t * node, 1730 ast::FunctionType::ForallList parent_t::* forallField 1731 ) { 1732 for ( unsigned i = 0; i < (node->* forallField).size(); ++i ) { 1733 const ast::TypeDecl * type = (node->* forallField)[i]; 1734 if ( type->assertions.empty() ) continue; 1735 1736 std::vector< ast::ptr< ast::DeclWithType > > asserts; 1737 asserts.reserve( type->assertions.size() ); 1738 1739 // expand trait instances into their members 1740 for ( const ast::DeclWithType * assn : type->assertions ) { 1741 auto traitInst = 1742 dynamic_cast< const ast::TraitInstType * >( assn->get_type() ); 1743 if ( traitInst ) { 1744 // expand trait instance to all its members 1745 expandAssertions( traitInst, asserts ); 1746 } else { 1747 // pass other assertions through 1748 asserts.emplace_back( assn ); 1749 } 1750 } 1751 1752 // apply FixFunction to every assertion to check for invalid void type 1753 for ( ast::ptr< ast::DeclWithType > & assn : asserts ) { 1754 bool isVoid = false; 1755 assn = fixFunction( assn, isVoid ); 1756 if ( isVoid ) { 1757 SemanticError( loc, node, "invalid type void in assertion of function " ); 1758 } 1759 } 1760 1761 // place mutated assertion list in node 1762 auto mut = mutate( type ); 1763 mut->assertions = move( asserts ); 1764 node = ast::mutate_field_index( node, forallField, i, mut ); 1765 } 1766 return node; 1767 } 1768 1769 const ast::FunctionType * previsit( const ast::FunctionType * ftype ) { 1770 return forallFixer( location, ftype, &ast::FunctionType::forall ); 1771 } 1772 1773 const ast::StructDecl * previsit( const ast::StructDecl * aggrDecl ) { 1774 return forallFixer( aggrDecl->location, aggrDecl, &ast::StructDecl::params ); 1775 } 1776 1777 const ast::UnionDecl * previsit( const ast::UnionDecl * aggrDecl ) { 1778 return forallFixer( aggrDecl->location, aggrDecl, &ast::UnionDecl::params ); 1779 } 1780 }; 1781 */ 1782 } // anonymous namespace 1783 1784 /* 1785 const ast::Type * validateType( 1786 const CodeLocation & loc, const ast::Type * type, const ast::SymbolTable & symtab ) { 1787 // ast::Pass< EnumAndPointerDecay_new > epc; 1788 ast::Pass< LinkReferenceToTypes_new > lrt{ loc, symtab }; 1789 ast::Pass< ForallPointerDecay_new > fpd{ loc }; 1790 1791 return type->accept( lrt )->accept( fpd ); 1792 } 1793 */ 1794 1321 1795 } // namespace SymTab 1322 1796
Note:
See TracChangeset
for help on using the changeset viewer.