On 7/2/26 6:42 PM, Marek Polacek wrote:
On Thu, Jul 02, 2026 at 01:17:12PM -0400, Jason Merrill wrote:
On 7/2/26 12:49 PM, Marek Polacek wrote:
Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?
I'm not sure about backporting this.  It might make future 16 backports
easier.

-- >8 --
This PR laments that our meta::is_trivially_copyable_type gives the wrong
result when its argument is a reflection of an uninstantiated template,
because its TYPE_HAS_* flags haven't been properly set.  They are set in
finish_struct_1, called while instantiating the template.

This led to a much broader problem: we're not checking Preconditions in
[meta.unary.prop] and Comments in [meta.rel].  Jason pointed out to me
that check_trait_type and its KIND parameter already does this kind of
checking; our Reflection code just wasn't using it fully.  With this patch
we give an error when finish_trait_expr returns an error node.
finish_trait_expr and check_trait_type need a complain parameter.  Many
metafuncions weren't using the finish_trait_expr mechanism as they
should.  The rest of the patch is adding the extra arguments.

I found PR126073, XFAILd for now.

+eval_type_trait (location_t loc, const constexpr_ctx *ctx, tree type1,
+                tree type2, cp_trait_kind kind, bool *non_constant_p,
+                tree fun)
   {
-  tree r = finish_trait_expr (loc, kind, type1, type2);
-  gcc_checking_assert (r != error_mark_node);
+  tree r = finish_trait_expr (loc, kind, type1, type2, tf_none);
+  if (r == error_mark_node)
+    {
+      /* [meta.reflection.traits]/3.2: Otherwise, if the instantiation of S
+        would result in undefined behavior due to dependence on an incomplete
+        type, then the call is not a constant subexpression.  */
+      if (!cxx_constexpr_quiet_p (ctx))
+       {
+         auto_diagnostic_group d;
+         error_at (loc, "type trait %qE preconditions not satisfied", fun);
+         inform (loc, "argument has a type that cannot be completed");

Since the type in question is probably type1 or type2, we should usually be
able to identify it and cxx_incomplete_type_diagnostic.

I added a search for the incomplete type.  Since a lot of the preconditions
talk about "complete type, cv void, or array of unknown bound", I'm using
COMPLETE_OR_VOID_TYPE_P + array_of_unknown_bound_p not to complain about
the wrong argument.  The diagnostic now looks like this:

type_trait17.C:13:48: error: type trait 'std::meta::is_trivially_copyable_type' 
preconditions not satisfied
    13 | constexpr bool b0 = is_trivially_copyable_type (^^S<int>);    // { dg-error 
"invalid use of incomplete type" }
       |                     ~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~
type_trait17.C:13:48: note: invalid use of incomplete type 'struct S<int>'
type_trait17.C:9:8: note: declaration of 'struct S<int>'
     9 | struct S;
       |        ^

@@ -14286,10 +14286,13 @@ trait_expr_value (cp_trait_kind kind, tree type1, 
tree type2)
      If TYPE is a non-union class type, it must be complete.
      When KIND == 4:
-   If TYPE is a class type, it must be complete.  */
+   If TYPE is a class type, it must be complete.
+
+   If COMPLAIN is not tf_none, we emit error messages and return false only
+   if -fpermissive wasn't specified.  */

I might phrase this as "we permerror and return false if that doesn't
produce a hard error".

Done.

Tested dg.exp.

OK.

Jason

Reply via email to