[v1: https://gcc.gnu.org/pipermail/gcc-patches/2025-October/697210.html
Changed from v1: remove the complicated flag_checking check on the new
versus existing annotation, which wouldn't actually buy us anything at
the end of the day. Reword commentary. ]
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 from each are accumulated in DECL_ATTRIBUTES. The existing
annotation may not be the same as the one being added, since new tags
will be added to the head of the chain.
The proper behavior is to always replace any existing AT_GNU_annotation
to refer to the chain of annotations we have just constructed, whether
the head of that chain is the same or not.
Bootstrapped and tested on x86_64-linux-gnu.
I think this qualifies as obvious, but will leave a few days for
comments before pushing.
PR debug/122248
gcc/
* dwarf2out.cc (gen_btf_tag_dies): Always replace an existing
AT_GNU_annotation on the target die.
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 | 16 ++++-----
.../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, 95 insertions(+), 8 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..ac39cf51f74 100644
--- a/gcc/dwarf2out.cc
+++ b/gcc/dwarf2out.cc
@@ -13842,14 +13842,14 @@ 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. */
- 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);
+ /* Add (or replace) AT_GNU_annotation referring to the annotation DIE.
+ Replacement may happen for example when 'die' is a global variable
+ which has been re-declared multiple times. In any case, the set of
+ input attributes is the one that ought to be reflected. For global
+ variable re-declarations which add additional decl tags, they will
+ have been accumulated in the variable's DECL_ATTRIBUTES for us. */
+ remove_AT (die, DW_AT_GNU_annotation);
+ add_AT_die_ref (die, DW_AT_GNU_annotation, tag_die);
}
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 } } */
--
2.51.0