On 1/17/24 10:43, Patrick Palka wrote:
On Mon, 15 Jan 2024, Jason Merrill wrote:
On 1/5/24 11:50, Patrick Palka wrote:

invalid_tparm_referent_p was rejecting using the address of a class NTTP
object as a template argument, but this should be fine.

Hmm, I suppose so; https://eel.is/c++draft/temp#param-8 saying "No two
template parameter objects are template-argument-equivalent" suggests there
can be only one.  And clang/msvc allow it.

+       else if (VAR_P (decl) && !DECL_NTTP_OBJECT_P (decl)
+                && DECL_ARTIFICIAL (decl))

If now some artificial variables are OK and others are not, perhaps we should
enumerate them either way and abort if it's one we haven't specifically
considered.

Sounds good, like so?  Shall we backport this patch or the original
patch to the 13 branch?

Hmm, looks like this patch changes the non-checking default behavior from reject to accept; maybe just add a checking_assert (tinfo || fname) to your original patch? OK with that change, for trunk and 13.

-- >8 --

Subject: [PATCH] c++: address of class NTTP object as targ [PR113242]

invalid_tparm_referent_p was rejecting using the address of a class NTTP
object as a template argument, but this should be fine.

This patch fixes this by refining the DECL_ARTIFICIAL rejection test to
check specifically for the kinds of artificial variables we want to
exclude.

        PR c++/113242

gcc/cp/ChangeLog:

        * pt.cc (invalid_tparm_referent_p) <case ADDR_EXPR>: Refine
        DECL_ARTIFICIAL rejection test.  Assert that C++20 template
        parameter objects are the only artificial variables we accept.

gcc/testsuite/ChangeLog:

        * g++.dg/cpp2a/nontype-class61.C: New test.
---
  gcc/cp/pt.cc                                 | 13 +++++++---
  gcc/testsuite/g++.dg/cpp2a/nontype-class61.C | 27 ++++++++++++++++++++
  2 files changed, 37 insertions(+), 3 deletions(-)
  create mode 100644 gcc/testsuite/g++.dg/cpp2a/nontype-class61.C

diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index b6117231de1..885c297450e 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -7212,12 +7212,14 @@ invalid_tparm_referent_p (tree type, tree expr, 
tsubst_flags_t complain)
        /* 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 subobject (4.5), (relaxed in C++20)
           * a temporary object (15.2),
-          * a string literal (5.13.5),
+          * a string literal (5.13.5), (we diagnose this early in
+            convert_nontype_argument)
           * the result of a typeid expression (8.2.8), or
           * a predefined __func__ variable (11.4.1).  */
-       else if (VAR_P (decl) && DECL_ARTIFICIAL (decl))
+       else if (VAR_P (decl)
+                && (DECL_TINFO_P (decl) || DECL_FNAME_P (decl)))
          {
            if (complain & tf_error)
              error ("the address of %qD is not a valid template argument",
@@ -7242,6 +7244,11 @@ invalid_tparm_referent_p (tree type, tree expr, 
tsubst_flags_t complain)
                     decl);
            return true;
          }
+
+       /* The only artificial variables we do accept are C++20
+          template parameter objects.   */
+       if (VAR_P (decl) && DECL_ARTIFICIAL (decl))
+         gcc_checking_assert (DECL_NTTP_OBJECT_P (decl));
        }
        break;
diff --git a/gcc/testsuite/g++.dg/cpp2a/nontype-class61.C b/gcc/testsuite/g++.dg/cpp2a/nontype-class61.C
new file mode 100644
index 00000000000..90805a05ecf
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/nontype-class61.C
@@ -0,0 +1,27 @@
+// PR c++/113242
+// { dg-do compile { target c++20 } }
+
+struct wrapper {
+  int n;
+};
+
+template<const wrapper& X>
+void f1() {
+  static_assert(X.n == 42);
+}
+
+template<const wrapper* X>
+void f2() {
+  static_assert(X->n == 42);
+}
+
+template<wrapper X>
+void g() {
+  f1<X>();
+  f2<&X>();
+}
+
+int main() {
+  constexpr wrapper X = {42};
+  g<X>();
+}

Reply via email to