Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk/branches?
-- >8 --
The patch that allowed DECL_NTTP_OBJECT_P in invalid_tparm_referent_p
also added the assert checking for tinfos/__func__ (r14-8189). But in
these tests we got to the assert with a temporary object coming from
create_temporary_var: either a reference temporary or compound literal
temporary. The former could be checked by seeing if the name starts
with _ZGR but the latter don't have it. So perhaps we can just check
DECL_IGNORED_P, always set for create_temporary_var objects.
PR c++/115181
PR c++/125043
PR c++/124979
gcc/cp/ChangeLog:
* pt.cc (invalid_tparm_referent_p): Allow DECL_IGNORED_P in an
assert.
gcc/testsuite/ChangeLog:
* g++.dg/cpp1z/nontype-auto27.C: New test.
* g++.dg/cpp1z/nontype-auto28.C: New test.
* g++.dg/cpp2a/nontype-class75.C: New test.
---
gcc/cp/pt.cc | 22 +++++++------
gcc/testsuite/g++.dg/cpp1z/nontype-auto27.C | 5 +++
gcc/testsuite/g++.dg/cpp1z/nontype-auto28.C | 14 ++++++++
gcc/testsuite/g++.dg/cpp2a/nontype-class75.C | 34 ++++++++++++++++++++
4 files changed, 66 insertions(+), 9 deletions(-)
create mode 100644 gcc/testsuite/g++.dg/cpp1z/nontype-auto27.C
create mode 100644 gcc/testsuite/g++.dg/cpp1z/nontype-auto28.C
create mode 100644 gcc/testsuite/g++.dg/cpp2a/nontype-class75.C
diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index 6992b5196fe..b6e8948f005 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -7439,18 +7439,22 @@ invalid_tparm_referent_p (tree type, tree expr,
tsubst_flags_t complain)
"because %qD has no linkage", expr, type, decl);
return true;
}
- /* C++17: For a non-type template-parameter of reference or pointer
- type, the value of the constant expression shall not refer to (or
- for a pointer type, shall not be the address of):
- * a subobject (4.5),
- * a temporary object (15.2),
- * a string literal (5.13.5),
- * the result of a typeid expression (8.2.8), or
- * a predefined __func__ variable (11.4.1). */
+ /* For a constant template parameter of reference or pointer type,
+ or for each non-static data member of reference or pointer type
+ in a constant template parameter of class type or subobject thereof,
+ the reference or pointer value shall not refer or point to
+ (respectively):
+ -- a temporary object,
+ -- a string literal object,
+ -- the result of a typeid expression,
+ -- a predefined __func__ variable, or
+ -- a subobject of one of the above. */
else if (VAR_P (decl) && DECL_ARTIFICIAL (decl)
&& !DECL_NTTP_OBJECT_P (decl))
{
- gcc_checking_assert (DECL_TINFO_P (decl) || DECL_FNAME_P (decl));
+ gcc_checking_assert (DECL_TINFO_P (decl)
+ || DECL_FNAME_P (decl)
+ || DECL_IGNORED_P (decl));
if (complain & tf_error)
error ("the address of %qD is not a valid template argument",
decl);
diff --git a/gcc/testsuite/g++.dg/cpp1z/nontype-auto27.C
b/gcc/testsuite/g++.dg/cpp1z/nontype-auto27.C
new file mode 100644
index 00000000000..51ff86dfc25
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1z/nontype-auto27.C
@@ -0,0 +1,5 @@
+// PR c++/115181
+// { dg-do compile { target c++17 } }
+
+template <auto> struct S {};
+__extension__ S<(int[]){1}> x; // { dg-error "not a valid template argument" }
diff --git a/gcc/testsuite/g++.dg/cpp1z/nontype-auto28.C
b/gcc/testsuite/g++.dg/cpp1z/nontype-auto28.C
new file mode 100644
index 00000000000..d9165f87987
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1z/nontype-auto28.C
@@ -0,0 +1,14 @@
+// PR c++/125043
+// { dg-do compile { target c++17 } }
+
+template <auto V>
+struct wrapper {
+ static constexpr const auto& value = V;
+};
+
+template <int const& I>
+auto f() -> void;
+
+auto main() -> int {
+ f<wrapper<42>::value>(); // { dg-error "no matching function|not a valid
template argument" }
+}
diff --git a/gcc/testsuite/g++.dg/cpp2a/nontype-class75.C
b/gcc/testsuite/g++.dg/cpp2a/nontype-class75.C
new file mode 100644
index 00000000000..a30ccbee85d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/nontype-class75.C
@@ -0,0 +1,34 @@
+// PR c++/124979
+// { dg-do compile { target c++20 } }
+
+template<auto X, class = decltype(X)>
+struct cw;
+
+struct base {
+
+ template <class L>
+ friend constexpr auto operator &(L) noexcept
+ -> cw<(&L::value)> {
+ return {};
+ }
+};
+
+template<auto X, class>
+struct cw : base {
+ static constexpr const auto& value = X;
+};
+ template <auto L, auto R>
+ constexpr auto operator ->*(cw<L>, cw<R>) noexcept
+ -> cw<L ->* R> {
+ return {};
+ }
+
+struct Divide { int value; };
+auto cvalue = cw<&Divide::value>{};
+constexpr const Divide &t = {42};
+auto co = cw<Divide{42}>{};
+auto co1 = cw<&t>{}; // { dg-error "not a valid template argument|is invalid"
}
+
+template<class> class TD;
+template<int t> class TD<cw<t>>{};
+TD<decltype((co1)->*cvalue)> _; // { dg-error "is invalid" }
base-commit: 8a17f707c90ea92271c9a52846f9be5ca24c6c5a
--
2.54.0