On Tue, Mar 10, 2026 at 07:51:53AM +0100, Jakub Jelinek wrote: > Hi! > > The following testcases FAIL (annotations12.C is directly from > https://eel.is/c++draft/meta.reflection#annotation-4 ) because it is > called on a reflection of class template instantiation which has been > just looked up but not yet completed, and in that case it doesn't > have any attributes instantiated. > Only complete_type instantiates those. Unlike the second argument > of annotations_of_with_type where the standard requires is_complete_type, > in this case it doesn't, so it is fine if one uses > struct S; > static_assert (annotations_of (^^S).size () == 0); > but I'm afraid we need to instantiate the argument to get the annotations. > > Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?
This patch also fixes constant_of5.C (except line 84), which is awesome. Please also adjust that test. Otherwise looks good to me, thanks. > 2026-03-10 Jakub Jelinek <[email protected]> > > PR c++/124399 > * reflect.cc (eval_annotations_of): Call complete_type on r if it > is a type. > > * g++.dg/reflect/annotations3.C: Uncomment 3 test lines. > * g++.dg/reflect/annotations12.C: New test. > * g++.dg/reflect/constant_of6.C: Remove dg-error directive. > * g++.dg/reflect/extract6.C: Remove 2 dg-error directives. > > --- gcc/cp/reflect.cc.jj 2026-03-06 14:25:25.978299299 +0100 > +++ gcc/cp/reflect.cc 2026-03-09 11:04:26.056073667 +0100 > @@ -3800,6 +3800,7 @@ eval_annotations_of (location_t loc, con > } > else if (TYPE_P (r)) > { > + complete_type (r); > if (typedef_variant_p (r)) > r = DECL_ATTRIBUTES (TYPE_NAME (r)); > else > --- gcc/testsuite/g++.dg/reflect/annotations3.C.jj 2026-01-15 > 16:33:47.004726583 +0100 > +++ gcc/testsuite/g++.dg/reflect/annotations3.C 2026-03-09 > 11:05:35.695889229 +0100 > @@ -41,9 +41,9 @@ static_assert (type_of (a0) == ^^int); > template <class T> > struct [[=42]] D {}; > > -//constexpr std::meta::info a1 = annotations_of (^^D<int>)[0]; > -//constexpr std::meta::info a2 = annotations_of (^^D<char>)[0]; > -//static_assert (is_annotation (a1) && is_annotation (a2)); > +constexpr std::meta::info a1 = annotations_of (^^D<int>)[0]; > +constexpr std::meta::info a2 = annotations_of (^^D<char>)[0]; > +static_assert (is_annotation (a1) && is_annotation (a2)); > > [[=1, =2L, =3.0, =4U, =5U, =6L, =7U]] int y; > static_assert (annotations_of (^^y).size () == 7); > --- gcc/testsuite/g++.dg/reflect/annotations12.C.jj 2026-03-09 > 11:05:49.720650693 +0100 > +++ gcc/testsuite/g++.dg/reflect/annotations12.C 2026-03-09 > 11:16:59.402260389 +0100 > @@ -0,0 +1,13 @@ > +// PR c++/124399 > +// { dg-do compile { target c++26 } } > +// { dg-options "-freflection" } > + > +#include <meta> > + > +template <class T> > + struct [[=42]] D { }; > + > +constexpr std::meta::info a1 = annotations_of (^^D <int>)[0]; > +constexpr std::meta::info a2 = annotations_of (^^D <char>)[0]; > +static_assert (a1 != a2); > +static_assert (constant_of (a1) == constant_of (a2)); > --- gcc/testsuite/g++.dg/reflect/constant_of6.C.jj 2026-01-15 > 16:33:47.005097993 +0100 > +++ gcc/testsuite/g++.dg/reflect/constant_of6.C 2026-03-09 > 11:15:52.006406700 +0100 > @@ -17,4 +17,3 @@ struct [[=[:constant_of (annotations_of > > constexpr auto y = constant_of (annotations_of (^^bar<^^::fn>)[0]); > constexpr auto z = constant_of (annotations_of (^^Y<^^::S>)[0]); > -// { dg-error "call to non-.constexpr." "" { target *-*-* } 0 } > --- gcc/testsuite/g++.dg/reflect/extract6.C.jj 2026-01-15 > 16:33:47.008097942 +0100 > +++ gcc/testsuite/g++.dg/reflect/extract6.C 2026-03-09 11:16:33.271704833 > +0100 > @@ -15,6 +15,5 @@ template<info R> > struct [[=[:constant_of (annotations_of (R)[0]):]]] TCls {}; > > static_assert (extract<int>(annotations_of (^^TFn<^^::fn>)[0]) == 1); > -static_assert (extract<int>(annotations_of (^^TCls<^^::S>)[0]) == 3); // { > dg-error "non-constant" } > +static_assert (extract<int>(annotations_of (^^TCls<^^::S>)[0]) == 3); > static_assert (extract<int>(annotations_of (^^fn)[0]) == 1); > -// { dg-error "call to non-.constexpr." "" { target *-*-* } 0 } > > Jakub > Marek
