]> granicus.if.org Git - clang/commitdiff
When perform exact-qualifier-match template argument deduction,
authorJohn McCall <rjmccall@apple.com>
Sat, 28 Aug 2010 22:14:41 +0000 (22:14 +0000)
committerJohn McCall <rjmccall@apple.com>
Sat, 28 Aug 2010 22:14:41 +0000 (22:14 +0000)
properly account for the possibility that certain opaque types
might be more qualified than they appear.  Fixes PR7708.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@112390 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Sema/SemaTemplateDeduction.cpp
test/SemaTemplate/deduction.cpp

index 469118111146d92e6f97442190de26b63721bc53..87d9febfb13036a8e5127efca8bc00178c908cc9 100644 (file)
@@ -350,6 +350,29 @@ DeduceTemplateArguments(Sema &S,
   return Sema::TDK_Success;
 }
 
+/// \brief Determines whether the given type is an opaque type that
+/// might be more qualified when instantiated.
+static bool IsPossiblyOpaquelyQualifiedType(QualType T) {
+  switch (T->getTypeClass()) {
+  case Type::TypeOfExpr:
+  case Type::TypeOf:
+  case Type::DependentName:
+  case Type::Decltype:
+  case Type::UnresolvedUsing:
+    return true;
+
+  case Type::ConstantArray:
+  case Type::IncompleteArray:
+  case Type::VariableArray:
+  case Type::DependentSizedArray:
+    return IsPossiblyOpaquelyQualifiedType(
+                                      cast<ArrayType>(T)->getElementType());
+
+  default:
+    return false;
+  }
+}
+
 /// \brief Deduce the template arguments by comparing the parameter type and
 /// the argument type (C++ [temp.deduct.type]).
 ///
@@ -474,7 +497,7 @@ DeduceTemplateArguments(Sema &S,
     if (TDF & TDF_ParamWithReferenceType) {
       if (Param.isMoreQualifiedThan(Arg))
         return Sema::TDK_NonDeducedMismatch;
-    } else {
+    } else if (!IsPossiblyOpaquelyQualifiedType(Param)) {
       if (Param.getCVRQualifiers() != Arg.getCVRQualifiers())
         return Sema::TDK_NonDeducedMismatch;
     }
index c4c668898f0fae312ae22c42a9afb7a7d87f5ecc..9400a0aba96be29b8b9df0b87e5f01e3af8d6312 100644 (file)
@@ -121,3 +121,16 @@ namespace test1 {
     foo(a);
   }
 }
+
+// PR7708
+namespace test2 {
+  template<typename T> struct Const { typedef void const type; };
+
+  template<typename T> void f(T, typename Const<T>::type*);
+  template<typename T> void f(T, void const *);
+
+  void test() {
+    void *p = 0;
+    f(0, p);
+  }
+}