Changes in / [98a8290:de8dfac2]


Ignore:
Location:
src
Files:
10 edited

Legend:

Unmodified
Added
Removed
  • src/AST/Expr.cpp

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

    r98a8290 rde8dfac2  
    166166        const o_node_t * as() const { return dynamic_cast<const o_node_t *>(node); }
    167167
     168        /// wrapper for convenient access to strict_dynamic_cast
     169        template<typename o_node_t>
     170        const o_node_t * strict_as() const { return strict_dynamic_cast<const o_node_t *>(node); }
     171
    168172        /// Returns a mutable version of the pointer in this node.
    169173        node_t * get_and_mutate();
  • src/AST/Type.hpp

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

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

    r98a8290 rde8dfac2  
    112112        EqvClass( const std::string & v, const Type * b, bool w, const TypeDecl::Data & d )
    113113        : vars{ v }, bound( b ), allowWidening( w ), data( d ) {
    114                 clear_qualifiers( bound );
     114                reset_qualifiers( bound );
    115115        }
    116116
  • src/ResolvExpr/CommonType.cc

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

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

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

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

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