Patchwork Fix PR debug/45088

login
register
mail settings
Submitter Dodji Seketeli
Date Nov. 12, 2010, 11:47 a.m.
Message ID <m3bp5ubw6h.fsf@seketeli.org>
Download mbox | patch
Permalink /patch/70957/
State New
Headers show

Comments

Dodji Seketeli - Nov. 12, 2010, 11:47 a.m.
Hello,

In the first example of the patch below the DW_AT_pointer_type
DIE describing the type of the C::ai member lacks the DW_AT_type
attribute, making C::ai look like if it had void* type in a debugger.

This is because the type of C::ai is the self-reference type of
C. When gen_type_die_with_usage sees that self-reference it recognizes
it as a typedef, tries to emit a DIE for that typedef but it's
lieutenant gen_decl_die refuses to do so because the typedef is
artificial. So it looks like the dwarf emitter is sometimes faced with
artificial typedefs it must drop on the floor, and sometimes with
artificial typedefs for which it has to emit the underlying type.

One possible way to do resolve that dilemma is [at the FE level] to
fixup the type of *ai to make it be A instead of the self-reference
type of A. I figure the fact that the self-reference type is different
from A itself should be kept as an implementation detail of the FE
anyway.

The second hunk of the patch below hopefully does the fixup during the
parsing of the simple-type-specifier production for cases where the
type is neither a template nor a template instantiation. This is
because the self-reference information is useful for those template
related classes to resolve some ambiguities later e.g, with
maybe_get_template_decl_from_type_decl.

I noticed we were trying to do a similar fixup in
check_elaborated_type_specifier but were failing in doing so, maybe
because the representation of self-reference types has changed since
then. The first hunk addresses that.

Bootstrapped and tested on x86-64-unknown-linux-gnu against trunk.
Jason Merrill - Nov. 24, 2010, 11:10 p.m.
On 11/12/2010 06:47 AM, Dodji Seketeli wrote:
> One possible way to do resolve that dilemma is [at the FE level] to
> fixup the type of *ai to make it be A instead of the self-reference
> type of A. I figure the fact that the self-reference type is different
> from A itself should be kept as an implementation detail of the FE
> anyway.

I think the typedef should be emitted so that name lookup in the 
debugger can find it.  TYPE_DECL_IS_STUB should not be true for the 
injected-class-name.

Jason

Patch

diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index fb5ca7f..feba130 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -10902,7 +10902,7 @@  check_elaborated_type_specifier (enum tag_types tag_code,
      name lookup will find the TYPE_DECL for the implicit "S::S"
      typedef.  Adjust for that here.  */
   if (DECL_SELF_REFERENCE_P (decl))
-    decl = TYPE_NAME (TREE_TYPE (decl));
+    decl = TYPE_NAME (DECL_ORIGINAL_TYPE (decl));
 
   type = TREE_TYPE (decl);
 
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 6a9e4d7..c3ed5b2 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -12791,6 +12791,23 @@  cp_parser_simple_type_specifier (cp_parser* parser,
       /* Otherwise, look for a type-name.  */
       else
 	type = cp_parser_type_name (parser);
+
+      /* Self reference typedefs should not be kept because it
+	 confuses the debug info emitter that wouldn't know how to
+	 tell the difference between an artificial typedef to drop
+	 and an artificial self reference typedef to keep.
+	 So let's replace the self reference by the type by its
+	 underlying type.  */
+      if (type && TREE_CODE (type) == TYPE_DECL
+	  && DECL_SELF_REFERENCE_P (type)
+	  /* If TYPE is a decl of a template or a template
+	     instantiation we need to keep it because the information
+	     is used later by e.g,
+	     maybe_get_template_decl_from_type_decl.  */
+	  && !CLASSTYPE_IS_TEMPLATE (TREE_TYPE (type))
+	  && !CLASSTYPE_TEMPLATE_INFO (TREE_TYPE (type)))
+	type = TYPE_NAME (DECL_ORIGINAL_TYPE (type));
+
       /* Keep track of all name-lookups performed in class scopes.  */
       if (type
 	  && !global_p
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..ee8342b
--- /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" 3 } }
+
+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;
+}
+