On Tue, Mar 10, 2026 at 07:58:55AM +0100, Jakub Jelinek wrote:
> Hi!
>
> https://eel.is/c++draft/meta.reflection#annotation-4
> testcase also contains
> [[=1]] int x, y;
> static_assert(annotations_of(^^x)[0] == annotations_of(^^y)[0]);
> so in case of an annotation shared by multiple declarations we need
> to compare the TREE_VALUE of the attributes (which is shared in that
> case) rather than the TREE_LIST with that TREE_VALUE and TREE_PURPOSE
> being "internal ":"annotation ".
> For mangling we already handle it right:
> if (eval_is_annotation (h, kind) == boolean_true_node)
> {
> strcpy (prefix, "an");
> if (TREE_PURPOSE (TREE_VALUE (h)) == NULL_TREE)
> TREE_PURPOSE (TREE_VALUE (h))
> = build_int_cst (integer_type_node, annotation_idx++);
> return TREE_PURPOSE (TREE_VALUE (h));
> }
> so the annotation index is stored on TREE_PURPOSE of the TREE_VALUE,
> so in shared annotation like the above it will have the same index
> in both cases.
>
> Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?
>
> When I was adding further tests for this, I've noticed that we don't
> handle correctly
> [[=1]] int x [[=2]], y [[=3]];
> because the attributes list which is shared is clearly added as a shared
> tail of the other attributes. For now this is commented out in the
> test, will try to deal with it somehow incrementally.
>
> 2026-03-10 Jakub Jelinek <[email protected]>
>
> PR c++/124399
> * reflect.cc (compare_reflections): For REFLECT_ANNOTATION, compare
> TREE_VALUE of lhs and rhs instead of lhs and rhs.
>
> * g++.dg/reflect/annotations12.C: Add further tests.
>
> --- gcc/cp/reflect.cc.jj 2026-03-09 11:04:26.056073667 +0100
> +++ gcc/cp/reflect.cc 2026-03-09 11:41:58.060768044 +0100
> @@ -8334,7 +8334,7 @@ compare_reflections (tree lhs, tree rhs)
> TREE_VEC_ELT (rhs, 3))
> && TREE_VEC_ELT (lhs, 4) == TREE_VEC_ELT (rhs, 4));
> else if (lkind == REFLECT_ANNOTATION)
> - return lhs == rhs;
> + return TREE_VALUE (lhs) == TREE_VALUE (rhs);
We can't use cp_tree_equal because of
struct [[=42, =42.0f]] S1;
struct [[=42, =40]] S2;
static_assert (annotations_of (^^S1)[0] != annotations_of (^^S2)[0]);
where cp_tree_equal would compare them ==.
So, patch LGTM.
> else if (TYPE_P (lhs) && TYPE_P (rhs))
> {
> /* Given "using A = int;", "^^int != ^^A" should hold. */
> --- gcc/testsuite/g++.dg/reflect/annotations12.C.jj 2026-03-09
> 12:10:39.212043644 +0100
> +++ gcc/testsuite/g++.dg/reflect/annotations12.C 2026-03-09
> 11:52:51.332668039 +0100
> @@ -11,3 +11,15 @@ constexpr std::meta::info a1 = annotatio
> constexpr std::meta::info a2 = annotations_of (^^D <char>)[0];
> static_assert (a1 != a2);
> static_assert (constant_of (a1) == constant_of (a2));
> +
> +[[=1]] int x, y;
> +static_assert (annotations_of (^^x)[0] == annotations_of (^^y)[0]);
> +int z [[=2]], w [[=2]];
> +static_assert (annotations_of (^^z)[0] != annotations_of (^^w)[0]);
> +[[=3]] int u [[=3]], v [[=3]];
> +static_assert ((annotations_of (^^u)[0] == annotations_of (^^v)[0])
> + != (annotations_of (^^u)[1] == annotations_of (^^v)[1]));
> +//static_assert (annotations_of (^^u)[0] == annotations_of (^^v)[0]);
> +//static_assert (annotations_of (^^u)[1] != annotations_of (^^v)[1]);
> +static_assert (annotations_of (^^u)[0] != annotations_of (^^u)[1]);
> +static_assert (annotations_of (^^v)[0] != annotations_of (^^v)[1]);
>
> Jakub
>
Marek