Changeset 67130fe


Ignore:
Timestamp:
Jun 4, 2019, 6:39:23 PM (2 years ago)
Author:
Peter A. Buhr <pabuhr@…>
Branches:
arm-eh, jacob/cs343-translation, jenkins-sandbox, master, new-ast, new-ast-unique-expr
Children:
c6a1e8a
Parents:
7564e10 (diff), 1346914 (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:
4 added
38 edited

Legend:

Unmodified
Added
Removed
  • src/AST/Convert.cpp

    r7564e10 r67130fe  
    4747namespace {
    4848
    49 // This is to preserve the SymTab::dereferenceOperator hack. It does not (and perhaps should not)
     49// This is to preserve the FindSpecialDecls hack. It does not (and perhaps should not)
    5050// allow us to use the same stratagy in the new ast.
    5151ast::FunctionDecl * dereferenceOperator = nullptr;
     52ast::StructDecl   * dtorStruct = nullptr;
     53ast::FunctionDecl * dtorStructDestroy = nullptr;
    5254
    5355}
     
    7577                std::list< T * > acceptL( const U & container ) {
    7678                        std::list< T * > ret;
    77                         for (auto ptr : container ) {
     79                        for ( auto ptr : container ) {
    7880                                ret.emplace_back( accept1( ptr ) );
    7981                        }
     
    176178                        Validate::dereferenceOperator = decl;
    177179                }
     180                if ( dtorStructDestroy == node ) {
     181                        Validate::dtorStructDestroy = decl;
     182                }
    178183                return declWithTypePostamble( decl, node );
    179184        }
     
    231236                        LinkageSpec::Spec( node->linkage.val )
    232237                );
     238
     239                if ( dtorStruct == node ) {
     240                        Validate::dtorStruct = decl;
     241                }
     242
    233243                return aggregatePostamble( decl, node );
    234244        }
     
    14451455                };
    14461456                cache.emplace( old, decl );
     1457                decl->withExprs = GET_ACCEPT_V(withExprs, Expr);
    14471458                decl->stmts = GET_ACCEPT_1(statements, CompoundStmt);
    14481459                decl->scopeLevel = old->scopeLevel;
     
    14561467                if ( Validate::dereferenceOperator == old ) {
    14571468                        dereferenceOperator = decl;
     1469                }
     1470
     1471                if ( Validate::dtorStructDestroy == old ) {
     1472                        dtorStructDestroy = decl;
    14581473                }
    14591474        }
     
    14781493
    14791494                this->node = decl;
     1495
     1496                if ( Validate::dtorStruct == old ) {
     1497                        dtorStruct = decl;
     1498                }
    14801499        }
    14811500
  • src/AST/Decl.cpp

    r7564e10 r67130fe  
    1717
    1818#include <cassert>             // for assert, strict_dynamic_cast
     19#include <iostream>
    1920#include <string>
    2021#include <unordered_map>
     
    7071}
    7172
     73std::ostream & operator<< ( std::ostream & out, const TypeDecl::Data & data ) {
     74        return out << data.kind << ", " << data.isComplete;
     75}
     76
    7277// --- EnumDecl
    7378
  • src/AST/Decl.hpp

    r7564e10 r67130fe  
    1616#pragma once
    1717
     18#include <iosfwd>
    1819#include <string>              // for string, to_string
    1920#include <unordered_map>
     
    101102        ptr<Expr> bitfieldWidth;
    102103
    103         ObjectDecl( const CodeLocation & loc, const std::string & name, const Type * type, Init * init = nullptr,
    104                 Storage::Classes storage = {}, Linkage::Spec linkage = Linkage::C, Expr * bitWd = nullptr,
    105                 std::vector< ptr<Attribute> > && attrs = {}, Function::Specs fs = {})
     104        ObjectDecl( const CodeLocation & loc, const std::string & name, const Type * type,
     105                Init * init = nullptr, Storage::Classes storage = {}, Linkage::Spec linkage = Linkage::C,
     106                Expr * bitWd = nullptr, std::vector< ptr<Attribute> > && attrs = {},
     107                Function::Specs fs = {} )
    106108        : DeclWithType( loc, name, storage, linkage, std::move(attrs), fs ), type( type ),
    107109          init( init ), bitfieldWidth( bitWd ) {}
     
    121123        ptr<FunctionType> type;
    122124        ptr<CompoundStmt> stmts;
    123         std::list< ptr<Expr> > withExprs;
     125        std::vector< ptr<Expr> > withExprs;
    124126
    125127        FunctionDecl( const CodeLocation & loc, const std::string &name, FunctionType * type,
     
    172174
    173175                Data() : kind( (TypeVar::Kind)-1 ), isComplete( false ) {}
    174                 Data( TypeDecl* d ) : kind( d->kind ), isComplete( d->sized ) {}
     176                Data( const TypeDecl * d ) : kind( d->kind ), isComplete( d->sized ) {}
    175177                Data( TypeVar::Kind k, bool c ) : kind( k ), isComplete( c ) {}
    176                 Data( const Data& d1, const Data& d2 )
     178                Data( const Data & d1, const Data & d2 )
    177179                : kind( d1.kind ), isComplete( d1.isComplete || d2.isComplete ) {}
    178180
    179                 bool operator== ( const Data& o ) const {
     181                bool operator== ( const Data & o ) const {
    180182                        return kind == o.kind && isComplete == o.isComplete;
    181183                }
    182                 bool operator!= ( const Data& o ) const { return !(*this == o); }
     184                bool operator!= ( const Data & o ) const { return !(*this == o); }
    183185        };
    184186
     
    200202        MUTATE_FRIEND
    201203};
     204
     205std::ostream & operator<< ( std::ostream &, const TypeDecl::Data & );
    202206
    203207/// C-style typedef `typedef Foo Bar`
  • src/AST/Expr.cpp

    r7564e10 r67130fe  
    6464                        // references have been removed, in which case dereference returns an lvalue of the
    6565                        // base type
    66                         ret->result.set_and_mutate( base )->set_lvalue( true );
     66                        ret->result = base;
     67                        add_qualifiers( ret->result, CV::Lvalue );
    6768                }
    6869        }
     
    164165        genericSubsitution( aggregate->result ).apply( result );
    165166        // ensure lvalue and appropriate restrictions from aggregate type
    166         result.get_and_mutate()->qualifiers |= aggregate->result->qualifiers | CV::Lvalue;
     167        add_qualifiers( result, aggregate->result->qualifiers | CV::Lvalue );
    167168}
    168169
     
    173174        assert( var );
    174175        assert( var->get_type() );
    175         result.set_and_mutate( var->get_type() )->set_lvalue( true );
     176        result = var->get_type();
     177        add_qualifiers( result, CV::Lvalue );
    176178}
    177179
     
    306308: Expr( loc ), init( i ) {
    307309        assert( t && i );
    308         result.set_and_mutate( t )->set_lvalue( true );
     310        result = t;
     311        add_qualifiers( result, CV::Lvalue );
    309312}
    310313
     
    322325                "index %d in expr %s", type->size(), index, toString( tuple ).c_str() );
    323326        // like MemberExpr, TupleIndexExpr is always an lvalue
    324         result.set_and_mutate( type->types[ index ] )->set_lvalue( true );
     327        result = type->types[ index ];
     328        add_qualifiers( result, CV::Lvalue );
    325329}
    326330
  • src/AST/Node.hpp

    r7564e10 r67130fe  
    1010// Created On       : Wed May 8 10:27:04 2019
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Thu May 23 16:00:00 2019
    13 // Update Count     : 4
     12// Last Modified On : Mon Jun  3 13:26:00 2019
     13// Update Count     : 5
    1414//
    1515
     
    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.
     
    107127        ptr_base() : node(nullptr) {}
    108128        ptr_base( const node_t * n ) : node(n) { if( node ) _inc(node); }
    109         ~ptr_base() { if( node ) _dec(node); }
     129        ~ptr_base() { if( node ) { auto tmp = node; node = nullptr; _dec(tmp); } }
    110130
    111131        ptr_base( const ptr_base & o ) : node(o.node) {
     
    113133        }
    114134
    115         ptr_base( ptr_base && o ) : node(o.node) {
    116                 if( node ) _inc(node);
    117         }
     135        ptr_base( ptr_base && o ) : node(o.node) { o.node = nullptr; }
    118136
    119137        template< enum Node::ref_type o_ref_t >
     
    129147        template<typename o_node_t>
    130148        ptr_base & operator=( const o_node_t * node ) {
    131                 assign( node ? strict_dynamic_cast<const node_t *>(node) : nullptr );
     149                assign( strict_dynamic_cast<const node_t *, nullptr>(node) );
    132150                return *this;
    133151        }
     
    139157
    140158        ptr_base & operator=( ptr_base && o ) {
    141                 assign(o.node);
     159                if ( node == o.node ) return *this;
     160                if ( node ) _dec(node);
     161                node = o.node;
     162                o.node = nullptr;
    142163                return *this;
    143164        }
     
    165186        const o_node_t * as() const { return dynamic_cast<const o_node_t *>(node); }
    166187
     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
    167192        /// Returns a mutable version of the pointer in this node.
    168193        node_t * get_and_mutate();
  • src/AST/Pass.hpp

    r7564e10 r67130fe  
    179179
    180180        template<typename pass_type>
    181         friend void acceptAll( std::list< ptr<Decl> > & decls, Pass<pass_type>& visitor );
     181        friend void accept_all( std::list< ptr<Decl> > & decls, Pass<pass_type>& visitor );
    182182private:
    183183
  • src/AST/Pass.proto.hpp

    r7564e10 r67130fe  
    312312                INDEXER_FUNC1( addTrait  , const TraitDecl *     );
    313313                INDEXER_FUNC2( addWith   , const std::vector< ptr<Expr> > &, const Node * );
    314                 INDEXER_FUNC2( addWith   , const std::list  < ptr<Expr> > &, const Node * );
    315314
    316315                // A few extra functions have more complicated behaviour, they are hand written
  • src/AST/Print.hpp

    r7564e10 r67130fe  
    1717
    1818#include <iosfwd>
     19#include <utility> // for forward
    1920
    2021#include "AST/Node.hpp"
     
    2829void print( std::ostream & os, const ast::Node * node, Indenter indent = {} );
    2930
    30 inline void print( std::ostream & os, const ast::Node * node, unsigned int indent ) {
    31     print( os, node, Indenter{ Indenter::tabsize, indent });
     31/// Wrap any standard format printer (matching above) with integer Indenter constructor
     32template<typename T>
     33inline void print( std::ostream & os, T && x, unsigned int indent ) {
     34    print( os, std::forward<T>(x), Indenter{ Indenter::tabsize, indent });
    3235}
    3336
  • src/AST/Type.cpp

    r7564e10 r67130fe  
    2727namespace ast {
    2828
    29 const Type * Type::getComponent( unsigned i ) {
     29const Type * Type::getComponent( unsigned i ) const {
    3030        assertf( size() == 1 && i == 0, "Type::getComponent was called with size %d and index %d\n", size(), i );
    3131        return this;
    3232}
    3333
    34 const Type * Type::stripDeclarator() {
     34const Type * Type::stripDeclarator() const {
    3535        const Type * t;
    3636        const Type * a;
     
    3939}
    4040
    41 const Type * Type::stripReferences() {
     41const Type * Type::stripReferences() const {
    4242        const Type * t;
    4343        const ReferenceType * r;
  • src/AST/Type.hpp

    r7564e10 r67130fe  
    2525#include "Decl.hpp"          // for AggregateDecl subclasses
    2626#include "Fwd.hpp"
    27 #include "Node.hpp"          // for Node, ptr
     27#include "Node.hpp"          // for Node, ptr, ptr_base
    2828#include "TypeVar.hpp"
    2929#include "Visitor.hpp"
     
    4848
    4949        Type * set_const( bool v ) { qualifiers.is_const = v; return this; }
     50        Type * set_volatile( bool v ) { qualifiers.is_volatile = v; return this; }
    5051        Type * set_restrict( bool v ) { qualifiers.is_restrict = v; return this; }
    5152        Type * set_lvalue( bool v ) { qualifiers.is_lvalue = v; return this; }
     
    5859        virtual bool isVoid() const { return size() == 0; }
    5960        /// Get the i'th component of this type
    60         virtual const Type * getComponent( unsigned i );
     61        virtual const Type * getComponent( unsigned i ) const;
    6162
    6263        /// type without outer pointers and arrays
    63         const Type * stripDeclarator();
     64        const Type * stripDeclarator() const;
    6465        /// type without outer references
    65         const Type * stripReferences();
     66        const Type * stripReferences() const;
    6667        /// number of reference occuring consecutively on the outermost layer of this type
    6768        /// (i.e. do not count references nested within other types)
     
    7576        MUTATE_FRIEND
    7677};
     78
     79/// Clear/reset the qualifiers on this type, cloning only if necessary
     80template< enum Node::ref_type ref_t >
     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;
     83}
     84
     85/// Add the specified qualifiers to this type, cloning only if necessary
     86template< enum Node::ref_type ref_t >
     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;
     95}
    7796
    7897/// `void`
     
    437456        unsigned size() const override { return types.size(); }
    438457
    439         const Type * getComponent( unsigned i ) override {
     458        const Type * getComponent( unsigned i ) const override {
    440459                assertf( i < size(), "TupleType::getComponent: index %d must be less than size %d",
    441460                        i, size() );
  • src/AST/TypeSubstitution.cpp

    r7564e10 r67130fe  
    99// Author           : Richard C. Bilson
    1010// Created On       : Mon May 18 07:44:20 2015
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Thu Mar 16 15:54:35 2017
    13 // Update Count     : 4
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Mon Jun  3 13:26:00 2017
     13// Update Count     : 5
    1414//
    1515
     
    2626}
    2727
    28 TypeSubstitution::~TypeSubstitution() {
    29         for ( TypeEnvType::iterator i = typeEnv.begin(); i != typeEnv.end(); ++i ) {
    30                 delete( i->second );
    31         }
    32         for ( VarEnvType::iterator i = varEnv.begin(); i != varEnv.end(); ++i ) {
    33                 delete( i->second );
    34         }
    35 }
     28TypeSubstitution::~TypeSubstitution() {}
    3629
    3730TypeSubstitution &TypeSubstitution::operator=( const TypeSubstitution &other ) {
  • src/AST/module.mk

    r7564e10 r67130fe  
    2828        AST/Print.cpp \
    2929        AST/Stmt.cpp \
     30        AST/SymbolTable.cpp \
    3031        AST/Type.cpp \
     32        AST/TypeEnvironment.cpp \
    3133        AST/TypeSubstitution.cpp
    3234
  • src/AST/porting.md

    r7564e10 r67130fe  
    104104          * `LinkageSpec::isMangled(Spec)` etc. => `Spec.is_mangled` etc.
    105105          * `LinkageSpec::Intrinsic` etc. => `ast::Linkage::Intrinsic` etc.
     106  * Boolean flags to `SymTab::Mangler::mangle` are now a `SymTab::Mangle::Mode` struct
     107    * uses `bitfield`
     108  * Because `Indexer` isn't a terribly evocative name:
     109    * `SymTab::Indexer` => `ast::SymbolTable`
     110    * `SymTab/Indexer.{h,cc}` => `AST/SymbolTable.{hpp,cpp}`
     111    * **TODO** `WithIndexer` => `WithSymbolTable`
     112      * `indexer` => `symTab`
     113    * `IdData::deleteStmt` => `IdData::deleter`
     114    * `lookupId()` now returns a vector rather than an out-param list
     115    * To avoid name collisions:
     116      * `SymTab::Mangler` => `Mangle`
     117  * `ResolvExpr::TypeEnvironment` => `ast::TypeEnvironment`
     118    * in `AST/TypeEnvironment.hpp`
    106119* Boolean constructor parameters get replaced with a dedicated flag enum:
    107120  * e.g. `bool isVarLen;` => `enum LengthFlag { FixedLen, VariableLen };` `LengthFlag isVarLen;`
     
    261274  * feature is `type@thing` e.g. `int@MAX`
    262275
     276`referenceToRvalueConversion`
     277* now returns `const Expr *` rather than mutating argument
     278
     279`printAssertionSet`, `printOpenVarSet`
     280* `ostream &` now first argument, for consistency
     281
     282`EqvClass`
     283* `type` => `bound`
     284
     285`TypeEnvironment`
     286* `makeSubstitution()` => `writeToSubstitution()`
     287* `isEmpty()` => `empty()`
     288* removed `clone()` in favour of explicit copies
     289
     290`occurs`
     291* moved to be helper function in `TypeEnvironment.cpp` (its only use)
     292
     293`WidenMode`
     294* changed `widenFirst`, `widenSecond` => `first`, `second`
     295* changed `WidenMode widenMode` => `WidenMode widen`
     296
    263297[1] https://gcc.gnu.org/onlinedocs/gcc-9.1.0/gcc/Type-Attributes.html#Type-Attributes
    264298
  • src/GenPoly/GenPoly.cc

    r7564e10 r67130fe  
    2424#include <vector>                       // for vector
    2525
     26#include "AST/Type.hpp"
    2627#include "GenPoly/ErasableScopedMap.h"  // for ErasableScopedMap<>::const_it...
    2728#include "ResolvExpr/typeops.h"         // for flatten
     
    262263                } else {
    263264                        return dynamic_cast< FunctionType* >( ty ); // pointer if FunctionType, NULL otherwise
     265                }
     266        }
     267
     268        const ast::FunctionType * getFunctionType( const ast::Type * ty ) {
     269                if ( auto pty = dynamic_cast< const ast::PointerType * >( ty ) ) {
     270                        return pty->base.as< ast::FunctionType >();
     271                } else {
     272                        return dynamic_cast< const ast::FunctionType * >( ty );
    264273                }
    265274        }
  • src/GenPoly/GenPoly.h

    r7564e10 r67130fe  
    2020
    2121#include "ErasableScopedMap.h"    // for ErasableScopedMap
     22#include "AST/Fwd.hpp"
    2223#include "SymTab/Mangler.h"       // for Mangler
    2324#include "SynTree/Declaration.h"  // for TypeDecl::Data, AggregateDecl, Type...
     
    7273        /// Returns a pointer to the base FunctionType if ty is the type of a function (or pointer to one), NULL otherwise
    7374        FunctionType *getFunctionType( Type *ty );
     75        const ast::FunctionType * getFunctionType( const ast::Type * ty );
    7476
    7577        /// If expr (after dereferencing N >= 0 pointers) is a variable expression, returns the variable expression, NULL otherwise;
  • src/InitTweak/FixInit.cc

    r7564e10 r67130fe  
    7272                };
    7373
     74                struct StmtExprResult {
     75                        static void link( std::list< Declaration * > & translationUnit );
     76
     77                        void previsit( StmtExpr * stmtExpr );
     78                };
     79
    7480                struct InsertImplicitCalls : public WithConstTypeSubstitution {
    7581                        /// wrap function application expressions as ImplicitCopyCtorExpr nodes so that it is easy to identify which
     
    226232                acceptAll( translationUnit, checker );
    227233
     234                // fixes StmtExpr to properly link to their resulting expression
     235                StmtExprResult::link( translationUnit );
     236
    228237                // fixes ConstructorInit for global variables. should happen before fixInitializers.
    229238                InitTweak::fixGlobalInit( translationUnit, inLibrary );
     
    299308
    300309                        return dtorFunc;
     310                }
     311
     312                void StmtExprResult::link( std::list< Declaration * > & translationUnit ) {
     313                        PassVisitor<StmtExprResult> linker;
     314                        acceptAll( translationUnit, linker );
    301315                }
    302316
     
    349363                        PassVisitor<FixCtorExprs> fixer;
    350364                        mutateAll( translationUnit, fixer );
     365                }
     366
     367                void StmtExprResult::previsit( StmtExpr * stmtExpr ) {
     368                        // we might loose the result expression here so add a pointer to trace back
     369                        assert( stmtExpr->result );
     370                        Type * result = stmtExpr->result;
     371                        if ( ! result->isVoid() ) {
     372                                CompoundStmt * body = stmtExpr->statements;
     373                                assert( ! body->kids.empty() );
     374                                stmtExpr->resultExpr = strict_dynamic_cast< ExprStmt * >( body->kids.back() );
     375                        }
    351376                }
    352377
     
    655680                        // function call temporaries should be placed at statement-level, rather than nested inside of a new statement expression,
    656681                        // since temporaries can be shared across sub-expressions, e.g.
    657                         //   [A, A] f();
    658                         //   g([A] x, [A] y);
    659                         //   g(f());
     682                        //   [A, A] f();       // decl
     683                        //   g([A] x, [A] y);  // decl
     684                        //   g(f());           // call
    660685                        // f is executed once, so the return temporary is shared across the tuple constructors for x and y.
    661686                        // Explicitly mutating children instead of mutating the inner compound statement forces the temporaries to be added
     
    665690                        assert( env );
    666691
     692                        indexer.enterScope();
    667693                        // visit all statements
    668694                        std::list< Statement * > & stmts = stmtExpr->statements->get_kids();
     
    670696                                stmt = stmt->acceptMutator( *visitor );
    671697                        } // for
     698                        indexer.leaveScope();
    672699
    673700                        assert( stmtExpr->result );
     
    688715                                stmtsToAddBefore.push_back( new DeclStmt( ret ) );
    689716
    690                                 // must have a non-empty body, otherwise it wouldn't have a result
    691                                 CompoundStmt * body = stmtExpr->statements;
    692                                 assert( ! body->kids.empty() );
    693                                 // must be an ExprStmt, otherwise it wouldn't have a result
    694                                 ExprStmt * last = strict_dynamic_cast< ExprStmt * >( body->kids.back() );
    695                                 last->expr = makeCtorDtor( "?{}", ret, last->expr );
     717                                if(!stmtExpr->resultExpr) {
     718                                        SemanticError(stmtExpr, "Statment-Expression should have a resulting expression");
     719                                }
     720                                ExprStmt * last = stmtExpr->resultExpr;
     721                                try {
     722                                        last->expr = makeCtorDtor( "?{}", ret, last->expr );
     723                                } catch(...) {
     724                                        std::cerr << "=======================" << std::endl;
     725                                        std::cerr << "ERROR, can't resolve" << std::endl;
     726                                        ret->print(std::cerr);
     727                                        std::cerr << std::endl << "---" << std::endl;
     728                                        last->expr->print(std::cerr);
     729
     730                                        abort();
     731                                }
    696732
    697733                                // add destructors after current statement
  • src/InitTweak/InitTweak.cc

    r7564e10 r67130fe  
    756756        }
    757757
     758        bool isCopyFunction( const ast::FunctionDecl * decl ) {
     759                const ast::FunctionType * ftype = decl->type;
     760                if ( ftype->params.size() != 2 ) return false;
     761
     762                const ast::Type * t1 = getPointerBase( ftype->params.front()->get_type() );
     763                if ( ! t1 ) return false;
     764                const ast::Type * t2 = ftype->params.back()->get_type();
     765               
     766                return ResolvExpr::typesCompatibleIgnoreQualifiers( t1, t2, ast::SymbolTable{} );
     767        }
     768
    758769        FunctionDecl * isAssignment( Declaration * decl ) {
    759770                return isCopyFunction( decl, "?=?" );
  • src/InitTweak/InitTweak.h

    r7564e10 r67130fe  
    3030        FunctionDecl * isCopyConstructor( Declaration * decl );
    3131        FunctionDecl * isCopyFunction( Declaration * decl, const std::string & fname );
     32        bool isCopyFunction( const ast::FunctionDecl * decl );
    3233
    3334        /// returns the base type of the first parameter to a constructor/destructor/assignment function
  • src/Makefile.in

    r7564e10 r67130fe  
    170170        AST/Init.$(OBJEXT) AST/LinkageSpec.$(OBJEXT) \
    171171        AST/Node.$(OBJEXT) AST/Pass.$(OBJEXT) AST/Print.$(OBJEXT) \
    172         AST/Stmt.$(OBJEXT) AST/Type.$(OBJEXT) \
     172        AST/Stmt.$(OBJEXT) AST/SymbolTable.$(OBJEXT) \
     173        AST/Type.$(OBJEXT) AST/TypeEnvironment.$(OBJEXT) \
    173174        AST/TypeSubstitution.$(OBJEXT)
    174175am__objects_2 = CodeGen/CodeGenerator.$(OBJEXT) \
     
    586587        AST/Print.cpp \
    587588        AST/Stmt.cpp \
     589        AST/SymbolTable.cpp \
    588590        AST/Type.cpp \
     591        AST/TypeEnvironment.cpp \
    589592        AST/TypeSubstitution.cpp
    590593
     
    754757AST/Print.$(OBJEXT): AST/$(am__dirstamp) AST/$(DEPDIR)/$(am__dirstamp)
    755758AST/Stmt.$(OBJEXT): AST/$(am__dirstamp) AST/$(DEPDIR)/$(am__dirstamp)
     759AST/SymbolTable.$(OBJEXT): AST/$(am__dirstamp) \
     760        AST/$(DEPDIR)/$(am__dirstamp)
    756761AST/Type.$(OBJEXT): AST/$(am__dirstamp) AST/$(DEPDIR)/$(am__dirstamp)
     762AST/TypeEnvironment.$(OBJEXT): AST/$(am__dirstamp) \
     763        AST/$(DEPDIR)/$(am__dirstamp)
    757764AST/TypeSubstitution.$(OBJEXT): AST/$(am__dirstamp) \
    758765        AST/$(DEPDIR)/$(am__dirstamp)
     
    11901197@AMDEP_TRUE@@am__include@ @am__quote@AST/$(DEPDIR)/Print.Po@am__quote@
    11911198@AMDEP_TRUE@@am__include@ @am__quote@AST/$(DEPDIR)/Stmt.Po@am__quote@
     1199@AMDEP_TRUE@@am__include@ @am__quote@AST/$(DEPDIR)/SymbolTable.Po@am__quote@
    11921200@AMDEP_TRUE@@am__include@ @am__quote@AST/$(DEPDIR)/Type.Po@am__quote@
     1201@AMDEP_TRUE@@am__include@ @am__quote@AST/$(DEPDIR)/TypeEnvironment.Po@am__quote@
    11931202@AMDEP_TRUE@@am__include@ @am__quote@AST/$(DEPDIR)/TypeSubstitution.Po@am__quote@
    11941203@AMDEP_TRUE@@am__include@ @am__quote@CodeGen/$(DEPDIR)/CodeGenerator.Po@am__quote@
  • src/ResolvExpr/AlternativeFinder.cc

    r7564e10 r67130fe  
    2828#include "Alternative.h"           // for AltList, Alternative
    2929#include "AlternativeFinder.h"
     30#include "AST/Expr.hpp"
     31#include "AST/Type.hpp"
    3032#include "Common/SemanticError.h"  // for SemanticError
    3133#include "Common/utility.h"        // for deleteAll, printAll, CodeLocation
     
    222224                        cost.incReference();
    223225                }
     226        }
     227
     228        const ast::Expr * referenceToRvalueConversion( const ast::Expr * expr, Cost & cost ) {
     229                if ( expr->result.as< ast::ReferenceType >() ) {
     230                        // cast away reference from expr
     231                        cost.incReference();
     232                        return new ast::CastExpr{ expr->location, expr, expr->result->stripReferences() };
     233                }
     234               
     235                return expr;
    224236        }
    225237
  • src/ResolvExpr/CommonType.cc

    r7564e10 r67130fe  
    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();
     
    483485        );
    484486
    485         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 )
    486488                : result( 0 ), type2( type2 ), widenFirst( widenFirst ), widenSecond( widenSecond ), indexer( indexer ), env( env ), openVars( openVars ) {
    487489        }
    488490
    489         void CommonType::postvisit( VoidType * ) {}
    490 
    491         void CommonType::postvisit( BasicType *basicType ) {
     491        void CommonType_old::postvisit( VoidType * ) {}
     492
     493        void CommonType_old::postvisit( BasicType *basicType ) {
    492494                if ( BasicType *otherBasic = dynamic_cast< BasicType* >( type2 ) ) {
    493495                        BasicType::Kind newType = commonTypes[ basicType->get_kind() ][ otherBasic->get_kind() ];
     
    505507
    506508        template< typename Pointer >
    507         void CommonType::getCommonWithVoidPointer( Pointer* voidPointer, Pointer* otherPointer ) {
     509        void CommonType_old::getCommonWithVoidPointer( Pointer* voidPointer, Pointer* otherPointer ) {
    508510                if ( TypeInstType* var = dynamic_cast< TypeInstType* >( otherPointer->get_base() ) ) {
    509511                        OpenVarSet::const_iterator entry = openVars.find( var->get_name() );
     
    518520        }
    519521
    520         void CommonType::postvisit( PointerType *pointerType ) {
     522        void CommonType_old::postvisit( PointerType *pointerType ) {
    521523                if ( PointerType *otherPointer = dynamic_cast< PointerType* >( type2 ) ) {
    522524                        // std::cerr << "commonType: two pointers: " << pointerType << " / " << otherPointer << std::endl;
     
    553555        }
    554556
    555         void CommonType::postvisit( ArrayType * ) {}
    556 
    557         void CommonType::postvisit( ReferenceType *refType ) {
     557        void CommonType_old::postvisit( ArrayType * ) {}
     558
     559        void CommonType_old::postvisit( ReferenceType *refType ) {
    558560                if ( ReferenceType *otherRef = dynamic_cast< ReferenceType* >( type2 ) ) {
    559561                        // std::cerr << "commonType: both references: " << refType << " / " << otherRef << std::endl;
     
    590592        }
    591593
    592         void CommonType::postvisit( FunctionType * ) {}
    593         void CommonType::postvisit( StructInstType * ) {}
    594         void CommonType::postvisit( UnionInstType * ) {}
    595 
    596         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 ) {
    597599                if ( dynamic_cast< BasicType * >( type2 ) || dynamic_cast< ZeroType* >( type2 ) || dynamic_cast< OneType* >( type2 ) ) {
    598600                        // reuse BasicType, EnumInstType code by swapping type2 with enumInstType
     
    601603        }
    602604
    603         void CommonType::postvisit( TraitInstType * ) {
    604         }
    605 
    606         void CommonType::postvisit( TypeInstType *inst ) {
     605        void CommonType_old::postvisit( TraitInstType * ) {
     606        }
     607
     608        void CommonType_old::postvisit( TypeInstType *inst ) {
    607609                if ( widenFirst ) {
    608610                        NamedTypeDecl *nt = indexer.lookupType( inst->get_name() );
     
    626628        }
    627629
    628         void CommonType::postvisit( TupleType * ) {}
    629         void CommonType::postvisit( VarArgsType * ) {}
    630 
    631         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 ) {
    632634                if ( widenFirst ) {
    633635                        if ( dynamic_cast< BasicType* >( type2 ) || dynamic_cast< PointerType* >( type2 ) || dynamic_cast< EnumInstType* >( type2 ) ) {
     
    643645        }
    644646
    645         void CommonType::postvisit( OneType *oneType ) {
     647        void CommonType_old::postvisit( OneType *oneType ) {
    646648                if ( widenFirst ) {
    647649                        if ( dynamic_cast< BasicType* >( type2 ) || dynamic_cast< EnumInstType* >( type2 ) ) {
     
    656658                }
    657659        }
     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
    658999} // namespace ResolvExpr
    6591000
  • src/ResolvExpr/FindOpenVars.cc

    r7564e10 r67130fe  
    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                };
     135        }
     136
     137        void findOpenVars(
     138                        const ast::Type * type, ast::OpenVarSet & open, ast::OpenVarSet & closed,
     139                        ast::AssertionSet & need, ast::AssertionSet & have, FirstMode firstIsOpen ) {
     140                ast::Pass< FindOpenVars_new > finder{ open, closed, need, have, firstIsOpen };
     141                type->accept( finder );
    94142        }
    95143} // namespace ResolvExpr
  • src/ResolvExpr/FindOpenVars.h

    r7564e10 r67130fe  
    1616#pragma once
    1717
     18#include "AST/TypeEnvironment.hpp"  // for AssertionSet, OpenVarSet
    1819#include "ResolvExpr/TypeEnvironment.h"  // for AssertionSet, OpenVarSet
    1920
    2021class Type;
     22namespace ast {
     23        class Type;
     24}
    2125
    2226namespace ResolvExpr {
    2327        // Updates open and closed variables and their associated assertions
    2428        void findOpenVars( Type *type, OpenVarSet &openVars, OpenVarSet &closedVars, AssertionSet &needAssertions, AssertionSet &haveAssertions, bool firstIsOpen );
     29
     30        enum FirstMode { FirstClosed, FirstOpen };
     31
     32        // Updates open and closed variables and their associated assertions
     33        void findOpenVars(
     34                const ast::Type * type, ast::OpenVarSet & open, ast::OpenVarSet & closed,
     35                ast::AssertionSet & need, ast::AssertionSet & have, FirstMode firstIsOpen );
    2536} // namespace ResolvExpr
    2637
  • src/ResolvExpr/ResolveAssertions.cc

    r7564e10 r67130fe  
    3030#include "Common/Indenter.h"        // for Indenter
    3131#include "Common/utility.h"         // for sort_mins
     32#include "GenPoly/GenPoly.h"        // for getFunctionType
    3233#include "ResolvExpr/RenameVars.h"  // for renameTyVars
    3334#include "SymTab/Indexer.h"         // for Indexer
     
    154155                        Cost k = Cost::zero;
    155156                        for ( const auto& assn : x.assns ) {
     157                                // compute conversion cost from satisfying decl to assertion
    156158                                k += computeConversionCost(
    157159                                        assn.match.adjType, assn.decl->get_type(), indexer, x.env );
    158160                               
    159161                                // mark vars+specialization cost on function-type assertions
    160                                 Type* assnType = assn.match.cdata.id->get_type();
    161                                 FunctionType* func;
    162                                 if ( PointerType* ptr = dynamic_cast< PointerType* >( assnType ) ) {
    163                                         func = dynamic_cast< FunctionType* >( ptr->base );
    164                                 } else {
    165                                         func = dynamic_cast< FunctionType* >( assnType );
    166                                 }
     162                                FunctionType* func = GenPoly::getFunctionType( assn.match.cdata.id->get_type() );
    167163                                if ( ! func ) continue;
    168164                               
  • src/ResolvExpr/Resolver.cc

    r7564e10 r67130fe  
    77// Resolver.cc --
    88//
    9 // Author           : Richard C. Bilson
     9// Author           : Aaron B. Moss
    1010// Created On       : Sun May 17 12:17:01 2015
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Tue Feb 19 18:09:56 2019
    13 // Update Count     : 240
     11// Last Modified By : Aaron B. Moss
     12// Last Modified On : Wed May 29 11:00:00 2019
     13// Update Count     : 241
    1414//
    1515
     
    2121#include "Alternative.h"                 // for Alternative, AltList
    2222#include "AlternativeFinder.h"           // for AlternativeFinder, resolveIn...
     23#include "CurrentObject.h"               // for CurrentObject
     24#include "RenameVars.h"                  // for RenameVars, global_renamer
     25#include "Resolver.h"
     26#include "ResolvMode.h"                  // for ResolvMode
     27#include "typeops.h"                     // for extractResultType
     28#include "Unify.h"                       // for unify
     29#include "AST/Pass.hpp"
     30#include "AST/SymbolTable.hpp"
    2331#include "Common/PassVisitor.h"          // for PassVisitor
    2432#include "Common/SemanticError.h"        // for SemanticError
    2533#include "Common/utility.h"              // for ValueGuard, group_iterate
    26 #include "CurrentObject.h"               // for CurrentObject
    2734#include "InitTweak/GenInit.h"
    2835#include "InitTweak/InitTweak.h"         // for isIntrinsicSingleArgCallStmt
    29 #include "RenameVars.h"                  // for RenameVars, global_renamer
    3036#include "ResolvExpr/TypeEnvironment.h"  // for TypeEnvironment
    31 #include "Resolver.h"
    32 #include "ResolvMode.h"                  // for ResolvMode
    3337#include "SymTab/Autogen.h"              // for SizeType
    3438#include "SymTab/Indexer.h"              // for Indexer
     
    4145#include "SynTree/Visitor.h"             // for acceptAll, maybeAccept
    4246#include "Tuples/Tuples.h"
    43 #include "typeops.h"                     // for extractResultType
    44 #include "Unify.h"                       // for unify
    4547#include "Validate/FindSpecialDecls.h"   // for SizeType
    4648
     
    4850
    4951namespace ResolvExpr {
    50         struct Resolver final : public WithIndexer, public WithGuards, public WithVisitorRef<Resolver>, public WithShortCircuiting, public WithStmtsToAdd {
    51                 Resolver() {}
    52                 Resolver( const SymTab::Indexer & other ) {
     52        struct Resolver_old final : public WithIndexer, public WithGuards, public WithVisitorRef<Resolver_old>, public WithShortCircuiting, public WithStmtsToAdd {
     53                Resolver_old() {}
     54                Resolver_old( const SymTab::Indexer & other ) {
    5355                        indexer = other;
    5456                }
     
    101103
    102104        void resolve( std::list< Declaration * > translationUnit ) {
    103                 PassVisitor<Resolver> resolver;
     105                PassVisitor<Resolver_old> resolver;
    104106                acceptAll( translationUnit, resolver );
    105107        }
    106108
    107109        void resolveDecl( Declaration * decl, const SymTab::Indexer & indexer ) {
    108                 PassVisitor<Resolver> resolver( indexer );
     110                PassVisitor<Resolver_old> resolver( indexer );
    109111                maybeAccept( decl, resolver );
    110112        }
     
    402404        }
    403405
    404         void Resolver::previsit( ObjectDecl * objectDecl ) {
    405                 // To handle initialization of routine pointers, e.g., int (*fp)(int) = foo(), means that
    406                 // class-variable initContext is changed multiple time because the LHS is analysed twice.
    407                 // The second analysis changes initContext because of a function type can contain object
    408                 // declarations in the return and parameter types. So each value of initContext is
     406        void Resolver_old::previsit( ObjectDecl * objectDecl ) {
     407                // To handle initialization of routine pointers, e.g., int (*fp)(int) = foo(), means that 
     408                // class-variable initContext is changed multiple time because the LHS is analysed twice. 
     409                // The second analysis changes initContext because of a function type can contain object 
     410                // declarations in the return and parameter types. So each value of initContext is 
    409411                // retained, so the type on the first analysis is preserved and used for selecting the RHS.
    410412                GuardValue( currentObject );
     
    418420
    419421        template< typename PtrType >
    420         void Resolver::handlePtrType( PtrType * type ) {
     422        void Resolver_old::handlePtrType( PtrType * type ) {
    421423                if ( type->get_dimension() ) {
    422424                        findSingleExpression( type->dimension, Validate::SizeType->clone(), indexer );
     
    424426        }
    425427
    426         void Resolver::previsit( ArrayType * at ) {
     428        void Resolver_old::previsit( ArrayType * at ) {
    427429                handlePtrType( at );
    428430        }
    429431
    430         void Resolver::previsit( PointerType * pt ) {
     432        void Resolver_old::previsit( PointerType * pt ) {
    431433                handlePtrType( pt );
    432434        }
    433435
    434         void Resolver::previsit( FunctionDecl * functionDecl ) {
     436        void Resolver_old::previsit( FunctionDecl * functionDecl ) {
    435437#if 0
    436438                std::cerr << "resolver visiting functiondecl ";
     
    442444        }
    443445
    444         void Resolver::postvisit( FunctionDecl * functionDecl ) {
    445                 // default value expressions have an environment which shouldn't be there and trips up
     446        void Resolver_old::postvisit( FunctionDecl * functionDecl ) {
     447                // default value expressions have an environment which shouldn't be there and trips up 
    446448                // later passes.
    447449                // xxx - it might be necessary to somehow keep the information from this environment, but I
     
    457459        }
    458460
    459         void Resolver::previsit( EnumDecl * ) {
     461        void Resolver_old::previsit( EnumDecl * ) {
    460462                // in case we decide to allow nested enums
    461463                GuardValue( inEnumDecl );
     
    463465        }
    464466
    465         void Resolver::previsit( StaticAssertDecl * assertDecl ) {
     467        void Resolver_old::previsit( StaticAssertDecl * assertDecl ) {
    466468                findIntegralExpression( assertDecl->condition, indexer );
    467469        }
    468470
    469         void Resolver::previsit( ExprStmt * exprStmt ) {
     471        void Resolver_old::previsit( ExprStmt * exprStmt ) {
    470472                visit_children = false;
    471473                assertf( exprStmt->expr, "ExprStmt has null Expression in resolver" );
     
    473475        }
    474476
    475         void Resolver::previsit( AsmExpr * asmExpr ) {
     477        void Resolver_old::previsit( AsmExpr * asmExpr ) {
    476478                visit_children = false;
    477479                findVoidExpression( asmExpr->operand, indexer );
     
    481483        }
    482484
    483         void Resolver::previsit( AsmStmt * asmStmt ) {
     485        void Resolver_old::previsit( AsmStmt * asmStmt ) {
    484486                visit_children = false;
    485487                acceptAll( asmStmt->get_input(), *visitor );
     
    487489        }
    488490
    489         void Resolver::previsit( IfStmt * ifStmt ) {
     491        void Resolver_old::previsit( IfStmt * ifStmt ) {
    490492                findIntegralExpression( ifStmt->condition, indexer );
    491493        }
    492494
    493         void Resolver::previsit( WhileStmt * whileStmt ) {
     495        void Resolver_old::previsit( WhileStmt * whileStmt ) {
    494496                findIntegralExpression( whileStmt->condition, indexer );
    495497        }
    496498
    497         void Resolver::previsit( ForStmt * forStmt ) {
     499        void Resolver_old::previsit( ForStmt * forStmt ) {
    498500                if ( forStmt->condition ) {
    499501                        findIntegralExpression( forStmt->condition, indexer );
     
    505507        }
    506508
    507         void Resolver::previsit( SwitchStmt * switchStmt ) {
     509        void Resolver_old::previsit( SwitchStmt * switchStmt ) {
    508510                GuardValue( currentObject );
    509511                findIntegralExpression( switchStmt->condition, indexer );
     
    512514        }
    513515
    514         void Resolver::previsit( CaseStmt * caseStmt ) {
     516        void Resolver_old::previsit( CaseStmt * caseStmt ) {
    515517                if ( caseStmt->condition ) {
    516518                        std::list< InitAlternative > initAlts = currentObject.getOptions();
     
    531533        }
    532534
    533         void Resolver::previsit( BranchStmt * branchStmt ) {
     535        void Resolver_old::previsit( BranchStmt * branchStmt ) {
    534536                visit_children = false;
    535537                // must resolve the argument for a computed goto
     
    542544        }
    543545
    544         void Resolver::previsit( ReturnStmt * returnStmt ) {
     546        void Resolver_old::previsit( ReturnStmt * returnStmt ) {
    545547                visit_children = false;
    546548                if ( returnStmt->expr ) {
     
    549551        }
    550552
    551         void Resolver::previsit( ThrowStmt * throwStmt ) {
     553        void Resolver_old::previsit( ThrowStmt * throwStmt ) {
    552554                visit_children = false;
    553555                // TODO: Replace *exception type with &exception type.
     
    561563        }
    562564
    563         void Resolver::previsit( CatchStmt * catchStmt ) {
     565        void Resolver_old::previsit( CatchStmt * catchStmt ) {
    564566                if ( catchStmt->cond ) {
    565567                        findSingleExpression( catchStmt->cond, new BasicType( noQualifiers, BasicType::Bool ), indexer );
     
    576578        }
    577579
    578         void Resolver::previsit( WaitForStmt * stmt ) {
     580        void Resolver_old::previsit( WaitForStmt * stmt ) {
    579581                visit_children = false;
    580582
     
    782784        }
    783785
    784         void Resolver::previsit( SingleInit * singleInit ) {
     786        void Resolver_old::previsit( SingleInit * singleInit ) {
    785787                visit_children = false;
    786788                // resolve initialization using the possibilities as determined by the currentObject cursor
     
    834836        }
    835837
    836         void Resolver::previsit( ListInit * listInit ) {
     838        void Resolver_old::previsit( ListInit * listInit ) {
    837839                visit_children = false;
    838840                // move cursor into brace-enclosed initializer-list
     
    869871
    870872        // ConstructorInit - fall back on C-style initializer
    871         void Resolver::fallbackInit( ConstructorInit * ctorInit ) {
     873        void Resolver_old::fallbackInit( ConstructorInit * ctorInit ) {
    872874                // could not find valid constructor, or found an intrinsic constructor
    873875                // fall back on C-style initializer
     
    882884        void resolveCtorInit( ConstructorInit * ctorInit, const SymTab::Indexer & indexer ) {
    883885                assert( ctorInit );
    884                 PassVisitor<Resolver> resolver( indexer );
     886                PassVisitor<Resolver_old> resolver( indexer );
    885887                ctorInit->accept( resolver );
    886888        }
     
    888890        void resolveStmtExpr( StmtExpr * stmtExpr, const SymTab::Indexer & indexer ) {
    889891                assert( stmtExpr );
    890                 PassVisitor<Resolver> resolver( indexer );
     892                PassVisitor<Resolver_old> resolver( indexer );
    891893                stmtExpr->accept( resolver );
    892894                stmtExpr->computeResult();
     
    894896        }
    895897
    896         void Resolver::previsit( ConstructorInit * ctorInit ) {
     898        void Resolver_old::previsit( ConstructorInit * ctorInit ) {
    897899                visit_children = false;
    898900                // xxx - fallback init has been removed => remove fallbackInit function and remove complexity from FixInit and remove C-init from ConstructorInit
     
    928930                // }
    929931        }
     932
     933        ///////////////////////////////////////////////////////////////////////////
     934        //
     935        // *** NEW RESOLVER ***
     936        //
     937        ///////////////////////////////////////////////////////////////////////////
     938
     939        class Resolver_new final
     940        : public ast::WithIndexer, public ast::WithGuards, public ast::WithVisitorRef<Resolver_new>,
     941          public ast::WithShortCircuiting, public ast::WithStmtsToAdd<> {
     942                 
     943        public:
     944                Resolver_new() = default;
     945                Resolver_new( const ast::SymbolTable & syms ) { /*symtab = syms;*/ }
     946
     947                void previsit( ast::FunctionDecl * functionDecl );
     948                ast::DeclWithType * postvisit( ast::FunctionDecl * functionDecl );
     949                void previsit( ast::ObjectDecl * objectDecl );
     950                void previsit( ast::EnumDecl * enumDecl );
     951                void previsit( ast::StaticAssertDecl * assertDecl );
     952
     953                void previsit( ast::ArrayType * at );
     954                void previsit( ast::PointerType * pt );
     955
     956                void previsit( ast::ExprStmt * exprStmt );
     957                void previsit( ast::AsmExpr * asmExpr );
     958                void previsit( ast::AsmStmt * asmStmt );
     959                void previsit( ast::IfStmt * ifStmt );
     960                void previsit( ast::WhileStmt * whileStmt );
     961                void previsit( ast::ForStmt * forStmt );
     962                void previsit( ast::SwitchStmt * switchStmt );
     963                void previsit( ast::CaseStmt * caseStmt );
     964                void previsit( ast::BranchStmt * branchStmt );
     965                void previsit( ast::ReturnStmt * returnStmt );
     966                void previsit( ast::ThrowStmt * throwStmt );
     967                void previsit( ast::CatchStmt * catchStmt );
     968                void previsit( ast::WaitForStmt * stmt );
     969
     970                void previsit( ast::SingleInit * singleInit );
     971                void previsit( ast::ListInit * listInit );
     972                void previsit( ast::ConstructorInit * ctorInit );
     973        };
     974
     975        void resolve( std::list< ast::ptr<ast::Decl> >& translationUnit ) {
     976                ast::Pass<Resolver_new> resolver;
     977                accept_all( translationUnit, resolver );
     978        }
     979
     980        void previsit( ast::FunctionDecl * functionDecl ) {
     981                #warning unimplemented; Resolver port in progress
     982                (void)functionDecl;
     983                assert(false);
     984        }
     985
     986        ast::DeclWithType * postvisit( ast::FunctionDecl * functionDecl ) {
     987                #warning unimplemented; Resolver port in progress
     988                (void)functionDecl;
     989                assert(false);
     990                return nullptr;
     991        }
     992
     993        void previsit( ast::ObjectDecl * objectDecl ) {
     994                #warning unimplemented; Resolver port in progress
     995                (void)objectDecl;
     996                assert(false);
     997        }
     998
     999        void previsit( ast::EnumDecl * enumDecl ) {
     1000                #warning unimplemented; Resolver port in progress
     1001                (void)enumDecl;
     1002                assert(false);
     1003        }
     1004
     1005        void previsit( ast::StaticAssertDecl * assertDecl ) {
     1006                #warning unimplemented; Resolver port in progress
     1007                (void)assertDecl;
     1008                assert(false);
     1009        }
     1010
     1011        void previsit( ast::ArrayType * at ) {
     1012                #warning unimplemented; Resolver port in progress
     1013                (void)at;
     1014                assert(false);
     1015        }
     1016
     1017        void previsit( ast::PointerType * pt ) {
     1018                #warning unimplemented; Resolver port in progress
     1019                (void)pt;
     1020                assert(false);
     1021        }
     1022
     1023        void previsit( ast::ExprStmt * exprStmt ) {
     1024                #warning unimplemented; Resolver port in progress
     1025                (void)exprStmt;
     1026                assert(false);
     1027        }
     1028
     1029        void previsit( ast::AsmExpr * asmExpr ) {
     1030                #warning unimplemented; Resolver port in progress
     1031                (void)asmExpr;
     1032                assert(false);
     1033        }
     1034
     1035        void previsit( ast::AsmStmt * asmStmt ) {
     1036                #warning unimplemented; Resolver port in progress
     1037                (void)asmStmt;
     1038                assert(false);
     1039        }
     1040
     1041        void previsit( ast::IfStmt * ifStmt ) {
     1042                #warning unimplemented; Resolver port in progress
     1043                (void)ifStmt;
     1044                assert(false);
     1045        }
     1046
     1047        void previsit( ast::WhileStmt * whileStmt ) {
     1048                #warning unimplemented; Resolver port in progress
     1049                (void)whileStmt;
     1050                assert(false);
     1051        }
     1052
     1053        void previsit( ast::ForStmt * forStmt ) {
     1054                #warning unimplemented; Resolver port in progress
     1055                (void)forStmt;
     1056                assert(false);
     1057        }
     1058
     1059        void previsit( ast::SwitchStmt * switchStmt ) {
     1060                #warning unimplemented; Resolver port in progress
     1061                (void)switchStmt;
     1062                assert(false);
     1063        }
     1064
     1065        void previsit( ast::CaseStmt * caseStmt ) {
     1066                #warning unimplemented; Resolver port in progress
     1067                (void)caseStmt;
     1068                assert(false);
     1069        }
     1070
     1071        void previsit( ast::BranchStmt * branchStmt ) {
     1072                #warning unimplemented; Resolver port in progress
     1073                (void)branchStmt;
     1074                assert(false);
     1075        }
     1076
     1077        void previsit( ast::ReturnStmt * returnStmt ) {
     1078                #warning unimplemented; Resolver port in progress
     1079                (void)returnStmt;
     1080                assert(false);
     1081        }
     1082
     1083        void previsit( ast::ThrowStmt * throwStmt ) {
     1084                #warning unimplemented; Resolver port in progress
     1085                (void)throwStmt;
     1086                assert(false);
     1087        }
     1088
     1089        void previsit( ast::CatchStmt * catchStmt ) {
     1090                #warning unimplemented; Resolver port in progress
     1091                (void)catchStmt;
     1092                assert(false);
     1093        }
     1094
     1095        void previsit( ast::WaitForStmt * stmt ) {
     1096                #warning unimplemented; Resolver port in progress
     1097                (void)stmt;
     1098                assert(false);
     1099        }
     1100
     1101        void previsit( ast::SingleInit * singleInit ) {
     1102                #warning unimplemented; Resolver port in progress
     1103                (void)singleInit;
     1104                assert(false);
     1105        }
     1106
     1107        void previsit( ast::ListInit * listInit ) {
     1108                #warning unimplemented; Resolver port in progress
     1109                (void)listInit;
     1110                assert(false);
     1111        }
     1112
     1113        void previsit( ast::ConstructorInit * ctorInit ) {
     1114                #warning unimplemented; Resolver port in progress
     1115                (void)ctorInit;
     1116                assert(false);
     1117        }
     1118
    9301119} // namespace ResolvExpr
    9311120
  • src/ResolvExpr/Resolver.h

    r7564e10 r67130fe  
    1616#pragma once
    1717
    18 #include <list>  // for list
     18#include <list>          // for list
     19#include <AST/Node.hpp>  // for ptr
    1920
    2021class ConstructorInit;
     
    2324class StmtExpr;
    2425namespace SymTab {
    25 class Indexer;
    26 }  // namespace SymTab
     26        class Indexer;
     27} // namespace SymTab
     28
     29namespace ast {
     30        class Decl;
     31} // namespace ast
    2732
    2833namespace ResolvExpr {
     
    4045        /// Resolves with-stmts and with-clauses on functions
    4146        void resolveWithExprs( std::list< Declaration * > & translationUnit );
     47
     48        /// Checks types and binds syntactic constructs to typed representations
     49        void resolve( std::list< ast::ptr<ast::Decl> >& translationUnit );
    4250} // namespace ResolvExpr
    4351
  • src/ResolvExpr/TypeEnvironment.cc

    r7564e10 r67130fe  
    205205                                // attempt to unify bound types
    206206                                std::unique_ptr<Type> toType{ to.type->clone() }, fromType{ from.type->clone() };
    207                                 WidenMode widenMode{ to.allowWidening, from.allowWidening };
     207                                WidenMode widen{ to.allowWidening, from.allowWidening };
    208208                                Type* common = nullptr;
    209209                                AssertionSet need, have;
    210                                 if ( unifyInexact( toType.get(), fromType.get(), *this, need, have, openVars, widenMode, indexer, common ) ) {
     210                                if ( unifyInexact( toType.get(), fromType.get(), *this, need, have, openVars, widen, indexer, common ) ) {
    211211                                        // unifies, set common type if necessary
    212212                                        if ( common ) {
     
    343343        }
    344344
    345         bool TypeEnvironment::bindVar( TypeInstType *typeInst, Type *bindTo, const TypeDecl::Data & data, AssertionSet &need, AssertionSet &have, const OpenVarSet &openVars, WidenMode widenMode, const SymTab::Indexer &indexer ) {
     345        bool TypeEnvironment::bindVar( TypeInstType *typeInst, Type *bindTo, const TypeDecl::Data & data, AssertionSet &need, AssertionSet &have, const OpenVarSet &openVars, WidenMode widen, const SymTab::Indexer &indexer ) {
    346346
    347347                // remove references from other, so that type variables can only bind to value types
     
    362362                                std::unique_ptr< Type > newType( curClass->type->clone() );
    363363                                newType->get_qualifiers() = typeInst->get_qualifiers();
    364                                 if ( unifyInexact( newType.get(), bindTo, *this, need, have, openVars, widenMode & WidenMode( curClass->allowWidening, true ), indexer, common ) ) {
     364                                if ( unifyInexact( newType.get(), bindTo, *this, need, have, openVars, widen & WidenMode( curClass->allowWidening, true ), indexer, common ) ) {
    365365                                        if ( common ) {
    366366                                                common->get_qualifiers() = Type::Qualifiers{};
     
    372372                                newType->get_qualifiers() = Type::Qualifiers{};
    373373                                curClass->set_type( newType );
    374                                 curClass->allowWidening = widenMode.widenFirst && widenMode.widenSecond;
     374                                curClass->allowWidening = widen.first && widen.second;
    375375                        } // if
    376376                } else {
     
    379379                        newClass.type = bindTo->clone();
    380380                        newClass.type->get_qualifiers() = Type::Qualifiers();
    381                         newClass.allowWidening = widenMode.widenFirst && widenMode.widenSecond;
     381                        newClass.allowWidening = widen.first && widen.second;
    382382                        newClass.data = data;
    383383                        env.push_back( std::move(newClass) );
     
    388388        bool TypeEnvironment::bindVarToVar( TypeInstType *var1, TypeInstType *var2,
    389389                        TypeDecl::Data && data, AssertionSet &need, AssertionSet &have,
    390                         const OpenVarSet &openVars, WidenMode widenMode, const SymTab::Indexer &indexer ) {
     390                        const OpenVarSet &openVars, WidenMode widen, const SymTab::Indexer &indexer ) {
    391391
    392392                auto class1 = internal_lookup( var1->get_name() );
     
    395395                // exit early if variables already bound together
    396396                if ( class1 != env.end() && class1 == class2 ) {
    397                         class1->allowWidening &= widenMode;
     397                        class1->allowWidening &= widen;
    398398                        return true;
    399399                }
     
    408408                                type1 = class1->type;
    409409                        } // if
    410                         widen1 = widenMode.widenFirst && class1->allowWidening;
     410                        widen1 = widen.first && class1->allowWidening;
    411411                } // if
    412412                if ( class2 != env.end() ) {
     
    415415                                type2 = class2->type;
    416416                        } // if
    417                         widen2 = widenMode.widenSecond && class2->allowWidening;
     417                        widen2 = widen.second && class2->allowWidening;
    418418                } // if
    419419
  • src/ResolvExpr/TypeEnvironment.h

    r7564e10 r67130fe  
    136136                /// Binds the type class represented by `typeInst` to the type `bindTo`; will add
    137137                /// the class if needed. Returns false on failure.
    138                 bool bindVar( TypeInstType *typeInst, Type *bindTo, const TypeDecl::Data & data, AssertionSet &need, AssertionSet &have, const OpenVarSet &openVars, WidenMode widenMode, const SymTab::Indexer &indexer );
     138                bool bindVar( TypeInstType *typeInst, Type *bindTo, const TypeDecl::Data & data, AssertionSet &need, AssertionSet &have, const OpenVarSet &openVars, WidenMode widen, const SymTab::Indexer &indexer );
    139139               
    140140                /// Binds the type classes represented by `var1` and `var2` together; will add
    141141                /// one or both classes if needed. Returns false on failure.
    142                 bool bindVarToVar( TypeInstType *var1, TypeInstType *var2, TypeDecl::Data && data, AssertionSet &need, AssertionSet &have, const OpenVarSet &openVars, WidenMode widenMode, const SymTab::Indexer &indexer );
     142                bool bindVarToVar( TypeInstType *var1, TypeInstType *var2, TypeDecl::Data && data, AssertionSet &need, AssertionSet &have, const OpenVarSet &openVars, WidenMode widen, const SymTab::Indexer &indexer );
    143143
    144144                /// Disallows widening for all bindings in the environment
  • src/ResolvExpr/Unify.cc

    r7564e10 r67130fe  
    1414//
    1515
    16 #include <cassert>                // for assertf, assert
    17 #include <iterator>               // for back_insert_iterator, back_inserter
    18 #include <map>                    // for _Rb_tree_const_iterator, _Rb_tree_i...
    19 #include <memory>                 // for unique_ptr
    20 #include <set>                    // for set
    21 #include <string>                 // for string, operator==, operator!=, bas...
    22 #include <utility>                // for pair, move
     16#include "Unify.h"
     17
     18#include <cassert>                  // for assertf, assert
     19#include <iterator>                 // for back_insert_iterator, back_inserter
     20#include <map>                      // for _Rb_tree_const_iterator, _Rb_tree_i...
     21#include <memory>                   // for unique_ptr
     22#include <set>                      // for set
     23#include <string>                   // for string, operator==, operator!=, bas...
     24#include <utility>                  // for pair, move
    2325#include <vector>
    2426
     27#include "AST/Decl.hpp"
    2528#include "AST/Node.hpp"
     29#include "AST/Pass.hpp"
    2630#include "AST/Type.hpp"
    27 #include "Common/PassVisitor.h"   // for PassVisitor
    28 #include "FindOpenVars.h"         // for findOpenVars
    29 #include "Parser/LinkageSpec.h"   // for C
    30 #include "SynTree/Constant.h"     // for Constant
    31 #include "SynTree/Declaration.h"  // for TypeDecl, TypeDecl::Data, Declarati...
    32 #include "SynTree/Expression.h"   // for TypeExpr, Expression, ConstantExpr
    33 #include "SynTree/Mutator.h"      // for Mutator
    34 #include "SynTree/Type.h"         // for Type, TypeInstType, FunctionType
    35 #include "SynTree/Visitor.h"      // for Visitor
    36 #include "Tuples/Tuples.h"        // for isTtype
    37 #include "TypeEnvironment.h"      // for EqvClass, AssertionSet, OpenVarSet
    38 #include "Unify.h"
    39 #include "typeops.h"              // for flatten, occurs, commonType
     31#include "AST/TypeEnvironment.hpp"
     32#include "Common/PassVisitor.h"     // for PassVisitor
     33#include "FindOpenVars.h"           // for findOpenVars
     34#include "Parser/LinkageSpec.h"     // for C
     35#include "SynTree/Constant.h"       // for Constant
     36#include "SynTree/Declaration.h"    // for TypeDecl, TypeDecl::Data, Declarati...
     37#include "SynTree/Expression.h"     // for TypeExpr, Expression, ConstantExpr
     38#include "SynTree/Mutator.h"        // for Mutator
     39#include "SynTree/Type.h"           // for Type, TypeInstType, FunctionType
     40#include "SynTree/Visitor.h"        // for Visitor
     41#include "Tuples/Tuples.h"          // for isTtype
     42#include "TypeEnvironment.h"        // for EqvClass, AssertionSet, OpenVarSet
     43#include "typeops.h"                // for flatten, occurs, commonType
     44
     45namespace ast {
     46        class SymbolTable;
     47}
    4048
    4149namespace SymTab {
     
    4755namespace ResolvExpr {
    4856
    49         struct Unify : public WithShortCircuiting {
    50                 Unify( Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, WidenMode widenMode, const SymTab::Indexer &indexer );
     57        struct Unify_old : public WithShortCircuiting {
     58                Unify_old( Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, WidenMode widen, const SymTab::Indexer &indexer );
    5159
    5260                bool get_result() const { return result; }
     
    8088                AssertionSet &haveAssertions;
    8189                const OpenVarSet &openVars;
    82                 WidenMode widenMode;
     90                WidenMode widen;
    8391                const SymTab::Indexer &indexer;
    8492        };
     
    8694        /// Attempts an inexact unification of type1 and type2.
    8795        /// Returns false if no such unification; if the types can be unified, sets common (unless they unify exactly and have identical type qualifiers)
    88         bool unifyInexact( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, WidenMode widenMode, const SymTab::Indexer &indexer, Type *&common );
    89         bool unifyExact( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, WidenMode widenMode, const SymTab::Indexer &indexer );
     96        bool unifyInexact( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, WidenMode widen, const SymTab::Indexer &indexer, Type *&common );
     97        bool unifyExact( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, WidenMode widen, const SymTab::Indexer &indexer );
     98
     99        bool unifyExact(
     100                const ast::Type * type1, const ast::Type * type2, ast::TypeEnvironment & env,
     101                ast::AssertionSet & need, ast::AssertionSet & have, const ast::OpenVarSet & open,
     102                WidenMode widen, const ast::SymbolTable & symtab );
    90103
    91104        bool typesCompatible( Type *first, Type *second, const SymTab::Indexer &indexer, const TypeEnvironment &env ) {
     
    106119                delete newSecond;
    107120                return result;
     121        }
     122
     123        bool typesCompatible(
     124                        const ast::Type * first, const ast::Type * second, const ast::SymbolTable & symtab,
     125                        const ast::TypeEnvironment & env ) {
     126                ast::TypeEnvironment newEnv;
     127                ast::OpenVarSet open, closed;
     128                ast::AssertionSet need, have;
     129
     130                ast::ptr<ast::Type> newFirst{ first }, newSecond{ second };
     131                env.apply( newFirst );
     132                env.apply( newSecond );
     133
     134                findOpenVars( newFirst, open, closed, need, have, FirstClosed );
     135                findOpenVars( newSecond, open, closed, need, have, FirstOpen );
     136
     137                return unifyExact(
     138                        newFirst, newSecond, newEnv, need, have, open, noWiden(), symtab );
    108139        }
    109140
     
    132163        }
    133164
     165        bool typesCompatibleIgnoreQualifiers(
     166                        const ast::Type * first, const ast::Type * second, const ast::SymbolTable & symtab,
     167                        const ast::TypeEnvironment & env ) {
     168                ast::TypeEnvironment newEnv;
     169                ast::OpenVarSet open;
     170                ast::AssertionSet need, have;
     171               
     172                ast::ptr<ast::Type> newFirst{ first }, newSecond{ second };
     173                env.apply( newFirst );
     174                env.apply( newSecond );
     175                reset_qualifiers( newFirst );
     176                reset_qualifiers( newSecond );
     177
     178                return unifyExact(
     179                        newFirst, newSecond, newEnv, need, have, open, noWiden(), symtab );
     180        }
     181
    134182        bool unify( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, OpenVarSet &openVars, const SymTab::Indexer &indexer ) {
    135183                OpenVarSet closedVars;
     
    154202        }
    155203
    156         bool unifyExact( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, WidenMode widenMode, const SymTab::Indexer &indexer ) {
     204        bool unifyExact( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, WidenMode widen, const SymTab::Indexer &indexer ) {
    157205#ifdef DEBUG
    158206                TypeEnvironment debugEnv( env );
     
    181229                                result = env.bindVarToVar(
    182230                                        var1, var2, TypeDecl::Data{ entry1->second, entry2->second }, needAssertions,
    183                                         haveAssertions, openVars, widenMode, indexer );
     231                                        haveAssertions, openVars, widen, indexer );
    184232                        }
    185233                } else if ( isopen1 ) {
    186                         result = env.bindVar( var1, type2, entry1->second, needAssertions, haveAssertions, openVars, widenMode, indexer );
    187                 } else if ( isopen2 ) { // TODO: swap widenMode values in call, since type positions are flipped?
    188                         result = env.bindVar( var2, type1, entry2->second, needAssertions, haveAssertions, openVars, widenMode, indexer );
     234                        result = env.bindVar( var1, type2, entry1->second, needAssertions, haveAssertions, openVars, widen, indexer );
     235                } else if ( isopen2 ) { // TODO: swap widen values in call, since type positions are flipped?
     236                        result = env.bindVar( var2, type1, entry2->second, needAssertions, haveAssertions, openVars, widen, indexer );
    189237                } else {
    190                         PassVisitor<Unify> comparator( type2, env, needAssertions, haveAssertions, openVars, widenMode, indexer );
     238                        PassVisitor<Unify_old> comparator( type2, env, needAssertions, haveAssertions, openVars, widen, indexer );
    191239                        type1->accept( comparator );
    192240                        result = comparator.pass.get_result();
     
    213261        }
    214262
    215         bool unifyInexact( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, WidenMode widenMode, const SymTab::Indexer &indexer, Type *&common ) {
     263        bool unifyInexact( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, WidenMode widen, const SymTab::Indexer &indexer, Type *&common ) {
    216264                Type::Qualifiers tq1 = type1->get_qualifiers(), tq2 = type2->get_qualifiers();
    217265                type1->get_qualifiers() = Type::Qualifiers();
     
    225273                std::cerr << std::endl;
    226274#endif
    227                 if ( ! unifyExact( type1, type2, env, needAssertions, haveAssertions, openVars, widenMode, indexer ) ) {
     275                if ( ! unifyExact( type1, type2, env, needAssertions, haveAssertions, openVars, widen, indexer ) ) {
    228276#ifdef DEBUG
    229277                        std::cerr << "unifyInexact: no exact unification found" << std::endl;
    230278#endif
    231                         if ( ( common = commonType( type1, type2, widenMode.widenFirst, widenMode.widenSecond, indexer, env, openVars ) ) ) {
     279                        if ( ( common = commonType( type1, type2, widen.first, widen.second, indexer, env, openVars ) ) ) {
    232280                                common->get_qualifiers() = tq1 | tq2;
    233281#ifdef DEBUG
     
    245293                } else {
    246294                        if ( tq1 != tq2 ) {
    247                                 if ( ( tq1 > tq2 || widenMode.widenFirst ) && ( tq2 > tq1 || widenMode.widenSecond ) ) {
     295                                if ( ( tq1 > tq2 || widen.first ) && ( tq2 > tq1 || widen.second ) ) {
    248296                                        common = type1->clone();
    249297                                        common->get_qualifiers() = tq1 | tq2;
     
    263311        }
    264312
    265         Unify::Unify( Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, WidenMode widenMode, const SymTab::Indexer &indexer )
    266                 : result( false ), type2( type2 ), env( env ), needAssertions( needAssertions ), haveAssertions( haveAssertions ), openVars( openVars ), widenMode( widenMode ), indexer( indexer ) {
    267         }
    268 
    269         void Unify::postvisit( __attribute__((unused)) VoidType *voidType) {
     313        Unify_old::Unify_old( Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, WidenMode widen, const SymTab::Indexer &indexer )
     314                : result( false ), type2( type2 ), env( env ), needAssertions( needAssertions ), haveAssertions( haveAssertions ), openVars( openVars ), widen( widen ), indexer( indexer ) {
     315        }
     316
     317        void Unify_old::postvisit( __attribute__((unused)) VoidType *voidType) {
    270318                result = dynamic_cast< VoidType* >( type2 );
    271319        }
    272320
    273         void Unify::postvisit(BasicType *basicType) {
     321        void Unify_old::postvisit(BasicType *basicType) {
    274322                if ( BasicType *otherBasic = dynamic_cast< BasicType* >( type2 ) ) {
    275323                        result = basicType->get_kind() == otherBasic->get_kind();
     
    299347        }
    300348
    301         void Unify::postvisit(PointerType *pointerType) {
     349        void Unify_old::postvisit(PointerType *pointerType) {
    302350                if ( PointerType *otherPointer = dynamic_cast< PointerType* >( type2 ) ) {
    303351                        result = unifyExact( pointerType->get_base(), otherPointer->get_base(), env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer );
     
    307355        }
    308356
    309         void Unify::postvisit(ReferenceType *refType) {
     357        void Unify_old::postvisit(ReferenceType *refType) {
    310358                if ( ReferenceType *otherRef = dynamic_cast< ReferenceType* >( type2 ) ) {
    311359                        result = unifyExact( refType->get_base(), otherRef->get_base(), env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer );
     
    315363        }
    316364
    317         void Unify::postvisit(ArrayType *arrayType) {
     365        void Unify_old::postvisit(ArrayType *arrayType) {
    318366                ArrayType *otherArray = dynamic_cast< ArrayType* >( type2 );
    319367                // to unify, array types must both be VLA or both not VLA
     
    395443        /// If this isn't done then argument lists can have wildly different
    396444        /// size and structure, when they should be compatible.
    397         struct TtypeExpander : public WithShortCircuiting {
     445        struct TtypeExpander_old : public WithShortCircuiting {
    398446                TypeEnvironment & tenv;
    399                 TtypeExpander( TypeEnvironment & tenv ) : tenv( tenv ) {}
     447                TtypeExpander_old( TypeEnvironment & tenv ) : tenv( tenv ) {}
    400448                void premutate( TypeInstType * ) { visit_children = false; }
    401449                Type * postmutate( TypeInstType * typeInst ) {
     
    416464                dst.clear();
    417465                for ( DeclarationWithType * dcl : src ) {
    418                         PassVisitor<TtypeExpander> expander( env );
     466                        PassVisitor<TtypeExpander_old> expander( env );
    419467                        dcl->acceptMutator( expander );
    420468                        std::list< Type * > types;
     
    431479        }
    432480
    433         void Unify::postvisit(FunctionType *functionType) {
     481        void Unify_old::postvisit(FunctionType *functionType) {
    434482                FunctionType *otherFunction = dynamic_cast< FunctionType* >( type2 );
    435483                if ( otherFunction && functionType->get_isVarArgs() == otherFunction->get_isVarArgs() ) {
     
    442490
    443491                        // sizes don't have to match if ttypes are involved; need to be more precise wrt where the ttype is to prevent errors
    444                         if ( (flatFunc->parameters.size() == flatOther->parameters.size() && flatFunc->returnVals.size() == flatOther->returnVals.size()) || flatFunc->isTtype() || flatOther->isTtype() ) {
     492                        if (
     493                                        (flatFunc->parameters.size() == flatOther->parameters.size() &&
     494                                                flatFunc->returnVals.size() == flatOther->returnVals.size())
     495                                        || flatFunc->isTtype()
     496                                        || flatOther->isTtype()
     497                        ) {
    445498                                if ( unifyDeclList( flatFunc->parameters.begin(), flatFunc->parameters.end(), flatOther->parameters.begin(), flatOther->parameters.end(), env, needAssertions, haveAssertions, openVars, indexer ) ) {
    446499                                        if ( unifyDeclList( flatFunc->returnVals.begin(), flatFunc->returnVals.end(), flatOther->returnVals.begin(), flatOther->returnVals.end(), env, needAssertions, haveAssertions, openVars, indexer ) ) {
     
    458511
    459512        template< typename RefType >
    460         void Unify::handleRefType( RefType *inst, Type *other ) {
     513        void Unify_old::handleRefType( RefType *inst, Type *other ) {
    461514                // check that other type is compatible and named the same
    462515                RefType *otherStruct = dynamic_cast< RefType* >( other );
     
    465518
    466519        template< typename RefType >
    467         void Unify::handleGenericRefType( RefType *inst, Type *other ) {
     520        void Unify_old::handleGenericRefType( RefType *inst, Type *other ) {
    468521                // Check that other type is compatible and named the same
    469522                handleRefType( inst, other );
     
    533586        }
    534587
    535         void Unify::postvisit(StructInstType *structInst) {
     588        void Unify_old::postvisit(StructInstType *structInst) {
    536589                handleGenericRefType( structInst, type2 );
    537590        }
    538591
    539         void Unify::postvisit(UnionInstType *unionInst) {
     592        void Unify_old::postvisit(UnionInstType *unionInst) {
    540593                handleGenericRefType( unionInst, type2 );
    541594        }
    542595
    543         void Unify::postvisit(EnumInstType *enumInst) {
     596        void Unify_old::postvisit(EnumInstType *enumInst) {
    544597                handleRefType( enumInst, type2 );
    545598        }
    546599
    547         void Unify::postvisit(TraitInstType *contextInst) {
     600        void Unify_old::postvisit(TraitInstType *contextInst) {
    548601                handleRefType( contextInst, type2 );
    549602        }
    550603
    551         void Unify::postvisit(TypeInstType *typeInst) {
     604        void Unify_old::postvisit(TypeInstType *typeInst) {
    552605                assert( openVars.find( typeInst->get_name() ) == openVars.end() );
    553606                TypeInstType *otherInst = dynamic_cast< TypeInstType* >( type2 );
     
    604657        }
    605658
    606         void Unify::postvisit(TupleType *tupleType) {
     659        void Unify_old::postvisit(TupleType *tupleType) {
    607660                if ( TupleType *otherTuple = dynamic_cast< TupleType* >( type2 ) ) {
    608661                        std::unique_ptr<TupleType> flat1( tupleType->clone() );
     
    610663                        std::list<Type *> types1, types2;
    611664
    612                         PassVisitor<TtypeExpander> expander( env );
     665                        PassVisitor<TtypeExpander_old> expander( env );
    613666                        flat1->acceptMutator( expander );
    614667                        flat2->acceptMutator( expander );
     
    621674        }
    622675
    623         void Unify::postvisit( __attribute__((unused)) VarArgsType *varArgsType ) {
     676        void Unify_old::postvisit( __attribute__((unused)) VarArgsType *varArgsType ) {
    624677                result = dynamic_cast< VarArgsType* >( type2 );
    625678        }
    626679
    627         void Unify::postvisit( __attribute__((unused)) ZeroType *zeroType ) {
     680        void Unify_old::postvisit( __attribute__((unused)) ZeroType *zeroType ) {
    628681                result = dynamic_cast< ZeroType* >( type2 );
    629682        }
    630683
    631         void Unify::postvisit( __attribute__((unused)) OneType *oneType ) {
     684        void Unify_old::postvisit( __attribute__((unused)) OneType *oneType ) {
    632685                result = dynamic_cast< OneType* >( type2 );
    633686        }
     
    647700        }
    648701
     702        class Unify_new final : public ast::WithShortCircuiting {
     703                const ast::Type * type2;
     704                ast::TypeEnvironment & tenv;
     705                ast::AssertionSet & need;
     706                ast::AssertionSet & have;
     707                const ast::OpenVarSet & open;
     708                WidenMode widen;
     709                const ast::SymbolTable & symtab;
     710        public:
     711                bool result;
     712
     713                Unify_new(
     714                        const ast::Type * type2, ast::TypeEnvironment & env, ast::AssertionSet & need,
     715                        ast::AssertionSet & have, const ast::OpenVarSet & open, WidenMode widen,
     716                        const ast::SymbolTable & symtab )
     717                : type2(type2), tenv(env), need(need), have(have), open(open), widen(widen),
     718                  symtab(symtab), result(false) {}
     719
     720                void previsit( const ast::Node * ) { visit_children = false; }
     721               
     722                void postvisit( const ast::VoidType * ) {
     723                        result = dynamic_cast< const ast::VoidType * >( type2 );
     724                }
     725
     726                void postvisit( const ast::BasicType * basic ) {
     727                        if ( auto basic2 = dynamic_cast< const ast::BasicType * >( type2 ) ) {
     728                                result = basic->kind == basic2->kind;
     729                        }
     730                }
     731
     732                void postvisit( const ast::PointerType * pointer ) {
     733                        if ( auto pointer2 = dynamic_cast< const ast::PointerType * >( type2 ) ) {
     734                                result = unifyExact(
     735                                        pointer->base, pointer2->base, tenv, need, have, open,
     736                                        noWiden(), symtab );
     737                        }
     738                }
     739
     740                void postvisit( const ast::ArrayType * array ) {
     741                        auto array2 = dynamic_cast< const ast::ArrayType * >( type2 );
     742                        if ( ! array2 ) return;
     743
     744                        // to unify, array types must both be VLA or both not VLA and both must have a
     745                        // dimension expression or not have a dimension
     746                        if ( array->isVarLen != array2->isVarLen ) return;
     747                        if ( ! array->isVarLen && ! array2->isVarLen
     748                                        && array->dimension && array2->dimension ) {
     749                                auto ce1 = array->dimension.as< ast::ConstantExpr >();
     750                                auto ce2 = array2->dimension.as< ast::ConstantExpr >();
     751
     752                                // see C11 Reference Manual 6.7.6.2.6
     753                                // two array types with size specifiers that are integer constant expressions are
     754                                // compatible if both size specifiers have the same constant value
     755                                if ( ce1 && ce2 && ce1->intValue() != ce2->intValue() ) return;
     756                        }
     757
     758                        result = unifyExact(
     759                                array->base, array2->base, tenv, need, have, open, noWiden(),
     760                                symtab );
     761                }
     762
     763                void postvisit( const ast::ReferenceType * ref ) {
     764                        if ( auto ref2 = dynamic_cast< const ast::ReferenceType * >( type2 ) ) {
     765                                result = unifyExact(
     766                                        ref->base, ref2->base, tenv, need, have, open, noWiden(),
     767                                        symtab );
     768                        }
     769                }
     770
     771        private:
     772                /// Replaces ttype variables with their bound types.
     773                /// If this isn't done when satifying ttype assertions, then argument lists can have
     774                /// different size and structure when they should be compatible.
     775                struct TtypeExpander_new : public ast::WithShortCircuiting {
     776                        ast::TypeEnvironment & tenv;
     777
     778                        TtypeExpander_new( ast::TypeEnvironment & env ) : tenv( env ) {}
     779
     780                        const ast::Type * postvisit( const ast::TypeInstType * typeInst ) {
     781                                if ( const ast::EqvClass * clz = tenv.lookup( typeInst->name ) ) {
     782                                        // expand ttype parameter into its actual type
     783                                        if ( clz->data.kind == ast::TypeVar::Ttype && clz->bound ) {
     784                                                return clz->bound;
     785                                        }
     786                                }
     787                                return typeInst;
     788                        }
     789                };
     790
     791                /// returns flattened version of `src`
     792                static std::vector< ast::ptr< ast::DeclWithType > > flattenList(
     793                        const std::vector< ast::ptr< ast::DeclWithType > > & src, ast::TypeEnvironment & env
     794                ) {
     795                        std::vector< ast::ptr< ast::DeclWithType > > dst;
     796                        dst.reserve( src.size() );
     797                        for ( const ast::DeclWithType * d : src ) {
     798                                ast::Pass<TtypeExpander_new> expander{ env };
     799                                d = d->accept( expander );
     800                                auto types = flatten( d->get_type() );
     801                                for ( ast::ptr< ast::Type > & t : types ) {
     802                                        // outermost const, volatile, _Atomic qualifiers in parameters should not play
     803                                        // a role in the unification of function types, since they do not determine
     804                                        // whether a function is callable.
     805                                        // NOTE: **must** consider at least mutex qualifier, since functions can be
     806                                        // overloaded on outermost mutex and a mutex function has different
     807                                        // requirements than a non-mutex function
     808                                        remove_qualifiers( t, ast::CV::Const | ast::CV::Volatile | ast::CV::Atomic );
     809                                        dst.emplace_back( new ast::ObjectDecl{ d->location, "", t } );
     810                                }
     811                        }
     812                        return dst;
     813                }
     814
     815                /// Creates a tuple type based on a list of DeclWithType
     816                template< typename Iter >
     817                static ast::ptr< ast::Type > tupleFromDecls( Iter crnt, Iter end ) {
     818                        std::vector< ast::ptr< ast::Type > > types;
     819                        while ( crnt != end ) {
     820                                // it is guaranteed that a ttype variable will be bound to a flat tuple, so ensure
     821                                // that this results in a flat tuple
     822                                flatten( (*crnt)->get_type(), types );
     823
     824                                ++crnt;
     825                        }
     826
     827                        return { new ast::TupleType{ std::move(types) } };
     828                }
     829
     830                template< typename Iter >
     831                static bool unifyDeclList(
     832                        Iter crnt1, Iter end1, Iter crnt2, Iter end2, ast::TypeEnvironment & env,
     833                        ast::AssertionSet & need, ast::AssertionSet & have, const ast::OpenVarSet & open,
     834                        const ast::SymbolTable & symtab
     835                ) {
     836                        while ( crnt1 != end1 && crnt2 != end2 ) {
     837                                const ast::Type * t1 = (*crnt1)->get_type();
     838                                const ast::Type * t2 = (*crnt2)->get_type();
     839                                bool isTuple1 = Tuples::isTtype( t1 );
     840                                bool isTuple2 = Tuples::isTtype( t2 );
     841
     842                                // assumes here that ttype *must* be last parameter
     843                                if ( isTuple1 && ! isTuple2 ) {
     844                                        // combine remainder of list2, then unify
     845                                        return unifyExact(
     846                                                t1, tupleFromDecls( crnt2, end2 ), env, need, have, open,
     847                                                noWiden(), symtab );
     848                                } else if ( ! isTuple1 && isTuple2 ) {
     849                                        // combine remainder of list1, then unify
     850                                        return unifyExact(
     851                                                tupleFromDecls( crnt1, end1 ), t2, env, need, have, open,
     852                                                noWiden(), symtab );
     853                                }
     854
     855                                if ( ! unifyExact(
     856                                        t1, t2, env, need, have, open, noWiden(), symtab )
     857                                ) return false;
     858
     859                                ++crnt1; ++crnt2;
     860                        }
     861
     862                        // May get to the end of one argument list before the other. This is only okay if the
     863                        // other is a ttype
     864                        if ( crnt1 != end1 ) {
     865                                // try unifying empty tuple with ttype
     866                                const ast::Type * t1 = (*crnt1)->get_type();
     867                                if ( ! Tuples::isTtype( t1 ) ) return false;
     868                                return unifyExact(
     869                                        t1, tupleFromDecls( crnt2, end2 ), env, need, have, open,
     870                                        noWiden(), symtab );
     871                        } else if ( crnt2 != end2 ) {
     872                                // try unifying empty tuple with ttype
     873                                const ast::Type * t2 = (*crnt2)->get_type();
     874                                if ( ! Tuples::isTtype( t2 ) ) return false;
     875                                return unifyExact(
     876                                        tupleFromDecls( crnt1, end1 ), t2, env, need, have, open,
     877                                        noWiden(), symtab );
     878                        }
     879
     880                        return true;
     881                }
     882
     883                static bool unifyDeclList(
     884                        const std::vector< ast::ptr< ast::DeclWithType > > & list1,
     885                        const std::vector< ast::ptr< ast::DeclWithType > > & list2,
     886                        ast::TypeEnvironment & env, ast::AssertionSet & need, ast::AssertionSet & have,
     887                        const ast::OpenVarSet & open, const ast::SymbolTable & symtab
     888                ) {
     889                        return unifyDeclList(
     890                                list1.begin(), list1.end(), list2.begin(), list2.end(), env, need, have, open,
     891                                symtab );
     892                }
     893
     894                static void markAssertionSet( ast::AssertionSet & assns, const ast::DeclWithType * assn ) {
     895                        auto i = assns.find( assn );
     896                        if ( i != assns.end() ) {
     897                                i->second.isUsed = true;
     898                        }
     899                }
     900
     901                /// mark all assertions in `type` used in both `assn1` and `assn2`
     902                static void markAssertions(
     903                        ast::AssertionSet & assn1, ast::AssertionSet & assn2,
     904                        const ast::ParameterizedType * type
     905                ) {
     906                        for ( const auto & tyvar : type->forall ) {
     907                                for ( const ast::DeclWithType * assert : tyvar->assertions ) {
     908                                        markAssertionSet( assn1, assert );
     909                                        markAssertionSet( assn2, assert );
     910                                }
     911                        }
     912                }
     913
     914        public:
     915                void postvisit( const ast::FunctionType * func ) {
     916                        auto func2 = dynamic_cast< const ast::FunctionType * >( type2 );
     917                        if ( ! func2 ) return;
     918
     919                        if ( func->isVarArgs != func2->isVarArgs ) return;
     920                       
     921                        // Flatten the parameter lists for both functions so that tuple structure does not
     922                        // affect unification. Does not actually mutate function parameters.
     923                        auto params = flattenList( func->params, tenv );
     924                        auto params2 = flattenList( func2->params, tenv );
     925
     926                        // sizes don't have to match if ttypes are involved; need to be more precise w.r.t.
     927                        // where the ttype is to prevent errors
     928                        if (
     929                                ( params.size() != params2.size() || func->returns.size() != func2->returns.size() )
     930                                && ! func->isTtype()
     931                                && ! func2->isTtype()
     932                        ) return;
     933
     934                        if ( ! unifyDeclList( params, params2, tenv, need, have, open, symtab ) ) return;
     935                        if ( ! unifyDeclList(
     936                                func->returns, func2->returns, tenv, need, have, open, symtab ) ) return;
     937                       
     938                        markAssertions( have, need, func );
     939                        markAssertions( have, need, func2 );
     940
     941                        result = true;
     942                }
     943       
     944        private:
     945                template< typename RefType >
     946                const RefType * handleRefType( const RefType * inst, const ast::Type * other ) {
     947                        // check that the other type is compatible and named the same
     948                        auto otherInst = dynamic_cast< const RefType * >( other );
     949                        result = otherInst && inst->name == otherInst->name;
     950                        return otherInst;
     951                }
     952
     953                /// Creates a tuple type based on a list of TypeExpr
     954                template< typename Iter >
     955                static const ast::Type * tupleFromExprs(
     956                        const ast::TypeExpr * param, Iter & crnt, Iter end, ast::CV::Qualifiers qs
     957                ) {
     958                        std::vector< ast::ptr< ast::Type > > types;
     959                        do {
     960                                types.emplace_back( param->type );
     961
     962                                ++crnt;
     963                                if ( crnt == end ) break;
     964                                param = strict_dynamic_cast< const ast::TypeExpr * >( crnt->get() );
     965                        } while(true);
     966
     967                        return new ast::TupleType{ std::move(types), qs };
     968                }
     969
     970                template< typename RefType >
     971                void handleGenericRefType( const RefType * inst, const ast::Type * other ) {
     972                        // check that other type is compatible and named the same
     973                        const RefType * inst2 = handleRefType( inst, other );
     974                        if ( ! inst2 ) return;
     975                       
     976                        // check that parameters of types unify, if any
     977                        const std::vector< ast::ptr< ast::Expr > > & params = inst->params;
     978                        const std::vector< ast::ptr< ast::Expr > > & params2 = inst2->params;
     979
     980                        auto it = params.begin();
     981                        auto jt = params2.begin();
     982                        for ( ; it != params.end() && jt != params2.end(); ++it, ++jt ) {
     983                                auto param = strict_dynamic_cast< const ast::TypeExpr * >( it->get() );
     984                                auto param2 = strict_dynamic_cast< const ast::TypeExpr * >( jt->get() );
     985
     986                                ast::ptr< ast::Type > pty = param->type;
     987                                ast::ptr< ast::Type > pty2 = param2->type;
     988
     989                                bool isTuple = Tuples::isTtype( pty );
     990                                bool isTuple2 = Tuples::isTtype( pty2 );
     991
     992                                if ( isTuple && isTuple2 ) {
     993                                        ++it; ++jt;  // skip ttype parameters before break
     994                                } else if ( isTuple ) {
     995                                        // bundle remaining params into tuple
     996                                        pty2 = tupleFromExprs( param2, jt, params2.end(), pty->qualifiers );
     997                                        ++it;  // skip ttype parameter for break
     998                                } else if ( isTuple2 ) {
     999                                        // bundle remaining params into tuple
     1000                                        pty = tupleFromExprs( param, it, params.end(), pty2->qualifiers );
     1001                                        ++jt;  // skip ttype parameter for break
     1002                                }
     1003
     1004                                if ( ! unifyExact(
     1005                                                pty, pty2, tenv, need, have, open, noWiden(), symtab ) ) {
     1006                                        result = false;
     1007                                        return;
     1008                                }
     1009
     1010                                // ttype parameter should be last
     1011                                if ( isTuple || isTuple2 ) break;
     1012                        }
     1013                        result = it == params.end() && jt == params2.end();
     1014                }
     1015
     1016        public:
     1017                void postvisit( const ast::StructInstType * aggrType ) {
     1018                        handleGenericRefType( aggrType, type2 );
     1019                }
     1020
     1021                void postvisit( const ast::UnionInstType * aggrType ) {
     1022                        handleGenericRefType( aggrType, type2 );
     1023                }
     1024
     1025                void postvisit( const ast::EnumInstType * aggrType ) {
     1026                        handleRefType( aggrType, type2 );
     1027                }
     1028
     1029                void postvisit( const ast::TraitInstType * aggrType ) {
     1030                        handleRefType( aggrType, type2 );
     1031                }
     1032
     1033                void postvisit( const ast::TypeInstType * typeInst ) {
     1034                        assert( open.find( typeInst->name ) == open.end() );
     1035                        handleRefType( typeInst, type2 );
     1036                }
     1037
     1038        private:
     1039                /// Creates a tuple type based on a list of Type
     1040                static ast::ptr< ast::Type > tupleFromTypes(
     1041                        const std::vector< ast::ptr< ast::Type > > & tys
     1042                ) {
     1043                        std::vector< ast::ptr< ast::Type > > out;
     1044                        for ( const ast::Type * ty : tys ) {
     1045                                // it is guaranteed that a ttype variable will be bound to a flat tuple, so ensure
     1046                                // that this results in a flat tuple
     1047                                flatten( ty, out );
     1048                        }
     1049
     1050                        return { new ast::TupleType{ std::move(out) } };
     1051                }
     1052
     1053                static bool unifyList(
     1054                        const std::vector< ast::ptr< ast::Type > > & list1,
     1055                        const std::vector< ast::ptr< ast::Type > > & list2, ast::TypeEnvironment & env,
     1056                        ast::AssertionSet & need, ast::AssertionSet & have, const ast::OpenVarSet & open,
     1057                        const ast::SymbolTable & symtab
     1058                ) {
     1059                        auto crnt1 = list1.begin();
     1060                        auto crnt2 = list2.begin();
     1061                        while ( crnt1 != list1.end() && crnt2 != list2.end() ) {
     1062                                const ast::Type * t1 = *crnt1;
     1063                                const ast::Type * t2 = *crnt2;
     1064                                bool isTuple1 = Tuples::isTtype( t1 );
     1065                                bool isTuple2 = Tuples::isTtype( t2 );
     1066
     1067                                // assumes ttype must be last parameter
     1068                                if ( isTuple1 && ! isTuple2 ) {
     1069                                        // combine entirety of list2, then unify
     1070                                        return unifyExact(
     1071                                                t1, tupleFromTypes( list2 ), env, need, have, open,
     1072                                                noWiden(), symtab );
     1073                                } else if ( ! isTuple1 && isTuple2 ) {
     1074                                        // combine entirety of list1, then unify
     1075                                        return unifyExact(
     1076                                                tupleFromTypes( list1 ), t2, env, need, have, open,
     1077                                                noWiden(), symtab );
     1078                                }
     1079
     1080                                if ( ! unifyExact(
     1081                                        t1, t2, env, need, have, open, noWiden(), symtab )
     1082                                ) return false;
     1083
     1084                                ++crnt1; ++crnt2;
     1085                        }
     1086
     1087                        if ( crnt1 != list1.end() ) {
     1088                                // try unifying empty tuple type with ttype
     1089                                const ast::Type * t1 = *crnt1;
     1090                                if ( ! Tuples::isTtype( t1 ) ) return false;
     1091                                // xxx - this doesn't generate an empty tuple, contrary to comment; both ported
     1092                                // from Rob's code
     1093                                return unifyExact(
     1094                                                t1, tupleFromTypes( list2 ), env, need, have, open,
     1095                                                noWiden(), symtab );
     1096                        } else if ( crnt2 != list2.end() ) {
     1097                                // try unifying empty tuple with ttype
     1098                                const ast::Type * t2 = *crnt2;
     1099                                if ( ! Tuples::isTtype( t2 ) ) return false;
     1100                                // xxx - this doesn't generate an empty tuple, contrary to comment; both ported
     1101                                // from Rob's code
     1102                                return unifyExact(
     1103                                                tupleFromTypes( list1 ), t2, env, need, have, open,
     1104                                                noWiden(), symtab );
     1105                        }
     1106
     1107                        return true;
     1108                }
     1109
     1110        public:
     1111                void postvisit( const ast::TupleType * tuple ) {
     1112                        auto tuple2 = dynamic_cast< const ast::TupleType * >( type2 );
     1113                        if ( ! tuple2 ) return;
     1114
     1115                        ast::Pass<TtypeExpander_new> expander{ tenv };
     1116                        const ast::Type * flat = tuple->accept( expander );
     1117                        const ast::Type * flat2 = tuple2->accept( expander );
     1118
     1119                        auto types = flatten( flat );
     1120                        auto types2 = flatten( flat2 );
     1121
     1122                        result = unifyList( types, types2, tenv, need, have, open, symtab );
     1123                }
     1124
     1125                void postvisit( const ast::VarArgsType * ) {
     1126                        result = dynamic_cast< const ast::VarArgsType * >( type2 );
     1127                }
     1128
     1129                void postvisit( const ast::ZeroType * ) {
     1130                        result = dynamic_cast< const ast::ZeroType * >( type2 );
     1131                }
     1132
     1133                void postvisit( const ast::OneType * ) {
     1134                        result = dynamic_cast< const ast::OneType * >( type2 );
     1135                }       
     1136
     1137          private:
     1138                template< typename RefType > void handleRefType( RefType *inst, Type *other );
     1139                template< typename RefType > void handleGenericRefType( RefType *inst, Type *other );
     1140        };
     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        }
     1153
     1154        bool unifyExact(
     1155                        const ast::Type * type1, const ast::Type * type2, ast::TypeEnvironment & env,
     1156                        ast::AssertionSet & need, ast::AssertionSet & have, const ast::OpenVarSet & open,
     1157                        WidenMode widen, const ast::SymbolTable & symtab
     1158        ) {
     1159                if ( type1->qualifiers != type2->qualifiers ) return false;
     1160
     1161                auto var1 = dynamic_cast< const ast::TypeInstType * >( type1 );
     1162                auto var2 = dynamic_cast< const ast::TypeInstType * >( type2 );
     1163                ast::OpenVarSet::const_iterator
     1164                        entry1 = var1 ? open.find( var1->name ) : open.end(),
     1165                        entry2 = var2 ? open.find( var2->name ) : open.end();
     1166                bool isopen1 = entry1 != open.end();
     1167                bool isopen2 = entry2 != open.end();
     1168
     1169                if ( isopen1 && isopen2 ) {
     1170                        if ( entry1->second.kind != entry2->second.kind ) return false;
     1171                        return env.bindVarToVar(
     1172                                var1, var2, ast::TypeDecl::Data{ entry1->second, entry2->second }, need, have,
     1173                                open, widen, symtab );
     1174                } else if ( isopen1 ) {
     1175                        return env.bindVar( var1, type2, entry1->second, need, have, open, widen, symtab );
     1176                } else if ( isopen2 ) {
     1177                        return env.bindVar( var2, type1, entry2->second, need, have, open, widen, symtab );
     1178                } else {
     1179                        ast::Pass<Unify_new> comparator{ type2, env, need, have, open, widen, symtab };
     1180                        type1->accept( comparator );
     1181                        return comparator.pass.result;
     1182                }
     1183        }
     1184
     1185        bool unifyInexact(
     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
     1190        ) {
     1191                ast::CV::Qualifiers q1 = type1->qualifiers, q2 = type2->qualifiers;
     1192               
     1193                // force t1 and t2 to be cloned if their qualifiers must be stripped, so that type1 and
     1194                // type2 are left unchanged; calling convention forces type{1,2}->strong_ref >= 1
     1195                ast::ptr<ast::Type> t1{ type1 }, t2{ type2 };
     1196                reset_qualifiers( t1 );
     1197                reset_qualifiers( t2 );
     1198               
     1199                if ( unifyExact( t1, t2, env, need, have, open, widen, symtab ) ) {
     1200                        t1 = nullptr; t2 = nullptr; // release t1, t2 to avoid spurious clones
     1201
     1202                        // if exact unification on unqualified types, try to merge qualifiers
     1203                        if ( q1 == q2 || ( ( q1 > q2 || widen.first ) && ( q2 > q1 || widen.second ) ) ) {
     1204                                common = type1;
     1205                                reset_qualifiers( common, q1 | q2 );
     1206                                return true;
     1207                        } else {
     1208                                return false;
     1209                        }
     1210
     1211                } else if (( common = commonType( t1, t2, widen, symtab, env, open ) )) {
     1212                        t1 = nullptr; t2 = nullptr; // release t1, t2 to avoid spurious clones
     1213
     1214                        // no exact unification, but common type
     1215                        reset_qualifiers( common, q1 | q2 );
     1216                        return true;
     1217                } else {
     1218                        return false;
     1219                }
     1220        }
     1221
    6491222        ast::ptr<ast::Type> extractResultType( const ast::FunctionType * func ) {
    6501223                if ( func->returns.empty() ) return new ast::VoidType{};
  • src/ResolvExpr/Unify.h

    r7564e10 r67130fe  
    1818#include <list>                   // for list
    1919
     20#include "AST/Node.hpp"             // for ptr
     21#include "AST/TypeEnvironment.hpp"  // for TypeEnvironment, AssertionSet, OpenVarSet
    2022#include "Common/utility.h"       // for deleteAll
    2123#include "SynTree/Declaration.h"  // for TypeDecl, TypeDecl::Data
    2224#include "TypeEnvironment.h"      // for AssertionSet, OpenVarSet
    23 #include "WidenMode.h"            // for WidenMode
     25#include "WidenMode.h"              // for WidenMode
    2426
    2527class Type;
    2628class TypeInstType;
    2729namespace SymTab {
    28 class Indexer;
    29 }  // namespace SymTab
     30        class Indexer;
     31}
     32
     33namespace ast {
     34        class SymbolTable;
     35        class Type;
     36}
    3037
    3138namespace ResolvExpr {
     
    3340        bool unify( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, OpenVarSet &openVars, const SymTab::Indexer &indexer, Type *&commonType );
    3441        bool unifyExact( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, OpenVarSet &openVars, const SymTab::Indexer &indexer );
    35         bool unifyInexact( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, WidenMode widenMode, const SymTab::Indexer &indexer, Type *&common );
     42        bool unifyInexact( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, WidenMode widen, const SymTab::Indexer &indexer, Type *&common );
    3643
    3744        template< typename Iterator1, typename Iterator2 >
     
    6269        }
    6370
     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
     76        bool unifyExact(
     77                const ast::Type * type1, const ast::Type * type2, ast::TypeEnvironment & env,
     78                ast::AssertionSet & need, ast::AssertionSet & have, const ast::OpenVarSet & open,
     79                WidenMode widen, const ast::SymbolTable & symtab );
     80
     81        bool unifyInexact(
     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 );
     86
    6487} // namespace ResolvExpr
    6588
  • src/ResolvExpr/WidenMode.h

    r7564e10 r67130fe  
    1818namespace ResolvExpr {
    1919        struct WidenMode {
    20                 WidenMode( bool widenFirst, bool widenSecond ): widenFirst( widenFirst ), widenSecond( widenSecond ) {}
    21                 WidenMode &operator|=( const WidenMode &other ) { widenFirst |= other.widenFirst; widenSecond |= other.widenSecond; return *this; }
    22                 WidenMode &operator&=( const WidenMode &other ) { widenFirst &= other.widenFirst; widenSecond &= other.widenSecond; return *this; }
    23                 WidenMode operator|( const WidenMode &other ) { WidenMode newWM( *this ); newWM |= other; return newWM; }
    24                 WidenMode operator&( const WidenMode &other ) { WidenMode newWM( *this ); newWM &= other; return newWM; }
    25                 operator bool() { return widenFirst && widenSecond; }
     20                WidenMode( bool first, bool second ): first( first ), second( second ) {}
     21               
     22                WidenMode &operator|=( const WidenMode &other ) {
     23                        first |= other.first; second |= other.second; return *this;
     24                }
    2625
    27                 bool widenFirst : 1, widenSecond : 1;
     26                WidenMode &operator&=( const WidenMode &other ) {
     27                        first &= other.first; second &= other.second; return *this;
     28                }
     29
     30                WidenMode operator|( const WidenMode &other ) {
     31                        WidenMode newWM( *this ); newWM |= other; return newWM;
     32                }
     33
     34                WidenMode operator&( const WidenMode &other ) {
     35                        WidenMode newWM( *this ); newWM &= other; return newWM;
     36                }
     37               
     38                operator bool() { return first && second; }
     39
     40                bool first : 1, second : 1;
    2841        };
     42
     43        static inline WidenMode noWiden() { return { false, false }; }
    2944} // namespace ResolvExpr
    3045
  • src/ResolvExpr/typeops.h

    r7564e10 r67130fe  
    1818#include <vector>
    1919
     20#include "Cost.h"
     21#include "TypeEnvironment.h"
     22#include "WidenMode.h"
     23#include "AST/Fwd.hpp"
    2024#include "AST/Node.hpp"
     25#include "AST/SymbolTable.hpp"
    2126#include "AST/Type.hpp"
     27#include "AST/TypeEnvironment.hpp"
    2228#include "SynTree/SynTree.h"
    2329#include "SynTree/Type.h"
    2430#include "SymTab/Indexer.h"
    25 #include "Cost.h"
    26 #include "TypeEnvironment.h"
    2731
    2832namespace ResolvExpr {
     
    8589
    8690        // in Unify.cc
    87         bool isFtype( Type *type );
    8891        bool typesCompatible( Type *, Type *, const SymTab::Indexer &indexer, const TypeEnvironment &env );
    8992        bool typesCompatibleIgnoreQualifiers( Type *, Type *, const SymTab::Indexer &indexer, const TypeEnvironment &env );
     
    99102        }
    100103
     104        bool typesCompatible(
     105                const ast::Type *, const ast::Type *, const ast::SymbolTable &,
     106                const ast::TypeEnvironment & env = {} );
     107       
     108        bool typesCompatibleIgnoreQualifiers(
     109                const ast::Type *, const ast::Type *, const ast::SymbolTable &,
     110                const ast::TypeEnvironment & env = {} );
     111
    101112        /// creates the type represented by the list of returnVals in a FunctionType. The caller owns the return value.
    102113        Type * extractResultType( FunctionType * functionType );
     
    106117        // in CommonType.cc
    107118        Type * commonType( Type *type1, Type *type2, bool widenFirst, bool widenSecond, const SymTab::Indexer &indexer, TypeEnvironment &env, const OpenVarSet &openVars );
     119        ast::ptr< ast::Type > commonType(
     120                const ast::ptr< ast::Type > & type1, const ast::ptr< ast::Type > & type2, WidenMode widen,
     121                const ast::SymbolTable & symtab, ast::TypeEnvironment & env, const ast::OpenVarSet & open );
    108122
    109123        // in PolyCost.cc
     
    115129        // in Occurs.cc
    116130        bool occurs( Type *type, std::string varName, const TypeEnvironment &env );
     131        // new AST version in TypeEnvironment.cpp (only place it was used in old AST)
    117132
    118133        template<typename Iter>
     
    127142        // in AlternativeFinder.cc
    128143        void referenceToRvalueConversion( Expression *& expr, Cost & cost );
     144        const ast::Expr * referenceToRvalueConversion( const ast::Expr * expr, Cost & cost );
    129145
    130         // flatten tuple type into list of types
     146        /// flatten tuple type into list of types
    131147        template< typename OutputIterator >
    132148        void flatten( Type * type, OutputIterator out ) {
     
    139155                }
    140156        }
     157
     158        /// flatten tuple type into existing list of types
     159        static inline void flatten(
     160                const ast::Type * type, std::vector< ast::ptr< ast::Type > > & out
     161        ) {
     162                if ( auto tupleType = dynamic_cast< const ast::TupleType * >( type ) ) {       
     163                        for ( const ast::Type * t : tupleType->types ) {
     164                                flatten( t, out );
     165                        }
     166                } else {
     167                        out.emplace_back( type );
     168                }
     169        }
     170
     171        /// flatten tuple type into list of types
     172        static inline std::vector< ast::ptr< ast::Type > > flatten( const ast::Type * type ) {
     173                std::vector< ast::ptr< ast::Type > > out;
     174                out.reserve( type->size() );
     175                flatten( type, out );
     176                return out;
     177        }
     178
     179        // in TypeEnvironment.cc
     180        bool isFtype( Type *type );
    141181} // namespace ResolvExpr
     182
     183namespace ast {
     184        // in TypeEnvironment.cpp
     185        bool isFtype( const ast::Type * type );
     186} // namespace ast
    142187
    143188// Local Variables: //
  • src/SymTab/Mangler.cc

    r7564e10 r67130fe  
    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 );
     
    390392} // namespace SymTab
    391393
     394namespace 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
     451        std::string mangle( const ast::Node * decl, Mangle::Mode mode ) {
     452                ast::Pass<Mangler_new> mangler( mode );
     453                maybeAccept( decl, mangler );
     454                return mangler.pass.get_mangleName();
     455        }
     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
     738} // namespace Mangle
     739
    392740// Local Variables: //
    393741// tab-width: 4 //
  • src/SymTab/Mangler.h

    r7564e10 r67130fe  
    2121#include <utility>            // for pair
    2222
     23#include "AST/Bitfield.hpp"
     24#include "AST/Fwd.hpp"
    2325#include "SynTree/SynTree.h"  // for Types
    2426#include "SynTree/Visitor.h"  // for Visitor, maybeAccept
     
    7577} // SymTab
    7678
     79namespace Mangle {
     80        /// Bitflags for mangle modes
     81        enum {
     82                NoOverrideable  = 1 << 0,
     83                Type            = 1 << 1,
     84                NoGenericParams = 1 << 2
     85        };
     86
     87        /// Bitflag type for mangler modes
     88        struct mangle_flags {
     89                union {
     90                        unsigned int val;
     91                        struct {
     92                                bool no_overrideable   : 1;
     93                                bool type              : 1;
     94                                bool no_generic_params : 1;
     95                        };
     96                };
     97
     98                constexpr mangle_flags( unsigned int val ) : val(val) {}
     99        };
     100
     101        using Mode = bitfield<mangle_flags>;
     102
     103        /// Mangle declaration name
     104        std::string mangle( const ast::Node * decl, Mode mode = {} );
     105
     106        namespace Encoding {
     107                using namespace SymTab::Mangler::Encoding;
     108        };
     109}
     110
    77111extern "C" {
    78112        char * cforall_demangle(const char *, int);
  • src/SynTree/Expression.cc

    r7564e10 r67130fe  
    610610        computeResult();
    611611}
    612 StmtExpr::StmtExpr( const StmtExpr & other ) : Expression( other ), statements( other.statements->clone() ) {
     612StmtExpr::StmtExpr( const StmtExpr & other ) : Expression( other ), statements( other.statements->clone() ), resultExpr( other.resultExpr ) {
    613613        cloneAll( other.returnDecls, returnDecls );
    614614        cloneAll( other.dtors, dtors );
  • src/SynTree/Expression.h

    r7564e10 r67130fe  
    6262        InferredParams inferParams;       ///< Post-resolution inferred parameter slots
    6363        std::vector<UniqueId> resnSlots;  ///< Pre-resolution inferred parameter slots
    64        
     64
    6565        // xxx - should turn inferParams+resnSlots into a union to save some memory
    6666
     
    744744        std::list< Expression * > dtors; // destructor(s) for return variable(s)
    745745
     746        // readonly
     747        ExprStmt * resultExpr = nullptr;
     748
    746749        StmtExpr( CompoundStmt * statements );
    747750        StmtExpr( const StmtExpr & other );
  • src/Validate/FindSpecialDecls.cc

    r7564e10 r67130fe  
    2626namespace Validate {
    2727        Type * SizeType = nullptr;
    28   FunctionDecl * dereferenceOperator = nullptr;
    29   StructDecl * dtorStruct = nullptr;
    30   FunctionDecl * dtorStructDestroy = nullptr;
     28        FunctionDecl * dereferenceOperator = nullptr;
     29        StructDecl * dtorStruct = nullptr;
     30        FunctionDecl * dtorStructDestroy = nullptr;
    3131
    3232        namespace {
  • src/include/cassert

    r7564e10 r67130fe  
    1010// Created On       : Thu Aug 18 13:19:26 2016
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Thu May 23 15:30:00 2017
    13 // Update Count     : 17
     12// Last Modified On : Mon Jun  3 13:11:00 2017
     13// Update Count     : 18
    1414//
    1515
     
    4343#endif
    4444
    45 enum StrictAllowNull {NonNull, AllowNull};
    46 
    47 template<typename T, StrictAllowNull nullable = NonNull, typename U>
     45template<typename T, typename U>
    4846static inline T strict_dynamic_cast( const U & src ) {
    49         if (nullable == AllowNull && src == nullptr) {
    50                 return nullptr;
    51         }
    5247        assert(src);
    5348        T ret = dynamic_cast<T>(src);
    5449        assertf(ret, "%s", toString(src).c_str());
    5550        return ret;
     51}
     52
     53template<typename T, decltype(nullptr) null, typename U>
     54static inline T strict_dynamic_cast( const U & src ) {
     55        return src ? strict_dynamic_cast<T, U>( src ) : nullptr;
    5656}
    5757
Note: See TracChangeset for help on using the changeset viewer.