[gcc r16-9283] c++: Fix up ICEs with some metafns with non-dependent args in templates [PR126036]

Jakub Jelinek via Gcc-cvs <[email protected]>
Newsgroups gmane.comp.gcc.cvs
Message-ID <[email protected]>
https://gcc.gnu.org/g:08015780e5130c062e1f828c37c7904e1e9bc7c0

commit r16-9283-g08015780e5130c062e1f828c37c7904e1e9bc7c0
Author: Jakub Jelinek <[email protected]>
Date:   Fri Jul 3 20:41:45 2026 +0200

    c++: Fix up ICEs with some metafns with non-dependent args in templates [PR126036]
    
    The following testcase ICEs, because potential_constant_expression_1 handles
    some forms of CAST_EXPR, but cxx_eval_constant_expression doesn't.
    Normally, if we have e.g. a non-dependent compound literal in a template,
    finish_compound_literal will create a CAST_EXPR, but
    fold_non_dependent_expr_template -> instantiate_non_dependent_expr_internal
    will fold that away, so constexpr.cc evaluation doesn't see it.
    reflect.cc calls finish_compound_literal in 3 spots, one is to create
    std::array <type, 0> {}, another one is when creating the
    std::meta::exception object to throw and the last one when creating
    std::vector <std::meta::info> object to return from various metafns.
    If that is done with processing_template_decl, finish_compound_literal
    will again return a CAST_EXPR, but unlike the usual case it is during
    constant evaluation and so instantiate_non_dependent_expr_internal
    will not be invoked on it to clean that up.
    
    Now, in the get_meta_exception_object case, we already have
      /* Don't throw in a template.  */
      if (processing_template_decl)
        {
          *non_constant_p = true;
          return NULL_TREE;
        }
    This patch uses the same thing (i.e. avoid folding even non-dependent
    metafn calls that would need finish_compound_literal during
    processing_template_decl) to fix this.
    I think in both cases it is fine to defer the constant evaluation,
    the return type from those metafns is not dependent (std::meta::info
    in the reflect_constant_array case, std::vector <std::meta::info>
    otherwise).
    
    2026-07-03  Jakub Jelinek  <[email protected]>
    
            PR c++/126036
            * reflect.cc (get_range_elts): Avoid calling finish_compound_literal
            when processing_template_decl, instead set *non_constant_p and
            return NULL_TREE.
            (process_metafunction): Likewise.
    
            * g++.dg/reflect/pr126036.C: New test.
    
    Reviewed-by: Jason Merrill <[email protected]>
    (cherry picked from commit a55bba03ab13df7140bcf4edd97481e584687d00)

Diff:
---
 gcc/cp/reflect.cc                       | 14 ++++++++++++++
 gcc/testsuite/g++.dg/reflect/pr126036.C | 21 +++++++++++++++++++++
 2 files changed, 35 insertions(+)

diff --git a/gcc/cp/reflect.cc b/gcc/cp/reflect.cc
index cc26ede2e443..58795cfd6bf1 100644
--- a/gcc/cp/reflect.cc
+++ b/gcc/cp/reflect.cc
@@ -685,6 +685,12 @@ get_range_elts (location_t loc, const constexpr_ctx *ctx, tree call, int n,
       }
     if (kind == REFLECT_CONSTANT_ARRAY && sz == 0)
       {
+	/* Don't call finish_compound_literal in a template.  */
+	if (processing_template_decl)
+	  {
+	    *non_constant_p = true;
+	    return NULL_TREE;
+	  }
 	/* Return std::array <valuet, 0> {}.  */
 	tree args = make_tree_vec (2);
 	TREE_VEC_ELT (args, 0) = valuet;
@@ -8007,6 +8013,14 @@ process_metafunction (const constexpr_ctx *ctx, tree fun, tree call,
   if (check_metafn_return_type (loc, METAFN_KIND_RET (minfo), rettype,
 				non_constant_p))
     return NULL_TREE;
+  /* Don't call get_vector_of_info_elts (for any metafn which returns
+     vector<info>) in a template.  */
+  if (processing_template_decl
+      && METAFN_KIND_RET (minfo) == METAFN_KIND_RET_VECTOR_INFO)
+    {
+      *non_constant_p = true;
+      return NULL_TREE;
+    }
   for (int argno = 0; argno < 3; ++argno)
     switch (METAFN_KIND_ARG (minfo, argno))
       {
diff --git a/gcc/testsuite/g++.dg/reflect/pr126036.C b/gcc/testsuite/g++.dg/reflect/pr126036.C
new file mode 100644
index 000000000000..ad99aba37d94
--- /dev/null
+++ b/gcc/testsuite/g++.dg/reflect/pr126036.C
@@ -0,0 +1,21 @@
+// PR c++/126036
+// { dg-do compile { target c++26 } }
+// { dg-additional-options "-freflection" }
+
+#include <meta>
+
+namespace A { int a; };
+
+template <int N>
+void
+foo ()
+{
+  constexpr auto m = std::meta::members_of (^^A, std::meta::access_context::unchecked ());
+  // { dg-error "is not a constant expression because it refers to a result of 'operator new'" "" { target *-*-* } .-1 }
+}
+
+void
+bar ()
+{
+  foo <42> ();
+}
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.