On 5/8/26 10:05 AM, Marek Polacek wrote:
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.

The latter should be IDENTIFIER_ANON_P, but your approach is OK for an assert.

        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

Reply via email to