Tested x86_64-pc-linux-gnu, applying to trunk.
-- 8< --
A conversation today pointed out that the current diagnostic for this case
doesn't mention the constant evaluation failure, it just says e.g.
"'p' is not a valid template argument for 'int*' because it is not the
address of a variable"
This patch improves the diagnostic in C++17 and above (post-N4268) to
diagnose failed constant-evaluation.
gcc/cp/ChangeLog:
* pt.cc (convert_nontype_argument_function): Check
cxx_constant_value on failure.
(invalid_tparm_referent_p): Likewise.
gcc/testsuite/ChangeLog:
* g++.dg/tc1/dr49.C: Adjust diagnostic.
* g++.dg/template/func2.C: Likewise.
* g++.dg/cpp1z/nontype8.C: New test.
---
gcc/cp/pt.cc | 52 +++++++++++++++------------
gcc/testsuite/g++.dg/cpp1z/nontype8.C | 12 +++++++
gcc/testsuite/g++.dg/tc1/dr49.C | 4 +--
gcc/testsuite/g++.dg/template/func2.C | 3 +-
4 files changed, 45 insertions(+), 26 deletions(-)
create mode 100644 gcc/testsuite/g++.dg/cpp1z/nontype8.C
diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index 71ae764ce8d..0b7a05c3455 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -6952,14 +6952,22 @@ convert_nontype_argument_function (tree type, tree expr,
{
auto_diagnostic_group d;
location_t loc = cp_expr_loc_or_input_loc (expr);
- error_at (loc, "%qE is not a valid template argument for type %qT",
- expr, type);
- if (TYPE_PTR_P (type))
- inform (loc, "it must be the address of a function "
- "with external linkage");
+ tree c;
+ if (cxx_dialect >= cxx17
+ && (c = cxx_constant_value (fn),
+ c == error_mark_node))
+ ;
else
- inform (loc, "it must be the name of a function with "
- "external linkage");
+ {
+ error_at (loc, "%qE is not a valid template argument for "
+ "type %qT", expr, type);
+ if (TYPE_PTR_P (type))
+ inform (loc, "it must be the address of a function "
+ "with external linkage");
+ else
+ inform (loc, "it must be the name of a function with "
+ "external linkage");
+ }
}
return NULL_TREE;
}
@@ -7402,22 +7410,22 @@ invalid_tparm_referent_p (tree type, tree expr,
tsubst_flags_t complain)
/* Null pointer values are OK in C++11. */;
else
{
- if (VAR_P (expr))
- {
- if (complain & tf_error)
- error ("%qD is not a valid template argument "
- "because %qD is a variable, not the address of "
- "a variable", expr, expr);
- return true;
- }
+ tree c;
+ if (!(complain & tf_error))
+ ;
+ else if (cxx_dialect >= cxx17
+ && (c = cxx_constant_value (expr),
+ c == error_mark_node))
+ ;
+ else if (VAR_P (expr))
+ error ("%qD is not a valid template argument "
+ "because %qD is a variable, not the address of "
+ "a variable", expr, expr);
else
- {
- if (complain & tf_error)
- error ("%qE is not a valid template argument for %qT "
- "because it is not the address of a variable",
- expr, type);
- return true;
- }
+ error ("%qE is not a valid template argument for %qT "
+ "because it is not the address of a variable",
+ expr, type);
+ return true;
}
}
return false;
diff --git a/gcc/testsuite/g++.dg/cpp1z/nontype8.C
b/gcc/testsuite/g++.dg/cpp1z/nontype8.C
new file mode 100644
index 00000000000..b81e85b9044
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1z/nontype8.C
@@ -0,0 +1,12 @@
+// Test that the diagnostic mentions lack of constexpr
+// { dg-do compile { target c++17 } }
+
+template <auto f> void g() {}
+void x()
+{
+ using fp = void (*)();
+ fp f = nullptr; // { dg-message "constexpr" }
+ g<f>(); // { dg-error "" }
+ int *p = nullptr; // { dg-message "constexpr" }
+ g<p>(); // { dg-error "" }
+}
diff --git a/gcc/testsuite/g++.dg/tc1/dr49.C b/gcc/testsuite/g++.dg/tc1/dr49.C
index 753d96b6977..6ddea6bf2dd 100644
--- a/gcc/testsuite/g++.dg/tc1/dr49.C
+++ b/gcc/testsuite/g++.dg/tc1/dr49.C
@@ -10,8 +10,8 @@ template struct R<&p>; // OK
template struct S<&p>; // OK due to parameter adjustment
int *ptr;
-template struct R<ptr>; // { dg-error "argument" }
-template struct S<ptr>; // { dg-error "argument" }
+template struct R<ptr>; // { dg-error "template argument|constant expression" }
+template struct S<ptr>; // { dg-error "template argument|constant expression" }
int v[5];
template struct R<v>; // OK due to implicit argument conversion
diff --git a/gcc/testsuite/g++.dg/template/func2.C
b/gcc/testsuite/g++.dg/template/func2.C
index 0116f23d945..360f4301517 100644
--- a/gcc/testsuite/g++.dg/template/func2.C
+++ b/gcc/testsuite/g++.dg/template/func2.C
@@ -4,8 +4,7 @@ typedef void (*fptr)();
fptr zeroptr = 0;
template<typename T, fptr F> struct foo { };
template<typename T> struct foo<T,zeroptr> { };
-// { dg-error "not a valid template argument" "not valid" { target *-*-* } .-1
}
-// { dg-message "must be the address" "must be the address " { target *-*-* }
.-2 }
+// { dg-error "template argument|constant expression" "not valid" { target
*-*-* } .-1 }
// The rest is needed to trigger the ICE in 4.0 to 4.3:
void f() { }
base-commit: 45fd943eabfe8e71aeecf001e9200f4d52748610
--
2.50.1