Changes in / [98a8290:de8dfac2]
- Location:
- src
- Files:
-
- 10 edited
Legend:
- Unmodified
- Added
- Removed
-
src/AST/Expr.cpp
r98a8290 rde8dfac2 65 65 // base type 66 66 ret->result = base; 67 add_ lvalue( ret->result);67 add_qualifiers( ret->result, CV::Lvalue ); 68 68 } 69 69 } … … 165 165 genericSubsitution( aggregate->result ).apply( result ); 166 166 // 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 ); 168 168 } 169 169 … … 175 175 assert( var->get_type() ); 176 176 result = var->get_type(); 177 add_ lvalue( result);177 add_qualifiers( result, CV::Lvalue ); 178 178 } 179 179 … … 309 309 assert( t && i ); 310 310 result = t; 311 add_ lvalue( result);311 add_qualifiers( result, CV::Lvalue ); 312 312 } 313 313 … … 326 326 // like MemberExpr, TupleIndexExpr is always an lvalue 327 327 result = type->types[ index ]; 328 add_ lvalue( result);328 add_qualifiers( result, CV::Lvalue ); 329 329 } 330 330 -
src/AST/Node.hpp
r98a8290 rde8dfac2 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_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 168 172 /// Returns a mutable version of the pointer in this node. 169 173 node_t * get_and_mutate(); -
src/AST/Type.hpp
r98a8290 rde8dfac2 77 77 }; 78 78 79 /// Set the `is_lvalue` qualifieron this type, cloning only if necessary79 /// Clear/reset the qualifiers on this type, cloning only if necessary 80 80 template< 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;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; 83 83 } 84 84 85 /// Clear the qualifiers onthis type, cloning only if necessary85 /// Add the specified qualifiers to this type, cloning only if necessary 86 86 template< 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{}; 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; 89 95 } 90 96 -
src/AST/TypeEnvironment.cpp
r98a8290 rde8dfac2 235 235 } 236 236 237 /// true if a type is a function type 238 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 237 246 namespace { 238 /// true if a type is a function type239 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 newType.get_and_mutate()->qualifiers = typeInst->qualifiers;287 reset_qualifiers( newType, 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 clear_qualifiers( it->bound );293 reset_qualifiers( it->bound ); 294 294 } 295 295 } else return false; 296 296 } else { 297 297 it->bound = std::move(target); 298 clear_qualifiers( it->bound );298 reset_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 clear_qualifiers( c1->bound );353 reset_qualifiers( c1->bound ); 354 354 } 355 355 c1->data.isComplete |= data.isComplete; … … 411 411 if ( common ) { 412 412 to.bound = std::move(common); 413 clear_qualifiers( to.bound );413 reset_qualifiers( to.bound ); 414 414 } 415 415 } else return false; // cannot unify -
src/AST/TypeEnvironment.hpp
r98a8290 rde8dfac2 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 clear_qualifiers( bound );114 reset_qualifiers( bound ); 115 115 } 116 116 -
src/ResolvExpr/CommonType.cc
r98a8290 rde8dfac2 18 18 #include <utility> // for pair 19 19 20 #include "AST/Decl.hpp" 21 #include "AST/Type.hpp" 20 22 #include "Common/PassVisitor.h" 21 23 #include "ResolvExpr/TypeEnvironment.h" // for OpenVarSet, AssertionSet … … 35 37 36 38 namespace 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 ); 39 41 Type *get_result() const { return result; } 40 42 … … 94 96 95 97 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 ); 97 99 98 100 int depth1 = type1->referenceDepth(); … … 176 178 } 177 179 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 unimplemented183 (void)type1; (void)type2; (void)widen; (void)symtab; (void)env; (void)open;184 assert(false);185 return nullptr;186 }187 188 180 // GENERATED START, DO NOT EDIT 189 181 // GENERATED BY BasicTypes-gen.cc … … 493 485 ); 494 486 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 ) 496 488 : result( 0 ), type2( type2 ), widenFirst( widenFirst ), widenSecond( widenSecond ), indexer( indexer ), env( env ), openVars( openVars ) { 497 489 } 498 490 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 ) { 502 494 if ( BasicType *otherBasic = dynamic_cast< BasicType* >( type2 ) ) { 503 495 BasicType::Kind newType = commonTypes[ basicType->get_kind() ][ otherBasic->get_kind() ]; … … 515 507 516 508 template< typename Pointer > 517 void CommonType ::getCommonWithVoidPointer( Pointer* voidPointer, Pointer* otherPointer ) {509 void CommonType_old::getCommonWithVoidPointer( Pointer* voidPointer, Pointer* otherPointer ) { 518 510 if ( TypeInstType* var = dynamic_cast< TypeInstType* >( otherPointer->get_base() ) ) { 519 511 OpenVarSet::const_iterator entry = openVars.find( var->get_name() ); … … 528 520 } 529 521 530 void CommonType ::postvisit( PointerType *pointerType ) {522 void CommonType_old::postvisit( PointerType *pointerType ) { 531 523 if ( PointerType *otherPointer = dynamic_cast< PointerType* >( type2 ) ) { 532 524 // std::cerr << "commonType: two pointers: " << pointerType << " / " << otherPointer << std::endl; … … 563 555 } 564 556 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 ) { 568 560 if ( ReferenceType *otherRef = dynamic_cast< ReferenceType* >( type2 ) ) { 569 561 // std::cerr << "commonType: both references: " << refType << " / " << otherRef << std::endl; … … 600 592 } 601 593 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 ) { 607 599 if ( dynamic_cast< BasicType * >( type2 ) || dynamic_cast< ZeroType* >( type2 ) || dynamic_cast< OneType* >( type2 ) ) { 608 600 // reuse BasicType, EnumInstType code by swapping type2 with enumInstType … … 611 603 } 612 604 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 ) { 617 609 if ( widenFirst ) { 618 610 NamedTypeDecl *nt = indexer.lookupType( inst->get_name() ); … … 636 628 } 637 629 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 ) { 642 634 if ( widenFirst ) { 643 635 if ( dynamic_cast< BasicType* >( type2 ) || dynamic_cast< PointerType* >( type2 ) || dynamic_cast< EnumInstType* >( type2 ) ) { … … 653 645 } 654 646 655 void CommonType ::postvisit( OneType *oneType ) {647 void CommonType_old::postvisit( OneType *oneType ) { 656 648 if ( widenFirst ) { 657 649 if ( dynamic_cast< BasicType* >( type2 ) || dynamic_cast< EnumInstType* >( type2 ) ) { … … 666 658 } 667 659 } 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 668 999 } // namespace ResolvExpr 669 1000 -
src/ResolvExpr/Unify.cc
r98a8290 rde8dfac2 136 136 137 137 return unifyExact( 138 newFirst, newSecond, newEnv, need, have, open, WidenMode{ false, false }, symtab );138 newFirst, newSecond, newEnv, need, have, open, noWiden(), symtab ); 139 139 } 140 140 … … 173 173 env.apply( newFirst ); 174 174 env.apply( newSecond ); 175 clear_qualifiers( newFirst );176 clear_qualifiers( newSecond );175 reset_qualifiers( newFirst ); 176 reset_qualifiers( newSecond ); 177 177 178 178 return unifyExact( 179 newFirst, newSecond, newEnv, need, have, open, WidenMode{ false, false }, symtab );179 newFirst, newSecond, newEnv, need, have, open, noWiden(), symtab ); 180 180 } 181 181 … … 700 700 } 701 701 702 class Unify_new : public ast::WithShortCircuiting {702 class Unify_new final : 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 previsit( const ast::VoidType * ) { 723 visit_children = false; 722 void postvisit( const ast::VoidType * ) { 724 723 result = dynamic_cast< const ast::VoidType * >( type2 ); 725 724 } 726 725 727 void previsit( const ast::BasicType * basic ) { 728 visit_children = false; 726 void postvisit( const ast::BasicType * basic ) { 729 727 if ( auto basic2 = dynamic_cast< const ast::BasicType * >( type2 ) ) { 730 728 result = basic->kind == basic2->kind; … … 732 730 } 733 731 734 void previsit( const ast::PointerType * pointer ) { 735 visit_children = false; 732 void postvisit( const ast::PointerType * pointer ) { 736 733 if ( auto pointer2 = dynamic_cast< const ast::PointerType * >( type2 ) ) { 737 734 result = unifyExact( 738 735 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 ) { 745 741 auto array2 = dynamic_cast< const ast::ArrayType * >( type2 ); 746 742 if ( ! array2 ) return; … … 761 757 762 758 result = unifyExact( 763 array->base, array2->base, tenv, need, have, open, WidenMode{ false, false },759 array->base, array2->base, tenv, need, have, open, noWiden(), 764 760 symtab ); 765 761 } 766 762 767 void previsit( const ast::ReferenceType * ref ) { 768 visit_children = false; 763 void postvisit( const ast::ReferenceType * ref ) { 769 764 if ( auto ref2 = dynamic_cast< const ast::ReferenceType * >( type2 ) ) { 770 765 result = unifyExact( 771 ref->base, ref2->base, tenv, need, have, open, WidenMode{ false, false },766 ref->base, ref2->base, tenv, need, have, open, noWiden(), 772 767 symtab ); 773 768 } … … 783 778 TtypeExpander_new( ast::TypeEnvironment & env ) : tenv( env ) {} 784 779 785 const ast::Type * post mutate( const ast::TypeInstType * typeInst ) {780 const ast::Type * postvisit( const ast::TypeInstType * typeInst ) { 786 781 if ( const ast::EqvClass * clz = tenv.lookup( typeInst->name ) ) { 787 782 // expand ttype parameter into its actual type … … 811 806 // overloaded on outermost mutex and a mutex function has different 812 807 // 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 ); 815 809 dst.emplace_back( new ast::ObjectDecl{ d->location, "", t } ); 816 810 } … … 851 845 return unifyExact( 852 846 t1, tupleFromDecls( crnt2, end2 ), env, need, have, open, 853 WidenMode{ false, false }, symtab );847 noWiden(), symtab ); 854 848 } else if ( ! isTuple1 && isTuple2 ) { 855 849 // combine remainder of list1, then unify 856 850 return unifyExact( 857 851 tupleFromDecls( crnt1, end1 ), t2, env, need, have, open, 858 WidenMode{ false, false }, symtab );852 noWiden(), symtab ); 859 853 } 860 854 861 855 if ( ! unifyExact( 862 t1, t2, env, need, have, open, WidenMode{ false, false }, symtab )856 t1, t2, env, need, have, open, noWiden(), symtab ) 863 857 ) return false; 864 858 … … 874 868 return unifyExact( 875 869 t1, tupleFromDecls( crnt2, end2 ), env, need, have, open, 876 WidenMode{ false, false }, symtab );870 noWiden(), symtab ); 877 871 } else if ( crnt2 != end2 ) { 878 872 // try unifying empty tuple with ttype … … 881 875 return unifyExact( 882 876 tupleFromDecls( crnt1, end1 ), t2, env, need, have, open, 883 WidenMode{ false, false }, symtab );877 noWiden(), symtab ); 884 878 } 885 879 … … 919 913 920 914 public: 921 void previsit( const ast::FunctionType * func ) { 922 visit_children = false; 915 void postvisit( const ast::FunctionType * func ) { 923 916 auto func2 = dynamic_cast< const ast::FunctionType * >( type2 ); 924 917 if ( ! func2 ) return; … … 952 945 template< typename RefType > 953 946 const RefType * handleRefType( const RefType * inst, const ast::Type * other ) { 954 visit_children = false;955 947 // check that the other type is compatible and named the same 956 948 auto otherInst = dynamic_cast< const RefType * >( other ); … … 1011 1003 1012 1004 if ( ! unifyExact( 1013 pty, pty2, tenv, need, have, open, WidenMode{ false, false }, symtab ) ) {1005 pty, pty2, tenv, need, have, open, noWiden(), symtab ) ) { 1014 1006 result = false; 1015 1007 return; … … 1023 1015 1024 1016 public: 1025 void p revisit( const ast::StructInstType * aggrType ) {1017 void postvisit( const ast::StructInstType * aggrType ) { 1026 1018 handleGenericRefType( aggrType, type2 ); 1027 1019 } 1028 1020 1029 void p revisit( const ast::UnionInstType * aggrType ) {1021 void postvisit( const ast::UnionInstType * aggrType ) { 1030 1022 handleGenericRefType( aggrType, type2 ); 1031 1023 } 1032 1024 1033 void p revisit( const ast::EnumInstType * aggrType ) {1025 void postvisit( const ast::EnumInstType * aggrType ) { 1034 1026 handleRefType( aggrType, type2 ); 1035 1027 } 1036 1028 1037 void p revisit( const ast::TraitInstType * aggrType ) {1029 void postvisit( const ast::TraitInstType * aggrType ) { 1038 1030 handleRefType( aggrType, type2 ); 1039 1031 } 1040 1032 1041 void p revisit( const ast::TypeInstType * typeInst ) {1033 void postvisit( const ast::TypeInstType * typeInst ) { 1042 1034 assert( open.find( typeInst->name ) == open.end() ); 1043 1035 handleRefType( typeInst, type2 ); … … 1078 1070 return unifyExact( 1079 1071 t1, tupleFromTypes( list2 ), env, need, have, open, 1080 WidenMode{ false, false }, symtab );1072 noWiden(), symtab ); 1081 1073 } else if ( ! isTuple1 && isTuple2 ) { 1082 1074 // combine entirety of list1, then unify 1083 1075 return unifyExact( 1084 1076 tupleFromTypes( list1 ), t2, env, need, have, open, 1085 WidenMode{ false, false }, symtab );1077 noWiden(), symtab ); 1086 1078 } 1087 1079 1088 1080 if ( ! unifyExact( 1089 t1, t2, env, need, have, open, WidenMode{ false, false }, symtab )1081 t1, t2, env, need, have, open, noWiden(), symtab ) 1090 1082 ) return false; 1091 1083 … … 1101 1093 return unifyExact( 1102 1094 t1, tupleFromTypes( list2 ), env, need, have, open, 1103 WidenMode{ false, false }, symtab );1095 noWiden(), symtab ); 1104 1096 } else if ( crnt2 != list2.end() ) { 1105 1097 // try unifying empty tuple with ttype … … 1110 1102 return unifyExact( 1111 1103 tupleFromTypes( list1 ), t2, env, need, have, open, 1112 WidenMode{ false, false }, symtab );1104 noWiden(), symtab ); 1113 1105 } 1114 1106 … … 1117 1109 1118 1110 public: 1119 void previsit( const ast::TupleType * tuple ) { 1120 visit_children = false; 1111 void postvisit( const ast::TupleType * tuple ) { 1121 1112 auto tuple2 = dynamic_cast< const ast::TupleType * >( type2 ); 1122 1113 if ( ! tuple2 ) return; … … 1132 1123 } 1133 1124 1134 void previsit( const ast::VarArgsType * ) { 1135 visit_children = false; 1125 void postvisit( const ast::VarArgsType * ) { 1136 1126 result = dynamic_cast< const ast::VarArgsType * >( type2 ); 1137 1127 } 1138 1128 1139 void previsit( const ast::ZeroType * ) { 1140 visit_children = false; 1129 void postvisit( const ast::ZeroType * ) { 1141 1130 result = dynamic_cast< const ast::ZeroType * >( type2 ); 1142 1131 } 1143 1132 1144 void previsit( const ast::OneType * ) { 1145 visit_children = false; 1133 void postvisit( const ast::OneType * ) { 1146 1134 result = dynamic_cast< const ast::OneType * >( type2 ); 1147 1135 } … … 1151 1139 template< typename RefType > void handleGenericRefType( RefType *inst, Type *other ); 1152 1140 }; 1141 1142 bool unify( 1143 const ast::ptr<ast::Type> & type1, const ast::ptr<ast::Type> & type2, 1144 ast::TypeEnvironment & env, ast::AssertionSet & need, ast::AssertionSet & have, 1145 ast::OpenVarSet & open, const ast::SymbolTable & symtab, ast::ptr<ast::Type> & common 1146 ) { 1147 ast::OpenVarSet closed; 1148 findOpenVars( type1, open, closed, need, have, FirstClosed ); 1149 findOpenVars( type2, open, closed, need, have, FirstOpen ); 1150 return unifyInexact( 1151 type1, type2, env, need, have, open, WidenMode{ true, true }, symtab, common ); 1152 } 1153 1153 1154 1154 bool unifyExact( … … 1184 1184 1185 1185 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 1189 1190 ) { 1190 1191 ast::CV::Qualifiers q1 = type1->qualifiers, q2 = type2->qualifiers; … … 1193 1194 // type2 are left unchanged; calling convention forces type{1,2}->strong_ref >= 1 1194 1195 ast::ptr<ast::Type> t1{ type1 }, t2{ type2 }; 1195 clear_qualifiers( t1 );1196 clear_qualifiers( t2 );1196 reset_qualifiers( t1 ); 1197 reset_qualifiers( t2 ); 1197 1198 1198 1199 if ( unifyExact( t1, t2, env, need, have, open, widen, symtab ) ) { … … 1201 1202 // if exact unification on unqualified types, try to merge qualifiers 1202 1203 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 ); 1204 1206 return true; 1205 1207 } else { … … 1211 1213 1212 1214 // no exact unification, but common type 1213 common.get_and_mutate()->qualifiers = q1 | q2;1215 reset_qualifiers( common, q1 | q2 ); 1214 1216 return true; 1215 1217 } else { -
src/ResolvExpr/Unify.h
r98a8290 rde8dfac2 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 71 76 bool unifyExact( 72 77 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 ); 75 80 76 81 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 ); 80 86 81 87 } // namespace ResolvExpr -
src/ResolvExpr/WidenMode.h
r98a8290 rde8dfac2 40 40 bool first : 1, second : 1; 41 41 }; 42 43 static inline WidenMode noWiden() { return { false, false }; } 42 44 } // namespace ResolvExpr 43 45 -
src/ResolvExpr/typeops.h
r98a8290 rde8dfac2 89 89 90 90 // in Unify.cc 91 bool isFtype( Type *type );92 91 bool typesCompatible( Type *, Type *, const SymTab::Indexer &indexer, const TypeEnvironment &env ); 93 92 bool typesCompatibleIgnoreQualifiers( Type *, Type *, const SymTab::Indexer &indexer, const TypeEnvironment &env ); … … 118 117 // in CommonType.cc 119 118 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, 122 121 const ast::SymbolTable & symtab, ast::TypeEnvironment & env, const ast::OpenVarSet & open ); 123 122 … … 177 176 return out; 178 177 } 178 179 // in TypeEnvironment.cc 180 bool isFtype( Type *type ); 179 181 } // namespace ResolvExpr 182 183 namespace ast { 184 // in TypeEnvironment.cpp 185 bool isFtype( const ast::Type * type ); 186 } // namespace ast 180 187 181 188 // Local Variables: //
Note: See TracChangeset
for help on using the changeset viewer.