On Tue, 5 May 2026, Jason Merrill wrote:
> 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.
In that lambda case, where TYPE_FIELDS is set but TYPE_COMPLETE_P is
false, we won't always return unknonwn, we could return true if one of
its TYPE_FIELDS is consteval-only.
>
> Jason
>
>