[Sema] Do not match function type with const T in template argument deduction
authorLei Liu <lei.liu2@windriver.com>
Thu, 3 May 2018 01:43:23 +0000 (01:43 +0000)
committerLei Liu <lei.liu2@windriver.com>
Thu, 3 May 2018 01:43:23 +0000 (01:43 +0000)
From http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1584,
function type should not match cv-qualified type in template argument
deduction. This also matches what GCC and EDG do in template argument
deduction.

Differential Revision: https://reviews.llvm.org/D45755

llvm-svn: 331424

clang/lib/Sema/SemaTemplateDeduction.cpp
clang/test/CXX/drs/dr15xx.cpp
clang/test/CXX/drs/dr4xx.cpp
clang/test/SemaTemplate/function-pointer-qualifier.cpp [new file with mode: 0644]

index 22e5b73..e4a158f 100644 (file)
@@ -1273,6 +1273,12 @@ DeduceTemplateArgumentsByTypeMatch(Sema &S,
       return Sema::TDK_Underqualified;
     }
 
+    // Do not match a function type with a cv-qualified type.
+    // http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1584
+    if (Arg->isFunctionType() && Param.hasQualifiers()) {
+      return Sema::TDK_NonDeducedMismatch;
+    }
+
     assert(TemplateTypeParm->getDepth() == Info.getDeducedDepth() &&
            "saw template type parameter with wrong depth");
     assert(Arg != S.Context.OverloadTy && "Unresolved overloaded function");
index a68928f..2060047 100644 (file)
@@ -357,6 +357,19 @@ auto DR1579_lambda_invalid = []() -> GenericMoveOnly<char> {
 };
 } // end namespace dr1579
 
+namespace dr1584 {
+  // Deducing function types from cv-qualified types
+  template<typename T> void f(const T *); // expected-note {{candidate template ignored}}
+  template<typename T> void g(T *, const T * = 0);
+  template<typename T> void h(T *) { T::error; } // expected-error {{no members}}
+  template<typename T> void h(const T *);
+  void i() {
+    f(&i); // expected-error {{no matching function}}
+    g(&i);
+    h(&i); // expected-note {{here}}
+  }
+}
+
 namespace dr1589 {   // dr1589: 3.7 c++11
   // Ambiguous ranking of list-initialization sequences
 
index b7d65e3..2d30831 100644 (file)
@@ -796,24 +796,9 @@ namespace dr468 { // dr468: yes c++11
 }
 
 namespace dr469 { // dr469: no
-  // FIXME: The core issue here didn't really answer the question. We don't
-  // deduce 'const T' from a function or reference type in a class template...
-  template<typename T> struct X; // expected-note 2{{here}}
+  template<typename T> struct X; // expected-note {{here}}
   template<typename T> struct X<const T> {};
   X<int&> x; // expected-error {{undefined}}
-  X<int()> y; // expected-error {{undefined}}
-
-  // ... but we do in a function template. GCC and EDG fail deduction of 'f'
-  // and the second 'h'.
-  template<typename T> void f(const T *);
-  template<typename T> void g(T *, const T * = 0);
-  template<typename T> void h(T *) { T::error; }
-  template<typename T> void h(const T *);
-  void i() {
-    f(&i);
-    g(&i);
-    h(&i);
-  }
 }
 
 namespace dr470 { // dr470: yes
diff --git a/clang/test/SemaTemplate/function-pointer-qualifier.cpp b/clang/test/SemaTemplate/function-pointer-qualifier.cpp
new file mode 100644 (file)
index 0000000..97d1607
--- /dev/null
@@ -0,0 +1,29 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+// expected-no-diagnostics
+
+template<class _Ty> inline
+       void testparam(_Ty **, _Ty **)
+       {
+       }
+
+template<class _Ty> inline
+       void testparam(_Ty *const *, _Ty **)
+       {
+       }
+
+template<class _Ty> inline
+       void testparam(_Ty **, const _Ty **)
+       {
+       }
+
+template<class _Ty> inline
+       void testparam(_Ty *const *, const _Ty **)
+       {
+       }
+
+void case0()
+{
+    void (**p1)();
+    void (**p2)();
+    testparam(p1, p2);
+}