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

commit r16-8903-gce1e520ea349ffe18e3bd80ec79029f49efd1984
Author: Marek Polacek <[email protected]>
Date:   Tue May 12 17:01:29 2026 -0400

    c++/reflection: overzealous complete_type in consteval_only_p [PR125280]
    
    This bug report shows that we generate a bogus "has incomplete type"
    error for Element::mData in type12.C with -freflection: consteval_only_p
    attempts to complete Array when finishing mData, but mData uses Element
    which is currently being defined, so we can't complete it yet.  We could
    fix this bogus error by checking can_complete_type_without_circularity
    before calling complete_type in consteval_only_p, but I'm no longer so
    sure that we must call complete_type at all.  This patch removes that
    call.  One consequence of that is that we don't produce the "outside
    a constant-evaluated context" error for C::mData (only when mData is
    defined outside the class as with A::mData above).  This behavior
    matches clang++ though so I'm not too worried about it.
    
    type13.C shows that even without the complete_type we can still get
    to consteval_only_p_walker::walk with a member with erroneous type
    which currently crashes.
    
            PR c++/125280
    
    gcc/cp/ChangeLog:
    
            * reflect.cc (consteval_only_p): Don't complete_type.
            (consteval_only_p_walker::walk): Return false for
            error_mark_node.
    
    gcc/testsuite/ChangeLog:
    
            * g++.dg/reflect/init19.C: New test.
            * g++.dg/reflect/type12.C: New test.
            * g++.dg/reflect/type13.C: New test.
    
    Reviewed-by: Patrick Palka <[email protected]>
    (cherry picked from commit de3a3064f65bb52053d771fa44fb982e8ec80727)

Diff:
---
 gcc/cp/reflect.cc                     | 10 +++-------
 gcc/testsuite/g++.dg/reflect/init19.C | 12 ++++++++++++
 gcc/testsuite/g++.dg/reflect/type12.C | 28 ++++++++++++++++++++++++++++
 gcc/testsuite/g++.dg/reflect/type13.C | 13 +++++++++++++
 4 files changed, 56 insertions(+), 7 deletions(-)

diff --git a/gcc/cp/reflect.cc b/gcc/cp/reflect.cc
index 71794529e5f8..2be4ba6d2a8e 100644
--- a/gcc/cp/reflect.cc
+++ b/gcc/cp/reflect.cc
@@ -8611,13 +8611,6 @@ consteval_only_p (tree t)
   if (dependent_type_p (t))
     return false;
 
-  /* We need the complete type otherwise we'd have no fields for class
-     templates and thus come up with zilch for things like
-       template<typename T>
-       struct X : T { };
-     which could be consteval-only, depending on T.  */
-  t = complete_type (t);
-
   consteval_only_p_walker walker;
   return walker.walk (t).is_true ();
 }
@@ -8629,6 +8622,9 @@ consteval_only_p (tree t)
 tristate
 consteval_only_p_walker::walk (tree t)
 {
+  if (t == error_mark_node)
+    return false;
+
   t = TYPE_MAIN_VARIANT (t);
 
   if (REFLECTION_TYPE_P (t))
diff --git a/gcc/testsuite/g++.dg/reflect/init19.C 
b/gcc/testsuite/g++.dg/reflect/init19.C
new file mode 100644
index 000000000000..bfebe4cf2d72
--- /dev/null
+++ b/gcc/testsuite/g++.dg/reflect/init19.C
@@ -0,0 +1,12 @@
+// PR c++/125280
+// { dg-do compile { target c++26 } }
+// { dg-additional-options "-freflection" }
+
+struct C { decltype(^^::) i; };
+struct N { int i; };
+
+template<typename T>
+struct X : T { };
+
+auto a = X<C>{}; // { dg-error "outside a constant-evaluated context" }
+auto b = X<N>{};
diff --git a/gcc/testsuite/g++.dg/reflect/type12.C 
b/gcc/testsuite/g++.dg/reflect/type12.C
new file mode 100644
index 000000000000..c066f27fb699
--- /dev/null
+++ b/gcc/testsuite/g++.dg/reflect/type12.C
@@ -0,0 +1,28 @@
+// PR c++/125280
+// { dg-do compile { target c++26 } }
+// { dg-additional-options "-freflection" }
+
+template <class T, int N>
+struct Array {
+  T mElements[N];
+};
+
+struct Element {
+  static const Array<Element, 9> mData;
+};
+const Array<Element, 9> Element::mData;
+
+struct CE { decltype(^^::) i; };
+
+struct A {
+  static const Array<CE, 10> mData;
+};
+const Array<CE, 10> A::mData{}; // { dg-error "outside a constant-evaluated 
context" }
+
+struct B {
+  static constexpr Array<CE, 11> mData{};
+};
+
+struct C {
+  static const Array<CE, 12> mData;
+};
diff --git a/gcc/testsuite/g++.dg/reflect/type13.C 
b/gcc/testsuite/g++.dg/reflect/type13.C
new file mode 100644
index 000000000000..22d26852ec95
--- /dev/null
+++ b/gcc/testsuite/g++.dg/reflect/type13.C
@@ -0,0 +1,13 @@
+// PR c++/125280
+// { dg-do compile { target c++26 } }
+// { dg-additional-options "-freflection" }
+
+template <class T, int N>
+struct Array {
+  T mElements[N]; // { dg-error "incomplete type" }
+};
+
+struct Element {
+  static const Array<Element, 10> mData{}; // { dg-error "initialization of 
static data member" }
+};
+const Array<Element, 10> Element::mData;

Reply via email to