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 > >
