On Tue, Mar 31, 2026 at 04:27:32PM -0400, Jason Merrill wrote:
> > @@ -5874,17 +5922,38 @@ eval_data_member_spec (location_t loc, c
> >                             "alignment is smaller than alignment_of",
> >                             fun, non_constant_p, jump_target);
> >       }
> > -  tree ret = make_tree_vec (5);
> > +  for (int i = 0; i < TREE_VEC_LENGTH (args[5]); ++i)
> > +    {
> > +      tree r = REFLECT_EXPR_HANDLE (TREE_VEC_ELT (args[5], i));
> > +      reflect_kind kind = REFLECT_EXPR_KIND (TREE_VEC_ELT (args[5], i));
> > +      if (!has_type (r, kind))
> > +   return throw_exception (loc, ctx, "reflection does not have a type",
> > +                           fun, non_constant_p, jump_target);
> > +      tree type = type_of (r, kind);
> > +      if (eval_is_array_type (loc, type) == boolean_true_node
> > +     || eval_is_object_type (loc, type) == boolean_false_node)
> > +   return throw_exception (loc, ctx, "reflection does not have "
> > +                                     "non-array object type",
> > +                           fun, non_constant_p, jump_target);
> 
> For these errors it might be useful to use the location of element i rather
> than of the whole data member spec?  OK either way.

The loc is what is returned from std::meta::exception's where () method.
And right now we consistently use there the location_t of the CALL_EXPR or
AGGR_INIT_EXPR that invoked the metafunction which throws, I think it would
be weird to use something else in a few exceptions.

> Incidentally, it seems like we don't currently check these exceptions at all
> in the testsuite?

For this particular patch, I check just that exceptions are thrown, but not
the exact message.
+consteval bool
+valid_data_member_spec (info type, data_member_options opts)
+{
+  try { data_member_spec (type, opts); }
+  catch (std::meta::exception &) { return false; }
+  return true;
+}
and
+static_assert (!valid_data_member_spec (^^int, { .name = "a", .annotations = { 
^^:: } }));
+static_assert (!valid_data_member_spec (^^int, { .name = "a", .annotations = { 
^^foo } }));
+static_assert (!valid_data_member_spec (^^int, { .name = "a", .annotations = { 
^^arr } }));
+static_assert (!valid_data_member_spec (^^int, { .name = "a", .annotations = { 
^^arr } }));
+static_assert (!valid_data_member_spec (^^int, { .bit_width = 0, .annotations 
= { ^^i } }));
in the patch.  This is used similarly in quite a few tests, other tests just
use something that throws and check for the mesasge using dg-error, but
some of them also without the exact message, e.g.
static_assert ((rank (^^i), true)); // { dg-error "non-constant|uncaught 
exception" }
others like
static_assert (current_function () != ^^::);            // { dg-error "uncaught 
exception of type 'std::meta::exception'; 'what\\\(\\\)': 'current scope does 
not represent a function'" }
and some check all the details, like:
  try
    {
      is_class_type (x);
    }
  catch (std::meta::exception &ex)
    {
      std::string_view what = ex.what ();
      info from = ex.from ();
      std::source_location loc = ex.where ();
      if (loc.line () != std::source_location::current ().line () - 7
          || from != ^^std::meta::is_class_type
          || what != "reflection does not represent a type"
          || ex.u8what () != u8"reflection does not represent a type")
        return false;
      return true;
    }

        Jakub

Reply via email to