On Mon, 29 Jun 2026 at 12:06, Jonathan Wakely <[email protected]> wrote:
>
> On Fri, 26 Jun 2026 at 18:46, Jason Merrill <[email protected]> wrote:
> >
> > On 6/26/26 12:17 PM, Marek Polacek wrote:
> > > Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk/16?
> > >
> > > -- >8 --
> > > Our meta::is_trivially_copyable_type may give 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.  We can't
> > > call complete_type on all reflection arguments, but that's fine because
> > > only eval_is_trivially_copyable_type needs it.
> > >
> > >       PR c++/125901
> > >
> > > gcc/cp/ChangeLog:
> > >
> > >       * reflect.cc (process_metafunction): Complete type before
> > >       calling eval_is_trivially_copyable_type.
> >
> > Why here rather than in eval_is_trivially_copyable_type?
> >
> > Perhaps trivially_copyable_p should assert that strip_array_types (type)
> > is complete or void, since it cannot give an accurate answer for an
> > incomplete class.
> >
> > I would expect that meta::is_trivially_copyable_type should throw on
> > incomplete type.  More generally I'd expect check_trait_type failures to
> > translate to throw.
> >
> > But oddly, the complete-type requirement column in table
> > https://eel.is/c++draft/meta#tab:meta.unary.prop is titled
> > "preconditions" which doesn't translate to throw under
> > https://eel.is/c++draft/meta#reflection.traits-3 .  It seems to me that
> > the column should instead be "mandates".  Jonathan, what do you think?
>
> I misremembered that we had mode

s/mode/made/


> violating those preconditions
> ill-formed, but that's just what
> https://cplusplus.github.io/LWG/issue2797 wanted to do. That issue was
> resolved by P1285 which just makes it UB.
>
> I agree that for the reflection metafunctions we want this to throw,
> but I'm not sure about changing the type traits. I'll raise this with
> LWG.
>
>
> > > gcc/testsuite/ChangeLog:
> > >
> > >       * g++.dg/reflect/type_trait16.C: New test.
> > > ---
> > >   gcc/cp/reflect.cc                           |  7 ++++
> > >   gcc/testsuite/g++.dg/reflect/type_trait16.C | 37 +++++++++++++++++++++
> > >   2 files changed, 44 insertions(+)
> > >   create mode 100644 gcc/testsuite/g++.dg/reflect/type_trait16.C
> > >
> > > diff --git a/gcc/cp/reflect.cc b/gcc/cp/reflect.cc
> > > index 3d6d24eb23a..03079f7c3a7 100644
> > > --- a/gcc/cp/reflect.cc
> > > +++ b/gcc/cp/reflect.cc
> > > @@ -8311,6 +8311,13 @@ process_metafunction (const constexpr_ctx *ctx, 
> > > tree fun, tree call,
> > >       case METAFN_IS_VOLATILE_TYPE:
> > >         return eval_is_volatile_type (h);
> > >       case METAFN_IS_TRIVIALLY_COPYABLE_TYPE:
> > > +      /* Need to complete the type since we will be looking at the 
> > > TYPE_HAS_*
> > > +      bits.  */
> > > +      if (!complete_type_or_maybe_complain (h, NULL_TREE, 
> > > tf_warning_or_error))
> > > +     {
> > > +       *non_constant_p = true;
> > > +       return NULL_TREE;
> > > +     }
> > >         return eval_is_trivially_copyable_type (h);
> > >       case METAFN_IS_STANDARD_LAYOUT_TYPE:
> > >         return eval_is_standard_layout_type (h);
> > > diff --git a/gcc/testsuite/g++.dg/reflect/type_trait16.C 
> > > b/gcc/testsuite/g++.dg/reflect/type_trait16.C
> > > new file mode 100644
> > > index 00000000000..5fca8658f1c
> > > --- /dev/null
> > > +++ b/gcc/testsuite/g++.dg/reflect/type_trait16.C
> > > @@ -0,0 +1,37 @@
> > > +// PR c++/125901
> > > +// { dg-do compile { target c++26 } }
> > > +// { dg-additional-options "-freflection" }
> > > +
> > > +#include <meta>
> > > +
> > > +template<typename T>
> > > +struct S {
> > > +  T t;
> > > +};
> > > +
> > > +static_assert(is_trivially_copyable_type(^^S<int>));
> > > +static_assert(!is_trivially_copyable_type(^^std::vector<int>));
> > > +static_assert(is_standard_layout_type(^^std::vector<int>));
> > > +static_assert(is_default_constructible_type(^^std::vector<int>));
> > > +static_assert(!is_trivially_default_constructible_type(^^std::vector<int>));
> > > +static_assert(!is_trivially_copy_constructible_type(^^std::vector<int>));
> > > +static_assert(!is_trivially_move_constructible_type(^^std::vector<int>));
> > > +static_assert(is_copy_assignable_type(^^std::vector<int>));
> > > +static_assert(!is_implicit_lifetime_type(^^std::vector<int>));
> > > +static_assert(!has_virtual_destructor(^^std::vector<int>));
> > > +static_assert(!has_unique_object_representations(^^std::vector<int>));
> > > +
> > > +const std::vector<int> vec{};
> > > +const S<int> s{};
> > > +
> > > +static_assert(is_trivially_copyable_type(^^S<int>));
> > > +static_assert(!is_trivially_copyable_type(^^std::vector<int>));
> > > +static_assert(is_standard_layout_type(^^std::vector<int>));
> > > +static_assert(is_default_constructible_type(^^std::vector<int>));
> > > +static_assert(!is_trivially_default_constructible_type(^^std::vector<int>));
> > > +static_assert(!is_trivially_copy_constructible_type(^^std::vector<int>));
> > > +static_assert(!is_trivially_move_constructible_type(^^std::vector<int>));
> > > +static_assert(is_copy_assignable_type(^^std::vector<int>));
> > > +static_assert(!is_implicit_lifetime_type(^^std::vector<int>));
> > > +static_assert(!has_virtual_destructor(^^std::vector<int>));
> > > +static_assert(!has_unique_object_representations(^^std::vector<int>));
> > >
> > > base-commit: ae80ad655d514d7c275b21f5d1ad155793ae4cc0
> >

Reply via email to