This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: Fix PR debug/45088


Jason Merrill <jason@redhat.com> writes:

> On 12/12/2010 10:04 AM, Dodji Seketeli wrote:
>>     /* 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))
>> +  if (typedef_variant_p (type)
>> +      &&  !is_redundant_typedef (TYPE_NAME (type)))
>
> I would expect this to cause problems when things use both the main
> type and the injected variant, since the two types have different
> TREE_ASM_WRITTEN.

I see.

>  Rather, if type is a redundant typedef, we should
> strip it to get the underlying type.

Okay, the patch below hopefully does that.

Boostrapped and tested on x86_64-unknown-linux-gnu.

-- 
	Dodji

commit 2befd0376755e820b60bf6654689b59a7b9e22cd
Author: Dodji Seketeli <dodji@seketeli.org>
Date:   Thu Nov 11 23:42:51 2010 +0100

    Fix PR debug/45088
    
    gcc/
    	* dwarf2out.c (is_injected_class_name): New function.
    	(gen_type_die_with_usage): Use it. Don't try to generate a typedef
    	DIE for an injected-class-name. Consider its underlying class name
    	instead.
    
    gcc/testsuite/
    
    	* g++.dg/debug/dwarf2/self-ref-1.C: New test.
    	* g++.dg/debug/dwarf2/self-ref-2.C: Likewise.

diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c
index c985527..3c9eb95 100644
--- a/gcc/dwarf2out.c
+++ b/gcc/dwarf2out.c
@@ -6454,6 +6454,7 @@ static void gen_typedef_die (tree, dw_die_ref);
 static void gen_type_die (tree, dw_die_ref);
 static void gen_block_die (tree, dw_die_ref, int);
 static void decls_for_scope (tree, dw_die_ref, int);
+static bool is_injected_class_name (const_tree decl);
 static int is_redundant_typedef (const_tree);
 static bool is_naming_typedef_decl (const_tree);
 static inline dw_die_ref get_context_die (tree);
@@ -20251,13 +20252,21 @@ 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;
 
+  /* The C++ FE uses a special typedef variant to represent the
+     injected-class-name of a type. Letting this through confuses us
+     because we'd consider this typedef as bloat and won't generate
+     debug info for it. What we really want is the underlying type of
+     the injected-class-name.  */
+  if (is_injected_class_name (TYPE_NAME (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))
@@ -20567,6 +20576,22 @@ decls_for_scope (tree stmt, dw_die_ref context_die, int depth)
     gen_block_die (subblocks, context_die, depth + 1);
 }
 
+/* Return TRUE if DECL is a C++ injected-class-name.  */
+
+static inline bool
+is_injected_class_name (const_tree decl)
+{
+  if (is_typedef_decl (CONST_CAST_TREE (decl))
+      && !TYPE_DECL_IS_STUB (decl)
+      && DECL_ARTIFICIAL (decl)
+      && DECL_CONTEXT (decl)
+      && is_tagged_type (DECL_CONTEXT (decl))
+      && TREE_CODE (TYPE_NAME (DECL_CONTEXT (decl))) == TYPE_DECL
+      && DECL_NAME (decl) == DECL_NAME (TYPE_NAME (DECL_CONTEXT (decl))))
+    return 1;
+  return 0;
+}
+
 /* Is this a typedef we can avoid emitting?  */
 
 static inline int
@@ -20575,12 +20600,7 @@ is_redundant_typedef (const_tree decl)
   if (TYPE_DECL_IS_STUB (decl))
     return 1;
 
-  if (DECL_ARTIFICIAL (decl)
-      && DECL_CONTEXT (decl)
-      && is_tagged_type (DECL_CONTEXT (decl))
-      && TREE_CODE (TYPE_NAME (DECL_CONTEXT (decl))) == TYPE_DECL
-      && DECL_NAME (decl) == DECL_NAME (TYPE_NAME (DECL_CONTEXT (decl))))
-    /* Also ignore the artificial member typedef for the class name.  */
+  if (is_injected_class_name (decl))
     return 1;
 
   return 0;
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;
+}
+


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]