On 03/25/2015 12:37 PM, Jason Merrill wrote:
On 03/24/2015 02:00 PM, Aldy Hernandez wrote:
I found that for locally scoped functions we were not emitting early
dwarf.

Why weren't they being emitted as part of their enclosing function? They
should be.

Jason


Hmm, you're right.  Sorry for being so sloppy.

What is actually happening is that when the declaration is seen, nameless DIEs for the types are generated, which are then used when the cached subprogram DIE is seen the second time. The nameless DIEs end up looking like this because we don't have the "this" name:

    char Object_method(Object * const);

whereas the function type should be:

    char Object_method(void);

I now understand what this was doing in mainline:

          /* Clear out the declaration attribute and the formal parameters.
             Do not remove all children, because it is possible that this
             declaration die was forced using force_decl_die(). In such
             cases die that forced declaration die (e.g. TAG_imported_module)
             is one of the children that we do not want to remove.  */
          remove_AT (subr_die, DW_AT_declaration);
          remove_AT (subr_die, DW_AT_object_pointer);
          remove_child_TAG (subr_die, DW_TAG_formal_parameter);

I suppose we could re-use the DW_AT_object_pointer and DW_TAG_formal_parameter, and tack on the DW_AT_name now that we know it? Or we could cheat and just remove them as mainline does, but only when reusing a declaration (as in the attached patch).

What do you think?

Aldy
diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c
index 48e2eed..4bc945f 100644
--- a/gcc/dwarf2out.c
+++ b/gcc/dwarf2out.c
@@ -3113,7 +3113,7 @@ static inline dw_die_ref get_AT_ref (dw_die_ref, enum 
dwarf_attribute);
 static bool is_cxx (void);
 static bool is_fortran (void);
 static bool is_ada (void);
-static void remove_AT (dw_die_ref, enum dwarf_attribute);
+static bool remove_AT (dw_die_ref, enum dwarf_attribute);
 static void remove_child_TAG (dw_die_ref, enum dwarf_tag);
 static void add_child_die (dw_die_ref, dw_die_ref);
 static dw_die_ref new_die (enum dwarf_tag, dw_die_ref, tree);
@@ -4752,16 +4752,17 @@ is_ada (void)
   return lang == DW_LANG_Ada95 || lang == DW_LANG_Ada83;
 }
 
-/* Remove the specified attribute if present.  */
+/* Remove the specified attribute if present.  Return TRUE if removal
+   was successful.  */
 
-static void
+static bool
 remove_AT (dw_die_ref die, enum dwarf_attribute attr_kind)
 {
   dw_attr_ref a;
   unsigned ix;
 
   if (! die)
-    return;
+    return false;
 
   FOR_EACH_VEC_SAFE_ELT (die->die_attr, ix, a)
     if (a->dw_attr == attr_kind)
@@ -4773,8 +4774,9 @@ remove_AT (dw_die_ref die, enum dwarf_attribute attr_kind)
        /* vec::ordered_remove should help reduce the number of abbrevs
           that are needed.  */
        die->die_attr->ordered_remove (ix);
-       return;
+       return true;
       }
+  return false;
 }
 
 /* Remove CHILD from its parent.  PREV must have the property that
@@ -18790,8 +18792,15 @@ gen_subprogram_die (tree decl, dw_die_ref context_die)
 
          /* Clear out the declaration attribute, but leave the
             parameters so they can be augmented with location
-            information later.  */
-         remove_AT (subr_die, DW_AT_declaration);
+            information later.  Unless this was a declaration, in
+            which case, wipe out the nameless parameters and recreate
+            them further down.  */
+         if (remove_AT (subr_die, DW_AT_declaration))
+           {
+
+             remove_AT (subr_die, DW_AT_object_pointer);
+             remove_child_TAG (subr_die, DW_TAG_formal_parameter);
+           }
        }
       /* Make a specification pointing to the previously built
         declaration.  */

Reply via email to