Changeset 67d2b97 for src/SymTab
- Timestamp:
- Jun 24, 2019, 2:24:57 PM (6 years ago)
- Branches:
- ADT, arm-eh, ast-experimental, enum, forall-pointer-decay, jacob/cs343-translation, jenkins-sandbox, master, new-ast, new-ast-unique-expr, pthread-emulation, qualifiedEnum
- Children:
- 093a5d7, da7454c
- Parents:
- 70a141d4 (diff), 08c0780 (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/SymTab
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
src/SymTab/Validate.cc
r70a141d4 r67d2b97 44 44 #include <list> // for list 45 45 #include <string> // for string 46 #include <unordered_map> // for unordered_map 46 47 #include <utility> // for pair 47 48 49 #include "AST/Chain.hpp" 48 50 #include "AST/Decl.hpp" 49 51 #include "AST/Node.hpp" … … 51 53 #include "AST/SymbolTable.hpp" 52 54 #include "AST/Type.hpp" 55 #include "AST/TypeSubstitution.hpp" 53 56 #include "CodeGen/CodeGenerator.h" // for genName 54 57 #include "CodeGen/OperatorTable.h" // for isCtorDtor, isCtorDtorAssign 55 58 #include "ControlStruct/Mutate.h" // for ForExprMutator 59 #include "Common/CodeLocation.h" // for CodeLocation 56 60 #include "Common/Stats.h" // for Stats::Heap 57 61 #include "Common/PassVisitor.h" // for PassVisitor, WithDeclsToAdd … … 1427 1431 }; 1428 1432 1433 /// expand assertions from a trait instance, performing appropriate type variable substitutions 1434 void expandAssertions( 1435 const ast::TraitInstType * inst, std::vector< ast::ptr< ast::DeclWithType > > & out 1436 ) { 1437 assertf( inst->base, "Trait instance not linked to base trait: %s", toCString( inst ) ); 1438 1439 // build list of trait members, substituting trait decl parameters for instance parameters 1440 ast::TypeSubstitution sub{ 1441 inst->base->params.begin(), inst->base->params.end(), inst->params.begin() }; 1442 // deliberately take ast::ptr by-value to ensure this does not mutate inst->base 1443 for ( ast::ptr< ast::Decl > decl : inst->base->members ) { 1444 auto member = decl.strict_as< ast::DeclWithType >(); 1445 sub.apply( member ); 1446 out.emplace_back( member ); 1447 } 1448 } 1449 1429 1450 /// Associates forward declarations of aggregates with their definitions 1430 structLinkReferenceToTypes_new final1451 class LinkReferenceToTypes_new final 1431 1452 : public ast::WithSymbolTable, public ast::WithGuards, public 1432 1453 ast::WithVisitorRef<LinkReferenceToTypes_new>, public ast::WithShortCircuiting { 1433 1454 1434 const ast::SymbolTable * localSyms; 1435 1436 LinkReferenceToTypes_new( const ast::SymbolTable & syms ) : localSyms( &syms ) {} 1437 1438 #warning incomplete 1455 // these maps of uses of forward declarations of types need to have the actual type 1456 // declaration switched in *after* they have been traversed. To enable this in the 1457 // ast::Pass framework, any node that needs to be so mutated has mutate() called on it 1458 // before it is placed in the map, properly updating its parents in the usual traversal, 1459 // then can have the actual mutation applied later 1460 using ForwardEnumsType = std::unordered_multimap< std::string, ast::EnumInstType * >; 1461 using ForwardStructsType = std::unordered_multimap< std::string, ast::StructInstType * >; 1462 using ForwardUnionsType = std::unordered_multimap< std::string, ast::UnionInstType * >; 1463 1464 const CodeLocation & location; 1465 const ast::SymbolTable * localSymtab; 1466 1467 ForwardEnumsType forwardEnums; 1468 ForwardStructsType forwardStructs; 1469 ForwardUnionsType forwardUnions; 1470 1471 /// true if currently in a generic type body, so that type parameter instances can be 1472 /// renamed appropriately 1473 bool inGeneric = false; 1474 1475 public: 1476 /// contstruct using running symbol table 1477 LinkReferenceToTypes_new( const CodeLocation & loc ) 1478 : location( loc ), localSymtab( &symtab ) {} 1479 1480 /// construct using provided symbol table 1481 LinkReferenceToTypes_new( const CodeLocation & loc, const ast::SymbolTable & syms ) 1482 : location( loc ), localSymtab( &syms ) {} 1483 1484 const ast::Type * postvisit( const ast::TypeInstType * typeInst ) { 1485 // ensure generic parameter instances are renamed like the base type 1486 if ( inGeneric && typeInst->base ) { 1487 typeInst = ast::mutate_field( 1488 typeInst, &ast::TypeInstType::name, typeInst->base->name ); 1489 } 1490 1491 if ( 1492 auto typeDecl = dynamic_cast< const ast::TypeDecl * >( 1493 localSymtab->lookupType( typeInst->name ) ) 1494 ) { 1495 typeInst = ast::mutate_field( typeInst, &ast::TypeInstType::kind, typeDecl->kind ); 1496 } 1497 1498 return typeInst; 1499 } 1500 1501 const ast::Type * postvisit( const ast::EnumInstType * inst ) { 1502 const ast::EnumDecl * decl = localSymtab->lookupEnum( inst->name ); 1503 // not a semantic error if the enum is not found, just an implicit forward declaration 1504 if ( decl ) { 1505 inst = ast::mutate_field( inst, &ast::EnumInstType::base, decl ); 1506 } 1507 if ( ! decl || ! decl->body ) { 1508 // forward declaration 1509 auto mut = mutate( inst ); 1510 forwardEnums.emplace( inst->name, mut ); 1511 inst = mut; 1512 } 1513 return inst; 1514 } 1515 1516 void checkGenericParameters( const ast::ReferenceToType * inst ) { 1517 for ( const ast::Expr * param : inst->params ) { 1518 if ( ! dynamic_cast< const ast::TypeExpr * >( param ) ) { 1519 SemanticError( 1520 location, inst, "Expression parameters for generic types are currently " 1521 "unsupported: " ); 1522 } 1523 } 1524 } 1525 1526 const ast::StructInstType * postvisit( const ast::StructInstType * inst ) { 1527 const ast::StructDecl * decl = localSymtab->lookupStruct( inst->name ); 1528 // not a semantic error if the struct is not found, just an implicit forward declaration 1529 if ( decl ) { 1530 inst = ast::mutate_field( inst, &ast::StructInstType::base, decl ); 1531 } 1532 if ( ! decl || ! decl->body ) { 1533 // forward declaration 1534 auto mut = mutate( inst ); 1535 forwardStructs.emplace( inst->name, mut ); 1536 inst = mut; 1537 } 1538 checkGenericParameters( inst ); 1539 return inst; 1540 } 1541 1542 const ast::UnionInstType * postvisit( const ast::UnionInstType * inst ) { 1543 const ast::UnionDecl * decl = localSymtab->lookupUnion( inst->name ); 1544 // not a semantic error if the struct is not found, just an implicit forward declaration 1545 if ( decl ) { 1546 inst = ast::mutate_field( inst, &ast::UnionInstType::base, decl ); 1547 } 1548 if ( ! decl || ! decl->body ) { 1549 // forward declaration 1550 auto mut = mutate( inst ); 1551 forwardUnions.emplace( inst->name, mut ); 1552 inst = mut; 1553 } 1554 checkGenericParameters( inst ); 1555 return inst; 1556 } 1557 1558 const ast::Type * postvisit( const ast::TraitInstType * traitInst ) { 1559 // handle other traits 1560 const ast::TraitDecl * traitDecl = localSymtab->lookupTrait( traitInst->name ); 1561 if ( ! traitDecl ) { 1562 SemanticError( location, "use of undeclared trait " + traitInst->name ); 1563 } 1564 if ( traitDecl->params.size() != traitInst->params.size() ) { 1565 SemanticError( location, traitInst, "incorrect number of trait parameters: " ); 1566 } 1567 traitInst = ast::mutate_field( traitInst, &ast::TraitInstType::base, traitDecl ); 1568 1569 // need to carry over the "sized" status of each decl in the instance 1570 for ( unsigned i = 0; i < traitDecl->params.size(); ++i ) { 1571 auto expr = traitInst->params[i].as< ast::TypeExpr >(); 1572 if ( ! expr ) { 1573 SemanticError( 1574 traitInst->params[i].get(), "Expression parameters for trait instances " 1575 "are currently unsupported: " ); 1576 } 1577 1578 if ( auto inst = expr->type.as< ast::TypeInstType >() ) { 1579 if ( traitDecl->params[i]->sized && ! inst->base->sized ) { 1580 // traitInst = ast::mutate_field_index( 1581 // traitInst, &ast::TraitInstType::params, i, 1582 // ... 1583 // ); 1584 ast::TraitInstType * mut = ast::mutate( traitInst ); 1585 ast::chain_mutate( mut->params[i] ) 1586 ( &ast::TypeExpr::type ) 1587 ( &ast::TypeInstType::base )->sized = true; 1588 traitInst = mut; 1589 } 1590 } 1591 } 1592 1593 return traitInst; 1594 } 1595 1596 void previsit( const ast::QualifiedType * ) { visit_children = false; } 1597 1598 const ast::Type * postvisit( const ast::QualifiedType * qualType ) { 1599 // linking only makes sense for the "oldest ancestor" of the qualified type 1600 return ast::mutate_field( 1601 qualType, &ast::QualifiedType::parent, qualType->parent->accept( *visitor ) ); 1602 } 1603 1604 const ast::Decl * postvisit( const ast::EnumDecl * enumDecl ) { 1605 // visit enum members first so that the types of self-referencing members are updated 1606 // properly 1607 if ( ! enumDecl->body ) return enumDecl; 1608 1609 // update forward declarations to point here 1610 auto fwds = forwardEnums.equal_range( enumDecl->name ); 1611 if ( fwds.first != fwds.second ) { 1612 auto inst = fwds.first; 1613 do { 1614 // forward decl is stored *mutably* in map, can thus be updated 1615 inst->second->base = enumDecl; 1616 } while ( ++inst != fwds.second ); 1617 forwardEnums.erase( fwds.first, fwds.second ); 1618 } 1619 1620 // ensure that enumerator initializers are properly set 1621 for ( unsigned i = 0; i < enumDecl->members.size(); ++i ) { 1622 auto field = enumDecl->members[i].strict_as< ast::ObjectDecl >(); 1623 if ( field->init ) { 1624 // need to resolve enumerator initializers early so that other passes that 1625 // determine if an expression is constexpr have appropriate information 1626 auto init = field->init.strict_as< ast::SingleInit >(); 1627 1628 enumDecl = ast::mutate_field_index( 1629 enumDecl, &ast::EnumDecl::members, i, 1630 ast::mutate_field( field, &ast::ObjectDecl::init, 1631 ast::mutate_field( init, &ast::SingleInit::value, 1632 ResolvExpr::findSingleExpression( 1633 init->value, new ast::BasicType{ ast::BasicType::SignedInt }, 1634 symtab ) ) ) ); 1635 } 1636 } 1637 1638 return enumDecl; 1639 } 1640 1641 /// rename generic type parameters uniquely so that they do not conflict with user defined 1642 /// function forall parameters, e.g. the T in Box and the T in f, below 1643 /// forall(otype T) 1644 /// struct Box { 1645 /// T x; 1646 /// }; 1647 /// forall(otype T) 1648 /// void f(Box(T) b) { 1649 /// ... 1650 /// } 1651 template< typename AggrDecl > 1652 const AggrDecl * renameGenericParams( const AggrDecl * aggr ) { 1653 GuardValue( inGeneric ); 1654 inGeneric = ! aggr->params.empty(); 1655 1656 for ( unsigned i = 0; i < aggr->params.size(); ++i ) { 1657 const ast::TypeDecl * td = aggr->params[i]; 1658 1659 aggr = ast::mutate_field_index( 1660 aggr, &AggrDecl::params, i, 1661 ast::mutate_field( td, &ast::TypeDecl::name, "__" + td->name + "_generic_" ) ); 1662 } 1663 return aggr; 1664 } 1665 1666 const ast::StructDecl * previsit( const ast::StructDecl * structDecl ) { 1667 return renameGenericParams( structDecl ); 1668 } 1669 1670 void postvisit( const ast::StructDecl * structDecl ) { 1671 // visit struct members first so that the types of self-referencing members are 1672 // updated properly 1673 if ( ! structDecl->body ) return; 1674 1675 // update forward declarations to point here 1676 auto fwds = forwardStructs.equal_range( structDecl->name ); 1677 if ( fwds.first != fwds.second ) { 1678 auto inst = fwds.first; 1679 do { 1680 // forward decl is stored *mutably* in map, can thus be updated 1681 inst->second->base = structDecl; 1682 } while ( ++inst != fwds.second ); 1683 forwardStructs.erase( fwds.first, fwds.second ); 1684 } 1685 } 1686 1687 const ast::UnionDecl * previsit( const ast::UnionDecl * unionDecl ) { 1688 return renameGenericParams( unionDecl ); 1689 } 1690 1691 void postvisit( const ast::UnionDecl * unionDecl ) { 1692 // visit union members first so that the types of self-referencing members are updated 1693 // properly 1694 if ( ! unionDecl->body ) return; 1695 1696 // update forward declarations to point here 1697 auto fwds = forwardUnions.equal_range( unionDecl->name ); 1698 if ( fwds.first != fwds.second ) { 1699 auto inst = fwds.first; 1700 do { 1701 // forward decl is stored *mutably* in map, can thus be updated 1702 inst->second->base = unionDecl; 1703 } while ( ++inst != fwds.second ); 1704 forwardUnions.erase( fwds.first, fwds.second ); 1705 } 1706 } 1707 1708 const ast::Decl * postvisit( const ast::TraitDecl * traitDecl ) { 1709 // set the "sized" status for the special "sized" trait 1710 if ( traitDecl->name == "sized" ) { 1711 assertf( traitDecl->params.size() == 1, "Built-in trait 'sized' has incorrect " 1712 "number of parameters: %zd", traitDecl->params.size() ); 1713 1714 traitDecl = ast::mutate_field_index( 1715 traitDecl, &ast::TraitDecl::params, 0, 1716 ast::mutate_field( 1717 traitDecl->params.front().get(), &ast::TypeDecl::sized, true ) ); 1718 } 1719 1720 // move assertions from type parameters into the body of the trait 1721 std::vector< ast::ptr< ast::DeclWithType > > added; 1722 for ( const ast::TypeDecl * td : traitDecl->params ) { 1723 for ( const ast::DeclWithType * assn : td->assertions ) { 1724 auto inst = dynamic_cast< const ast::TraitInstType * >( assn->get_type() ); 1725 if ( inst ) { 1726 expandAssertions( inst, added ); 1727 } else { 1728 added.emplace_back( assn ); 1729 } 1730 } 1731 } 1732 if ( ! added.empty() ) { 1733 auto mut = mutate( traitDecl ); 1734 for ( const ast::DeclWithType * decl : added ) { 1735 mut->members.emplace_back( decl ); 1736 } 1737 traitDecl = mut; 1738 } 1739 1740 return traitDecl; 1741 } 1439 1742 }; 1440 1743 1441 1744 /// Replaces array and function types in forall lists by appropriate pointer type and assigns 1442 1745 /// each object and function declaration a unique ID 1443 struct ForallPointerDecay_new { 1444 #warning incomplete 1746 class ForallPointerDecay_new { 1747 const CodeLocation & location; 1748 public: 1749 ForallPointerDecay_new( const CodeLocation & loc ) : location( loc ) {} 1750 1751 const ast::ObjectDecl * previsit( const ast::ObjectDecl * obj ) { 1752 // ensure that operator names only apply to functions or function pointers 1753 if ( 1754 CodeGen::isOperator( obj->name ) 1755 && ! dynamic_cast< const ast::FunctionType * >( obj->type->stripDeclarator() ) 1756 ) { 1757 SemanticError( obj->location, toCString( "operator ", obj->name.c_str(), " is not " 1758 "a function or function pointer." ) ); 1759 } 1760 1761 // ensure object has unique ID 1762 if ( obj->uniqueId ) return obj; 1763 auto mut = mutate( obj ); 1764 mut->fixUniqueId(); 1765 return mut; 1766 } 1767 1768 const ast::FunctionDecl * previsit( const ast::FunctionDecl * func ) { 1769 // ensure function has unique ID 1770 if ( func->uniqueId ) return func; 1771 auto mut = mutate( func ); 1772 mut->fixUniqueId(); 1773 return mut; 1774 } 1775 1776 /// Fix up assertions -- flattens assertion lists, removing all trait instances 1777 template< typename node_t, typename parent_t > 1778 static const node_t * forallFixer( 1779 const CodeLocation & loc, const node_t * node, 1780 ast::ParameterizedType::ForallList parent_t::* forallField 1781 ) { 1782 for ( unsigned i = 0; i < (node->*forallField).size(); ++i ) { 1783 const ast::TypeDecl * type = (node->*forallField)[i]; 1784 if ( type->assertions.empty() ) continue; 1785 1786 std::vector< ast::ptr< ast::DeclWithType > > asserts; 1787 asserts.reserve( type->assertions.size() ); 1788 1789 // expand trait instances into their members 1790 for ( const ast::DeclWithType * assn : type->assertions ) { 1791 auto traitInst = 1792 dynamic_cast< const ast::TraitInstType * >( assn->get_type() ); 1793 if ( traitInst ) { 1794 // expand trait instance to all its members 1795 expandAssertions( traitInst, asserts ); 1796 } else { 1797 // pass other assertions through 1798 asserts.emplace_back( assn ); 1799 } 1800 } 1801 1802 // apply FixFunction to every assertion to check for invalid void type 1803 for ( ast::ptr< ast::DeclWithType > & assn : asserts ) { 1804 bool isVoid = false; 1805 assn = fixFunction( assn, isVoid ); 1806 if ( isVoid ) { 1807 SemanticError( loc, node, "invalid type void in assertion of function " ); 1808 } 1809 } 1810 1811 // place mutated assertion list in node 1812 auto mut = mutate( type ); 1813 mut->assertions = move( asserts ); 1814 node = ast::mutate_field_index( node, forallField, i, mut ); 1815 } 1816 return node; 1817 } 1818 1819 const ast::FunctionType * previsit( const ast::FunctionType * ftype ) { 1820 return forallFixer( location, ftype, &ast::FunctionType::forall ); 1821 } 1822 1823 const ast::StructDecl * previsit( const ast::StructDecl * aggrDecl ) { 1824 return forallFixer( aggrDecl->location, aggrDecl, &ast::StructDecl::params ); 1825 } 1826 1827 const ast::UnionDecl * previsit( const ast::UnionDecl * aggrDecl ) { 1828 return forallFixer( aggrDecl->location, aggrDecl, &ast::UnionDecl::params ); 1829 } 1445 1830 }; 1446 1831 } // anonymous namespace 1447 1832 1448 const ast::Type * validateType( const ast::Type * type, const ast::SymbolTable & symtab ) { 1833 const ast::Type * validateType( 1834 const CodeLocation & loc, const ast::Type * type, const ast::SymbolTable & symtab ) { 1449 1835 ast::Pass< EnumAndPointerDecay_new > epc; 1450 ast::Pass< LinkReferenceToTypes_new > lrt{ symtab };1451 ast::Pass< ForallPointerDecay_new > fpd ;1836 ast::Pass< LinkReferenceToTypes_new > lrt{ loc, symtab }; 1837 ast::Pass< ForallPointerDecay_new > fpd{ loc }; 1452 1838 1453 1839 return type->accept( epc )->accept( lrt )->accept( fpd ); -
src/SymTab/Validate.h
r70a141d4 r67d2b97 19 19 #include <list> // for list 20 20 21 class CodeLocation; 21 22 class Declaration; 22 23 class Type; … … 34 35 void validateType( Type *type, const Indexer *indexer ); 35 36 36 const ast::Type * validateType( const ast::Type * type, const ast::SymbolTable & symtab ); 37 const ast::Type * validateType( 38 const CodeLocation & loc, const ast::Type * type, const ast::SymbolTable & symtab ); 37 39 } // namespace SymTab 38 40
Note:
See TracChangeset
for help on using the changeset viewer.