https://gcc.gnu.org/g:cb617bedc8fe8008980841e019f7bddd1cc296ee

commit r16-7582-gcb617bedc8fe8008980841e019f7bddd1cc296ee
Author: Jakub Jelinek <[email protected]>
Date:   Thu Feb 19 07:55:38 2026 +0100

    c++: Fix up convert_nontype_argument [PR124070]
    
    Some of the following testcases are incorrectly accepted.
    The problem is in convert_nontype_argument.  It just does
    maybe_constant_value earlier.  Later on for integral/enum/floating
    point args it uses cxx_constant_value for complain & tf_error if
    not val_dep_p and expr is not a simple constant, similarly for
    class type it calls
          /* Replace the argument with a reference to the corresponding template
             parameter object.  */
          if (!val_dep_p)
            expr = create_template_parm_object (expr, complain);
          if (expr == error_mark_node)
            return NULL_TREE;
    etc.  But for NULLPTR_TYPE_P and REFLECTION_TYPE_P cases (I bet
    Marek has based the latter on the former) it only verifies the type
    and not the actual expression.
    I think we need to do that, because if maybe_constant_value fails, it
    just returns the passed in argument and if nothing checks it, we accept
    whatever was there (and sometimes ICE later).
    
    The following patch implements that.
    
    2026-02-19  Jakub Jelinek  <[email protected]>
    
            PR c++/124070
            * pt.cc (convert_nontype_argument): For NULLPTR_TYPE_P case
            if expr is not integer_zerop and is not val_dep_p try harder,
            for complain & tf_error use cxx_constant_value and return NULL_TREE
            for error_mark_node, without tf_error return NULL_TREE.  Similarly
            for REFLECTION_TYPE_P case if expr is not REFLECT_EXPR and is not
            val_dep_p try harder like for NULLPTR_TYPE_P.
    
            * g++.dg/cpp26/pr124070.C: New test.
            * g++.dg/reflect/parameters_of4.C: Expect different diagnostics.
            * g++.dg/reflect/define_aggregate7.C: New test.
            * g++.dg/reflect/define_aggregate8.C: New test.

Diff:
---
 gcc/cp/pt.cc                                     | 24 ++++++++++++++++++++++++
 gcc/testsuite/g++.dg/cpp26/pr124070.C            | 20 ++++++++++++++++++++
 gcc/testsuite/g++.dg/reflect/define_aggregate7.C | 13 +++++++++++++
 gcc/testsuite/g++.dg/reflect/define_aggregate8.C | 12 ++++++++++++
 gcc/testsuite/g++.dg/reflect/parameters_of4.C    |  5 +++--
 5 files changed, 72 insertions(+), 2 deletions(-)

diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index 00804a7eea15..c17870039ed2 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -8017,6 +8017,18 @@ convert_nontype_argument (tree type, tree expr, 
tsubst_flags_t complain)
                   "because it is of type %qT", expr, type, TREE_TYPE (expr));
          return NULL_TREE;
        }
+      if (!integer_zerop (expr) && !val_dep_p)
+       {
+         if (complain & tf_error)
+           {
+             expr = cxx_constant_value (expr);
+             if (expr == error_mark_node)
+               return NULL_TREE;
+             gcc_assert (integer_zerop (expr));
+           }
+         else
+           return NULL_TREE;
+       }
       return expr;
     }
   else if (CLASS_TYPE_P (type))
@@ -8037,6 +8049,18 @@ convert_nontype_argument (tree type, tree expr, 
tsubst_flags_t complain)
                   "because it is of type %qT", expr, type, TREE_TYPE (expr));
          return NULL_TREE;
        }
+      if (!REFLECT_EXPR_P (expr) && !val_dep_p)
+       {
+         if (complain & tf_error)
+           {
+             expr = cxx_constant_value (expr);
+             if (expr == error_mark_node)
+               return NULL_TREE;
+             gcc_assert (REFLECT_EXPR_P (expr));
+           }
+         else
+           return NULL_TREE;
+       }
       return expr;
     }
   /* A template non-type parameter must be one of the above.  */
diff --git a/gcc/testsuite/g++.dg/cpp26/pr124070.C 
b/gcc/testsuite/g++.dg/cpp26/pr124070.C
new file mode 100644
index 000000000000..4721c0ff2154
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp26/pr124070.C
@@ -0,0 +1,20 @@
+// PR c++/124070
+// { dg-do compile { target c++26 } }
+
+constexpr decltype (nullptr)
+bar (bool x)
+{
+  if (x)
+    throw 1;
+  return nullptr;
+}
+
+template <decltype (nullptr) I = bar (true)>   // { dg-error "uncaught 
exception '1'" }
+constexpr void
+foo ()
+{
+}
+
+consteval {
+  foo <> ();                                   // { dg-error "no matching 
function for call to 'foo<>\\\(\\\)'" }
+}
diff --git a/gcc/testsuite/g++.dg/reflect/define_aggregate7.C 
b/gcc/testsuite/g++.dg/reflect/define_aggregate7.C
new file mode 100644
index 000000000000..2ea8f86f35e2
--- /dev/null
+++ b/gcc/testsuite/g++.dg/reflect/define_aggregate7.C
@@ -0,0 +1,13 @@
+// PR c++/124070
+// { dg-do compile { target c++26 } }
+// { dg-additional-options "-freflection" }
+
+#include <meta>
+
+struct S;
+template <std::meta::info I = define_aggregate (^^S, {})>      // { dg-error 
"'define_aggregate' not evaluated from 'consteval' block" }
+constexpr void foo () {}
+
+consteval {
+  foo <> ();   // { dg-error "no matching function for call to 
'foo<>\\\(\\\)'" }
+}
diff --git a/gcc/testsuite/g++.dg/reflect/define_aggregate8.C 
b/gcc/testsuite/g++.dg/reflect/define_aggregate8.C
new file mode 100644
index 000000000000..55372d2e3cad
--- /dev/null
+++ b/gcc/testsuite/g++.dg/reflect/define_aggregate8.C
@@ -0,0 +1,12 @@
+// PR c++/124070
+// { dg-do compile { target c++26 } }
+// { dg-additional-options "-freflection" }
+
+#include <meta>
+
+struct S;
+consteval void bar (std::meta::info a = define_aggregate (^^S, {})) {}
+consteval {
+  bar ();
+}
+S s;
diff --git a/gcc/testsuite/g++.dg/reflect/parameters_of4.C 
b/gcc/testsuite/g++.dg/reflect/parameters_of4.C
index a5b4230db770..fe646e2f253f 100644
--- a/gcc/testsuite/g++.dg/reflect/parameters_of4.C
+++ b/gcc/testsuite/g++.dg/reflect/parameters_of4.C
@@ -4,9 +4,10 @@
 
 #include <meta>
 
-template<auto R> void foo () {}  // { dg-message "sorry, unimplemented: 
mangling" }
+template<auto R> void foo () {}
 void
 g ()
 {
-  foo<std::meta::parameters_of(^^g)[0]>();
+  foo<std::meta::parameters_of(^^g)[0]>();     // { dg-error "no matching 
function for call to" }
 }
+// { dg-error "call to non-'constexpr' function" "" { target *-*-* } 0 }

Reply via email to