aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2011-04-30 17:07:52 +0000
committerDouglas Gregor <dgregor@apple.com>2011-04-30 17:07:52 +0000
commit769d0cc72b1831785596d0e76f327bdb887823be (patch)
tree1b8f3b1861cdabb9e74622b17da91cb5dcc36500
parent0c4e5d6c499e926a99812a92937df587f67e8362 (diff)
When comparing parameters of reference-to-qualified type during
partial ordering of function templates, use a simple superset relationship rather than the convertibility-implying isMoreQualifiedThan/compatibilyIncludes relationship. Fixes partial ordering between references and address-space-qualified references. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@130612 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/clang/AST/Type.h4
-rw-r--r--lib/AST/Type.cpp12
-rw-r--r--lib/Sema/SemaTemplateDeduction.cpp7
-rw-r--r--test/SemaTemplate/address-spaces.cpp11
4 files changed, 32 insertions, 2 deletions
diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h
index c1b8a775a6..f01e2351ab 100644
--- a/include/clang/AST/Type.h
+++ b/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/lib/AST/Type.cpp b/lib/AST/Type.cpp
index 59cd5a3dc7..0ca9b1fd2f 100644
--- a/lib/AST/Type.cpp
+++ b/lib/AST/Type.cpp
@@ -27,6 +27,18 @@
#include <algorithm>
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/lib/Sema/SemaTemplateDeduction.cpp b/lib/Sema/SemaTemplateDeduction.cpp
index 73d523f8bb..7df6de4a30 100644
--- a/lib/Sema/SemaTemplateDeduction.cpp
+++ b/lib/Sema/SemaTemplateDeduction.cpp
@@ -901,9 +901,12 @@ DeduceTemplateArguments(Sema &S,
Comparison.ParamIsRvalueRef = ParamRef->getAs<RValueReferenceType>();
Comparison.ArgIsRvalueRef = ArgRef->getAs<RValueReferenceType>();
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/test/SemaTemplate/address-spaces.cpp b/test/SemaTemplate/address-spaces.cpp
index df262e1dc6..eda03dbac2 100644
--- a/test/SemaTemplate/address-spaces.cpp
+++ b/test/SemaTemplate/address-spaces.cpp
@@ -73,3 +73,14 @@ void test_arg_in_address_space_1() {
identity<int> ii = accept_arg_in_address_space_1(int_1);
identity<int __attribute__((address_space(1)))> ii2 = accept_any_arg(int_1);
}
+
+// Partial ordering
+template<typename T> int &order1(__attribute__((address_space(1))) T&);
+template<typename T> float &order1(T&);
+
+void test_order1() {
+ static __attribute__((address_space(1))) int i1;
+ int i;
+ int &ir = order1(i1);
+ float &fr = order1(i);
+}