https://gcc.gnu.org/bugzilla/show_bug.cgi?id=78112

--- Comment #9 from Pierre-Marie de Rodat <derodat at adacore dot com> ---
Back to business. ;-)

Thank you very much, Jakub! During investigation, I managed to reduce this even
further:

    void run (int *int_p, void(*func)(int *)) { func (int_p); }
    namespace foo {
       struct Foo {
          int a;
          Foo() { run (&a, [](int *int_p) { *int_p = 0; }); }
       };
    }
    int main (void) { foo::Foo f; }

With today’s trunk (gcc/cc1plus -g -dA foo.C) and this reproducer, I see three
DW_TAG_subprogram having two DW_AT_object_pointer each.

Disclaimer: to be perfectly honnest, I have a very partial understanding of how
dwarf2out.c:gen_subprogram_die is supposed to work. It has a good share of
explaining comments, but it is still hard to grasp as it does quite complex
things. That being said…

My analysis so far is that gen_subprogram_die is supposed to be called a very
specific number of times for each function and my change from 2016-10-12 made
it run more times, so it unintentionally added some attributes more than just
once. The following patch seems to restore call count to what we had
previously:

diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c
index 78a2979..a85ab3b 100644
--- a/gcc/dwarf2out.c
+++ b/gcc/dwarf2out.c
@@ -23909,11 +23909,11 @@ dwarf2out_early_global_decl (tree decl)
          if (!DECL_STRUCT_FUNCTION (decl))
            goto early_decl_exit;

-         /* For nested functions, emit DIEs for the parents first so that all
-            nested DIEs are generated at the proper scope in the first
-            shot.  */
+         /* For nested functions, make sure we have DIEs for the parents first
+            so that all nested DIEs are generated at the proper scope in the
+            first shot.  */
          tree context = decl_function_context (decl);
-         if (context != NULL)
+         if (context != NULL && lookup_decl_die (context) == NULL)
            {
              current_function_decl = context;
              dwarf2out_decl (context);

I’m currently bootstrapping+regtesting it on x86_64-linux. I tried to come up
with a regression testcase for it, but I can’t find a human-friendly regexp for
scan-assembler-times to check that we don’t have multiple attributes per tag.
So for local testing, I wrote a Python3 script to use the pyelftools library.
I’ll file it right after sending this message if others need to use it.

Something bugs me, though: with Jakub’s reproducer, I get multiple
DW_AT_object_pointer attributes even at r241022 (i.e. right before my
2016-10-12 patch):

    $ gcc/cc1plus -g -dA pr78112.ii && gcc -c pr78112.s && ./check.py pr78112.o
    In (0x3c4) DW_TAG_subprogram: DW_AT_object_pointer appears 2 times
    In (0x46a) DW_TAG_subprogram: DW_AT_object_pointer appears 2 times
    In (0x4fe) DW_TAG_subprogram: DW_AT_object_pointer appears 2 times
    In (0x55a) DW_TAG_subprogram: DW_AT_object_pointer appears 2 times
    In (0x5cf) DW_TAG_subprogram: DW_AT_object_pointer appears 2 times
    In (0x668) DW_TAG_subprogram: DW_AT_object_pointer appears 2 times

So I’m surprised Rainer hasn’t spotted this kind of error before.

Thoughts?

Reply via email to