]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
c++/reflection: overzealous complete_type in consteval_only_p [PR125280]
authorMarek Polacek <polacek@redhat.com>
Tue, 12 May 2026 21:01:29 +0000 (17:01 -0400)
committerMarek Polacek <polacek@redhat.com>
Wed, 13 May 2026 13:49:33 +0000 (09:49 -0400)
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 <ppalka@redhat.com>
gcc/cp/reflect.cc
gcc/testsuite/g++.dg/reflect/init19.C [new file with mode: 0644]
gcc/testsuite/g++.dg/reflect/type12.C [new file with mode: 0644]
gcc/testsuite/g++.dg/reflect/type13.C [new file with mode: 0644]

index c30ba1582af4ee1decac4f5f880e328f86014445..1880a5ac7f5b9e3257cff62f1941326df66a1018 100644 (file)
@@ -8623,13 +8623,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 ();
 }
@@ -8641,6 +8634,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 (file)
index 0000000..bfebe4c
--- /dev/null
@@ -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 (file)
index 0000000..c066f27
--- /dev/null
@@ -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 (file)
index 0000000..22d2685
--- /dev/null
@@ -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;