Changeset 67d2b97 for src/SymTab


Ignore:
Timestamp:
Jun 24, 2019, 2:24:57 PM (6 years ago)
Author:
Thierry Delisle <tdelisle@…>
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.
Message:

Merge branch 'master' of plg.uwaterloo.ca:software/cfa/cfa-cc

Location:
src/SymTab
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • src/SymTab/Validate.cc

    r70a141d4 r67d2b97  
    4444#include <list>                        // for list
    4545#include <string>                      // for string
     46#include <unordered_map>               // for unordered_map
    4647#include <utility>                     // for pair
    4748
     49#include "AST/Chain.hpp"
    4850#include "AST/Decl.hpp"
    4951#include "AST/Node.hpp"
     
    5153#include "AST/SymbolTable.hpp"
    5254#include "AST/Type.hpp"
     55#include "AST/TypeSubstitution.hpp"
    5356#include "CodeGen/CodeGenerator.h"     // for genName
    5457#include "CodeGen/OperatorTable.h"     // for isCtorDtor, isCtorDtorAssign
    5558#include "ControlStruct/Mutate.h"      // for ForExprMutator
     59#include "Common/CodeLocation.h"       // for CodeLocation
    5660#include "Common/Stats.h"              // for Stats::Heap
    5761#include "Common/PassVisitor.h"        // for PassVisitor, WithDeclsToAdd
     
    14271431        };
    14281432
     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
    14291450        /// Associates forward declarations of aggregates with their definitions
    1430         struct LinkReferenceToTypes_new final
     1451        class LinkReferenceToTypes_new final
    14311452        : public ast::WithSymbolTable, public ast::WithGuards, public
    14321453          ast::WithVisitorRef<LinkReferenceToTypes_new>, public ast::WithShortCircuiting {
    14331454               
    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                }
    14391742        };
    14401743
    14411744        /// Replaces array and function types in forall lists by appropriate pointer type and assigns
    14421745        /// 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                }
    14451830        };
    14461831} // anonymous namespace
    14471832
    1448 const ast::Type * validateType( const ast::Type * type, const ast::SymbolTable & symtab ) {
     1833const ast::Type * validateType(
     1834                const CodeLocation & loc, const ast::Type * type, const ast::SymbolTable & symtab ) {
    14491835        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 };
    14521838
    14531839        return type->accept( epc )->accept( lrt )->accept( fpd );
  • src/SymTab/Validate.h

    r70a141d4 r67d2b97  
    1919#include <list>  // for list
    2020
     21class CodeLocation;
    2122class Declaration;
    2223class Type;
     
    3435        void validateType( Type *type, const Indexer *indexer );
    3536
    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 );
    3739} // namespace SymTab
    3840
Note: See TracChangeset for help on using the changeset viewer.