https://gcc.gnu.org/g:3073ae7fa70b29a495831359cc31d38ba1541d73

commit r16-4754-g3073ae7fa70b29a495831359cc31d38ba1541d73
Author: David Faust <[email protected]>
Date:   Tue Oct 28 11:13:25 2025 -0700

    dwarf: handle repeated decl with different btf_decl_tags [PR122248]
    
    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.
    
            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.

Diff:
---
 gcc/dwarf2out.cc                                   | 16 +++++-----
 .../gcc.dg/debug/dwarf2/dwarf-btf-decl-tag-4.c     | 28 +++++++++++++++++
 .../gcc.dg/debug/dwarf2/dwarf-btf-decl-tag-5.c     | 35 ++++++++++++++++++++++
 .../gcc.dg/debug/dwarf2/dwarf-btf-decl-tag-6.c     | 24 +++++++++++++++
 4 files changed, 95 insertions(+), 8 deletions(-)

diff --git a/gcc/dwarf2out.cc b/gcc/dwarf2out.cc
index a817c69c95af..ac39cf51f747 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 000000000000..6fdcdc6e864c
--- /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 000000000000..c7cb60ca986c
--- /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 000000000000..dd89d1142b9a
--- /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 } } */

Reply via email to