On 5/5/26 4:34 PM, Patrick Palka wrote:
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 unknown, we could return true if one of
its TYPE_FIELDS is consteval-only.
Hmm, we currently return true but don't cache it? So we could be
returning consteval-only about a type that later turns out not to be.
That doesn't seem better to me than just returning unknown.
Jason