Changes in / [9a19608:1867c96]
- Location:
- src
- Files:
-
- 10 edited
-
AST/Expr.cpp (modified) (5 diffs)
-
AST/Node.hpp (modified) (1 diff)
-
AST/Type.hpp (modified) (1 diff)
-
AST/TypeEnvironment.cpp (modified) (5 diffs)
-
AST/TypeEnvironment.hpp (modified) (1 diff)
-
ResolvExpr/CommonType.cc (modified) (13 diffs)
-
ResolvExpr/Unify.cc (modified) (25 diffs)
-
ResolvExpr/Unify.h (modified) (1 diff)
-
ResolvExpr/WidenMode.h (modified) (1 diff)
-
ResolvExpr/typeops.h (modified) (3 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/AST/Expr.cpp
r9a19608 r1867c96 65 65 // base type 66 66 ret->result = base; 67 add_ qualifiers( ret->result, CV::Lvalue);67 add_lvalue( ret->result ); 68 68 } 69 69 } … … 165 165 genericSubsitution( aggregate->result ).apply( result ); 166 166 // ensure lvalue and appropriate restrictions from aggregate type 167 add_qualifiers( result, aggregate->result->qualifiers | CV::Lvalue );167 result.get_and_mutate()->qualifiers |= aggregate->result->qualifiers | CV::Lvalue; 168 168 } 169 169 … … 175 175 assert( var->get_type() ); 176 176 result = var->get_type(); 177 add_ qualifiers( result, CV::Lvalue);177 add_lvalue( result ); 178 178 } 179 179 … … 309 309 assert( t && i ); 310 310 result = t; 311 add_ qualifiers( result, CV::Lvalue);311 add_lvalue( result ); 312 312 } 313 313 … … 326 326 // like MemberExpr, TupleIndexExpr is always an lvalue 327 327 result = type->types[ index ]; 328 add_ qualifiers( result, CV::Lvalue);328 add_lvalue( result ); 329 329 } 330 330 -
src/AST/Node.hpp
r9a19608 r1867c96 166 166 const o_node_t * as() const { return dynamic_cast<const o_node_t *>(node); } 167 167 168 /// wrapper for convenient access to strict_dynamic_cast169 template<typename o_node_t>170 const o_node_t * strict_as() const { return strict_dynamic_cast<const o_node_t *>(node); }171 172 168 /// Returns a mutable version of the pointer in this node. 173 169 node_t * get_and_mutate(); -
src/AST/Type.hpp
r9a19608 r1867c96 77 77 }; 78 78 79 /// Clear/reset the qualifierson this type, cloning only if necessary79 /// Set the `is_lvalue` qualifier on this type, cloning only if necessary 80 80 template< enum Node::ref_type ref_t > 81 void reset_qualifiers( ptr_base< Type, ref_t > & p, CV::Qualifiers q = {}) {82 if ( p->qualifiers.val != q.val ) p.get_and_mutate()->qualifiers = q;81 void add_lvalue( ptr_base< Type, ref_t > & p ) { 82 if ( ! p->qualifiers.is_lvalue ) p.get_and_mutate()->qualifiers.is_lvalue = true; 83 83 } 84 84 85 /// Add the specified qualifiers tothis type, cloning only if necessary85 /// Clear the qualifiers on this type, cloning only if necessary 86 86 template< enum Node::ref_type ref_t > 87 void 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 92 template< enum Node::ref_type ref_t > 93 void 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; 87 void clear_qualifiers( ptr_base< Type, ref_t > & p ) { 88 if ( p->qualifiers != CV::Qualifiers{} ) p.get_and_mutate()->qualifiers = CV::Qualifiers{}; 95 89 } 96 90 -
src/AST/TypeEnvironment.cpp
r9a19608 r1867c96 235 235 } 236 236 237 /// true if a type is a function type238 bool 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 246 237 namespace { 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 247 247 /// true if the given type can be bound to the given type variable 248 248 bool tyVarCompatible( const TypeDecl::Data & data, const Type * type ) { … … 285 285 ptr<Type> common; 286 286 ptr<Type> newType = it->bound; 287 reset_qualifiers( newType, typeInst->qualifiers );287 newType.get_and_mutate()->qualifiers = typeInst->qualifiers; 288 288 if ( unifyInexact( 289 289 newType, target, *this, need, have, open, … … 291 291 if ( common ) { 292 292 it->bound = std::move(common); 293 reset_qualifiers( it->bound );293 clear_qualifiers( it->bound ); 294 294 } 295 295 } else return false; 296 296 } else { 297 297 it->bound = std::move(target); 298 reset_qualifiers( it->bound );298 clear_qualifiers( it->bound ); 299 299 it->allowWidening = widen.first && widen.second; 300 300 } … … 351 351 if ( common ) { 352 352 c1->bound = std::move(common); 353 reset_qualifiers( c1->bound );353 clear_qualifiers( c1->bound ); 354 354 } 355 355 c1->data.isComplete |= data.isComplete; … … 411 411 if ( common ) { 412 412 to.bound = std::move(common); 413 reset_qualifiers( to.bound );413 clear_qualifiers( to.bound ); 414 414 } 415 415 } else return false; // cannot unify -
src/AST/TypeEnvironment.hpp
r9a19608 r1867c96 112 112 EqvClass( const std::string & v, const Type * b, bool w, const TypeDecl::Data & d ) 113 113 : vars{ v }, bound( b ), allowWidening( w ), data( d ) { 114 reset_qualifiers( bound );114 clear_qualifiers( bound ); 115 115 } 116 116 -
src/ResolvExpr/CommonType.cc
r9a19608 r1867c96 18 18 #include <utility> // for pair 19 19 20 #include "AST/Decl.hpp"21 #include "AST/Type.hpp"22 20 #include "Common/PassVisitor.h" 23 21 #include "ResolvExpr/TypeEnvironment.h" // for OpenVarSet, AssertionSet … … 37 35 38 36 namespace ResolvExpr { 39 struct CommonType _old: public WithShortCircuiting {40 CommonType _old( Type *type2, bool widenFirst, bool widenSecond, const SymTab::Indexer &indexer, TypeEnvironment &env, const OpenVarSet &openVars );37 struct CommonType : public WithShortCircuiting { 38 CommonType( Type *type2, bool widenFirst, bool widenSecond, const SymTab::Indexer &indexer, TypeEnvironment &env, const OpenVarSet &openVars ); 41 39 Type *get_result() const { return result; } 42 40 … … 96 94 97 95 Type *commonType( Type *type1, Type *type2, bool widenFirst, bool widenSecond, const SymTab::Indexer &indexer, TypeEnvironment &env, const OpenVarSet &openVars ) { 98 PassVisitor<CommonType _old> visitor( type2, widenFirst, widenSecond, indexer, env, openVars );96 PassVisitor<CommonType> visitor( type2, widenFirst, widenSecond, indexer, env, openVars ); 99 97 100 98 int depth1 = type1->referenceDepth(); … … 178 176 } 179 177 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 180 188 // GENERATED START, DO NOT EDIT 181 189 // GENERATED BY BasicTypes-gen.cc … … 485 493 ); 486 494 487 CommonType _old::CommonType_old( Type *type2, bool widenFirst, bool widenSecond, const SymTab::Indexer &indexer, TypeEnvironment &env, const OpenVarSet &openVars )495 CommonType::CommonType( Type *type2, bool widenFirst, bool widenSecond, const SymTab::Indexer &indexer, TypeEnvironment &env, const OpenVarSet &openVars ) 488 496 : result( 0 ), type2( type2 ), widenFirst( widenFirst ), widenSecond( widenSecond ), indexer( indexer ), env( env ), openVars( openVars ) { 489 497 } 490 498 491 void CommonType _old::postvisit( VoidType * ) {}492 493 void CommonType _old::postvisit( BasicType *basicType ) {499 void CommonType::postvisit( VoidType * ) {} 500 501 void CommonType::postvisit( BasicType *basicType ) { 494 502 if ( BasicType *otherBasic = dynamic_cast< BasicType* >( type2 ) ) { 495 503 BasicType::Kind newType = commonTypes[ basicType->get_kind() ][ otherBasic->get_kind() ]; … … 507 515 508 516 template< typename Pointer > 509 void CommonType _old::getCommonWithVoidPointer( Pointer* voidPointer, Pointer* otherPointer ) {517 void CommonType::getCommonWithVoidPointer( Pointer* voidPointer, Pointer* otherPointer ) { 510 518 if ( TypeInstType* var = dynamic_cast< TypeInstType* >( otherPointer->get_base() ) ) { 511 519 OpenVarSet::const_iterator entry = openVars.find( var->get_name() ); … … 520 528 } 521 529 522 void CommonType _old::postvisit( PointerType *pointerType ) {530 void CommonType::postvisit( PointerType *pointerType ) { 523 531 if ( PointerType *otherPointer = dynamic_cast< PointerType* >( type2 ) ) { 524 532 // std::cerr << "commonType: two pointers: " << pointerType << " / " << otherPointer << std::endl; … … 555 563 } 556 564 557 void CommonType _old::postvisit( ArrayType * ) {}558 559 void CommonType _old::postvisit( ReferenceType *refType ) {565 void CommonType::postvisit( ArrayType * ) {} 566 567 void CommonType::postvisit( ReferenceType *refType ) { 560 568 if ( ReferenceType *otherRef = dynamic_cast< ReferenceType* >( type2 ) ) { 561 569 // std::cerr << "commonType: both references: " << refType << " / " << otherRef << std::endl; … … 592 600 } 593 601 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 ) {602 void CommonType::postvisit( FunctionType * ) {} 603 void CommonType::postvisit( StructInstType * ) {} 604 void CommonType::postvisit( UnionInstType * ) {} 605 606 void CommonType::postvisit( EnumInstType *enumInstType ) { 599 607 if ( dynamic_cast< BasicType * >( type2 ) || dynamic_cast< ZeroType* >( type2 ) || dynamic_cast< OneType* >( type2 ) ) { 600 608 // reuse BasicType, EnumInstType code by swapping type2 with enumInstType … … 603 611 } 604 612 605 void CommonType _old::postvisit( TraitInstType * ) {606 } 607 608 void CommonType _old::postvisit( TypeInstType *inst ) {613 void CommonType::postvisit( TraitInstType * ) { 614 } 615 616 void CommonType::postvisit( TypeInstType *inst ) { 609 617 if ( widenFirst ) { 610 618 NamedTypeDecl *nt = indexer.lookupType( inst->get_name() ); … … 628 636 } 629 637 630 void CommonType _old::postvisit( TupleType * ) {}631 void CommonType _old::postvisit( VarArgsType * ) {}632 633 void CommonType _old::postvisit( ZeroType *zeroType ) {638 void CommonType::postvisit( TupleType * ) {} 639 void CommonType::postvisit( VarArgsType * ) {} 640 641 void CommonType::postvisit( ZeroType *zeroType ) { 634 642 if ( widenFirst ) { 635 643 if ( dynamic_cast< BasicType* >( type2 ) || dynamic_cast< PointerType* >( type2 ) || dynamic_cast< EnumInstType* >( type2 ) ) { … … 645 653 } 646 654 647 void CommonType _old::postvisit( OneType *oneType ) {655 void CommonType::postvisit( OneType *oneType ) { 648 656 if ( widenFirst ) { 649 657 if ( dynamic_cast< BasicType* >( type2 ) || dynamic_cast< EnumInstType* >( type2 ) ) { … … 658 666 } 659 667 } 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 AST682 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 AST697 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.first731 && pointer2->base.as< ast::VoidType >()732 && ! ast::isFtype( pointer->base )733 ) {734 getCommonWithVoidPointer( pointer2, pointer );735 } else if (736 widen.second737 && 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 that749 // pointer{,2}->base are unchanged750 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 qualifiers760 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 that791 // ref{,2}->base are unchanged792 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 qualifiers802 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 swapping827 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 )->base838 ) {839 ast::CV::Qualifiers q1 = inst->qualifiers, q2 = type2->qualifiers;840 841 // force t{1,2} to be cloned if their qualifiers must be mutated842 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 & open900 ) {901 ast::ptr<ast::Type> common;902 ast::AssertionSet have, need;903 ast::OpenVarSet newOpen{ open };904 905 // need unify to bind type variables906 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 & open931 ) {932 unsigned depth1 = type1->referenceDepth();933 unsigned depth2 = type2->referenceDepth();934 935 if ( depth1 != depth2 ) { // implies depth1 > 0 || depth2 > 0936 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 < depth2947 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 reference953 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 visitor966 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 that981 // type1 and type->base are left unchanged; calling convention forces982 // {type1,type->base}->strong_ref >= 1983 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 999 668 } // namespace ResolvExpr 1000 669 -
src/ResolvExpr/Unify.cc
r9a19608 r1867c96 136 136 137 137 return unifyExact( 138 newFirst, newSecond, newEnv, need, have, open, noWiden(), symtab );138 newFirst, newSecond, newEnv, need, have, open, WidenMode{ false, false }, symtab ); 139 139 } 140 140 … … 173 173 env.apply( newFirst ); 174 174 env.apply( newSecond ); 175 reset_qualifiers( newFirst );176 reset_qualifiers( newSecond );175 clear_qualifiers( newFirst ); 176 clear_qualifiers( newSecond ); 177 177 178 178 return unifyExact( 179 newFirst, newSecond, newEnv, need, have, open, noWiden(), symtab );179 newFirst, newSecond, newEnv, need, have, open, WidenMode{ false, false }, symtab ); 180 180 } 181 181 … … 700 700 } 701 701 702 class Unify_new final: public ast::WithShortCircuiting {702 class Unify_new : public ast::WithShortCircuiting { 703 703 const ast::Type * type2; 704 704 ast::TypeEnvironment & tenv; … … 720 720 void previsit( const ast::Node * ) { visit_children = false; } 721 721 722 void postvisit( const ast::VoidType * ) { 722 void previsit( const ast::VoidType * ) { 723 visit_children = false; 723 724 result = dynamic_cast< const ast::VoidType * >( type2 ); 724 725 } 725 726 726 void postvisit( const ast::BasicType * basic ) { 727 void previsit( const ast::BasicType * basic ) { 728 visit_children = false; 727 729 if ( auto basic2 = dynamic_cast< const ast::BasicType * >( type2 ) ) { 728 730 result = basic->kind == basic2->kind; … … 730 732 } 731 733 732 void postvisit( const ast::PointerType * pointer ) { 734 void previsit( const ast::PointerType * pointer ) { 735 visit_children = false; 733 736 if ( auto pointer2 = dynamic_cast< const ast::PointerType * >( type2 ) ) { 734 737 result = unifyExact( 735 738 pointer->base, pointer2->base, tenv, need, have, open, 736 noWiden(), symtab ); 737 } 738 } 739 740 void postvisit( const ast::ArrayType * array ) { 739 WidenMode{ false, false }, symtab ); 740 } 741 } 742 743 void previsit( const ast::ArrayType * array ) { 744 visit_children = false; 741 745 auto array2 = dynamic_cast< const ast::ArrayType * >( type2 ); 742 746 if ( ! array2 ) return; … … 757 761 758 762 result = unifyExact( 759 array->base, array2->base, tenv, need, have, open, noWiden(),763 array->base, array2->base, tenv, need, have, open, WidenMode{ false, false }, 760 764 symtab ); 761 765 } 762 766 763 void postvisit( const ast::ReferenceType * ref ) { 767 void previsit( const ast::ReferenceType * ref ) { 768 visit_children = false; 764 769 if ( auto ref2 = dynamic_cast< const ast::ReferenceType * >( type2 ) ) { 765 770 result = unifyExact( 766 ref->base, ref2->base, tenv, need, have, open, noWiden(),771 ref->base, ref2->base, tenv, need, have, open, WidenMode{ false, false }, 767 772 symtab ); 768 773 } … … 778 783 TtypeExpander_new( ast::TypeEnvironment & env ) : tenv( env ) {} 779 784 780 const ast::Type * post visit( const ast::TypeInstType * typeInst ) {785 const ast::Type * postmutate( const ast::TypeInstType * typeInst ) { 781 786 if ( const ast::EqvClass * clz = tenv.lookup( typeInst->name ) ) { 782 787 // expand ttype parameter into its actual type … … 806 811 // overloaded on outermost mutex and a mutex function has different 807 812 // requirements than a non-mutex function 808 remove_qualifiers( t, ast::CV::Const | ast::CV::Volatile | ast::CV::Atomic ); 813 t.get_and_mutate()->qualifiers 814 -= ast::CV::Const | ast::CV::Volatile | ast::CV::Atomic; 809 815 dst.emplace_back( new ast::ObjectDecl{ d->location, "", t } ); 810 816 } … … 845 851 return unifyExact( 846 852 t1, tupleFromDecls( crnt2, end2 ), env, need, have, open, 847 noWiden(), symtab );853 WidenMode{ false, false }, symtab ); 848 854 } else if ( ! isTuple1 && isTuple2 ) { 849 855 // combine remainder of list1, then unify 850 856 return unifyExact( 851 857 tupleFromDecls( crnt1, end1 ), t2, env, need, have, open, 852 noWiden(), symtab );858 WidenMode{ false, false }, symtab ); 853 859 } 854 860 855 861 if ( ! unifyExact( 856 t1, t2, env, need, have, open, noWiden(), symtab )862 t1, t2, env, need, have, open, WidenMode{ false, false }, symtab ) 857 863 ) return false; 858 864 … … 868 874 return unifyExact( 869 875 t1, tupleFromDecls( crnt2, end2 ), env, need, have, open, 870 noWiden(), symtab );876 WidenMode{ false, false }, symtab ); 871 877 } else if ( crnt2 != end2 ) { 872 878 // try unifying empty tuple with ttype … … 875 881 return unifyExact( 876 882 tupleFromDecls( crnt1, end1 ), t2, env, need, have, open, 877 noWiden(), symtab );883 WidenMode{ false, false }, symtab ); 878 884 } 879 885 … … 913 919 914 920 public: 915 void postvisit( const ast::FunctionType * func ) { 921 void previsit( const ast::FunctionType * func ) { 922 visit_children = false; 916 923 auto func2 = dynamic_cast< const ast::FunctionType * >( type2 ); 917 924 if ( ! func2 ) return; … … 945 952 template< typename RefType > 946 953 const RefType * handleRefType( const RefType * inst, const ast::Type * other ) { 954 visit_children = false; 947 955 // check that the other type is compatible and named the same 948 956 auto otherInst = dynamic_cast< const RefType * >( other ); … … 1003 1011 1004 1012 if ( ! unifyExact( 1005 pty, pty2, tenv, need, have, open, noWiden(), symtab ) ) {1013 pty, pty2, tenv, need, have, open, WidenMode{ false, false }, symtab ) ) { 1006 1014 result = false; 1007 1015 return; … … 1015 1023 1016 1024 public: 1017 void p ostvisit( const ast::StructInstType * aggrType ) {1025 void previsit( const ast::StructInstType * aggrType ) { 1018 1026 handleGenericRefType( aggrType, type2 ); 1019 1027 } 1020 1028 1021 void p ostvisit( const ast::UnionInstType * aggrType ) {1029 void previsit( const ast::UnionInstType * aggrType ) { 1022 1030 handleGenericRefType( aggrType, type2 ); 1023 1031 } 1024 1032 1025 void p ostvisit( const ast::EnumInstType * aggrType ) {1033 void previsit( const ast::EnumInstType * aggrType ) { 1026 1034 handleRefType( aggrType, type2 ); 1027 1035 } 1028 1036 1029 void p ostvisit( const ast::TraitInstType * aggrType ) {1037 void previsit( const ast::TraitInstType * aggrType ) { 1030 1038 handleRefType( aggrType, type2 ); 1031 1039 } 1032 1040 1033 void p ostvisit( const ast::TypeInstType * typeInst ) {1041 void previsit( const ast::TypeInstType * typeInst ) { 1034 1042 assert( open.find( typeInst->name ) == open.end() ); 1035 1043 handleRefType( typeInst, type2 ); … … 1070 1078 return unifyExact( 1071 1079 t1, tupleFromTypes( list2 ), env, need, have, open, 1072 noWiden(), symtab );1080 WidenMode{ false, false }, symtab ); 1073 1081 } else if ( ! isTuple1 && isTuple2 ) { 1074 1082 // combine entirety of list1, then unify 1075 1083 return unifyExact( 1076 1084 tupleFromTypes( list1 ), t2, env, need, have, open, 1077 noWiden(), symtab );1085 WidenMode{ false, false }, symtab ); 1078 1086 } 1079 1087 1080 1088 if ( ! unifyExact( 1081 t1, t2, env, need, have, open, noWiden(), symtab )1089 t1, t2, env, need, have, open, WidenMode{ false, false }, symtab ) 1082 1090 ) return false; 1083 1091 … … 1093 1101 return unifyExact( 1094 1102 t1, tupleFromTypes( list2 ), env, need, have, open, 1095 noWiden(), symtab );1103 WidenMode{ false, false }, symtab ); 1096 1104 } else if ( crnt2 != list2.end() ) { 1097 1105 // try unifying empty tuple with ttype … … 1102 1110 return unifyExact( 1103 1111 tupleFromTypes( list1 ), t2, env, need, have, open, 1104 noWiden(), symtab );1112 WidenMode{ false, false }, symtab ); 1105 1113 } 1106 1114 … … 1109 1117 1110 1118 public: 1111 void postvisit( const ast::TupleType * tuple ) { 1119 void previsit( const ast::TupleType * tuple ) { 1120 visit_children = false; 1112 1121 auto tuple2 = dynamic_cast< const ast::TupleType * >( type2 ); 1113 1122 if ( ! tuple2 ) return; … … 1123 1132 } 1124 1133 1125 void postvisit( const ast::VarArgsType * ) { 1134 void previsit( const ast::VarArgsType * ) { 1135 visit_children = false; 1126 1136 result = dynamic_cast< const ast::VarArgsType * >( type2 ); 1127 1137 } 1128 1138 1129 void postvisit( const ast::ZeroType * ) { 1139 void previsit( const ast::ZeroType * ) { 1140 visit_children = false; 1130 1141 result = dynamic_cast< const ast::ZeroType * >( type2 ); 1131 1142 } 1132 1143 1133 void postvisit( const ast::OneType * ) { 1144 void previsit( const ast::OneType * ) { 1145 visit_children = false; 1134 1146 result = dynamic_cast< const ast::OneType * >( type2 ); 1135 1147 } … … 1139 1151 template< typename RefType > void handleGenericRefType( RefType *inst, Type *other ); 1140 1152 }; 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> & common1146 ) {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 1153 1154 1154 bool unifyExact( … … 1184 1184 1185 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 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 1190 1189 ) { 1191 1190 ast::CV::Qualifiers q1 = type1->qualifiers, q2 = type2->qualifiers; … … 1194 1193 // type2 are left unchanged; calling convention forces type{1,2}->strong_ref >= 1 1195 1194 ast::ptr<ast::Type> t1{ type1 }, t2{ type2 }; 1196 reset_qualifiers( t1 );1197 reset_qualifiers( t2 );1195 clear_qualifiers( t1 ); 1196 clear_qualifiers( t2 ); 1198 1197 1199 1198 if ( unifyExact( t1, t2, env, need, have, open, widen, symtab ) ) { … … 1202 1201 // if exact unification on unqualified types, try to merge qualifiers 1203 1202 if ( q1 == q2 || ( ( q1 > q2 || widen.first ) && ( q2 > q1 || widen.second ) ) ) { 1204 common = type1; 1205 reset_qualifiers( common, q1 | q2 ); 1203 common.set_and_mutate( type1 )->qualifiers = q1 | q2; 1206 1204 return true; 1207 1205 } else { … … 1213 1211 1214 1212 // no exact unification, but common type 1215 reset_qualifiers( common, q1 | q2 );1213 common.get_and_mutate()->qualifiers = q1 | q2; 1216 1214 return true; 1217 1215 } else { -
src/ResolvExpr/Unify.h
r9a19608 r1867c96 69 69 } 70 70 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 71 bool unifyExact( 77 72 const ast::Type * type1, const ast::Type * type2, ast::TypeEnvironment & env, 78 ast::AssertionSet & need, ast::AssertionSet & have, constast::OpenVarSet & open,79 WidenMode widen,const ast::SymbolTable & symtab );73 ast::AssertionSet & need, ast::AssertionSet & have, ast::OpenVarSet & open, 74 const ast::SymbolTable & symtab ); 80 75 81 76 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 ); 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 ); 86 80 87 81 } // namespace ResolvExpr -
src/ResolvExpr/WidenMode.h
r9a19608 r1867c96 40 40 bool first : 1, second : 1; 41 41 }; 42 43 static inline WidenMode noWiden() { return { false, false }; }44 42 } // namespace ResolvExpr 45 43 -
src/ResolvExpr/typeops.h
r9a19608 r1867c96 89 89 90 90 // in Unify.cc 91 bool isFtype( Type *type ); 91 92 bool typesCompatible( Type *, Type *, const SymTab::Indexer &indexer, const TypeEnvironment &env ); 92 93 bool typesCompatibleIgnoreQualifiers( Type *, Type *, const SymTab::Indexer &indexer, const TypeEnvironment &env ); … … 117 118 // in CommonType.cc 118 119 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,120 const ast::Type * commonType( 121 const ast::Type * type1, const ast::Type * type2, WidenMode widen, 121 122 const ast::SymbolTable & symtab, ast::TypeEnvironment & env, const ast::OpenVarSet & open ); 122 123 … … 176 177 return out; 177 178 } 178 179 // in TypeEnvironment.cc180 bool isFtype( Type *type );181 179 } // namespace ResolvExpr 182 183 namespace ast {184 // in TypeEnvironment.cpp185 bool isFtype( const ast::Type * type );186 } // namespace ast187 180 188 181 // Local Variables: //
Note:
See TracChangeset
for help on using the changeset viewer.