On 1/30/26 8:39 AM, Marek Polacek wrote:
On Fri, Jan 30, 2026 at 01:33:46AM +0100, Jakub Jelinek wrote:
On Thu, Jan 29, 2026 at 07:06:52PM -0500, Marek Polacek wrote:
@@ -5953,21 +5961,9 @@ eval_define_aggregate (location_t loc, const 
constexpr_ctx *ctx,
    tree cscope = NULL_TREE, tscope = NULL_TREE;
    for (tree c = TYPE_CONTEXT (CP_DECL_CONTEXT (consteval_block)); c;
         c = get_containing_scope (c))
-    {
-      if (c == type)
-       {
-         auto_diagnostic_group d;
-         error_at (loc, "%<define_aggregate%> evaluated from "
-                        "%<consteval%> block enclosed by %qT being "
-                        "defined", type);
-         inform (DECL_SOURCE_LOCATION (consteval_block),
-                 "%<consteval%> block defined here");
-         return get_reflection_raw (loc, orig_type);
-       }
-      if (cscope == NULL_TREE
-         && (TYPE_P (c) || TREE_CODE (c) == FUNCTION_DECL))
-       cscope = c;
-    }
+    if (cscope == NULL_TREE
+       && (TYPE_P (c) || TREE_CODE (c) == FUNCTION_DECL))
+      cscope = c;

If this is now the sole body of the loop, we can also break;
once we set cscope to non-NULL, because there is no useful
work afterwards.  So make the body
     if (TYPE_P (c) || TREE_CODE (c) == FUNCTION_DECL)
       {
        cscope = c;
         break;
       }
instead?

Yeah, good point.  dg.exp/reflect* passed, ok for trunk?

OK.

-- >8 --
As discussed in
<https://gcc.gnu.org/pipermail/gcc-patches/2026-January/705756.html>,
we should check TYPE_BEING_DEFINED along with COMPLETE_TYPE_P in
eval_define_aggregate.  It seems that with this check added, we don't
need this code anymore:

       if (c == type)
         {
           auto_diagnostic_group d;
           error_at (loc, "%<define_aggregate%> evaluated from "
                          "%<consteval%> block enclosed by %qT being "
                          "defined", type);
          //...
        }

so I'm removing that in this patch.

gcc/cp/ChangeLog:

        * reflect.cc (eval_define_aggregate): Also give an error when
        TYPE_BEING_DEFINED is true for the first argument.  Remove code
        that did the same.

gcc/testsuite/ChangeLog:

        * g++.dg/reflect/define_aggregate3.C: Adjust expected diagnostic.
        * g++.dg/reflect/p2996-21.C: Likewise.
---
  gcc/cp/reflect.cc                             | 26 +++++++++----------
  .../g++.dg/reflect/define_aggregate3.C        | 16 ++++++------
  gcc/testsuite/g++.dg/reflect/p2996-21.C       |  4 +--
  3 files changed, 22 insertions(+), 24 deletions(-)

diff --git a/gcc/cp/reflect.cc b/gcc/cp/reflect.cc
index 78990ce414d..cd83490ca0c 100644
--- a/gcc/cp/reflect.cc
+++ b/gcc/cp/reflect.cc
@@ -5897,6 +5897,14 @@ eval_define_aggregate (location_t loc, const 
constexpr_ctx *ctx,
        *non_constant_p = true;
        return call;
      }
+  if (TYPE_BEING_DEFINED (type))
+    {
+      if (!cxx_constexpr_quiet_p (ctx))
+       error_at (loc, "first %<define_aggregate%> argument is a reflection "
+                      "of a class type %qT being defined", type);
+      *non_constant_p = true;
+      return call;
+    }
    hash_set<tree> nameset;
    for (int i = 0; i < TREE_VEC_LENGTH (rvec); ++i)
      {
@@ -5953,21 +5961,11 @@ eval_define_aggregate (location_t loc, const 
constexpr_ctx *ctx,
    tree cscope = NULL_TREE, tscope = NULL_TREE;
    for (tree c = TYPE_CONTEXT (CP_DECL_CONTEXT (consteval_block)); c;
         c = get_containing_scope (c))
-    {
-      if (c == type)
-       {
-         auto_diagnostic_group d;
-         error_at (loc, "%<define_aggregate%> evaluated from "
-                        "%<consteval%> block enclosed by %qT being "
-                        "defined", type);
-         inform (DECL_SOURCE_LOCATION (consteval_block),
-                 "%<consteval%> block defined here");
-         return get_reflection_raw (loc, orig_type);
-       }
-      if (cscope == NULL_TREE
-         && (TYPE_P (c) || TREE_CODE (c) == FUNCTION_DECL))
+    if (TYPE_P (c) || TREE_CODE (c) == FUNCTION_DECL)
+      {
        cscope = c;
-    }
+       break;
+      }
    for (tree c = TYPE_CONTEXT (type); c; c = get_containing_scope (c))
      {
        if (c == consteval_block)
diff --git a/gcc/testsuite/g++.dg/reflect/define_aggregate3.C 
b/gcc/testsuite/g++.dg/reflect/define_aggregate3.C
index db04a80bbe3..5951f7cf5b3 100644
--- a/gcc/testsuite/g++.dg/reflect/define_aggregate3.C
+++ b/gcc/testsuite/g++.dg/reflect/define_aggregate3.C
@@ -15,8 +15,8 @@ consteval bool foo () { return define_aggregate (^^S2, {}) == 
^^S2; }
  const bool a = foo ();                                        // { dg-error "call 
to consteval function 'foo\\\(\\\)' is not a constant expression" }
struct S3 {
-  consteval {                                          // { dg-message "'consteval' 
block defined here" }
-    define_aggregate (^^S3, {});                       // { dg-error 
"'define_aggregate' evaluated from 'consteval' block enclosed by 'S3' being 
defined" }
+  consteval {
+    define_aggregate (^^S3, {});                       // { dg-error "first 
'define_aggregate' argument is a reflection of a class type .S3. being defined" }
    }
  };
@@ -33,26 +33,26 @@ consteval { template <typename T>
  struct S5 {
-  consteval {                                          // { dg-message "'consteval' 
block defined here" }
-    define_aggregate (^^S5 <T>, {});                     // { dg-error 
"'define_aggregate' evaluated from 'consteval' block enclosed by 'S5<int>' being 
defined" }
+  consteval {
+    define_aggregate (^^S5 <T>, {});                     // { dg-error "first 
'define_aggregate' argument is a reflection of a class type .S5<int>. being defined" }
    }
  };
S5 <int> s5; -consteval bool bar (info x) { return define_aggregate (x, {}) == x; } // { dg-error "'define_aggregate' evaluated from 'consteval' block enclosed by 'S6' being defined" }
+consteval bool bar (info x) { return define_aggregate (x, {}) == x; }  // { dg-error 
"first 'define_aggregate' argument is a reflection of a class type .S6. being 
defined" }
struct S6 {
-  consteval {                                          // { dg-message "'consteval' 
block defined here" }
+  consteval {
      bar (^^S6);
    }
  };
-consteval bool baz (info x) { return define_aggregate (x, {}) == x; } // { dg-error "'define_aggregate' evaluated from 'consteval' block enclosed by 'S7<char>' being defined" }
+consteval bool baz (info x) { return define_aggregate (x, {}) == x; }  // { dg-error 
"first 'define_aggregate' argument is a reflection of a class type .S7<char>. being 
defined" }
template <typename T>
  struct S7 {
-  consteval {                                          // { dg-message "'consteval' 
block defined here" }
+  consteval {
      baz (^^S7 <T>);
    }
  };
diff --git a/gcc/testsuite/g++.dg/reflect/p2996-21.C 
b/gcc/testsuite/g++.dg/reflect/p2996-21.C
index 8a9f7895d59..478be47585e 100644
--- a/gcc/testsuite/g++.dg/reflect/p2996-21.C
+++ b/gcc/testsuite/g++.dg/reflect/p2996-21.C
@@ -7,9 +7,9 @@
  using namespace std::meta;
struct S0 {
-  consteval {                                          // { dg-message "'consteval' 
block defined here" }
+  consteval {
      std::meta::define_aggregate(^^S0, {});            // error: scope 
associated with S0 encloses the consteval block
-  }                                                    // { dg-error "'define_aggregate' 
evaluated from 'consteval' block enclosed by 'S0' being defined" "" { target *-*-* } 
.-1 }
+  }                                                    // { dg-error "first 
'define_aggregate' argument is a reflection of a class type .S0. being defined" "" { 
target *-*-* } .-1 }
  };
struct S1;

base-commit: aeba874068a057c684ef30352e2b209813c88857

Reply via email to