summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLei Liu <lei.liu2@windriver.com>2018-05-03 01:43:23 +0000
committerLei Liu <lei.liu2@windriver.com>2018-05-03 01:43:23 +0000
commitf5b6d5f6bf422b1ac0e9ff9287f865585fcb36da (patch)
tree4075c5f4a5ee4a18df48052a6130ea34d4270da7
parent094219deccc9dd36708632c3982a4142fedab446 (diff)
downloadclang-f5b6d5f6bf422b1ac0e9ff9287f865585fcb36da.tar.gz
[Sema] Do not match function type with const T in template argument deduction
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 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@331424 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/Sema/SemaTemplateDeduction.cpp6
-rw-r--r--test/CXX/drs/dr15xx.cpp13
-rw-r--r--test/CXX/drs/dr4xx.cpp17
-rw-r--r--test/SemaTemplate/function-pointer-qualifier.cpp29
4 files changed, 49 insertions, 16 deletions
diff --git a/lib/Sema/SemaTemplateDeduction.cpp b/lib/Sema/SemaTemplateDeduction.cpp
index 22e5b73a24..e4a158f650 100644
--- a/lib/Sema/SemaTemplateDeduction.cpp
+++ b/lib/Sema/SemaTemplateDeduction.cpp
@@ -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");
diff --git a/test/CXX/drs/dr15xx.cpp b/test/CXX/drs/dr15xx.cpp
index a68928f727..2060047571 100644
--- a/test/CXX/drs/dr15xx.cpp
+++ b/test/CXX/drs/dr15xx.cpp
@@ -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
diff --git a/test/CXX/drs/dr4xx.cpp b/test/CXX/drs/dr4xx.cpp
index b7d65e347a..2d30831fd4 100644
--- a/test/CXX/drs/dr4xx.cpp
+++ b/test/CXX/drs/dr4xx.cpp
@@ -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/test/SemaTemplate/function-pointer-qualifier.cpp b/test/SemaTemplate/function-pointer-qualifier.cpp
new file mode 100644
index 0000000000..97d160738a
--- /dev/null
+++ b/test/SemaTemplate/function-pointer-qualifier.cpp
@@ -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);
+}