Patchwork Fix PR debug/45088

login
register
mail settings
Submitter Dodji Seketeli
Date Dec. 16, 2010, 4:09 p.m.
Message ID <m37hf9hf7k.fsf@redhat.com>
Download mbox | patch
Permalink /patch/75776/
State New
Headers show

Comments

Dodji Seketeli - Dec. 16, 2010, 4:09 p.m.
Jason Merrill <jason@redhat.com> writes:

> On 12/14/2010 01:26 PM, Dodji Seketeli wrote:
>> +  if (is_injected_class_name (TYPE_NAME (type)))
>> +    type = DECL_ORIGINAL_TYPE (TYPE_NAME (type));
>
> Yes, that should do the trick, but I might still tweak it a bit.
>
> The problematic case is when is_redundant_typedef (decl) &&
> DECL_ORIGINAL_TYPE (decl) are both true; gen_decl_die assumes that
> these two conditions can't occur together, which is why things break.
> This change will make that assumption valid again, but I'd feel better
> about using that condition directly (that is, if (is_redundant_typedef
> (TYPE_NAME (type)) && DECL_ORIGINAL_TYPE (TYPE_NAME (type))) rather
> than assuming that the injected-class-name is the only redundant
> typedef for which this can happen.

OK.

> I think we should also add an explicit assert to gen_decl_die in the
> is_redundant_typedef case to make sure that DECL_ORIGINAL_TYPE is
> NULL_TREE.

That assert would be violated because gen_decl_die can be called e.g
from gen_member_die with the injected-class-name typedef in argument as
it is a member of the class. In that case, gen_decl_die sees the
injected-class-name, considers it as redundant typedef, tries to
generate debug info for its typedef variant type and at that point
gen_type_die_with_usage handles it correctly.

I have made and tested the first change you suggested about though.
Jason Merrill - Dec. 16, 2010, 8:06 p.m.
OK.

Jason

Patch

diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c
index c985527..1fa3300 100644
--- a/gcc/dwarf2out.c
+++ b/gcc/dwarf2out.c
@@ -20251,13 +20251,23 @@  gen_tagged_type_die (tree type,
 
 static void
 gen_type_die_with_usage (tree type, dw_die_ref context_die,
-				enum debug_info_usage usage)
+			 enum debug_info_usage usage)
 {
   struct array_descr_info info;
 
   if (type == NULL_TREE || type == error_mark_node)
     return;
 
+  if (TYPE_NAME (type) != NULL_TREE
+      && TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
+      && is_redundant_typedef (TYPE_NAME (type))
+      && DECL_ORIGINAL_TYPE (TYPE_NAME (type)))
+    /* The DECL of this type is a typedef we don't want to emit debug
+       info for but we want debug info for its underlying typedef.
+       This can happen for e.g, the injected-class-name of a C++
+       type.  */
+    type = DECL_ORIGINAL_TYPE (TYPE_NAME (type));
+
   /* If TYPE is a typedef type variant, let's generate debug info
      for the parent typedef which TYPE is a type of.  */
   if (typedef_variant_p (type))
diff --git a/gcc/testsuite/g++.dg/debug/dwarf2/self-ref-1.C b/gcc/testsuite/g++.dg/debug/dwarf2/self-ref-1.C
new file mode 100644
index 0000000..81bcb27
--- /dev/null
+++ b/gcc/testsuite/g++.dg/debug/dwarf2/self-ref-1.C
@@ -0,0 +1,28 @@ 
+// Origin: PR debug/45088
+// { dg-do compile }
+// { dg-options "-g -dA" }
+// { dg-final { scan-assembler-times "\[^\n\r\]*\\(DIE\[^\n\r\]*DW_TAG_pointer_type\\)\[\n\r\]{1,2}\[^\n\r\]*DW_AT_byte_size\[\n\r\]{1,2}\[^\n\r\]*DW_AT_type" 4 } }
+
+struct A
+{
+    virtual ~A();
+};
+
+struct B : public A
+{
+    virtual ~B(){}
+};
+
+struct C : public B
+{
+    A* a1;
+};
+
+int
+main()
+{
+    C c;
+    c.a1 = 0;
+    return 0;
+}
+
diff --git a/gcc/testsuite/g++.dg/debug/dwarf2/self-ref-2.C b/gcc/testsuite/g++.dg/debug/dwarf2/self-ref-2.C
new file mode 100644
index 0000000..b1c5401
--- /dev/null
+++ b/gcc/testsuite/g++.dg/debug/dwarf2/self-ref-2.C
@@ -0,0 +1,29 @@ 
+// Origin: PR debug/45088
+// { dg-do compile }
+// { dg-options "-g -dA" }
+// { dg-final { scan-assembler-times "\[^\n\r\]*\\(DIE\[^\n\r\]*DW_TAG_pointer_type\\)\[\n\r\]{1,2}\[^\n\r\]*DW_AT_byte_size\[\n\r\]{1,2}\[^\n\r\]*DW_AT_type" 4 } }
+
+template<class T>
+struct A
+{
+    virtual ~A();
+};
+
+struct B : public A<int>
+{
+    virtual ~B(){}
+};
+
+struct C : public B
+{
+    A<int>* a1;
+};
+
+int
+main()
+{
+    C c;
+    c.a1 = 0;
+    return 0;
+}
+