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

            Bug ID: 97599
           Summary: [8/9/10/11 Regression] missing unspecified_parameters
                    DIE in DWARF for functions with variable arguments
           Product: gcc
           Version: 11.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: debug
          Assignee: unassigned at gcc dot gnu.org
          Reporter: jakub at gcc dot gnu.org
                CC: aldyh at gcc dot gnu.org, woodard at redhat dot com
        Depends on: 71855
  Target Milestone: ---
            Target: x86-64-Linux

+++ This bug was initially created as a clone of Bug #71855 +++

Since PR71855, we emit bad debug info e.g. for
#include <stdarg.h>

static __attribute__((noinline)) int
foo (int unused, int args, ...)
{
  va_list ap;
  int ret = 0;
  va_start (ap, args);
  if (args)
    ret = va_arg (ap, int);
  va_end (ap);
  return ret;
}

int
bar (int x)
{
  return foo (0, 0) + foo (0, 1, 1) + foo (0, 1, 3) + foo (0, 0) + foo (0, 0,
4);
}

Also, with LTO:
#include <stdarg.h>

void
foo (int args, ...)
{
  va_list ap;
  va_start (ap, args);
  va_end (ap);
}
gcc -shared -g -fpic -flto test.c
As written in https://bugzilla.redhat.com/show_bug.cgi?id=1891787 , it seems it
isn't enough to rely on the DW_TAG_unspecified_parameters DIE being present
among the abstract origin DIE of the DW_TAG_subprogram's children; the debug
info consumer can't know if the clone of that original function is really still
variadic, or if e.g. the variadic-ness has been removed.

For the non-LTO case, it is I think fairly easy to do, subr_die != old_die
should be true if it is a fresh new DIE, but I'm afraid for in_lto_p we don't
really know easily if it is a fresh new DIE or not.

As we have nothing to lookup in the hash tables to find out cheaply if it is
there or not already, the following is a painful way of doing that.

Thoughts on that?

--- gcc/dwarf2out.c.jj  2020-10-26 10:53:56.000000000 +0100
+++ gcc/dwarf2out.c     2020-10-27 17:56:07.249711468 +0100
@@ -23365,6 +23365,35 @@ gen_subprogram_die (tree decl, dw_die_re
          else if (DECL_INITIAL (decl) == NULL_TREE)
            gen_unspecified_parameters_die (decl, subr_die);
        }
+      else if (prototype_p (TREE_TYPE (decl))
+              && stdarg_p (TREE_TYPE (decl)))
+       {
+         /* Emit DW_TAG_unspecified_parameters even in late DWARF,
+            but ensure to do it only when it isn't present already.
+            If subr_die != old_die, this is a new DIE to which it
+            should be added, otherwise if in_lto_p, we don't really
+            know if it is a freshly created one or something older,
+            so look it up.  */
+         bool emit = subr_die != old_die;
+         if (!emit && in_lto_p)
+           {
+             dw_die_ref c;
+             emit = true;
+             FOR_EACH_CHILD (subr_die, c,
+                             do
+                               {
+                                 if (c->die_tag
+                                     == DW_TAG_unspecified_parameters)
+                                   {
+                                     emit = false;
+                                     break;
+                                   }
+                               }
+                             while (0));
+           }
+         if (emit)
+           gen_unspecified_parameters_die (decl, subr_die);
+       }
     }

   if (subr_die != old_die)


Referenced Bugs:

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=71855
[Bug 71855] duplicate unspecified_parameters DIE in DWARF for functions with
variable arguments

Reply via email to