diff --git a/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h index c1b8a775a686..f01e2351abf2 100644 --- a/clang/include/clang/AST/Type.h +++ b/clang/include/clang/AST/Type.h @@ -299,6 +299,10 @@ public: (((Mask & CVRMask) | (other.Mask & CVRMask)) == (Mask & CVRMask)); } + /// \brief Determine whether this set of qualifiers is a strict superset of + /// another set of qualifiers, not considering qualifier compatibility. + bool isStrictSupersetOf(Qualifiers Other) const; + bool operator==(Qualifiers Other) const { return Mask == Other.Mask; } bool operator!=(Qualifiers Other) const { return Mask != Other.Mask; } diff --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp index 59cd5a3dc7cf..0ca9b1fd2fd2 100644 --- a/clang/lib/AST/Type.cpp +++ b/clang/lib/AST/Type.cpp @@ -27,6 +27,18 @@ #include using namespace clang; +bool Qualifiers::isStrictSupersetOf(Qualifiers Other) const { + return (*this != Other) && + // CVR qualifiers superset + (((Mask & CVRMask) | (Other.Mask & CVRMask)) == (Mask & CVRMask)) && + // ObjC GC qualifiers superset + ((getObjCGCAttr() == Other.getObjCGCAttr()) || + (hasObjCGCAttr() && !Other.hasObjCGCAttr())) && + // Address space superset. + ((getAddressSpace() == Other.getAddressSpace()) || + (hasAddressSpace()&& !Other.hasAddressSpace())); +} + bool QualType::isConstant(QualType T, ASTContext &Ctx) { if (T.isConstQualified()) return true; diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp index 73d523f8bb12..7df6de4a3097 100644 --- a/clang/lib/Sema/SemaTemplateDeduction.cpp +++ b/clang/lib/Sema/SemaTemplateDeduction.cpp @@ -901,9 +901,12 @@ DeduceTemplateArguments(Sema &S, Comparison.ParamIsRvalueRef = ParamRef->getAs(); Comparison.ArgIsRvalueRef = ArgRef->getAs(); Comparison.Qualifiers = NeitherMoreQualified; - if (Param.isMoreQualifiedThan(Arg)) + + Qualifiers ParamQuals = Param.getQualifiers(); + Qualifiers ArgQuals = Arg.getQualifiers(); + if (ParamQuals.isStrictSupersetOf(ArgQuals)) Comparison.Qualifiers = ParamMoreQualified; - else if (Arg.isMoreQualifiedThan(Param)) + else if (ArgQuals.isStrictSupersetOf(ParamQuals)) Comparison.Qualifiers = ArgMoreQualified; RefParamComparisons->push_back(Comparison); } diff --git a/clang/test/SemaTemplate/address-spaces.cpp b/clang/test/SemaTemplate/address-spaces.cpp index df262e1dc665..eda03dbac2bd 100644 --- a/clang/test/SemaTemplate/address-spaces.cpp +++ b/clang/test/SemaTemplate/address-spaces.cpp @@ -73,3 +73,14 @@ void test_arg_in_address_space_1() { identity ii = accept_arg_in_address_space_1(int_1); identity ii2 = accept_any_arg(int_1); } + +// Partial ordering +template int &order1(__attribute__((address_space(1))) T&); +template float &order1(T&); + +void test_order1() { + static __attribute__((address_space(1))) int i1; + int i; + int &ir = order1(i1); + float &fr = order1(i); +}