Changeset 44547b0
- Timestamp:
- Nov 7, 2022, 1:00:22 PM (18 months ago)
- Branches:
- ADT, ast-experimental, master
- Children:
- 4da152a
- Parents:
- a805100
- Location:
- src
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
src/AST/Convert.cpp
ra805100 r44547b0 1621 1621 { old->get_funcSpec().val } 1622 1622 ); 1623 decl->enumInLine = old->enumInLine;1624 1623 cache.emplace(old, decl); 1625 1624 assert(cache.find( old ) != cache.end()); -
src/AST/Decl.hpp
ra805100 r44547b0 105 105 ptr<Init> init; 106 106 ptr<Expr> bitfieldWidth; 107 bool enumInLine = false; // enum inline is not a real object declaration.108 // It is a place holder for a set of enum value (ObjectDecl)109 bool importValue = false; // if the value copied from somewhere else110 107 111 108 ObjectDecl( const CodeLocation & loc, const std::string & name, const Type * type, -
src/SymTab/Validate.cc
ra805100 r44547b0 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"56 49 #include "CodeGen/CodeGenerator.h" // for genName 57 50 #include "CodeGen/OperatorTable.h" // for isCtorDtor, isCtorDtorAssign … … 1326 1319 } 1327 1320 1328 namespace {1329 /// Replaces enum types by int, and function/array types in function parameter and return1330 /// lists by appropriate pointers1331 /*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 EnumConstant1335 for ( unsigned i = 0; i < enumDecl->members.size(); ++i ) {1336 // build new version of object with EnumConstant1337 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 decl1343 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::FixedArgs1354 ) {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 list1363 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 it1369 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 substitutions1384 void expandAssertions(1385 const ast::TraitInstType * inst, std::vector< ast::ptr< ast::DeclWithType > > & out1386 ) {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 parameters1390 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->base1393 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 definitions1401 class LinkReferenceToTypes_new final1402 : public ast::WithSymbolTable, public ast::WithGuards, public1403 ast::WithVisitorRef<LinkReferenceToTypes_new>, public ast::WithShortCircuiting {1404 1405 // these maps of uses of forward declarations of types need to have the actual type1406 // declaration switched in * after * they have been traversed. To enable this in the1407 // ast::Pass framework, any node that needs to be so mutated has mutate() called on it1408 // before it is placed in the map, properly updating its parents in the usual traversal,1409 // then can have the actual mutation applied later1410 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 be1422 /// renamed appropriately1423 bool inGeneric = false;1424 1425 public:1426 /// contstruct using running symbol table1427 LinkReferenceToTypes_new( const CodeLocation & loc )1428 : location( loc ), localSymtab( &symtab ) {}1429 1430 /// construct using provided symbol table1431 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 type1436 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 declaration1454 if ( decl ) {1455 inst = ast::mutate_field( inst, &ast::EnumInstType::base, decl );1456 }1457 if ( ! decl || ! decl->body ) {1458 // forward declaration1459 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 declaration1479 if ( decl ) {1480 inst = ast::mutate_field( inst, &ast::StructInstType::base, decl );1481 }1482 if ( ! decl || ! decl->body ) {1483 // forward declaration1484 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 declaration1495 if ( decl ) {1496 inst = ast::mutate_field( inst, &ast::UnionInstType::base, decl );1497 }1498 if ( ! decl || ! decl->body ) {1499 // forward declaration1500 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 traits1510 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 instance1520 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 type1550 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 updated1556 // properly1557 if ( ! enumDecl->body ) return enumDecl;1558 1559 // update forward declarations to point here1560 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 updated1565 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 set1571 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 that1575 // determine if an expression is constexpr have appropriate information1576 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 defined1592 /// function forall parameters, e.g. the T in Box and the T in f, below1593 /// 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 are1622 // updated properly1623 if ( ! structDecl->body ) return;1624 1625 // update forward declarations to point here1626 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 updated1631 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 updated1643 // properly1644 if ( ! unionDecl->body ) return;1645 1646 // update forward declarations to point here1647 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 updated1652 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" trait1660 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 trait1671 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 assigns1695 /// each object and function declaration a unique ID1696 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 pointers1703 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 ID1712 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 ID1720 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 instances1727 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::* forallField1731 ) {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 members1740 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 members1745 expandAssertions( traitInst, asserts );1746 } else {1747 // pass other assertions through1748 asserts.emplace_back( assn );1749 }1750 }1751 1752 // apply FixFunction to every assertion to check for invalid void type1753 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 node1762 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 namespace1783 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 1795 1321 } // namespace SymTab 1796 1322
Note: See TracChangeset
for help on using the changeset viewer.