https://gcc.gnu.org/g:cf63e47257ade5ec921fd090b6b925322f7a9ebf
commit r16-8534-gcf63e47257ade5ec921fd090b6b925322f7a9ebf Author: Marek Polacek <[email protected]> Date: Wed Mar 18 17:51:35 2026 -0400 c++/reflection: allow fns/arrays as annotation values [PR124177] With an annotation like [[=func]] gcc ends up calling handle_annotation_attribute with TREE_VALUE (args) being a VIEW_CONVERT_EXPR, whose type is a FUNCTION_TYPE. That kind of annotation value should be decayed before checking if the type is structural. PR c++/124177 gcc/cp/ChangeLog: * tree.cc (handle_annotation_attribute): Decay annotation values. Turn if !type_dependent_expression_p into an assert. gcc/testsuite/ChangeLog: * g++.dg/reflect/annotations18.C: New test. Co-authored-by: Boris Staletic <[email protected]> Reviewed-by: Jason Merrill <[email protected]> Diff: --- gcc/cp/tree.cc | 46 ++++++++++++++++------------ gcc/testsuite/g++.dg/reflect/annotations18.C | 17 ++++++++++ 2 files changed, 43 insertions(+), 20 deletions(-) diff --git a/gcc/cp/tree.cc b/gcc/cp/tree.cc index ff2e78cd89cf..15dc8025f1be 100644 --- a/gcc/cp/tree.cc +++ b/gcc/cp/tree.cc @@ -5920,32 +5920,38 @@ handle_annotation_attribute (tree *node, tree ARG_UNUSED (name), *no_add_attrs = true; return NULL_TREE; } - if (!type_dependent_expression_p (TREE_VALUE (args))) + + /* Annotations are treated as late attributes so we shouldn't see + anything type-dependent now. */ + gcc_assert (!type_dependent_expression_p (TREE_VALUE (args))); + /* FIXME We should be using convert_reflect_constant_arg here to + implement std::meta::reflect_constant(constant-expression) + properly, but that introduces new crashes. */ + TREE_VALUE (args) = decay_conversion (TREE_VALUE (args), tf_warning_or_error); + + if (!structural_type_p (TREE_TYPE (TREE_VALUE (args)))) { - if (!structural_type_p (TREE_TYPE (TREE_VALUE (args)))) + auto_diagnostic_group d; + error ("annotation does not have structural type"); + structural_type_p (TREE_TYPE (TREE_VALUE (args)), true); + *no_add_attrs = true; + return NULL_TREE; + } + if (CLASS_TYPE_P (TREE_TYPE (TREE_VALUE (args)))) + { + tree arg = make_tree_vec (1); + tree type = TREE_TYPE (TREE_VALUE (args)); + TREE_VEC_ELT (arg, 0) + = build_stub_type (type, cp_type_quals (type) | TYPE_QUAL_CONST, + /*rvalue=*/false); + if (!is_xible (INIT_EXPR, type, arg)) { auto_diagnostic_group d; - error ("annotation does not have structural type"); - structural_type_p (TREE_TYPE (TREE_VALUE (args)), true); + error ("annotation does not have copy constructible type"); + is_xible (INIT_EXPR, type, arg, /*explain=*/true); *no_add_attrs = true; return NULL_TREE; } - if (CLASS_TYPE_P (TREE_TYPE (TREE_VALUE (args)))) - { - tree arg = make_tree_vec (1); - tree type = TREE_TYPE (TREE_VALUE (args)); - TREE_VEC_ELT (arg, 0) - = build_stub_type (type, cp_type_quals (type) | TYPE_QUAL_CONST, - /*rvalue=*/false); - if (!is_xible (INIT_EXPR, type, arg)) - { - auto_diagnostic_group d; - error ("annotation does not have copy constructible type"); - is_xible (INIT_EXPR, type, arg, /*explain=*/true); - *no_add_attrs = true; - return NULL_TREE; - } - } } if (!processing_template_decl) { diff --git a/gcc/testsuite/g++.dg/reflect/annotations18.C b/gcc/testsuite/g++.dg/reflect/annotations18.C new file mode 100644 index 000000000000..8030960b0b23 --- /dev/null +++ b/gcc/testsuite/g++.dg/reflect/annotations18.C @@ -0,0 +1,17 @@ +// PR c++/124177 +// { dg-do compile { target c++26 } } +// { dg-additional-options "-freflection" } + +#include <meta> + +constexpr int f() { return 42; } +[[=f]] void g() {} + +static_assert (annotations_of (^^g).size () == 1); +static_assert (extract<int(*)()> (annotations_of (^^g)[0])() == 42); + +constexpr int x[5]{}; +[[=x]] void h() {} + +static_assert (annotations_of (^^h).size () == 1); +static_assert (type_of (annotations_of (^^h)[0]) == ^^const int*);
