aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2025-07-30 12:00:06 -0400
committerJason Merrill <jason@redhat.com>2025-07-30 12:00:06 -0400
commitd7cd6b0df54a29e23adbf98e47965c217f6e0107 (patch)
tree21107c91dc7571c93c11b5e57cca08e6ae47d23a
parent0340177d54d08b6375391ba164a878e6a596275e (diff)
downloadgcc-d7cd6b0df54a29e23adbf98e47965c217f6e0107.zip
gcc-d7cd6b0df54a29e23adbf98e47965c217f6e0107.tar.gz
gcc-d7cd6b0df54a29e23adbf98e47965c217f6e0107.tar.bz2
c++: improve non-constant template arg diagnostic
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.
-rw-r--r--gcc/cp/pt.cc52
-rw-r--r--gcc/testsuite/g++.dg/cpp1z/nontype8.C12
-rw-r--r--gcc/testsuite/g++.dg/tc1/dr49.C4
-rw-r--r--gcc/testsuite/g++.dg/template/func2.C3
4 files changed, 45 insertions, 26 deletions
diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index 71ae764..0b7a05c 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 0000000..b81e85b
--- /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 753d96b..6ddea6b 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 0116f23..360f430 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() { }