Changeset d4b6638


Ignore:
Timestamp:
Jun 5, 2019, 11:24:29 AM (4 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:
2a8f0c1, 300fbee
Parents:
4741dfe (diff), 0e42794 (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
Files:
19 edited

Legend:

Unmodified
Added
Removed
  • src/AST/Bitfield.hpp

    r4741dfe rd4b6638  
    99// Author           : Aaron B. Moss
    1010// Created On       : Thu May 9 10:00:00 2019
    11 // Last Modified By : Aaron B. Moss
    12 // Last Modified On : Thu May 9 10:00:00 2019
    13 // Update Count     : 1
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Wed Jun 5 10:00:00 2019
     13// Update Count     : 2
    1414//
    1515
    1616#pragma once
    1717
    18 #include <strings.h>  // for ffs
     18#include <strings.h>   // for ffs
     19#include <type_traits> // for is_unsigned
    1920
    2021/// Make a type a bitfield.
     
    2425template<typename T>
    2526struct bitfield : public T {
    26         static_assert(sizeof(T) == sizeof(unsigned int), "Type has incorrect size");
    2727        using T::val;
    2828        using val_t = decltype(val);
     29        static_assert(sizeof(T) == sizeof(unsigned int), "Type has incorrect size");
     30        static_assert(std::is_unsigned<val_t>::value, "Bitfield val field is not unsigned.");
    2931
    3032        constexpr bitfield() : T( 0 ) {}
  • src/AST/Expr.cpp

    r4741dfe rd4b6638  
    6565                        // base type
    6666                        ret->result = base;
    67                         add_lvalue( ret->result );
     67                        add_qualifiers( ret->result, CV::Lvalue );
    6868                }
    6969        }
     
    165165        genericSubsitution( aggregate->result ).apply( result );
    166166        // ensure lvalue and appropriate restrictions from aggregate type
    167         result.get_and_mutate()->qualifiers |= aggregate->result->qualifiers | CV::Lvalue;
     167        add_qualifiers( result, aggregate->result->qualifiers | CV::Lvalue );
    168168}
    169169
     
    175175        assert( var->get_type() );
    176176        result = var->get_type();
    177         add_lvalue( result );
     177        add_qualifiers( result, CV::Lvalue );
    178178}
    179179
     
    309309        assert( t && i );
    310310        result = t;
    311         add_lvalue( result );
     311        add_qualifiers( result, CV::Lvalue );
    312312}
    313313
     
    326326        // like MemberExpr, TupleIndexExpr is always an lvalue
    327327        result = type->types[ index ];
    328         add_lvalue( result );
     328        add_qualifiers( result, CV::Lvalue );
    329329}
    330330
  • src/AST/Node.hpp

    r4741dfe rd4b6638  
    1818#include <cassert>
    1919#include <iosfwd>
     20
     21#include "Common/ErrorObjects.h"  // for SemanticErrorException
    2022
    2123namespace ast {
     
    100102}
    101103
     104/// Call a visitor on a collection of nodes, throwing any exceptions when completed
     105template< typename Container >
     106void accept_each( const Container & c, Visitor & v ) {
     107        SemanticErrorException errors;
     108        for ( const auto & i : c ) {
     109                try {
     110                        if ( i ) {
     111                                i->accept( v );
     112                        }
     113                } catch ( SemanticErrorException & e ) {
     114                        errors.append( e );
     115                }
     116        }
     117        if ( ! errors.isEmpty() ) {
     118                throw errors;
     119        }
     120}
     121
    102122/// Base class for the smart pointer types
    103123/// should never really be used.
     
    166186        const o_node_t * as() const { return dynamic_cast<const o_node_t *>(node); }
    167187
     188        /// wrapper for convenient access to strict_dynamic_cast
     189        template<typename o_node_t>
     190        const o_node_t * strict_as() const { return strict_dynamic_cast<const o_node_t *>(node); }
     191
    168192        /// Returns a mutable version of the pointer in this node.
    169193        node_t * get_and_mutate();
  • src/AST/Pass.hpp

    r4741dfe rd4b6638  
    3333#include "AST/Visitor.hpp"
    3434
    35 #include "SymTab/Indexer.h"
     35#include "AST/SymbolTable.hpp"
    3636
    3737// Private prelude header, needed for some of the magic tricks this class pulls off
     
    6161//                          postvisit/postmutate teminates.
    6262// | WithVisitorRef       - provides an pointer to the templated visitor wrapper
    63 // | WithIndexer          - provides indexer functionality (i.e. up-to-date symbol table)
     63// | WithSymbolTable      - provides symbol table functionality
    6464//-------------------------------------------------------------------------------------------------
    6565template< typename pass_t >
     
    206206
    207207private:
    208         /// Internal RAII guard for indexer features
    209         struct guard_indexer {
    210                 guard_indexer( Pass<pass_t> & pass ): pass( pass ) { __pass::indexer::enter(pass, 0); }
    211                 ~guard_indexer()                                   { __pass::indexer::leave(pass, 0); }
     208        /// Internal RAII guard for symbol table features
     209        struct guard_symtab {
     210                guard_symtab( Pass<pass_t> & pass ): pass( pass ) { __pass::symtab::enter(pass, 0); }
     211                ~guard_symtab()                                   { __pass::symtab::leave(pass, 0); }
    212212                Pass<pass_t> & pass;
    213213        };
     
    294294};
    295295
    296 /// Use when the templated visitor should update the indexer
    297 struct WithIndexer {
    298         SymTab::Indexer indexer;
     296/// Use when the templated visitor should update the symbol table
     297struct WithSymbolTable {
     298        SymbolTable symtab;
    299299};
    300300}
  • src/AST/Pass.impl.hpp

    r4741dfe rd4b6638  
    398398        VISIT(
    399399                {
    400                         guard_indexer guard { *this };
     400                        guard_symtab guard { *this };
    401401                        maybe_accept( node, &ObjectDecl::type );
    402402                }
     
    406406        )
    407407
    408         __pass::indexer::addId( pass, 0, node );
     408        __pass::symtab::addId( pass, 0, node );
    409409
    410410        VISIT_END( DeclWithType, node );
     
    417417        VISIT_START( node );
    418418
    419         __pass::indexer::addId( pass, 0, node );
     419        __pass::symtab::addId( pass, 0, node );
    420420
    421421        VISIT(maybe_accept( node, &FunctionDecl::withExprs );)
    422422        {
    423423                // with clause introduces a level of scope (for the with expression members).
    424                 // with clause exprs are added to the indexer before parameters so that parameters
     424                // with clause exprs are added to the symbol table before parameters so that parameters
    425425                // shadow with exprs and not the other way around.
    426                 guard_indexer guard { *this };
    427                 __pass::indexer::addWith( pass, 0, node->withExprs, node );
     426                guard_symtab guard { *this };
     427                __pass::symtab::addWith( pass, 0, node->withExprs, node );
    428428                {
    429                         guard_indexer guard { *this };
     429                        guard_symtab guard { *this };
    430430                        // implicit add __func__ identifier as specified in the C manual 6.4.2.2
    431431                        static ast::ObjectDecl func(
     
    436436                                )
    437437                        );
    438                         __pass::indexer::addId( pass, 0, &func );
     438                        __pass::symtab::addId( pass, 0, &func );
    439439                        VISIT(
    440440                                maybe_accept( node, &FunctionDecl::type );
     
    460460        // make up a forward declaration and add it before processing the members
    461461        // needs to be on the heap because addStruct saves the pointer
    462         __pass::indexer::addStructFwd( pass, 0, node );
    463 
    464         VISIT({
    465                 guard_indexer guard { * this };
     462        __pass::symtab::addStructFwd( pass, 0, node );
     463
     464        VISIT({
     465                guard_symtab guard { * this };
    466466                maybe_accept( node, &StructDecl::params  );
    467467                maybe_accept( node, &StructDecl::members );
     
    469469
    470470        // this addition replaces the forward declaration
    471         __pass::indexer::addStruct( pass, 0, node );
     471        __pass::symtab::addStruct( pass, 0, node );
    472472
    473473        VISIT_END( Decl, node );
     
    481481
    482482        // make up a forward declaration and add it before processing the members
    483         __pass::indexer::addUnionFwd( pass, 0, node );
    484 
    485         VISIT({
    486                 guard_indexer guard { * this };
     483        __pass::symtab::addUnionFwd( pass, 0, node );
     484
     485        VISIT({
     486                guard_symtab guard { * this };
    487487                maybe_accept( node, &UnionDecl::params  );
    488488                maybe_accept( node, &UnionDecl::members );
    489489        })
    490490
    491         __pass::indexer::addUnion( pass, 0, node );
     491        __pass::symtab::addUnion( pass, 0, node );
    492492
    493493        VISIT_END( Decl, node );
     
    500500        VISIT_START( node );
    501501
    502         __pass::indexer::addEnum( pass, 0, node );
     502        __pass::symtab::addEnum( pass, 0, node );
    503503
    504504        VISIT(
     
    518518
    519519        VISIT({
    520                 guard_indexer guard { *this };
     520                guard_symtab guard { *this };
    521521                maybe_accept( node, &TraitDecl::params  );
    522522                maybe_accept( node, &TraitDecl::members );
    523523        })
    524524
    525         __pass::indexer::addTrait( pass, 0, node );
     525        __pass::symtab::addTrait( pass, 0, node );
    526526
    527527        VISIT_END( Decl, node );
     
    535535
    536536        VISIT({
    537                 guard_indexer guard { *this };
     537                guard_symtab guard { *this };
    538538                maybe_accept( node, &TypeDecl::params );
    539539                maybe_accept( node, &TypeDecl::base   );
     
    543543        // note that assertions come after the type is added to the symtab, since they are not part of the type proper
    544544        // and may depend on the type itself
    545         __pass::indexer::addType( pass, 0, node );
     545        __pass::symtab::addType( pass, 0, node );
    546546
    547547        VISIT(
     
    549549
    550550                {
    551                         guard_indexer guard { *this };
     551                        guard_symtab guard { *this };
    552552                        maybe_accept( node, &TypeDecl::init );
    553553                }
     
    564564
    565565        VISIT({
    566                 guard_indexer guard { *this };
     566                guard_symtab guard { *this };
    567567                maybe_accept( node, &TypedefDecl::params );
    568568                maybe_accept( node, &TypedefDecl::base   );
    569569        })
    570570
    571         __pass::indexer::addType( pass, 0, node );
     571        __pass::symtab::addType( pass, 0, node );
    572572
    573573        VISIT( maybe_accept( node, &TypedefDecl::assertions ); )
     
    611611                // do not enter a new scope if inFunction is true - needs to check old state before the assignment
    612612                auto guard1 = makeFuncGuard( [this, inFunction = this->inFunction]() {
    613                         if ( ! inFunction ) __pass::indexer::enter(pass, 0);
     613                        if ( ! inFunction ) __pass::symtab::enter(pass, 0);
    614614                }, [this, inFunction = this->inFunction]() {
    615                         if ( ! inFunction ) __pass::indexer::leave(pass, 0);
     615                        if ( ! inFunction ) __pass::symtab::leave(pass, 0);
    616616                });
    617617                ValueGuard< bool > guard2( inFunction );
     
    669669        VISIT({
    670670                // if statements introduce a level of scope (for the initialization)
    671                 guard_indexer guard { *this };
     671                guard_symtab guard { *this };
    672672                maybe_accept( node, &IfStmt::inits    );
    673673                maybe_accept( node, &IfStmt::cond     );
     
    687687        VISIT({
    688688                // while statements introduce a level of scope (for the initialization)
    689                 guard_indexer guard { *this };
     689                guard_symtab guard { *this };
    690690                maybe_accept( node, &WhileStmt::inits );
    691691                maybe_accept( node, &WhileStmt::cond  );
     
    704704        VISIT({
    705705                // for statements introduce a level of scope (for the initialization)
    706                 guard_indexer guard { *this };
     706                guard_symtab guard { *this };
    707707                maybe_accept( node, &ForStmt::inits );
    708708                maybe_accept( node, &ForStmt::cond  );
     
    800800        VISIT({
    801801                // catch statements introduce a level of scope (for the caught exception)
    802                 guard_indexer guard { *this };
     802                guard_symtab guard { *this };
    803803                maybe_accept( node, &CatchStmt::decl );
    804804                maybe_accept( node, &CatchStmt::cond );
     
    901901                {
    902902                        // catch statements introduce a level of scope (for the caught exception)
    903                         guard_indexer guard { *this };
    904                         __pass::indexer::addWith( pass, 0, node->exprs, node );
     903                        guard_symtab guard { *this };
     904                        __pass::symtab::addWith( pass, 0, node->exprs, node );
    905905                        maybe_accept( node, &WithStmt::stmt );
    906906                }
     
    953953        VISIT(
    954954                {
    955                         guard_indexer guard { *this };
     955                        guard_symtab guard { *this };
    956956                        maybe_accept( node, &ApplicationExpr::result );
    957957                }
     
    971971        VISIT(
    972972                {
    973                         guard_indexer guard { *this };
     973                        guard_symtab guard { *this };
    974974                        maybe_accept( node, &UntypedExpr::result );
    975975                }
     
    988988
    989989        VISIT({
    990                 guard_indexer guard { *this };
     990                guard_symtab guard { *this };
    991991                maybe_accept( node, &NameExpr::result );
    992992        })
     
    10021002
    10031003        VISIT({
    1004                         guard_indexer guard { *this };
     1004                        guard_symtab guard { *this };
    10051005                        maybe_accept( node, &CastExpr::result );
    10061006                }
     
    10181018
    10191019        VISIT({
    1020                         guard_indexer guard { *this };
     1020                        guard_symtab guard { *this };
    10211021                        maybe_accept( node, &KeywordCastExpr::result );
    10221022                }
     
    10341034
    10351035        VISIT({
    1036                         guard_indexer guard { *this };
     1036                        guard_symtab guard { *this };
    10371037                        maybe_accept( node, &VirtualCastExpr::result );
    10381038                }
     
    10501050
    10511051        VISIT({
    1052                         guard_indexer guard { *this };
     1052                        guard_symtab guard { *this };
    10531053                        maybe_accept( node, &AddressExpr::result );
    10541054                }
     
    10661066
    10671067        VISIT({
    1068                 guard_indexer guard { *this };
     1068                guard_symtab guard { *this };
    10691069                maybe_accept( node, &LabelAddressExpr::result );
    10701070        })
     
    10801080
    10811081        VISIT({
    1082                         guard_indexer guard { *this };
     1082                        guard_symtab guard { *this };
    10831083                        maybe_accept( node, &UntypedMemberExpr::result );
    10841084                }
     
    10971097
    10981098        VISIT({
    1099                         guard_indexer guard { *this };
     1099                        guard_symtab guard { *this };
    11001100                        maybe_accept( node, &MemberExpr::result );
    11011101                }
     
    11131113
    11141114        VISIT({
    1115                 guard_indexer guard { *this };
     1115                guard_symtab guard { *this };
    11161116                maybe_accept( node, &VariableExpr::result );
    11171117        })
     
    11271127
    11281128        VISIT({
    1129                 guard_indexer guard { *this };
     1129                guard_symtab guard { *this };
    11301130                maybe_accept( node, &ConstantExpr::result );
    11311131        })
     
    11411141
    11421142        VISIT({
    1143                         guard_indexer guard { *this };
     1143                        guard_symtab guard { *this };
    11441144                        maybe_accept( node, &SizeofExpr::result );
    11451145                }
     
    11611161
    11621162        VISIT({
    1163                         guard_indexer guard { *this };
     1163                        guard_symtab guard { *this };
    11641164                        maybe_accept( node, &AlignofExpr::result );
    11651165                }
     
    11811181
    11821182        VISIT({
    1183                         guard_indexer guard { *this };
     1183                        guard_symtab guard { *this };
    11841184                        maybe_accept( node, &UntypedOffsetofExpr::result );
    11851185                }
     
    11971197
    11981198        VISIT({
    1199                         guard_indexer guard { *this };
     1199                        guard_symtab guard { *this };
    12001200                        maybe_accept( node, &OffsetofExpr::result );
    12011201                }
     
    12131213
    12141214        VISIT({
    1215                         guard_indexer guard { *this };
     1215                        guard_symtab guard { *this };
    12161216                        maybe_accept( node, &OffsetPackExpr::result );
    12171217                }
     
    12291229
    12301230        VISIT({
    1231                         guard_indexer guard { *this };
     1231                        guard_symtab guard { *this };
    12321232                        maybe_accept( node, &LogicalExpr::result );
    12331233                }
     
    12461246
    12471247        VISIT({
    1248                         guard_indexer guard { *this };
     1248                        guard_symtab guard { *this };
    12491249                        maybe_accept( node, &ConditionalExpr::result );
    12501250                }
     
    12641264
    12651265        VISIT({
    1266                         guard_indexer guard { *this };
     1266                        guard_symtab guard { *this };
    12671267                        maybe_accept( node, &CommaExpr::result );
    12681268                }
     
    12811281
    12821282        VISIT({
    1283                         guard_indexer guard { *this };
     1283                        guard_symtab guard { *this };
    12841284                        maybe_accept( node, &TypeExpr::result );
    12851285                }
     
    12971297
    12981298        VISIT({
    1299                         guard_indexer guard { *this };
     1299                        guard_symtab guard { *this };
    13001300                        maybe_accept( node, &AsmExpr::result );
    13011301                }
     
    13151315
    13161316        VISIT({
    1317                         guard_indexer guard { *this };
     1317                        guard_symtab guard { *this };
    13181318                        maybe_accept( node, &ImplicitCopyCtorExpr::result );
    13191319                }
     
    13311331
    13321332        VISIT({
    1333                         guard_indexer guard { *this };
     1333                        guard_symtab guard { *this };
    13341334                        maybe_accept( node, &ConstructorExpr::result );
    13351335                }
     
    13471347
    13481348        VISIT({
    1349                         guard_indexer guard { *this };
     1349                        guard_symtab guard { *this };
    13501350                        maybe_accept( node, &CompoundLiteralExpr::result );
    13511351                }
     
    13631363
    13641364        VISIT({
    1365                         guard_indexer guard { *this };
     1365                        guard_symtab guard { *this };
    13661366                        maybe_accept( node, &RangeExpr::result );
    13671367                }
     
    13801380
    13811381        VISIT({
    1382                         guard_indexer guard { *this };
     1382                        guard_symtab guard { *this };
    13831383                        maybe_accept( node, &UntypedTupleExpr::result );
    13841384                }
     
    13961396
    13971397        VISIT({
    1398                         guard_indexer guard { *this };
     1398                        guard_symtab guard { *this };
    13991399                        maybe_accept( node, &TupleExpr::result );
    14001400                }
     
    14121412
    14131413        VISIT({
    1414                         guard_indexer guard { *this };
     1414                        guard_symtab guard { *this };
    14151415                        maybe_accept( node, &TupleIndexExpr::result );
    14161416                }
     
    14281428
    14291429        VISIT({
    1430                         guard_indexer guard { *this };
     1430                        guard_symtab guard { *this };
    14311431                        maybe_accept( node, &TupleAssignExpr::result );
    14321432                }
     
    14541454
    14551455                {
    1456                         guard_indexer guard { *this };
     1456                        guard_symtab guard { *this };
    14571457                        maybe_accept( node, &StmtExpr::result );
    14581458                }
     
    14721472
    14731473        VISIT({
    1474                         guard_indexer guard { *this };
     1474                        guard_symtab guard { *this };
    14751475                        maybe_accept( node, &UniqueExpr::result );
    14761476                }
     
    14881488
    14891489        VISIT({
    1490                         guard_indexer guard { *this };
     1490                        guard_symtab guard { *this };
    14911491                        maybe_accept( node, &UntypedInitExpr::result );
    14921492                }
     
    15051505
    15061506        VISIT({
    1507                         guard_indexer guard { *this };
     1507                        guard_symtab guard { *this };
    15081508                        maybe_accept( node, &InitExpr::result );
    15091509                }
     
    15221522
    15231523        VISIT({
    1524                         guard_indexer guard { *this };
     1524                        guard_symtab guard { *this };
    15251525                        maybe_accept( node, &DeletedExpr::result );
    15261526                }
     
    15391539
    15401540        VISIT({
    1541                         guard_indexer guard { *this };
     1541                        guard_symtab guard { *this };
    15421542                        maybe_accept( node, &DefaultArgExpr::result );
    15431543                }
     
    15551555
    15561556        VISIT({
    1557                         guard_indexer guard { *this };
     1557                        guard_symtab guard { *this };
    15581558                        maybe_accept( node, &GenericExpr::result );
    15591559                }
     
    15661566                        const Type * type = nullptr;
    15671567                        if( assoc.type ) {
    1568                                 guard_indexer guard { *this };
     1568                                guard_symtab guard { *this };
    15691569                                type = assoc.type->accept( *this );
    15701570                                if( type != assoc.type ) mutated = true;
     
    16821682        VISIT_START( node );
    16831683
    1684         __pass::indexer::addStruct( pass, 0, node->name );
    1685 
    1686         VISIT({
    1687                 guard_indexer guard { *this };
     1684        __pass::symtab::addStruct( pass, 0, node->name );
     1685
     1686        VISIT({
     1687                guard_symtab guard { *this };
    16881688                maybe_accept( node, &StructInstType::forall );
    16891689                maybe_accept( node, &StructInstType::params );
     
    16991699        VISIT_START( node );
    17001700
    1701         __pass::indexer::addStruct( pass, 0, node->name );
     1701        __pass::symtab::addStruct( pass, 0, node->name );
    17021702
    17031703        {
    1704                 guard_indexer guard { *this };
     1704                guard_symtab guard { *this };
    17051705                maybe_accept( node, &UnionInstType::forall );
    17061706                maybe_accept( node, &UnionInstType::params );
     
    18931893                        std::unordered_map< std::string, ast::ptr< ast::Type > > new_map;
    18941894                        for ( const auto & p : node->typeEnv ) {
    1895                                 guard_indexer guard { *this };
     1895                                guard_symtab guard { *this };
    18961896                                auto new_node = p.second->accept( *this );
    18971897                                if (new_node != p.second) mutated = false;
     
    19091909                        std::unordered_map< std::string, ast::ptr< ast::Expr > > new_map;
    19101910                        for ( const auto & p : node->varEnv ) {
    1911                                 guard_indexer guard { *this };
     1911                                guard_symtab guard { *this };
    19121912                                auto new_node = p.second->accept( *this );
    19131913                                if (new_node != p.second) mutated = false;
  • src/AST/Pass.proto.hpp

    r4741dfe rd4b6638  
    265265        };
    266266
    267         // Finally certain pass desire an up to date indexer automatically
    268         // detect the presence of a member name indexer and call all the members appropriately
    269         namespace indexer {
     267        // Finally certain pass desire an up to date symbol table automatically
     268        // detect the presence of a member name `symtab` and call all the members appropriately
     269        namespace symtab {
    270270                // Some simple scoping rules
    271271                template<typename pass_t>
    272                 static inline auto enter( pass_t & pass, int ) -> decltype( pass.indexer.enterScope(), void() ) {
    273                         pass.indexer.enterScope();
     272                static inline auto enter( pass_t & pass, int ) -> decltype( pass.symtab.enterScope(), void() ) {
     273                        pass.symtab.enterScope();
    274274                }
    275275
     
    278278
    279279                template<typename pass_t>
    280                 static inline auto leave( pass_t & pass, int ) -> decltype( pass.indexer.leaveScope(), void() ) {
    281                         pass.indexer.leaveScope();
     280                static inline auto leave( pass_t & pass, int ) -> decltype( pass.symtab.leaveScope(), void() ) {
     281                        pass.symtab.leaveScope();
    282282                }
    283283
     
    285285                static inline auto leave( pass_t &, long ) {}
    286286
    287                 // The indexer has 2 kind of functions mostly, 1 argument and 2 arguments
     287                // The symbol table has 2 kind of functions mostly, 1 argument and 2 arguments
    288288                // Create macro to condense these common patterns
    289                 #define INDEXER_FUNC1( func, type ) \
     289                #define SYMTAB_FUNC1( func, type ) \
    290290                template<typename pass_t> \
    291                 static inline auto func( pass_t & pass, int, type arg ) -> decltype( pass.indexer.func( arg ), void() ) {\
    292                         pass.indexer.func( arg ); \
     291                static inline auto func( pass_t & pass, int, type arg ) -> decltype( pass.symtab.func( arg ), void() ) {\
     292                        pass.symtab.func( arg ); \
    293293                } \
    294294                \
     
    296296                static inline void func( pass_t &, long, type ) {}
    297297
    298                 #define INDEXER_FUNC2( func, type1, type2 ) \
     298                #define SYMTAB_FUNC2( func, type1, type2 ) \
    299299                template<typename pass_t> \
    300                 static inline auto func( pass_t & pass, int, type1 arg1, type2 arg2 ) -> decltype( pass.indexer.func( arg1, arg2 ), void () ) {\
    301                         pass.indexer.func( arg1, arg2 ); \
     300                static inline auto func( pass_t & pass, int, type1 arg1, type2 arg2 ) -> decltype( pass.symtab.func( arg1, arg2 ), void () ) {\
     301                        pass.symtab.func( arg1, arg2 ); \
    302302                } \
    303303                        \
     
    305305                static inline void func( pass_t &, long, type1, type2 ) {}
    306306
    307                 INDEXER_FUNC1( addId     , const DeclWithType *  );
    308                 INDEXER_FUNC1( addType   , const NamedTypeDecl * );
    309                 INDEXER_FUNC1( addStruct , const StructDecl *    );
    310                 INDEXER_FUNC1( addEnum   , const EnumDecl *      );
    311                 INDEXER_FUNC1( addUnion  , const UnionDecl *     );
    312                 INDEXER_FUNC1( addTrait  , const TraitDecl *     );
    313                 INDEXER_FUNC2( addWith   , const std::vector< ptr<Expr> > &, const Node * );
     307                SYMTAB_FUNC1( addId     , const DeclWithType *  );
     308                SYMTAB_FUNC1( addType   , const NamedTypeDecl * );
     309                SYMTAB_FUNC1( addStruct , const StructDecl *    );
     310                SYMTAB_FUNC1( addEnum   , const EnumDecl *      );
     311                SYMTAB_FUNC1( addUnion  , const UnionDecl *     );
     312                SYMTAB_FUNC1( addTrait  , const TraitDecl *     );
     313                SYMTAB_FUNC2( addWith   , const std::vector< ptr<Expr> > &, const Node * );
    314314
    315315                // A few extra functions have more complicated behaviour, they are hand written
    316316                template<typename pass_t>
    317                 static inline auto addStructFwd( pass_t & pass, int, const ast::StructDecl * decl ) -> decltype( pass.indexer.addStruct( decl ), void() ) {
     317                static inline auto addStructFwd( pass_t & pass, int, const ast::StructDecl * decl ) -> decltype( pass.symtab.addStruct( decl ), void() ) {
    318318                        ast::StructDecl * fwd = new ast::StructDecl( decl->location, decl->name );
    319319                        fwd->params = decl->params;
    320                         pass.indexer.addStruct( fwd );
     320                        pass.symtab.addStruct( fwd );
    321321                }
    322322
     
    325325
    326326                template<typename pass_t>
    327                 static inline auto addUnionFwd( pass_t & pass, int, const ast::UnionDecl * decl ) -> decltype( pass.indexer.addUnion( decl ), void() ) {
     327                static inline auto addUnionFwd( pass_t & pass, int, const ast::UnionDecl * decl ) -> decltype( pass.symtab.addUnion( decl ), void() ) {
    328328                        UnionDecl * fwd = new UnionDecl( decl->location, decl->name );
    329329                        fwd->params = decl->params;
    330                         pass.indexer.addUnion( fwd );
     330                        pass.symtab.addUnion( fwd );
    331331                }
    332332
     
    335335
    336336                template<typename pass_t>
    337                 static inline auto addStruct( pass_t & pass, int, const std::string & str ) -> decltype( pass.indexer.addStruct( str ), void() ) {
    338                         if ( ! pass.indexer.lookupStruct( str ) ) {
    339                                 pass.indexer.addStruct( str );
     337                static inline auto addStruct( pass_t & pass, int, const std::string & str ) -> decltype( pass.symtab.addStruct( str ), void() ) {
     338                        if ( ! pass.symtab.lookupStruct( str ) ) {
     339                                pass.symtab.addStruct( str );
    340340                        }
    341341                }
     
    345345
    346346                template<typename pass_t>
    347                 static inline auto addUnion( pass_t & pass, int, const std::string & str ) -> decltype( pass.indexer.addUnion( str ), void() ) {
    348                         if ( ! pass.indexer.lookupUnion( str ) ) {
    349                                 pass.indexer.addUnion( str );
     347                static inline auto addUnion( pass_t & pass, int, const std::string & str ) -> decltype( pass.symtab.addUnion( str ), void() ) {
     348                        if ( ! pass.symtab.lookupUnion( str ) ) {
     349                                pass.symtab.addUnion( str );
    350350                        }
    351351                }
     
    354354                static inline void addUnion( pass_t &, long, const std::string & ) {}
    355355
    356                 #undef INDEXER_FUNC1
    357                 #undef INDEXER_FUNC2
     356                #undef SYMTAB_FUNC1
     357                #undef SYMTAB_FUNC2
    358358        };
    359359};
  • src/AST/SymbolTable.hpp

    r4741dfe rd4b6638  
    123123        void addType( const NamedTypeDecl * decl );
    124124        /// Adds a struct declaration to the symbol table by name
    125         void addStruct( const std::string &id );
     125        void addStruct( const std::string & id );
    126126        /// Adds a struct declaration to the symbol table
    127127        void addStruct( const StructDecl * decl );
    128128        /// Adds an enum declaration to the symbol table
    129         void addEnum( const EnumDecl *decl );
     129        void addEnum( const EnumDecl * decl );
    130130        /// Adds a union declaration to the symbol table by name
    131         void addUnion( const std::string &id );
     131        void addUnion( const std::string & id );
    132132        /// Adds a union declaration to the symbol table
    133133        void addUnion( const UnionDecl * decl );
  • src/AST/Type.hpp

    r4741dfe rd4b6638  
    7777};
    7878
    79 /// Set the `is_lvalue` qualifier on this type, cloning only if necessary
     79/// Clear/reset the qualifiers on this type, cloning only if necessary
    8080template< enum Node::ref_type ref_t >
    81 void add_lvalue( ptr_base< Type, ref_t > & p ) {
    82         if ( ! p->qualifiers.is_lvalue ) p.get_and_mutate()->qualifiers.is_lvalue = true;
     81void reset_qualifiers( ptr_base< Type, ref_t > & p, CV::Qualifiers q = {} ) {
     82        if ( p->qualifiers.val != q.val ) p.get_and_mutate()->qualifiers = q;
    8383}
    8484
    85 /// Clear the qualifiers on this type, cloning only if necessary
     85/// Add the specified qualifiers to this type, cloning only if necessary
    8686template< enum Node::ref_type ref_t >
    87 void clear_qualifiers( ptr_base< Type, ref_t > & p ) {
    88         if ( p->qualifiers != CV::Qualifiers{} ) p.get_and_mutate()->qualifiers = CV::Qualifiers{};
     87void add_qualifiers( ptr_base< Type, ref_t > & p, CV::Qualifiers q ) {
     88        if ( ( p->qualifiers.val & q.val ) != q.val ) p.get_and_mutate()->qualifiers |= q;
     89}
     90
     91/// Remove the specified qualifiers from this type, cloning only if necessary
     92template< enum Node::ref_type ref_t >
     93void remove_qualifiers( ptr_base< Type, ref_t > & p, CV::Qualifiers q ) {
     94        if ( ( p->qualifiers.val & q.val ) != 0 ) p.get_and_mutate()->qualifiers -= q;
    8995}
    9096
  • src/AST/TypeEnvironment.cpp

    r4741dfe rd4b6638  
    235235}
    236236
     237/// true if a type is a function type
     238bool isFtype( const Type * type ) {
     239        if ( dynamic_cast< const FunctionType * >( type ) ) {
     240                return true;
     241        } else if ( auto typeInst = dynamic_cast< const TypeInstType * >( type ) ) {
     242                return typeInst->kind == TypeVar::Ftype;
     243        } else return false;
     244}
     245
    237246namespace {
    238         /// true if a type is a function type
    239         bool isFtype( const Type * type ) {
    240                 if ( dynamic_cast< const FunctionType * >( type ) ) {
    241                         return true;
    242                 } else if ( auto typeInst = dynamic_cast< const TypeInstType * >( type ) ) {
    243                         return typeInst->kind == TypeVar::Ftype;
    244                 } else return false;
    245         }
    246 
    247247        /// true if the given type can be bound to the given type variable
    248248        bool tyVarCompatible( const TypeDecl::Data & data, const Type * type ) {
     
    285285                        ptr<Type> common;
    286286                        ptr<Type> newType = it->bound;
    287                         newType.get_and_mutate()->qualifiers = typeInst->qualifiers;
     287                        reset_qualifiers( newType, typeInst->qualifiers );
    288288                        if ( unifyInexact(
    289289                                        newType, target, *this, need, have, open,
     
    291291                                if ( common ) {
    292292                                        it->bound = std::move(common);
    293                                         clear_qualifiers( it->bound );
     293                                        reset_qualifiers( it->bound );
    294294                                }
    295295                        } else return false;
    296296                } else {
    297297                        it->bound = std::move(target);
    298                         clear_qualifiers( it->bound );
     298                        reset_qualifiers( it->bound );
    299299                        it->allowWidening = widen.first && widen.second;
    300300                }
     
    351351                        if ( common ) {
    352352                                c1->bound = std::move(common);
    353                                 clear_qualifiers( c1->bound );
     353                                reset_qualifiers( c1->bound );
    354354                        }
    355355                        c1->data.isComplete |= data.isComplete;
     
    411411                                if ( common ) {
    412412                                        to.bound = std::move(common);
    413                                         clear_qualifiers( to.bound );
     413                                        reset_qualifiers( to.bound );
    414414                                }
    415415                        } else return false; // cannot unify
  • src/AST/TypeEnvironment.hpp

    r4741dfe rd4b6638  
    112112        EqvClass( const std::string & v, const Type * b, bool w, const TypeDecl::Data & d )
    113113        : vars{ v }, bound( b ), allowWidening( w ), data( d ) {
    114                 clear_qualifiers( bound );
     114                reset_qualifiers( bound );
    115115        }
    116116
  • src/AST/porting.md

    r4741dfe rd4b6638  
    109109    * `SymTab::Indexer` => `ast::SymbolTable`
    110110    * `SymTab/Indexer.{h,cc}` => `AST/SymbolTable.{hpp,cpp}`
    111     * **TODO** `WithIndexer` => `WithSymbolTable`
     111    * `WithIndexer` => `WithSymbolTable`
    112112      * `indexer` => `symTab`
    113113    * `IdData::deleteStmt` => `IdData::deleter`
    114114    * `lookupId()` now returns a vector rather than an out-param list
    115     * To avoid name collisions:
    116       * `SymTab::Mangler` => `Mangle`
     115  * To avoid name collisions:
     116    * `SymTab::Mangler` => `Mangle`
    117117  * `ResolvExpr::TypeEnvironment` => `ast::TypeEnvironment`
    118118    * in `AST/TypeEnvironment.hpp`
  • src/ResolvExpr/CommonType.cc

    r4741dfe rd4b6638  
    1818#include <utility>                       // for pair
    1919
     20#include "AST/Decl.hpp"
     21#include "AST/Type.hpp"
    2022#include "Common/PassVisitor.h"
    2123#include "ResolvExpr/TypeEnvironment.h"  // for OpenVarSet, AssertionSet
     
    3537
    3638namespace ResolvExpr {
    37         struct CommonType : public WithShortCircuiting {
    38                 CommonType( Type *type2, bool widenFirst, bool widenSecond, const SymTab::Indexer &indexer, TypeEnvironment &env, const OpenVarSet &openVars );
     39        struct CommonType_old : public WithShortCircuiting {
     40                CommonType_old( Type *type2, bool widenFirst, bool widenSecond, const SymTab::Indexer &indexer, TypeEnvironment &env, const OpenVarSet &openVars );
    3941                Type *get_result() const { return result; }
    4042
     
    9496
    9597        Type *commonType( Type *type1, Type *type2, bool widenFirst, bool widenSecond, const SymTab::Indexer &indexer, TypeEnvironment &env, const OpenVarSet &openVars ) {
    96                 PassVisitor<CommonType> visitor( type2, widenFirst, widenSecond, indexer, env, openVars );
     98                PassVisitor<CommonType_old> visitor( type2, widenFirst, widenSecond, indexer, env, openVars );
    9799
    98100                int depth1 = type1->referenceDepth();
     
    176178        }
    177179
    178         const ast::Type * commonType(
    179                         const ast::Type * type1, const ast::Type * type2, WidenMode widen,
    180                         const ast::SymbolTable & symtab, ast::TypeEnvironment & env,
    181                         const ast::OpenVarSet & open ) {
    182                 #warning unimplemented
    183                 (void)type1; (void)type2; (void)widen; (void)symtab; (void)env; (void)open;
    184                 assert(false);
    185                 return nullptr;
    186         }
    187 
    188180        // GENERATED START, DO NOT EDIT
    189181        // GENERATED BY BasicTypes-gen.cc
     
    493485        );
    494486
    495         CommonType::CommonType( Type *type2, bool widenFirst, bool widenSecond, const SymTab::Indexer &indexer, TypeEnvironment &env, const OpenVarSet &openVars )
     487        CommonType_old::CommonType_old( Type *type2, bool widenFirst, bool widenSecond, const SymTab::Indexer &indexer, TypeEnvironment &env, const OpenVarSet &openVars )
    496488                : result( 0 ), type2( type2 ), widenFirst( widenFirst ), widenSecond( widenSecond ), indexer( indexer ), env( env ), openVars( openVars ) {
    497489        }
    498490
    499         void CommonType::postvisit( VoidType * ) {}
    500 
    501         void CommonType::postvisit( BasicType *basicType ) {
     491        void CommonType_old::postvisit( VoidType * ) {}
     492
     493        void CommonType_old::postvisit( BasicType *basicType ) {
    502494                if ( BasicType *otherBasic = dynamic_cast< BasicType* >( type2 ) ) {
    503495                        BasicType::Kind newType = commonTypes[ basicType->get_kind() ][ otherBasic->get_kind() ];
     
    515507
    516508        template< typename Pointer >
    517         void CommonType::getCommonWithVoidPointer( Pointer* voidPointer, Pointer* otherPointer ) {
     509        void CommonType_old::getCommonWithVoidPointer( Pointer* voidPointer, Pointer* otherPointer ) {
    518510                if ( TypeInstType* var = dynamic_cast< TypeInstType* >( otherPointer->get_base() ) ) {
    519511                        OpenVarSet::const_iterator entry = openVars.find( var->get_name() );
     
    528520        }
    529521
    530         void CommonType::postvisit( PointerType *pointerType ) {
     522        void CommonType_old::postvisit( PointerType *pointerType ) {
    531523                if ( PointerType *otherPointer = dynamic_cast< PointerType* >( type2 ) ) {
    532524                        // std::cerr << "commonType: two pointers: " << pointerType << " / " << otherPointer << std::endl;
     
    563555        }
    564556
    565         void CommonType::postvisit( ArrayType * ) {}
    566 
    567         void CommonType::postvisit( ReferenceType *refType ) {
     557        void CommonType_old::postvisit( ArrayType * ) {}
     558
     559        void CommonType_old::postvisit( ReferenceType *refType ) {
    568560                if ( ReferenceType *otherRef = dynamic_cast< ReferenceType* >( type2 ) ) {
    569561                        // std::cerr << "commonType: both references: " << refType << " / " << otherRef << std::endl;
     
    600592        }
    601593
    602         void CommonType::postvisit( FunctionType * ) {}
    603         void CommonType::postvisit( StructInstType * ) {}
    604         void CommonType::postvisit( UnionInstType * ) {}
    605 
    606         void CommonType::postvisit( EnumInstType *enumInstType ) {
     594        void CommonType_old::postvisit( FunctionType * ) {}
     595        void CommonType_old::postvisit( StructInstType * ) {}
     596        void CommonType_old::postvisit( UnionInstType * ) {}
     597
     598        void CommonType_old::postvisit( EnumInstType *enumInstType ) {
    607599                if ( dynamic_cast< BasicType * >( type2 ) || dynamic_cast< ZeroType* >( type2 ) || dynamic_cast< OneType* >( type2 ) ) {
    608600                        // reuse BasicType, EnumInstType code by swapping type2 with enumInstType
     
    611603        }
    612604
    613         void CommonType::postvisit( TraitInstType * ) {
    614         }
    615 
    616         void CommonType::postvisit( TypeInstType *inst ) {
     605        void CommonType_old::postvisit( TraitInstType * ) {
     606        }
     607
     608        void CommonType_old::postvisit( TypeInstType *inst ) {
    617609                if ( widenFirst ) {
    618610                        NamedTypeDecl *nt = indexer.lookupType( inst->get_name() );
     
    636628        }
    637629
    638         void CommonType::postvisit( TupleType * ) {}
    639         void CommonType::postvisit( VarArgsType * ) {}
    640 
    641         void CommonType::postvisit( ZeroType *zeroType ) {
     630        void CommonType_old::postvisit( TupleType * ) {}
     631        void CommonType_old::postvisit( VarArgsType * ) {}
     632
     633        void CommonType_old::postvisit( ZeroType *zeroType ) {
    642634                if ( widenFirst ) {
    643635                        if ( dynamic_cast< BasicType* >( type2 ) || dynamic_cast< PointerType* >( type2 ) || dynamic_cast< EnumInstType* >( type2 ) ) {
     
    653645        }
    654646
    655         void CommonType::postvisit( OneType *oneType ) {
     647        void CommonType_old::postvisit( OneType *oneType ) {
    656648                if ( widenFirst ) {
    657649                        if ( dynamic_cast< BasicType* >( type2 ) || dynamic_cast< EnumInstType* >( type2 ) ) {
     
    666658                }
    667659        }
     660
     661        class CommonType_new final : public ast::WithShortCircuiting {
     662                const ast::Type * type2;
     663                WidenMode widen;
     664                const ast::SymbolTable & symtab;
     665                ast::TypeEnvironment & tenv;
     666                const ast::OpenVarSet & open;
     667        public:
     668                ast::ptr< ast::Type > result;
     669
     670                CommonType_new(
     671                        const ast::Type * t2, WidenMode w, const ast::SymbolTable & st,
     672                        ast::TypeEnvironment & env, const ast::OpenVarSet & o )
     673                : type2( t2 ), widen( w ), symtab( st ), tenv( env ), open( o ), result() {}
     674
     675                void previsit( const ast::Node * ) { visit_children = false; }
     676
     677                void postvisit( const ast::VoidType * ) {}
     678
     679                void postvisit( const ast::BasicType * basic ) {
     680                        if ( auto basic2 = dynamic_cast< const ast::BasicType * >( type2 ) ) {
     681                                #warning remove casts when `commonTypes` moved to new AST
     682                                ast::BasicType::Kind kind = (ast::BasicType::Kind)(int)commonTypes[ (BasicType::Kind)(int)basic->kind ][ (BasicType::Kind)(int)basic2->kind ];
     683                                if (
     684                                        ( ( kind == basic->kind && basic->qualifiers >= basic2->qualifiers )
     685                                                || widen.first )
     686                                        && ( ( kind == basic2->kind && basic->qualifiers <= basic2->qualifiers )
     687                                                || widen.second )
     688                                ) {
     689                                        result = new ast::BasicType{ kind, basic->qualifiers | basic2->qualifiers };
     690                                }
     691                        } else if (
     692                                dynamic_cast< const ast::EnumInstType * >( type2 )
     693                                || dynamic_cast< const ast::ZeroType * >( type2 )
     694                                || dynamic_cast< const ast::OneType * >( type2 )
     695                        ) {
     696                                #warning remove casts when `commonTypes` moved to new AST
     697                                ast::BasicType::Kind kind = (ast::BasicType::Kind)(int)commonTypes[ (BasicType::Kind)(int)basic->kind ][ (BasicType::Kind)(int)ast::BasicType::SignedInt ];
     698                                if (
     699                                        ( ( kind == basic->kind && basic->qualifiers >= type2->qualifiers )
     700                                                || widen.first )
     701                                        && ( ( kind != basic->kind && basic->qualifiers <= type2->qualifiers )
     702                                                || widen.second )
     703                                ) {
     704                                        result = new ast::BasicType{ kind, basic->qualifiers | type2->qualifiers };
     705                                }
     706                        }
     707                }
     708
     709        private:
     710                template< typename Pointer >
     711                void getCommonWithVoidPointer( const Pointer * voidPtr, const Pointer * oPtr ) {
     712                        const ast::Type * base = oPtr->base;
     713                        if ( auto var = dynamic_cast< const ast::TypeInstType * >( base ) ) {
     714                                auto entry = open.find( var->name );
     715                                if ( entry != open.end() ) {
     716                                        ast::AssertionSet need, have;
     717                                        if ( ! tenv.bindVar(
     718                                                var, voidPtr->base, entry->second, need, have, open, widen, symtab )
     719                                        ) return;
     720                                }
     721                        }
     722                        result = voidPtr;
     723                        add_qualifiers( result, oPtr->qualifiers );
     724                }
     725
     726        public:
     727                void postvisit( const ast::PointerType * pointer ) {
     728                        if ( auto pointer2 = dynamic_cast< const ast::PointerType * >( type2 ) ) {
     729                                if (
     730                                        widen.first
     731                                        && pointer2->base.as< ast::VoidType >()
     732                                        && ! ast::isFtype( pointer->base )
     733                                ) {
     734                                        getCommonWithVoidPointer( pointer2, pointer );
     735                                } else if (
     736                                        widen.second
     737                                        && pointer->base.as< ast::VoidType >()
     738                                        && ! ast::isFtype( pointer2->base )
     739                                ) {
     740                                        getCommonWithVoidPointer( pointer, pointer2 );
     741                                } else if (
     742                                        ( pointer->base->qualifiers >= pointer2->base->qualifiers || widen.first )
     743                                        && ( pointer->base->qualifiers <= pointer2->base->qualifiers || widen.second )
     744                                ) {
     745                                        ast::CV::Qualifiers q1 = pointer->base->qualifiers;
     746                                        ast::CV::Qualifiers q2 = pointer2->base->qualifiers;
     747
     748                                        // force t{1,2} to be cloned if their qualifiers must be stripped, so that
     749                                        // pointer{,2}->base are unchanged
     750                                        ast::ptr< ast::Type > t1{ pointer->base }, t2{ pointer2->base };
     751                                        reset_qualifiers( t1 );
     752                                        reset_qualifiers( t2 );
     753                                       
     754                                        ast::AssertionSet have, need;
     755                                        ast::OpenVarSet newOpen{ open };
     756                                        if ( unifyExact( t1, t2, tenv, have, need, newOpen, noWiden(), symtab ) ) {
     757                                                result = pointer;
     758                                                if ( q1.val != q2.val ) {
     759                                                        // reset result->base->qualifiers to be union of two base qualifiers
     760                                                        strict_dynamic_cast< ast::PointerType * >(
     761                                                                result.get_and_mutate()
     762                                                        )->base.get_and_mutate()->qualifiers = q1 | q2;
     763                                                }
     764                                        }
     765                                }
     766                        } else if ( widen.second && dynamic_cast< const ast::ZeroType * >( type2 ) ) {
     767                                result = pointer;
     768                                add_qualifiers( result, type2->qualifiers );
     769                        }
     770                }
     771
     772                void postvisit( const ast::ArrayType * ) {}
     773
     774                void postvisit( const ast::ReferenceType * ref ) {
     775                        if ( auto ref2 = dynamic_cast< const ast::ReferenceType * >( type2 ) ) {
     776                                if (
     777                                        widen.first && ref2->base.as< ast::VoidType >() && ! ast::isFtype( ref->base )
     778                                ) {
     779                                        getCommonWithVoidPointer( ref2, ref );
     780                                } else if (
     781                                        widen.second && ref->base.as< ast::VoidType>() && ! ast::isFtype( ref2->base )
     782                                ) {
     783                                        getCommonWithVoidPointer( ref, ref2 );
     784                                } else if (
     785                                        ( ref->base->qualifiers >= ref2->base->qualifiers || widen.first )
     786                                        && ( ref->base->qualifiers <= ref2->base->qualifiers || widen.second )
     787                                ) {
     788                                        ast::CV::Qualifiers q1 = ref->base->qualifiers, q2 = ref2->base->qualifiers;
     789
     790                                        // force t{1,2} to be cloned if their qualifiers must be stripped, so that
     791                                        // ref{,2}->base are unchanged
     792                                        ast::ptr< ast::Type > t1{ ref->base }, t2{ ref2->base };
     793                                        reset_qualifiers( t1 );
     794                                        reset_qualifiers( t2 );
     795
     796                                        ast::AssertionSet have, need;
     797                                        ast::OpenVarSet newOpen{ open };
     798                                        if ( unifyExact( t1, t2, tenv, have, need, newOpen, noWiden(), symtab ) ) {
     799                                                result = ref;
     800                                                if ( q1.val != q2.val ) {
     801                                                        // reset result->base->qualifiers to be union of two base qualifiers
     802                                                        strict_dynamic_cast< ast::ReferenceType * >(
     803                                                                result.get_and_mutate()
     804                                                        )->base.get_and_mutate()->qualifiers = q1 | q2;
     805                                                }
     806                                        }
     807                                }
     808                        } else if ( widen.second && dynamic_cast< const ast::ZeroType * >( type2 ) ) {
     809                                result = ref;
     810                                add_qualifiers( result, type2->qualifiers );
     811                        }
     812                }
     813
     814                void postvisit( const ast::FunctionType * ) {}
     815
     816                void postvisit( const ast::StructInstType * ) {}
     817
     818                void postvisit( const ast::UnionInstType * ) {}
     819
     820                void postvisit( const ast::EnumInstType * enumInst ) {
     821                        if (
     822                                dynamic_cast< const ast::BasicType * >( type2 )
     823                                || dynamic_cast< const ast::ZeroType * >( type2 )
     824                                || dynamic_cast< const ast::OneType * >( type2 )
     825                        ) {
     826                                // reuse BasicType/EnumInstType common type by swapping
     827                                result = commonType( type2, enumInst, widen, symtab, tenv, open );
     828                        }
     829                }
     830
     831                void postvisit( const ast::TraitInstType * ) {}
     832
     833                void postvisit( const ast::TypeInstType * inst ) {
     834                        if ( ! widen.first ) return;
     835                        if ( const ast::NamedTypeDecl * nt = symtab.lookupType( inst->name ) ) {
     836                                if ( const ast::Type * base =
     837                                                strict_dynamic_cast< const ast::TypeDecl * >( nt )->base
     838                                ) {
     839                                        ast::CV::Qualifiers q1 = inst->qualifiers, q2 = type2->qualifiers;
     840
     841                                        // force t{1,2} to be cloned if their qualifiers must be mutated
     842                                        ast::ptr< ast::Type > t1{ base }, t2{ type2 };
     843                                        reset_qualifiers( t1, q1 );
     844                                        reset_qualifiers( t2 );
     845
     846                                        ast::AssertionSet have, need;
     847                                        ast::OpenVarSet newOpen{ open };
     848                                        if ( unifyExact( t1, t2, tenv, have, need, newOpen, noWiden(), symtab ) ) {
     849                                                result = type2;
     850                                                reset_qualifiers( result, q1 | q2 );
     851                                        }
     852                                }
     853                        }
     854                }
     855
     856                void postvisit( const ast::TupleType * ) {}
     857
     858                void postvisit( const ast::VarArgsType * ) {}
     859
     860                void postvisit( const ast::ZeroType * zero ) {
     861                        if ( ! widen.first ) return;
     862                        if (
     863                                dynamic_cast< const ast::BasicType * >( type2 )
     864                                || dynamic_cast< const ast::PointerType * >( type2 )
     865                                || dynamic_cast< const ast::EnumInstType * >( type2 )
     866                        ) {
     867                                if ( widen.second || zero->qualifiers <= type2->qualifiers ) {
     868                                        result = type2;
     869                                        add_qualifiers( result, zero->qualifiers );
     870                                }
     871                        } else if ( widen.second && dynamic_cast< const ast::OneType * >( type2 ) ) {
     872                                result = new ast::BasicType{
     873                                        ast::BasicType::SignedInt, zero->qualifiers | type2->qualifiers };
     874                        }
     875                }
     876
     877                void postvisit( const ast::OneType * one ) {
     878                        if ( ! widen.first ) return;
     879                        if (
     880                                dynamic_cast< const ast::BasicType * >( type2 )
     881                                || dynamic_cast< const ast::EnumInstType * >( type2 )
     882                        ) {
     883                                if ( widen.second || one->qualifiers <= type2->qualifiers ) {
     884                                        result = type2;
     885                                        add_qualifiers( result, one->qualifiers );
     886                                }
     887                        } else if ( widen.second && dynamic_cast< const ast::ZeroType * >( type2 ) ) {
     888                                result = new ast::BasicType{
     889                                        ast::BasicType::SignedInt, one->qualifiers | type2->qualifiers };
     890                        }
     891                }
     892
     893        };
     894
     895        namespace {
     896                ast::ptr< ast::Type > handleReference(
     897                        const ast::ptr< ast::Type > & t1, const ast::ptr< ast::Type > & t2, WidenMode widen,
     898                        const ast::SymbolTable & symtab, ast::TypeEnvironment & env,
     899                        const ast::OpenVarSet & open
     900                ) {
     901                        ast::ptr<ast::Type> common;
     902                        ast::AssertionSet have, need;
     903                        ast::OpenVarSet newOpen{ open };
     904
     905                        // need unify to bind type variables
     906                        if ( unify( t1, t2, env, have, need, newOpen, symtab, common ) ) {
     907                                ast::CV::Qualifiers q1 = t1->qualifiers, q2 = t2->qualifiers;
     908                                PRINT(
     909                                        std::cerr << "unify success: " << widenFirst << " " << widenSecond << std::endl;
     910                                )
     911                                if ( ( widen.first || q2 <= q1 ) && ( widen.second || q1 <= q2 ) ) {
     912                                        PRINT(
     913                                                std::cerr << "widen okay" << std::endl;
     914                                        )
     915                                        add_qualifiers( common, q1 | q2 );
     916                                        return common;
     917                                }
     918                        }
     919
     920                        PRINT(
     921                                std::cerr << "exact unify failed: " << t1 << " " << t2 << std::endl;
     922                        )
     923                        return { nullptr };
     924                }
     925        }
     926
     927        ast::ptr< ast::Type > commonType(
     928                        const ast::ptr< ast::Type > & type1, const ast::ptr< ast::Type > & type2,
     929                        WidenMode widen, const ast::SymbolTable & symtab, ast::TypeEnvironment & env,
     930                        const ast::OpenVarSet & open
     931        ) {
     932                unsigned depth1 = type1->referenceDepth();
     933                unsigned depth2 = type2->referenceDepth();
     934
     935                if ( depth1 != depth2 ) {  // implies depth1 > 0 || depth2 > 0
     936                        PRINT(
     937                                std::cerr << "reference depth diff: " << (depth1-depth2) << std::endl;
     938                        )
     939                        ast::ptr< ast::Type > result;
     940                        const ast::ReferenceType * ref1 = type1.as< ast::ReferenceType >();
     941                        const ast::ReferenceType * ref2 = type1.as< ast::ReferenceType >();
     942                       
     943                        if ( depth1 > depth2 ) {
     944                                assert( ref1 );
     945                                result = handleReference( ref1->base, type2, widen, symtab, env, open );
     946                        } else {  // implies depth1 < depth2
     947                                assert( ref2 );
     948                                result = handleReference( type1, ref2->base, widen, symtab, env, open );
     949                        }
     950
     951                        if ( result && ref1 ) {
     952                                // formal is reference, so result should be reference
     953                                PRINT(
     954                                        std::cerr << "formal is reference; result should be reference" << std::endl;
     955                                )
     956                                result = new ast::ReferenceType{ result, ref1->qualifiers };
     957                        }
     958
     959                        PRINT(
     960                                std::cerr << "common type of reference [" << type1 << "] and [" << type2 << "] is "
     961                                "[" << result << "]" << std::endl;
     962                        )
     963                        return result;
     964                }
     965                // otherwise both are reference types of the same depth and this is handled by the visitor
     966                ast::Pass<CommonType_new> visitor{ type2, widen, symtab, env, open };
     967                type1->accept( visitor );
     968                ast::ptr< ast::Type > result = visitor.pass.result;
     969
     970                // handling for opaque type declarations (?)
     971                if ( ! result && widen.second ) {
     972                        if ( const ast::TypeInstType * inst = type2.as< ast::TypeInstType >() ) {
     973                                if ( const ast::NamedTypeDecl * nt = symtab.lookupType( inst->name ) ) {
     974                                        auto type = strict_dynamic_cast< const ast::TypeDecl * >( nt );
     975                                        if ( type->base ) {
     976                                                ast::CV::Qualifiers q1 = type1->qualifiers, q2 = type2->qualifiers;
     977                                                ast::AssertionSet have, need;
     978                                                ast::OpenVarSet newOpen{ open };
     979
     980                                                // force t{1,2} to be cloned if its qualifiers must be stripped, so that
     981                                                // type1 and type->base are left unchanged; calling convention forces
     982                                                // {type1,type->base}->strong_ref >= 1
     983                                                ast::ptr<ast::Type> t1{ type1 }, t2{ type->base };
     984                                                reset_qualifiers( t1 );
     985                                                reset_qualifiers( t2, q1 );
     986                                               
     987                                                if ( unifyExact( t1, t2, env, have, need, newOpen, noWiden(), symtab ) ) {
     988                                                        result = t1;
     989                                                        reset_qualifiers( result, q1 | q2 );
     990                                                }
     991                                        }
     992                                }
     993                        }
     994                }
     995
     996                return result;
     997        }
     998
    668999} // namespace ResolvExpr
    6691000
  • src/ResolvExpr/FindOpenVars.cc

    r4741dfe rd4b6638  
    1919#include <map>                    // for map<>::mapped_type
    2020
     21#include "AST/Pass.hpp"
     22#include "AST/Type.hpp"
    2123#include "Common/PassVisitor.h"
    2224#include "SynTree/Declaration.h"  // for TypeDecl, DeclarationWithType (ptr ...
     
    2426
    2527namespace ResolvExpr {
    26         struct FindOpenVars : public WithGuards {
    27                 FindOpenVars( OpenVarSet &openVars, OpenVarSet &closedVars, AssertionSet &needAssertions, AssertionSet &haveAssertions, bool firstIsOpen );
     28        struct FindOpenVars_old : public WithGuards {
     29                FindOpenVars_old( OpenVarSet &openVars, OpenVarSet &closedVars, AssertionSet &needAssertions, AssertionSet &haveAssertions, bool firstIsOpen );
    2830
    2931                void previsit( PointerType * pointerType );
     
    4042
    4143        void findOpenVars( Type *type, OpenVarSet &openVars, OpenVarSet &closedVars, AssertionSet &needAssertions, AssertionSet &haveAssertions, bool firstIsOpen ) {
    42                 PassVisitor<FindOpenVars> finder( openVars, closedVars, needAssertions, haveAssertions, firstIsOpen );
     44                PassVisitor<FindOpenVars_old> finder( openVars, closedVars, needAssertions, haveAssertions, firstIsOpen );
    4345                type->accept( finder );
    4446        }
    4547
    46         FindOpenVars::FindOpenVars( OpenVarSet &openVars, OpenVarSet &closedVars, AssertionSet &needAssertions, AssertionSet &haveAssertions, bool firstIsOpen )
     48        FindOpenVars_old::FindOpenVars_old( OpenVarSet &openVars, OpenVarSet &closedVars, AssertionSet &needAssertions, AssertionSet &haveAssertions, bool firstIsOpen )
    4749                : openVars( openVars ), closedVars( closedVars ), needAssertions( needAssertions ), haveAssertions( haveAssertions ), nextIsOpen( firstIsOpen ) {
    4850        }
    4951
    50         void FindOpenVars::common_action( Type *type ) {
     52        void FindOpenVars_old::common_action( Type *type ) {
    5153                if ( nextIsOpen ) {
    5254                        for ( Type::ForallList::const_iterator i = type->get_forall().begin(); i != type->get_forall().end(); ++i ) {
     
    7678        }
    7779
    78         void FindOpenVars::previsit(PointerType *pointerType) {
     80        void FindOpenVars_old::previsit(PointerType *pointerType) {
    7981                common_action( pointerType );
    8082        }
    8183
    82         void FindOpenVars::previsit(ArrayType *arrayType) {
     84        void FindOpenVars_old::previsit(ArrayType *arrayType) {
    8385                common_action( arrayType );
    8486        }
    8587
    86         void FindOpenVars::previsit(FunctionType *functionType) {
     88        void FindOpenVars_old::previsit(FunctionType *functionType) {
    8789                common_action( functionType );
    8890                nextIsOpen = ! nextIsOpen;
     
    9092        }
    9193
    92         void FindOpenVars::previsit(TupleType *tupleType) {
     94        void FindOpenVars_old::previsit(TupleType *tupleType) {
    9395                common_action( tupleType );
     96        }
     97
     98        namespace {
     99                struct FindOpenVars_new final : public ast::WithGuards {
     100                        ast::OpenVarSet & open;
     101                        ast::OpenVarSet & closed;
     102                        ast::AssertionSet & need;
     103                        ast::AssertionSet & have;
     104                        bool nextIsOpen;
     105
     106                        FindOpenVars_new(
     107                                ast::OpenVarSet & o, ast::OpenVarSet & c, ast::AssertionSet & n,
     108                                ast::AssertionSet & h, FirstMode firstIsOpen )
     109                        : open( o ), closed( c ), need( n ), have( h ), nextIsOpen( firstIsOpen ) {}
     110
     111                        void previsit( const ast::FunctionType * type ) {
     112                                // mark open/closed variables
     113                                if ( nextIsOpen ) {
     114                                        for ( const ast::TypeDecl * decl : type->forall ) {
     115                                                open[ decl->name ] = ast::TypeDecl::Data{ decl };
     116                                                for ( const ast::DeclWithType * assert : decl->assertions ) {
     117                                                        need[ assert ].isUsed = false;
     118                                                }
     119                                        }
     120                                } else {
     121                                        for ( const ast::TypeDecl * decl : type->forall ) {
     122                                                closed[ decl->name ] = ast::TypeDecl::Data{ decl };
     123                                                for ( const ast::DeclWithType * assert : decl->assertions ) {
     124                                                        have[ assert ].isUsed = false;
     125                                                }
     126                                        }
     127                                }
     128
     129                                // flip open variables for contained function types
     130                                nextIsOpen = ! nextIsOpen;
     131                                GuardAction( [this](){ nextIsOpen = ! nextIsOpen; } );
     132                        }
     133
     134                };
    94135        }
    95136
     
    97138                        const ast::Type * type, ast::OpenVarSet & open, ast::OpenVarSet & closed,
    98139                        ast::AssertionSet & need, ast::AssertionSet & have, FirstMode firstIsOpen ) {
    99                 #warning unimplemented
    100                 (void)type; (void)open; (void)closed; (void)need; (void)have; (void)firstIsOpen;
    101                 assert(false);
     140                ast::Pass< FindOpenVars_new > finder{ open, closed, need, have, firstIsOpen };
     141                type->accept( finder );
    102142        }
    103143} // namespace ResolvExpr
  • src/ResolvExpr/Resolver.cc

    r4741dfe rd4b6638  
    938938
    939939        class Resolver_new final
    940         : public ast::WithIndexer, public ast::WithGuards, public ast::WithVisitorRef<Resolver_new>,
    941           public ast::WithShortCircuiting, public ast::WithStmtsToAdd<> {
     940        : public ast::WithSymbolTable, public ast::WithGuards,
     941          public ast::WithVisitorRef<Resolver_new>, public ast::WithShortCircuiting,
     942          public ast::WithStmtsToAdd<> {
    942943                 
    943944        public:
    944945                Resolver_new() = default;
    945                 Resolver_new( const ast::SymbolTable & syms ) { /*symtab = syms;*/ }
     946                Resolver_new( const ast::SymbolTable & syms ) { symtab = syms; }
    946947
    947948                void previsit( ast::FunctionDecl * functionDecl );
  • src/ResolvExpr/Unify.cc

    r4741dfe rd4b6638  
    136136
    137137                return unifyExact(
    138                         newFirst, newSecond, newEnv, need, have, open, WidenMode{ false, false }, symtab );
     138                        newFirst, newSecond, newEnv, need, have, open, noWiden(), symtab );
    139139        }
    140140
     
    173173                env.apply( newFirst );
    174174                env.apply( newSecond );
    175                 clear_qualifiers( newFirst );
    176                 clear_qualifiers( newSecond );
     175                reset_qualifiers( newFirst );
     176                reset_qualifiers( newSecond );
    177177
    178178                return unifyExact(
    179                         newFirst, newSecond, newEnv, need, have, open, WidenMode{ false, false }, symtab );
     179                        newFirst, newSecond, newEnv, need, have, open, noWiden(), symtab );
    180180        }
    181181
     
    700700        }
    701701
    702         class Unify_new : public ast::WithShortCircuiting {
     702        class Unify_new final : public ast::WithShortCircuiting {
    703703                const ast::Type * type2;
    704704                ast::TypeEnvironment & tenv;
     
    720720                void previsit( const ast::Node * ) { visit_children = false; }
    721721               
    722                 void previsit( const ast::VoidType * ) {
    723                         visit_children = false;
     722                void postvisit( const ast::VoidType * ) {
    724723                        result = dynamic_cast< const ast::VoidType * >( type2 );
    725724                }
    726725
    727                 void previsit( const ast::BasicType * basic ) {
    728                         visit_children = false;
     726                void postvisit( const ast::BasicType * basic ) {
    729727                        if ( auto basic2 = dynamic_cast< const ast::BasicType * >( type2 ) ) {
    730728                                result = basic->kind == basic2->kind;
     
    732730                }
    733731
    734                 void previsit( const ast::PointerType * pointer ) {
    735                         visit_children = false;
     732                void postvisit( const ast::PointerType * pointer ) {
    736733                        if ( auto pointer2 = dynamic_cast< const ast::PointerType * >( type2 ) ) {
    737734                                result = unifyExact(
    738735                                        pointer->base, pointer2->base, tenv, need, have, open,
    739                                         WidenMode{ false, false }, symtab );
    740                         }
    741                 }
    742 
    743                 void previsit( const ast::ArrayType * array ) {
    744                         visit_children = false;
     736                                        noWiden(), symtab );
     737                        }
     738                }
     739
     740                void postvisit( const ast::ArrayType * array ) {
    745741                        auto array2 = dynamic_cast< const ast::ArrayType * >( type2 );
    746742                        if ( ! array2 ) return;
     
    761757
    762758                        result = unifyExact(
    763                                 array->base, array2->base, tenv, need, have, open, WidenMode{ false, false },
     759                                array->base, array2->base, tenv, need, have, open, noWiden(),
    764760                                symtab );
    765761                }
    766762
    767                 void previsit( const ast::ReferenceType * ref ) {
    768                         visit_children = false;
     763                void postvisit( const ast::ReferenceType * ref ) {
    769764                        if ( auto ref2 = dynamic_cast< const ast::ReferenceType * >( type2 ) ) {
    770765                                result = unifyExact(
    771                                         ref->base, ref2->base, tenv, need, have, open, WidenMode{ false, false },
     766                                        ref->base, ref2->base, tenv, need, have, open, noWiden(),
    772767                                        symtab );
    773768                        }
     
    783778                        TtypeExpander_new( ast::TypeEnvironment & env ) : tenv( env ) {}
    784779
    785                         const ast::Type * postmutate( const ast::TypeInstType * typeInst ) {
     780                        const ast::Type * postvisit( const ast::TypeInstType * typeInst ) {
    786781                                if ( const ast::EqvClass * clz = tenv.lookup( typeInst->name ) ) {
    787782                                        // expand ttype parameter into its actual type
     
    811806                                        // overloaded on outermost mutex and a mutex function has different
    812807                                        // requirements than a non-mutex function
    813                                         t.get_and_mutate()->qualifiers
    814                                                 -= ast::CV::Const | ast::CV::Volatile | ast::CV::Atomic;
     808                                        remove_qualifiers( t, ast::CV::Const | ast::CV::Volatile | ast::CV::Atomic );
    815809                                        dst.emplace_back( new ast::ObjectDecl{ d->location, "", t } );
    816810                                }
     
    851845                                        return unifyExact(
    852846                                                t1, tupleFromDecls( crnt2, end2 ), env, need, have, open,
    853                                                 WidenMode{ false, false }, symtab );
     847                                                noWiden(), symtab );
    854848                                } else if ( ! isTuple1 && isTuple2 ) {
    855849                                        // combine remainder of list1, then unify
    856850                                        return unifyExact(
    857851                                                tupleFromDecls( crnt1, end1 ), t2, env, need, have, open,
    858                                                 WidenMode{ false, false }, symtab );
     852                                                noWiden(), symtab );
    859853                                }
    860854
    861855                                if ( ! unifyExact(
    862                                         t1, t2, env, need, have, open, WidenMode{ false, false }, symtab )
     856                                        t1, t2, env, need, have, open, noWiden(), symtab )
    863857                                ) return false;
    864858
     
    874868                                return unifyExact(
    875869                                        t1, tupleFromDecls( crnt2, end2 ), env, need, have, open,
    876                                         WidenMode{ false, false }, symtab );
     870                                        noWiden(), symtab );
    877871                        } else if ( crnt2 != end2 ) {
    878872                                // try unifying empty tuple with ttype
     
    881875                                return unifyExact(
    882876                                        tupleFromDecls( crnt1, end1 ), t2, env, need, have, open,
    883                                         WidenMode{ false, false }, symtab );
     877                                        noWiden(), symtab );
    884878                        }
    885879
     
    919913
    920914        public:
    921                 void previsit( const ast::FunctionType * func ) {
    922                         visit_children = false;
     915                void postvisit( const ast::FunctionType * func ) {
    923916                        auto func2 = dynamic_cast< const ast::FunctionType * >( type2 );
    924917                        if ( ! func2 ) return;
     
    952945                template< typename RefType >
    953946                const RefType * handleRefType( const RefType * inst, const ast::Type * other ) {
    954                         visit_children = false;
    955947                        // check that the other type is compatible and named the same
    956948                        auto otherInst = dynamic_cast< const RefType * >( other );
     
    10111003
    10121004                                if ( ! unifyExact(
    1013                                                 pty, pty2, tenv, need, have, open, WidenMode{ false, false }, symtab ) ) {
     1005                                                pty, pty2, tenv, need, have, open, noWiden(), symtab ) ) {
    10141006                                        result = false;
    10151007                                        return;
     
    10231015
    10241016        public:
    1025                 void previsit( const ast::StructInstType * aggrType ) {
     1017                void postvisit( const ast::StructInstType * aggrType ) {
    10261018                        handleGenericRefType( aggrType, type2 );
    10271019                }
    10281020
    1029                 void previsit( const ast::UnionInstType * aggrType ) {
     1021                void postvisit( const ast::UnionInstType * aggrType ) {
    10301022                        handleGenericRefType( aggrType, type2 );
    10311023                }
    10321024
    1033                 void previsit( const ast::EnumInstType * aggrType ) {
     1025                void postvisit( const ast::EnumInstType * aggrType ) {
    10341026                        handleRefType( aggrType, type2 );
    10351027                }
    10361028
    1037                 void previsit( const ast::TraitInstType * aggrType ) {
     1029                void postvisit( const ast::TraitInstType * aggrType ) {
    10381030                        handleRefType( aggrType, type2 );
    10391031                }
    10401032
    1041                 void previsit( const ast::TypeInstType * typeInst ) {
     1033                void postvisit( const ast::TypeInstType * typeInst ) {
    10421034                        assert( open.find( typeInst->name ) == open.end() );
    10431035                        handleRefType( typeInst, type2 );
     
    10781070                                        return unifyExact(
    10791071                                                t1, tupleFromTypes( list2 ), env, need, have, open,
    1080                                                 WidenMode{ false, false }, symtab );
     1072                                                noWiden(), symtab );
    10811073                                } else if ( ! isTuple1 && isTuple2 ) {
    10821074                                        // combine entirety of list1, then unify
    10831075                                        return unifyExact(
    10841076                                                tupleFromTypes( list1 ), t2, env, need, have, open,
    1085                                                 WidenMode{ false, false }, symtab );
     1077                                                noWiden(), symtab );
    10861078                                }
    10871079
    10881080                                if ( ! unifyExact(
    1089                                         t1, t2, env, need, have, open, WidenMode{ false, false }, symtab )
     1081                                        t1, t2, env, need, have, open, noWiden(), symtab )
    10901082                                ) return false;
    10911083
     
    11011093                                return unifyExact(
    11021094                                                t1, tupleFromTypes( list2 ), env, need, have, open,
    1103                                                 WidenMode{ false, false }, symtab );
     1095                                                noWiden(), symtab );
    11041096                        } else if ( crnt2 != list2.end() ) {
    11051097                                // try unifying empty tuple with ttype
     
    11101102                                return unifyExact(
    11111103                                                tupleFromTypes( list1 ), t2, env, need, have, open,
    1112                                                 WidenMode{ false, false }, symtab );
     1104                                                noWiden(), symtab );
    11131105                        }
    11141106
     
    11171109
    11181110        public:
    1119                 void previsit( const ast::TupleType * tuple ) {
    1120                         visit_children = false;
     1111                void postvisit( const ast::TupleType * tuple ) {
    11211112                        auto tuple2 = dynamic_cast< const ast::TupleType * >( type2 );
    11221113                        if ( ! tuple2 ) return;
     
    11321123                }
    11331124
    1134                 void previsit( const ast::VarArgsType * ) {
    1135                         visit_children = false;
     1125                void postvisit( const ast::VarArgsType * ) {
    11361126                        result = dynamic_cast< const ast::VarArgsType * >( type2 );
    11371127                }
    11381128
    1139                 void previsit( const ast::ZeroType * ) {
    1140                         visit_children = false;
     1129                void postvisit( const ast::ZeroType * ) {
    11411130                        result = dynamic_cast< const ast::ZeroType * >( type2 );
    11421131                }
    11431132
    1144                 void previsit( const ast::OneType * ) {
    1145                         visit_children = false;
     1133                void postvisit( const ast::OneType * ) {
    11461134                        result = dynamic_cast< const ast::OneType * >( type2 );
    11471135                }       
     
    11511139                template< typename RefType > void handleGenericRefType( RefType *inst, Type *other );
    11521140        };
     1141
     1142        bool unify(
     1143                        const ast::ptr<ast::Type> & type1, const ast::ptr<ast::Type> & type2,
     1144                        ast::TypeEnvironment & env, ast::AssertionSet & need, ast::AssertionSet & have,
     1145                        ast::OpenVarSet & open, const ast::SymbolTable & symtab, ast::ptr<ast::Type> & common
     1146        ) {
     1147                ast::OpenVarSet closed;
     1148                findOpenVars( type1, open, closed, need, have, FirstClosed );
     1149                findOpenVars( type2, open, closed, need, have, FirstOpen );
     1150                return unifyInexact(
     1151                        type1, type2, env, need, have, open, WidenMode{ true, true }, symtab, common );
     1152        }
    11531153
    11541154        bool unifyExact(
     
    11841184
    11851185        bool unifyInexact(
    1186                         ast::ptr<ast::Type> & type1, ast::ptr<ast::Type> & type2, ast::TypeEnvironment & env,
    1187                         ast::AssertionSet & need, ast::AssertionSet & have, const ast::OpenVarSet & open,
    1188                         WidenMode widen, const ast::SymbolTable & symtab, ast::ptr<ast::Type> & common
     1186                        const ast::ptr<ast::Type> & type1, const ast::ptr<ast::Type> & type2,
     1187                        ast::TypeEnvironment & env, ast::AssertionSet & need, ast::AssertionSet & have,
     1188                        const ast::OpenVarSet & open, WidenMode widen, const ast::SymbolTable & symtab,
     1189                        ast::ptr<ast::Type> & common
    11891190        ) {
    11901191                ast::CV::Qualifiers q1 = type1->qualifiers, q2 = type2->qualifiers;
     
    11931194                // type2 are left unchanged; calling convention forces type{1,2}->strong_ref >= 1
    11941195                ast::ptr<ast::Type> t1{ type1 }, t2{ type2 };
    1195                 clear_qualifiers( t1 );
    1196                 clear_qualifiers( t2 );
     1196                reset_qualifiers( t1 );
     1197                reset_qualifiers( t2 );
    11971198               
    11981199                if ( unifyExact( t1, t2, env, need, have, open, widen, symtab ) ) {
     
    12011202                        // if exact unification on unqualified types, try to merge qualifiers
    12021203                        if ( q1 == q2 || ( ( q1 > q2 || widen.first ) && ( q2 > q1 || widen.second ) ) ) {
    1203                                 common.set_and_mutate( type1 )->qualifiers = q1 | q2;
     1204                                common = type1;
     1205                                reset_qualifiers( common, q1 | q2 );
    12041206                                return true;
    12051207                        } else {
     
    12111213
    12121214                        // no exact unification, but common type
    1213                         common.get_and_mutate()->qualifiers = q1 | q2;
     1215                        reset_qualifiers( common, q1 | q2 );
    12141216                        return true;
    12151217                } else {
  • src/ResolvExpr/Unify.h

    r4741dfe rd4b6638  
    6969        }
    7070
     71        bool unify(
     72                const ast::ptr<ast::Type> & type1, const ast::ptr<ast::Type> & type2,
     73                ast::TypeEnvironment & env, ast::AssertionSet & need, ast::AssertionSet & have,
     74                ast::OpenVarSet & open, const ast::SymbolTable & symtab, ast::ptr<ast::Type> & common );
     75
    7176        bool unifyExact(
    7277                const ast::Type * type1, const ast::Type * type2, ast::TypeEnvironment & env,
    73                 ast::AssertionSet & need, ast::AssertionSet & have, ast::OpenVarSet & open,
    74                 const ast::SymbolTable & symtab );
     78                ast::AssertionSet & need, ast::AssertionSet & have, const ast::OpenVarSet & open,
     79                WidenMode widen, const ast::SymbolTable & symtab );
    7580
    7681        bool unifyInexact(
    77                 ast::ptr<ast::Type> & type1, ast::ptr<ast::Type> & type2, ast::TypeEnvironment & env,
    78                 ast::AssertionSet & need, ast::AssertionSet & have, const ast::OpenVarSet & open,
    79                 WidenMode widen, const ast::SymbolTable & symtab, ast::ptr<ast::Type> & common );
     82                const ast::ptr<ast::Type> & type1, const ast::ptr<ast::Type> & type2,
     83                ast::TypeEnvironment & env, ast::AssertionSet & need, ast::AssertionSet & have,
     84                const ast::OpenVarSet & open, WidenMode widen, const ast::SymbolTable & symtab,
     85                ast::ptr<ast::Type> & common );
    8086
    8187} // namespace ResolvExpr
  • src/ResolvExpr/WidenMode.h

    r4741dfe rd4b6638  
    4040                bool first : 1, second : 1;
    4141        };
     42
     43        static inline WidenMode noWiden() { return { false, false }; }
    4244} // namespace ResolvExpr
    4345
  • src/ResolvExpr/typeops.h

    r4741dfe rd4b6638  
    8989
    9090        // in Unify.cc
    91         bool isFtype( Type *type );
    9291        bool typesCompatible( Type *, Type *, const SymTab::Indexer &indexer, const TypeEnvironment &env );
    9392        bool typesCompatibleIgnoreQualifiers( Type *, Type *, const SymTab::Indexer &indexer, const TypeEnvironment &env );
     
    118117        // in CommonType.cc
    119118        Type * commonType( Type *type1, Type *type2, bool widenFirst, bool widenSecond, const SymTab::Indexer &indexer, TypeEnvironment &env, const OpenVarSet &openVars );
    120         const ast::Type * commonType(
    121                 const ast::Type * type1, const ast::Type * type2, WidenMode widen,
     119        ast::ptr< ast::Type > commonType(
     120                const ast::ptr< ast::Type > & type1, const ast::ptr< ast::Type > & type2, WidenMode widen,
    122121                const ast::SymbolTable & symtab, ast::TypeEnvironment & env, const ast::OpenVarSet & open );
    123122
     
    177176                return out;
    178177        }
     178
     179        // in TypeEnvironment.cc
     180        bool isFtype( Type *type );
    179181} // namespace ResolvExpr
     182
     183namespace ast {
     184        // in TypeEnvironment.cpp
     185        bool isFtype( const ast::Type * type );
     186} // namespace ast
    180187
    181188// Local Variables: //
  • src/SymTab/Mangler.cc

    r4741dfe rd4b6638  
    3232#include "SynTree/Type.h"                // for Type, ReferenceToType, Type::Fora...
    3333
     34#include "AST/Pass.hpp"
     35
    3436namespace SymTab {
    3537        namespace Mangler {
    3638                namespace {
    3739                        /// Mangles names to a unique C identifier
    38                         struct Mangler : public WithShortCircuiting, public WithVisitorRef<Mangler>, public WithGuards {
    39                                 Mangler( bool mangleOverridable, bool typeMode, bool mangleGenericParams );
    40                                 Mangler( const Mangler & ) = delete;
     40                        struct Mangler_old : public WithShortCircuiting, public WithVisitorRef<Mangler_old>, public WithGuards {
     41                                Mangler_old( bool mangleOverridable, bool typeMode, bool mangleGenericParams );
     42                                Mangler_old( const Mangler_old & ) = delete;
    4143
    4244                                void previsit( BaseSyntaxNode * ) { visit_children = false; }
     
    7779
    7880                          public:
    79                                 Mangler( bool mangleOverridable, bool typeMode, bool mangleGenericParams,
     81                                Mangler_old( bool mangleOverridable, bool typeMode, bool mangleGenericParams,
    8082                                        int nextVarNum, const VarMapType& varNums );
    8183
     
    8587
    8688                                void printQualifiers( Type *type );
    87                         }; // Mangler
     89                        }; // Mangler_old
    8890                } // namespace
    8991
    9092                std::string mangle( BaseSyntaxNode * decl, bool mangleOverridable, bool typeMode, bool mangleGenericParams ) {
    91                         PassVisitor<Mangler> mangler( mangleOverridable, typeMode, mangleGenericParams );
     93                        PassVisitor<Mangler_old> mangler( mangleOverridable, typeMode, mangleGenericParams );
    9294                        maybeAccept( decl, mangler );
    9395                        return mangler.pass.get_mangleName();
     
    9597
    9698                std::string mangleType( Type * ty ) {
    97                         PassVisitor<Mangler> mangler( false, true, true );
     99                        PassVisitor<Mangler_old> mangler( false, true, true );
    98100                        maybeAccept( ty, mangler );
    99101                        return mangler.pass.get_mangleName();
     
    101103
    102104                std::string mangleConcrete( Type * ty ) {
    103                         PassVisitor<Mangler> mangler( false, false, false );
     105                        PassVisitor<Mangler_old> mangler( false, false, false );
    104106                        maybeAccept( ty, mangler );
    105107                        return mangler.pass.get_mangleName();
     
    107109
    108110                namespace {
    109                         Mangler::Mangler( bool mangleOverridable, bool typeMode, bool mangleGenericParams )
     111                        Mangler_old::Mangler_old( bool mangleOverridable, bool typeMode, bool mangleGenericParams )
    110112                                : nextVarNum( 0 ), isTopLevel( true ),
    111113                                mangleOverridable( mangleOverridable ), typeMode( typeMode ),
    112114                                mangleGenericParams( mangleGenericParams ) {}
    113115                       
    114                         Mangler::Mangler( bool mangleOverridable, bool typeMode, bool mangleGenericParams,
     116                        Mangler_old::Mangler_old( bool mangleOverridable, bool typeMode, bool mangleGenericParams,
    115117                                int nextVarNum, const VarMapType& varNums )
    116118                                : varNums( varNums ), nextVarNum( nextVarNum ), isTopLevel( false ),
     
    118120                                mangleGenericParams( mangleGenericParams ) {}
    119121
    120                         void Mangler::mangleDecl( DeclarationWithType * declaration ) {
     122                        void Mangler_old::mangleDecl( DeclarationWithType * declaration ) {
    121123                                bool wasTopLevel = isTopLevel;
    122124                                if ( isTopLevel ) {
     
    148150                        }
    149151
    150                         void Mangler::postvisit( ObjectDecl * declaration ) {
     152                        void Mangler_old::postvisit( ObjectDecl * declaration ) {
    151153                                mangleDecl( declaration );
    152154                        }
    153155
    154                         void Mangler::postvisit( FunctionDecl * declaration ) {
     156                        void Mangler_old::postvisit( FunctionDecl * declaration ) {
    155157                                mangleDecl( declaration );
    156158                        }
    157159
    158                         void Mangler::postvisit( VoidType * voidType ) {
     160                        void Mangler_old::postvisit( VoidType * voidType ) {
    159161                                printQualifiers( voidType );
    160162                                mangleName << Encoding::void_t;
    161163                        }
    162164
    163                         void Mangler::postvisit( BasicType * basicType ) {
     165                        void Mangler_old::postvisit( BasicType * basicType ) {
    164166                                printQualifiers( basicType );
    165167                                assertf( basicType->get_kind() < BasicType::NUMBER_OF_BASIC_TYPES, "Unhandled basic type: %d", basicType->get_kind() );
     
    167169                        }
    168170
    169                         void Mangler::postvisit( PointerType * pointerType ) {
     171                        void Mangler_old::postvisit( PointerType * pointerType ) {
    170172                                printQualifiers( pointerType );
    171173                                // mangle void (*f)() and void f() to the same name to prevent overloading on functions and function pointers
     
    174176                        }
    175177
    176                         void Mangler::postvisit( ArrayType * arrayType ) {
     178                        void Mangler_old::postvisit( ArrayType * arrayType ) {
    177179                                // TODO: encode dimension
    178180                                printQualifiers( arrayType );
     
    181183                        }
    182184
    183                         void Mangler::postvisit( ReferenceType * refType ) {
     185                        void Mangler_old::postvisit( ReferenceType * refType ) {
    184186                                // don't print prefix (e.g. 'R') for reference types so that references and non-references do not overload.
    185187                                // Further, do not print the qualifiers for a reference type (but do run printQualifers because of TypeDecls, etc.),
     
    200202                        }
    201203
    202                         void Mangler::postvisit( FunctionType * functionType ) {
     204                        void Mangler_old::postvisit( FunctionType * functionType ) {
    203205                                printQualifiers( functionType );
    204206                                mangleName << Encoding::function;
     
    217219                        }
    218220
    219                         void Mangler::mangleRef( ReferenceToType * refType, std::string prefix ) {
     221                        void Mangler_old::mangleRef( ReferenceToType * refType, std::string prefix ) {
    220222                                printQualifiers( refType );
    221223
     
    236238                        }
    237239
    238                         void Mangler::postvisit( StructInstType * aggregateUseType ) {
     240                        void Mangler_old::postvisit( StructInstType * aggregateUseType ) {
    239241                                mangleRef( aggregateUseType, Encoding::struct_t );
    240242                        }
    241243
    242                         void Mangler::postvisit( UnionInstType * aggregateUseType ) {
     244                        void Mangler_old::postvisit( UnionInstType * aggregateUseType ) {
    243245                                mangleRef( aggregateUseType, Encoding::union_t );
    244246                        }
    245247
    246                         void Mangler::postvisit( EnumInstType * aggregateUseType ) {
     248                        void Mangler_old::postvisit( EnumInstType * aggregateUseType ) {
    247249                                mangleRef( aggregateUseType, Encoding::enum_t );
    248250                        }
    249251
    250                         void Mangler::postvisit( TypeInstType * typeInst ) {
     252                        void Mangler_old::postvisit( TypeInstType * typeInst ) {
    251253                                VarMapType::iterator varNum = varNums.find( typeInst->get_name() );
    252254                                if ( varNum == varNums.end() ) {
     
    264266                        }
    265267
    266                         void Mangler::postvisit( TraitInstType * inst ) {
     268                        void Mangler_old::postvisit( TraitInstType * inst ) {
    267269                                printQualifiers( inst );
    268270                                mangleName << inst->name.size() << inst->name;
    269271                        }
    270272
    271                         void Mangler::postvisit( TupleType * tupleType ) {
     273                        void Mangler_old::postvisit( TupleType * tupleType ) {
    272274                                printQualifiers( tupleType );
    273275                                mangleName << Encoding::tuple << tupleType->types.size();
     
    275277                        }
    276278
    277                         void Mangler::postvisit( VarArgsType * varArgsType ) {
     279                        void Mangler_old::postvisit( VarArgsType * varArgsType ) {
    278280                                printQualifiers( varArgsType );
    279281                                static const std::string vargs = "__builtin_va_list";
     
    281283                        }
    282284
    283                         void Mangler::postvisit( ZeroType * ) {
     285                        void Mangler_old::postvisit( ZeroType * ) {
    284286                                mangleName << Encoding::zero;
    285287                        }
    286288
    287                         void Mangler::postvisit( OneType * ) {
     289                        void Mangler_old::postvisit( OneType * ) {
    288290                                mangleName << Encoding::one;
    289291                        }
    290292
    291                         void Mangler::postvisit( QualifiedType * qualType ) {
     293                        void Mangler_old::postvisit( QualifiedType * qualType ) {
    292294                                bool inqual = inQualifiedType;
    293295                                if (! inqual ) {
     
    305307                        }
    306308
    307                         void Mangler::postvisit( TypeDecl * decl ) {
     309                        void Mangler_old::postvisit( TypeDecl * decl ) {
    308310                                // TODO: is there any case where mangling a TypeDecl makes sense? If so, this code needs to be
    309311                                // fixed to ensure that two TypeDecls mangle to the same name when they are the same type and vice versa.
     
    311313                                // and the case has not yet come up in practice. Alternatively, if not then this code can be removed
    312314                                // aside from the assert false.
    313                                 assertf(false, "Mangler should not visit typedecl: %s", toCString(decl));
     315                                assertf(false, "Mangler_old should not visit typedecl: %s", toCString(decl));
    314316                                assertf( decl->get_kind() < TypeDecl::NUMBER_OF_KINDS, "Unhandled type variable kind: %d", decl->get_kind() );
    315317                                mangleName << Encoding::typeVariables[ decl->get_kind() ] << ( decl->name.length() ) << decl->name;
     
    322324                        }
    323325
    324                         void Mangler::printQualifiers( Type * type ) {
     326                        void Mangler_old::printQualifiers( Type * type ) {
    325327                                // skip if not including qualifiers
    326328                                if ( typeMode ) return;
     
    345347                                                varNums[ (*i)->name ] = std::make_pair( nextVarNum, (int)(*i)->get_kind() );
    346348                                                for ( std::list< DeclarationWithType* >::iterator assert = (*i)->assertions.begin(); assert != (*i)->assertions.end(); ++assert ) {
    347                                                         PassVisitor<Mangler> sub_mangler(
     349                                                        PassVisitor<Mangler_old> sub_mangler(
    348350                                                                mangleOverridable, typeMode, mangleGenericParams, nextVarNum, varNums );
    349351                                                        (*assert)->accept( sub_mangler );
     
    391393
    392394namespace Mangle {
     395        namespace {
     396                /// Mangles names to a unique C identifier
     397                struct Mangler_new : public ast::WithShortCircuiting, public ast::WithVisitorRef<Mangler_new>, public ast::WithGuards {
     398                        Mangler_new( Mangle::Mode mode );
     399                        Mangler_new( const Mangler_new & ) = delete;
     400
     401                        void previsit( const ast::Node * ) { visit_children = false; }
     402
     403                        void postvisit( const ast::ObjectDecl * declaration );
     404                        void postvisit( const ast::FunctionDecl * declaration );
     405                        void postvisit( const ast::TypeDecl * declaration );
     406
     407                        void postvisit( const ast::VoidType * voidType );
     408                        void postvisit( const ast::BasicType * basicType );
     409                        void postvisit( const ast::PointerType * pointerType );
     410                        void postvisit( const ast::ArrayType * arrayType );
     411                        void postvisit( const ast::ReferenceType * refType );
     412                        void postvisit( const ast::FunctionType * functionType );
     413                        void postvisit( const ast::StructInstType * aggregateUseType );
     414                        void postvisit( const ast::UnionInstType * aggregateUseType );
     415                        void postvisit( const ast::EnumInstType * aggregateUseType );
     416                        void postvisit( const ast::TypeInstType * aggregateUseType );
     417                        void postvisit( const ast::TraitInstType * inst );
     418                        void postvisit( const ast::TupleType * tupleType );
     419                        void postvisit( const ast::VarArgsType * varArgsType );
     420                        void postvisit( const ast::ZeroType * zeroType );
     421                        void postvisit( const ast::OneType * oneType );
     422                        void postvisit( const ast::QualifiedType * qualType );
     423
     424                        std::string get_mangleName() { return mangleName.str(); }
     425                  private:
     426                        std::ostringstream mangleName;  ///< Mangled name being constructed
     427                        typedef std::map< std::string, std::pair< int, int > > VarMapType;
     428                        VarMapType varNums;             ///< Map of type variables to indices
     429                        int nextVarNum;                 ///< Next type variable index
     430                        bool isTopLevel;                ///< Is the Mangler at the top level
     431                        bool mangleOverridable;         ///< Specially mangle overridable built-in methods
     432                        bool typeMode;                  ///< Produce a unique mangled name for a type
     433                        bool mangleGenericParams;       ///< Include generic parameters in name mangling if true
     434                        bool inFunctionType = false;    ///< Include type qualifiers if false.
     435                        bool inQualifiedType = false;   ///< Add start/end delimiters around qualified type
     436
     437                  private:
     438                        Mangler_new( bool mangleOverridable, bool typeMode, bool mangleGenericParams, 
     439                                int nextVarNum, const VarMapType& varNums );
     440                        friend class ast::Pass<Mangler_new>;
     441
     442                  private:
     443                        void mangleDecl( const ast::DeclWithType *declaration );
     444                        void mangleRef( const ast::ReferenceToType *refType, std::string prefix );
     445
     446                        void printQualifiers( const ast::Type *type );
     447                }; // Mangler_new
     448        } // namespace
     449
     450
    393451        std::string mangle( const ast::Node * decl, Mangle::Mode mode ) {
    394                 #warning unimplemented
    395                 assert( decl && mode.val && false );
    396                 return "";
     452                ast::Pass<Mangler_new> mangler( mode );
     453                maybeAccept( decl, mangler );
     454                return mangler.pass.get_mangleName();
    397455        }
     456
     457        namespace {
     458                Mangler_new::Mangler_new( Mangle::Mode mode )
     459                        : nextVarNum( 0 ), isTopLevel( true ),
     460                        mangleOverridable  ( ! mode.no_overrideable   ),
     461                        typeMode           (   mode.type              ),
     462                        mangleGenericParams( ! mode.no_generic_params ) {}
     463               
     464                Mangler_new::Mangler_new( bool mangleOverridable, bool typeMode, bool mangleGenericParams,
     465                        int nextVarNum, const VarMapType& varNums )
     466                        : varNums( varNums ), nextVarNum( nextVarNum ), isTopLevel( false ),
     467                        mangleOverridable( mangleOverridable ), typeMode( typeMode ),
     468                        mangleGenericParams( mangleGenericParams ) {}
     469
     470                void Mangler_new::mangleDecl( const ast::DeclWithType * decl ) {
     471                        bool wasTopLevel = isTopLevel;
     472                        if ( isTopLevel ) {
     473                                varNums.clear();
     474                                nextVarNum = 0;
     475                                isTopLevel = false;
     476                        } // if
     477                        mangleName << Encoding::manglePrefix;
     478                        CodeGen::OperatorInfo opInfo;
     479                        if ( operatorLookup( decl->name, opInfo ) ) {
     480                                mangleName << opInfo.outputName.size() << opInfo.outputName;
     481                        } else {
     482                                mangleName << decl->name.size() << decl->name;
     483                        } // if
     484                        maybeAccept( decl->get_type(), *visitor );
     485                        if ( mangleOverridable && decl->linkage.is_overrideable ) {
     486                                // want to be able to override autogenerated and intrinsic routines,
     487                                // so they need a different name mangling
     488                                if ( decl->linkage == ast::Linkage::AutoGen ) {
     489                                        mangleName << Encoding::autogen;
     490                                } else if ( decl->linkage == ast::Linkage::Intrinsic ) {
     491                                        mangleName << Encoding::intrinsic;
     492                                } else {
     493                                        // if we add another kind of overridable function, this has to change
     494                                        assert( false && "unknown overrideable linkage" );
     495                                } // if
     496                        }
     497                        isTopLevel = wasTopLevel;
     498                }
     499
     500                void Mangler_new::postvisit( const ast::ObjectDecl * decl ) {
     501                        mangleDecl( decl );
     502                }
     503
     504                void Mangler_new::postvisit( const ast::FunctionDecl * decl ) {
     505                        mangleDecl( decl );
     506                }
     507
     508                void Mangler_new::postvisit( const ast::VoidType * voidType ) {
     509                        printQualifiers( voidType );
     510                        mangleName << Encoding::void_t;
     511                }
     512
     513                void Mangler_new::postvisit( const ast::BasicType * basicType ) {
     514                        printQualifiers( basicType );
     515                        assertf( basicType->kind < ast::BasicType::NUMBER_OF_BASIC_TYPES, "Unhandled basic type: %d", basicType->kind );
     516                        mangleName << Encoding::basicTypes[ basicType->kind ];
     517                }
     518
     519                void Mangler_new::postvisit( const ast::PointerType * pointerType ) {
     520                        printQualifiers( pointerType );
     521                        // mangle void (*f)() and void f() to the same name to prevent overloading on functions and function pointers
     522                        if ( ! pointerType->base.as<ast::FunctionType>() ) mangleName << Encoding::pointer;
     523                        maybe_accept( pointerType->base.get(), *visitor );
     524                }
     525
     526                void Mangler_new::postvisit( const ast::ArrayType * arrayType ) {
     527                        // TODO: encode dimension
     528                        printQualifiers( arrayType );
     529                        mangleName << Encoding::array << "0";
     530                        maybeAccept( arrayType->base.get(), *visitor );
     531                }
     532
     533                void Mangler_new::postvisit( const ast::ReferenceType * refType ) {
     534                        // don't print prefix (e.g. 'R') for reference types so that references and non-references do not overload.
     535                        // Further, do not print the qualifiers for a reference type (but do run printQualifers because of TypeDecls, etc.),
     536                        // by pretending every reference type is a function parameter.
     537                        GuardValue( inFunctionType );
     538                        inFunctionType = true;
     539                        printQualifiers( refType );
     540                        maybeAccept( refType->base.get(), *visitor );
     541                }
     542
     543                inline std::vector< ast::ptr< ast::Type > > getTypes( const std::vector< ast::ptr< ast::DeclWithType > > & decls ) {
     544                        std::vector< ast::ptr< ast::Type > > ret;
     545                        std::transform( decls.begin(), decls.end(), std::back_inserter( ret ),
     546                                                        std::mem_fun( &ast::DeclWithType::get_type ) );
     547                        return ret;
     548                }
     549
     550                void Mangler_new::postvisit( const ast::FunctionType * functionType ) {
     551                        printQualifiers( functionType );
     552                        mangleName << Encoding::function;
     553                        // turn on inFunctionType so that printQualifiers does not print most qualifiers for function parameters,
     554                        // since qualifiers on outermost parameter type do not differentiate function types, e.g.,
     555                        // void (*)(const int) and void (*)(int) are the same type, but void (*)(const int *) and void (*)(int *) are different
     556                        GuardValue( inFunctionType );
     557                        inFunctionType = true;
     558                        std::vector< ast::ptr< ast::Type > > returnTypes = getTypes( functionType->returns );
     559                        if (returnTypes.empty()) mangleName << Encoding::void_t;
     560                        else accept_each( returnTypes, *visitor );
     561                        mangleName << "_";
     562                        std::vector< ast::ptr< ast::Type > > paramTypes = getTypes( functionType->params );
     563                        accept_each( paramTypes, *visitor );
     564                        mangleName << "_";
     565                }
     566
     567                void Mangler_new::mangleRef( const ast::ReferenceToType * refType, std::string prefix ) {
     568                        printQualifiers( refType );
     569
     570                        mangleName << prefix << refType->name.length() << refType->name;
     571
     572                        if ( mangleGenericParams ) {
     573                                if ( ! refType->params.empty() ) {
     574                                        mangleName << "_";
     575                                        for ( const ast::Expr * param : refType->params ) {
     576                                                auto paramType = dynamic_cast< const ast::TypeExpr * >( param );
     577                                                assertf(paramType, "Aggregate parameters should be type expressions: %s", toCString(param));
     578                                                maybeAccept( paramType->type.get(), *visitor );
     579                                        }
     580                                        mangleName << "_";
     581                                }
     582                        }
     583                }
     584
     585                void Mangler_new::postvisit( const ast::StructInstType * aggregateUseType ) {
     586                        mangleRef( aggregateUseType, Encoding::struct_t );
     587                }
     588
     589                void Mangler_new::postvisit( const ast::UnionInstType * aggregateUseType ) {
     590                        mangleRef( aggregateUseType, Encoding::union_t );
     591                }
     592
     593                void Mangler_new::postvisit( const ast::EnumInstType * aggregateUseType ) {
     594                        mangleRef( aggregateUseType, Encoding::enum_t );
     595                }
     596
     597                void Mangler_new::postvisit( const ast::TypeInstType * typeInst ) {
     598                        VarMapType::iterator varNum = varNums.find( typeInst->name );
     599                        if ( varNum == varNums.end() ) {
     600                                mangleRef( typeInst, Encoding::type );
     601                        } else {
     602                                printQualifiers( typeInst );
     603                                // Note: Can't use name here, since type variable names do not actually disambiguate a function, e.g.
     604                                //   forall(dtype T) void f(T);
     605                                //   forall(dtype S) void f(S);
     606                                // are equivalent and should mangle the same way. This is accomplished by numbering the type variables when they
     607                                // are first found and prefixing with the appropriate encoding for the type class.
     608                                assertf( varNum->second.second < TypeDecl::NUMBER_OF_KINDS, "Unhandled type variable kind: %d", varNum->second.second );
     609                                mangleName << Encoding::typeVariables[varNum->second.second] << varNum->second.first;
     610                        } // if
     611                }
     612
     613                void Mangler_new::postvisit( const ast::TraitInstType * inst ) {
     614                        printQualifiers( inst );
     615                        mangleName << inst->name.size() << inst->name;
     616                }
     617
     618                void Mangler_new::postvisit( const ast::TupleType * tupleType ) {
     619                        printQualifiers( tupleType );
     620                        mangleName << Encoding::tuple << tupleType->types.size();
     621                        accept_each( tupleType->types, *visitor );
     622                }
     623
     624                void Mangler_new::postvisit( const ast::VarArgsType * varArgsType ) {
     625                        printQualifiers( varArgsType );
     626                        static const std::string vargs = "__builtin_va_list";
     627                        mangleName << Encoding::type << vargs.size() << vargs;
     628                }
     629
     630                void Mangler_new::postvisit( const ast::ZeroType * ) {
     631                        mangleName << Encoding::zero;
     632                }
     633
     634                void Mangler_new::postvisit( const ast::OneType * ) {
     635                        mangleName << Encoding::one;
     636                }
     637
     638                void Mangler_new::postvisit( const ast::QualifiedType * qualType ) {
     639                        bool inqual = inQualifiedType;
     640                        if (! inqual ) {
     641                                // N marks the start of a qualified type
     642                                inQualifiedType = true;
     643                                mangleName << Encoding::qualifiedTypeStart;
     644                        }
     645                        maybeAccept( qualType->parent.get(), *visitor );
     646                        maybeAccept( qualType->child.get(), *visitor );
     647                        if ( ! inqual ) {
     648                                // E marks the end of a qualified type
     649                                inQualifiedType = false;
     650                                mangleName << Encoding::qualifiedTypeEnd;
     651                        }
     652                }
     653
     654                void Mangler_new::postvisit( const ast::TypeDecl * decl ) {
     655                        // TODO: is there any case where mangling a TypeDecl makes sense? If so, this code needs to be
     656                        // fixed to ensure that two TypeDecls mangle to the same name when they are the same type and vice versa.
     657                        // Note: The current scheme may already work correctly for this case, I have not thought about this deeply
     658                        // and the case has not yet come up in practice. Alternatively, if not then this code can be removed
     659                        // aside from the assert false.
     660                        assertf(false, "Mangler_new should not visit typedecl: %s", toCString(decl));
     661                        assertf( decl->kind < ast::TypeVar::Kind::NUMBER_OF_KINDS, "Unhandled type variable kind: %d", decl->kind );
     662                        mangleName << Encoding::typeVariables[ decl->kind ] << ( decl->name.length() ) << decl->name;
     663                }
     664
     665                __attribute__((unused)) void printVarMap( const std::map< std::string, std::pair< int, int > > &varMap, std::ostream &os ) {
     666                        for ( std::map< std::string, std::pair< int, int > >::const_iterator i = varMap.begin(); i != varMap.end(); ++i ) {
     667                                os << i->first << "(" << i->second.first << "/" << i->second.second << ")" << std::endl;
     668                        } // for
     669                }
     670
     671                void Mangler_new::printQualifiers( const ast::Type * type ) {
     672                        // skip if not including qualifiers
     673                        if ( typeMode ) return;
     674                        if ( auto ptype = dynamic_cast< const ast::ParameterizedType * >(type) ) {
     675                                if ( ! ptype->forall.empty() ) {
     676                                        std::list< std::string > assertionNames;
     677                                        int dcount = 0, fcount = 0, vcount = 0, acount = 0;
     678                                        mangleName << Encoding::forall;
     679                                        for ( const ast::TypeDecl * decl : ptype->forall ) {
     680                                                switch ( decl->kind ) {
     681                                                case ast::TypeVar::Kind::Dtype:
     682                                                        dcount++;
     683                                                        break;
     684                                                case ast::TypeVar::Kind::Ftype:
     685                                                        fcount++;
     686                                                        break;
     687                                                case ast::TypeVar::Kind::Ttype:
     688                                                        vcount++;
     689                                                        break;
     690                                                default:
     691                                                        assert( false );
     692                                                } // switch
     693                                                varNums[ decl->name ] = std::make_pair( nextVarNum, (int)decl->kind );
     694                                                for ( const ast::DeclWithType * assert : decl->assertions ) {
     695                                                        ast::Pass<Mangler_new> sub_mangler(
     696                                                                mangleOverridable, typeMode, mangleGenericParams, nextVarNum, varNums );
     697                                                        assert->accept( sub_mangler );
     698                                                        assertionNames.push_back( sub_mangler.pass.get_mangleName() );
     699                                                        acount++;
     700                                                } // for
     701                                        } // for
     702                                        mangleName << dcount << "_" << fcount << "_" << vcount << "_" << acount << "_";
     703                                        std::copy( assertionNames.begin(), assertionNames.end(), std::ostream_iterator< std::string >( mangleName, "" ) );
     704                                        mangleName << "_";
     705                                } // if
     706                        } // if
     707                        if ( ! inFunctionType ) {
     708                                // these qualifiers do not distinguish the outermost type of a function parameter
     709                                if ( type->is_const() ) {
     710                                        mangleName << Encoding::qualifiers.at(Type::Const);
     711                                } // if
     712                                if ( type->is_volatile() ) {
     713                                        mangleName << Encoding::qualifiers.at(Type::Volatile);
     714                                } // if
     715                                // Removed due to restrict not affecting function compatibility in GCC
     716                                // if ( type->get_isRestrict() ) {
     717                                //      mangleName << "E";
     718                                // } // if
     719                                if ( type->is_atomic() ) {
     720                                        mangleName << Encoding::qualifiers.at(Type::Atomic);
     721                                } // if
     722                        }
     723                        if ( type->is_mutex() ) {
     724                                mangleName << Encoding::qualifiers.at(Type::Mutex);
     725                        } // if
     726                        if ( type->is_lvalue() ) {
     727                                // mangle based on whether the type is lvalue, so that the resolver can differentiate lvalues and rvalues
     728                                mangleName << Encoding::qualifiers.at(Type::Lvalue);
     729                        }
     730
     731                        if ( inFunctionType ) {
     732                                // turn off inFunctionType so that types can be differentiated for nested qualifiers
     733                                GuardValue( inFunctionType );
     734                                inFunctionType = false;
     735                        }
     736                }
     737        }       // namespace
    398738} // namespace Mangle
    399739
Note: See TracChangeset for help on using the changeset viewer.