> The check in gen_btf_tag_dies which asserted that if the target DIE
> already had an annotation then it must be the same as the one we are
> attempting to add was too strict. It is valid for multiple declarations
> of the same object to appear with different decl_tags, in which case the
> tags are accumulated in the DECL_ATTRIBUTES, but the existing tag may
> not be the same as the one being added. This was not handled correctly
> and led to the ICE reported in the PR.
>
> The more accurate requirement for consistency is that if there is an
> existing chain of annotations, then it is a sub-chain of the one we are
> adding in the current pass. This patch fixes gen_btf_tag_dies to use
> the more accurate check and properly handle the case in the PR.
>
> Bootstrapped and tested on x86_64-linux-gnu.
>
> OK for trunk?
> Thanks
>
> PR debug/122248
>
> gcc/
>
> * dwarf2out.cc (gen_btf_tag_dies): Handle repeated declarations
> of the same object with different decl_tags and improve accuracy
> of the consistency check under flag_checking.
>
> gcc/testsuite/
>
> * gcc.dg/debug/dwarf2/dwarf-btf-decl-tag-4.c: New.
> * gcc.dg/debug/dwarf2/dwarf-btf-decl-tag-5.c: New.
> * gcc.dg/debug/dwarf2/dwarf-btf-decl-tag-6.c: New.
> ---
> gcc/dwarf2out.cc | 27 +++++++++++---
> .../debug/dwarf2/dwarf-btf-decl-tag-4.c | 28 +++++++++++++++
> .../debug/dwarf2/dwarf-btf-decl-tag-5.c | 35 +++++++++++++++++++
> .../debug/dwarf2/dwarf-btf-decl-tag-6.c | 24 +++++++++++++
> 4 files changed, 109 insertions(+), 5 deletions(-)
> create mode 100644 gcc/testsuite/gcc.dg/debug/dwarf2/dwarf-btf-decl-tag-4.c
> create mode 100644 gcc/testsuite/gcc.dg/debug/dwarf2/dwarf-btf-decl-tag-5.c
> create mode 100644 gcc/testsuite/gcc.dg/debug/dwarf2/dwarf-btf-decl-tag-6.c
>
> diff --git a/gcc/dwarf2out.cc b/gcc/dwarf2out.cc
> index a817c69c95a..8fe6e3321e1 100644
> --- a/gcc/dwarf2out.cc
> +++ b/gcc/dwarf2out.cc
> @@ -13843,13 +13843,30 @@ gen_btf_tag_dies (tree attr, dw_die_ref die)
> if (die)
> {
> /* Add AT_GNU_annotation referring to the annotation DIE.
> - It may have already been added, some global declarations are processed
> - twice, but if so it must be the same or we have a bug. */
> + There may be an existing annotation chain, as in the case of global
> + decls which may can processed (and declared) multiple times.
> + Each time a global decl is processed it may have additional
> + decl_tags, but the set should never shrink. */
> dw_die_ref existing = get_AT_ref (die, DW_AT_GNU_annotation);
> if (existing)
> - gcc_checking_assert (existing == tag_die);
> - else
> - add_AT_die_ref (die, DW_AT_GNU_annotation, tag_die);
> + {
> + if (flag_checking)
> + {
> + /* If there is an existing annotation chain, then it must be a
> + sub-chain of this one, i.e. its head must be somewhere in the
> + chain from tag_die. Otherwise we may have a bug. */
> + dw_die_ref d = tag_die;
> + while (d && d != existing)
> + d = get_AT_ref (die, DW_AT_GNU_annotation);
> +
> + gcc_assert (d);
> + }
> +
> + /* Remove the existing annotation and replace it with the new. */
> + remove_AT (die, DW_AT_GNU_annotation);
> + }
> +
> + add_AT_die_ref (die, DW_AT_GNU_annotation, tag_die);
tag_die here contains the accummulated tags?
> }
>
> return tag_die;
> diff --git a/gcc/testsuite/gcc.dg/debug/dwarf2/dwarf-btf-decl-tag-4.c
> b/gcc/testsuite/gcc.dg/debug/dwarf2/dwarf-btf-decl-tag-4.c
> new file mode 100644
> index 00000000000..6fdcdc6e864
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/debug/dwarf2/dwarf-btf-decl-tag-4.c
> @@ -0,0 +1,28 @@
> +/* Test DWARF generation for decl_tags on global decls appearing multiple
> + times with different decl_tags. PR122248. */
> +/* { dg-do compile } */
> +/* { dg-options "-gdwarf -dA" } */
> +
> +#define __tag1 __attribute__((btf_decl_tag ("tag1")))
> +#define __tag2 __attribute__((btf_decl_tag ("tag2")))
> +#define __tag3 __attribute__((btf_decl_tag ("tag3")))
> +#define __tag4 __attribute__((btf_decl_tag ("tag4")))
> +
> +int foo __tag1;
> +int foo __tag2;
> +
> +/* Result: foo has __tag1 and __tag2. */
> +
> +int bar __tag3;
> +int bar;
> +
> +/* Result: bar has __tag3. */
> +
> +int baz;
> +int baz __tag4;
> +
> +/* Result: baz has __tag4. */
> +
> +/* { dg-final { scan-assembler-times "DIE \\(\[^\n\]*\\)
> DW_TAG_GNU_annotation" 4 } } */
> +/* { dg-final { scan-assembler-times " DW_AT_GNU_annotation" 4 } } */
> +
> diff --git a/gcc/testsuite/gcc.dg/debug/dwarf2/dwarf-btf-decl-tag-5.c
> b/gcc/testsuite/gcc.dg/debug/dwarf2/dwarf-btf-decl-tag-5.c
> new file mode 100644
> index 00000000000..c7cb60ca986
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/debug/dwarf2/dwarf-btf-decl-tag-5.c
> @@ -0,0 +1,35 @@
> +/* Test DWARF generation for decl_tags on global decls appearing multiple
> + times with different decl_tags. PR122248. */
> +/* { dg-do compile } */
> +/* { dg-options "-gdwarf -dA" } */
> +
> +#define __tag1 __attribute__((btf_decl_tag ("tag1")))
> +#define __tag2 __attribute__((btf_decl_tag ("tag2")))
> +#define __tag3 __attribute__((btf_decl_tag ("tag3")))
> +
> +struct S
> +{
> + int x;
> + char c;
> +};
> +
> +extern struct S foo __tag1;
> +struct S foo __tag2;
> +
> +/* Result: non-completing variable DIE for 'foo' has tag1, and the
> + completing DIE (with AT_specification) for 'foo' has tag2 -> tag1. */
> +
> +extern int a __tag3;
> +int a;
> +
> +/* Result: non-completing variable DIE for a has tag3, and the
> + completing DIE (with AT_specification) for 'a' also refers to tag3. */
> +
> +/* { dg-final { scan-assembler-times "DIE \\(\[^\n\]*\\)
> DW_TAG_GNU_annotation" 3 } } */
> +
> +/* 5 AT_GNU annotations:
> + - foo -> tag1
> + - foo -> tag2 -> tag1
> + - a -> tag3
> + - a -> tag3 */
> +/* { dg-final { scan-assembler-times " DW_AT_GNU_annotation" 5 } } */
> diff --git a/gcc/testsuite/gcc.dg/debug/dwarf2/dwarf-btf-decl-tag-6.c
> b/gcc/testsuite/gcc.dg/debug/dwarf2/dwarf-btf-decl-tag-6.c
> new file mode 100644
> index 00000000000..dd89d1142b9
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/debug/dwarf2/dwarf-btf-decl-tag-6.c
> @@ -0,0 +1,24 @@
> +/* Test DWARF generation for decl_tags on global decls appearing multiple
> + times with different decl_tags. PR122248. */
> +/* { dg-do compile } */
> +/* { dg-options "-gdwarf -dA" } */
> +
> +#define __tag1 __attribute__((btf_decl_tag ("tag1")))
> +#define __tag2 __attribute__((btf_decl_tag ("tag2")))
> +#define __tag3 __attribute__((btf_decl_tag ("tag3")))
> +
> +__tag1
> +extern int
> +do_thing (int);
> +
> +__tag2
> +__tag3
> +int
> +do_thing (int x)
> +{
> + return x * x;
> +}
> +
> +/* Result: do_thing has all 3 tags. */
> +/* { dg-final { scan-assembler-times "DIE \\(\[^\n\]*\\)
> DW_TAG_GNU_annotation" 3 } } */
> +/* { dg-final { scan-assembler-times " DW_AT_GNU_annotation" 3 } } */