On 5/5/26 3:53 PM, Patrick Palka wrote:
On Tue, 5 May 2026, Jason Merrill wrote:
On 5/5/26 1:20 PM, Patrick Palka wrote:
+/* Recursive workhorse of consteval_only_p.  Returns true if T is
definitely
+   consteval-only, false if it's definitely not, and unknown if we saw an
+   incomplete type and therefore don't know.  */
+
+tristate
+consteval_only_p_walker::walk (tree t)
+{
+  t = TYPE_MAIN_VARIANT (t);
+
+  if (REFLECTION_TYPE_P (t))
+    return true;
+  else if (INDIRECT_TYPE_P (t))
+    return walk (TREE_TYPE (t));
+  else if (TREE_CODE (t) == ARRAY_TYPE)
+    return walk (TREE_TYPE (t));
+  else if (FUNC_OR_METHOD_TYPE_P (t))
+    {
+      tristate r = walk (TREE_TYPE (t));
+      for (tree parm = TYPE_ARG_TYPES (t);
+          parm != NULL_TREE && parm != void_list_node;
+          parm = TREE_CHAIN (parm))
+       {
+         if (r.is_true ())
+           break;
+         r = r || walk (TREE_VALUE (parm));
+       }
+      return r;
+    }
+  else if (RECORD_OR_UNION_TYPE_P (t))
+    {
+      if (tree *slot = hash_map_safe_get (consteval_only_class_cache, t))
+       return *slot == boolean_true_node;
+
+      if (class_seen.add (t))
+       {
+         /* Optimistically assume this already seen consteval-unknown class
is
+            not consteval only, for sake of mutually recursive classes.  */
+         optimistic_p = true;
+         return false;
+       }
+      class_stack.safe_push (t);
+
+      tristate r = COMPLETE_TYPE_P (t) ? false : tristate::unknown ();
+      for (tree member = TYPE_FIELDS (t); member; member = DECL_CHAIN
(member))
+       if (TREE_CODE (member) == FIELD_DECL)
+         {
+           r = r || walk (TREE_TYPE (member));
+           if (r.is_true ())
+             break;
+         }
+
+      if (!COMPLETE_TYPE_P (t))
+       /* Until the type is laid out, we can't trust that its TYPE_FIELDS
+          won't change.  */;

We might move the COMPLETE_TYPE check...

+      else if (r.is_true ())
+       hash_map_safe_put<hm_ggc> (consteval_only_class_cache,
+                                  t, boolean_true_node);
+      else if (r.is_false ()

...into another exception for the is_false case, since I don't think the
TYPE_FIELDS can change in a way that would invalidate is_true().

Sadly, it can! prune_lambda_captures can remove consteval-only
TYPE_FIELDS (corresponding to folded-away captures) before the closure
type has been laid out, so if we'd cache the result now we'd get the
wrong answer after pruning.

Without this second COMPLETE_TYPE_P check we'd get a bogus error in
reflect/reflect_constant_array6.C due to treating the lambda as
consteval even after pruning.

Ah, lambdas, always keeping us on our toes. But then we could skip walking the fields at all if we're going to return unknown no matter what we see.

Jason

Reply via email to