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