better debug info for C++ cdtors, aliases, thunks and other trampolines

Richard Biener richard.guenther@gmail.com
Mon Feb 22 13:35:00 GMT 2016


On Sat, Feb 20, 2016 at 3:19 AM, Alexandre Oliva <aoliva@redhat.com> wrote:
> Keith Seitz reported we were missing debug information for cdtors.
> E.g., we emit a specification for the unified ctor and dtor, but then,
> if we emit one of the in-charge and not-in-charge versions as an alias
> to the other, from the debug info PoV it's as if one of them didn't
> exist.  If we emit declone them, emitting the unified cdtor and the
> others are trampolines to it, it's as if we had an extra cdtor, because
> there's no info that the others are just trampolines.
>
> This patch implements some improvements in this regard:
>
> - when we emit a symbol as an alias (or weakref) to another, we now emit
>   a DW_TAG_imported_decl definition for it, naming the alias target's
>   DIE in a DW_AT_import attribute.
>
> - when we emit decloned cdtor trampolines, or other kinds of thunks, we
>   now annotate their DIEs with DW_AT_trampoline, referencing the
>   target's DIE.
>
> I realize this is a bit late for GCC 6, but I figured I'd post it right
> now, so that I can work on any required changes while it's still fresh
> in my mind.  Now, if someone agrees it is safe enough even for 6, I
> surely wouldn't mind that either ;-)
>
> This was regstrapped on x86_64-linux-gnu and i686-linux-gnu, and I
> checked for any regressions in the GDB test results too, for good
> measure (there were none)
>
> Ok to install, now or later?

I think this breaks early-debug assumptions in creating new decl DIEs
rather than just annotating old ones.  So assemble_aliases is the
wrong spot to do this.

Richard.

>
> support aliases and trampolines in dwarf2
>
> for  gcc/ChangeLog
>
>         * debug.h (struct gcc_debug_hooks): Add aliased_decl and
>         trampoline_decl.
>         * dwarf2out.c (dwarf2out_aliased_decl): New.
>         (dwarf2out_trampoline_decl): New.
>         (dwarf2_debug_hooks): Add them.
>         (dwarf2_name): Skip leading '*' returned by langhook.
>         (dwarf2_lineno_debug_hooks): Add dummies.
>         * debug.c (do_nothing_debug_hooks): Likewise.
>         * dbxout.c (dbx_debug_hooks, xcoff_debug_hooks): Likewise.
>         * sdbout.c (sdb_debug_hooks): Likewise.
>         * vmsdbgout.c (vmsdbg_debug_hooks): Likewise.
>         * cgraph.h (cgraph_node::is_lang_trampoline): Declare.
>         * cgraphunit.c: Include demangle.h.
>         (cgraph_node::expand_thunk): Call function_decl debug_hook
>         after assembly expansion.  Do not mark thunk as ignored in
>         gimple expansion.
>         (cxx_cdtor_trampoline_p): New.
>         (cgraph_node::is_lang_trampoline): New.
>         (cgraph_node::assemble_thunks_and_aliases): Call the new
>         debug_hooks.
>         (symbol_table::output_weakrefs): Likewise.
>         * varpool.c (varpool_node::assemble_aliases): Likewise.
>
> for  gcc/cp/ChangeLog
>
>         * method.c (make_alias_for): Copy DECL_IGNORED_P.
>
> for  gcc/testsuite/ChangeLog
>
>         * g++.dg/debug/dwarf2/cdtor-1.C: Adjust linkage_name count.
>         * g++.dg/debug/dwarf2/cdtor-2.C: New.
>         * g++.dg/debug/dwarf2/cdtor-3.C: New.
>         * g++.dg/debug/dwarf2/covariant-1.C: New.
>         * gcc.dg/debug/dwarf2/attr-alias-1.c: New.
>         * gcc.dg/debug/dwarf2/attr-alias-2.c: New.
>         * gcc.dg/debug/dwarf2/attr-weakref-1.c: New.
>         * gcc.dg/debug/dwarf2/attr-weakref-2.c: New.
> ---
>  gcc/cgraph.h                                       |    4 +
>  gcc/cgraphunit.c                                   |  134 +++++++++++++++++++-
>  gcc/cp/method.c                                    |    1
>  gcc/dbxout.c                                       |    4 +
>  gcc/debug.c                                        |    2
>  gcc/debug.h                                        |    8 +
>  gcc/dwarf2out.c                                    |  100 +++++++++++++++
>  gcc/sdbout.c                                       |    2
>  gcc/testsuite/g++.dg/debug/dwarf2/cdtor-1.C        |    2
>  gcc/testsuite/g++.dg/debug/dwarf2/cdtor-2.C        |   13 ++
>  gcc/testsuite/g++.dg/debug/dwarf2/cdtor-3.C        |   17 +++
>  gcc/testsuite/g++.dg/debug/dwarf2/covariant-1.C    |   24 ++++
>  gcc/testsuite/gcc.dg/debug/dwarf2/attr-alias-1.c   |   10 +
>  gcc/testsuite/gcc.dg/debug/dwarf2/attr-alias-2.c   |   10 +
>  gcc/testsuite/gcc.dg/debug/dwarf2/attr-weakref-1.c |   10 +
>  gcc/testsuite/gcc.dg/debug/dwarf2/attr-weakref-2.c |   10 +
>  gcc/varpool.c                                      |    8 +
>  gcc/vmsdbgout.c                                    |    2
>  18 files changed, 349 insertions(+), 12 deletions(-)
>  create mode 100644 gcc/testsuite/g++.dg/debug/dwarf2/cdtor-2.C
>  create mode 100644 gcc/testsuite/g++.dg/debug/dwarf2/cdtor-3.C
>  create mode 100644 gcc/testsuite/g++.dg/debug/dwarf2/covariant-1.C
>  create mode 100644 gcc/testsuite/gcc.dg/debug/dwarf2/attr-alias-1.c
>  create mode 100644 gcc/testsuite/gcc.dg/debug/dwarf2/attr-alias-2.c
>  create mode 100644 gcc/testsuite/gcc.dg/debug/dwarf2/attr-weakref-1.c
>  create mode 100644 gcc/testsuite/gcc.dg/debug/dwarf2/attr-weakref-2.c
>
> diff --git a/gcc/cgraph.h b/gcc/cgraph.h
> index fc7bb22..4d8bf05 100644
> --- a/gcc/cgraph.h
> +++ b/gcc/cgraph.h
> @@ -1117,6 +1117,10 @@ public:
>       external means.  */
>    inline void mark_force_output (void);
>
> +  /* Return true when function is a language-defined trampoline, e.g.,
> +     C++ ctor and dtor "thunks" that just call the unified cdtor.  */
> +  bool is_lang_trampoline (void);
> +
>    /* Return true when function can be marked local.  */
>    bool local_p (void);
>
> diff --git a/gcc/cgraphunit.c b/gcc/cgraphunit.c
> index 0a745f0..b399d61 100644
> --- a/gcc/cgraphunit.c
> +++ b/gcc/cgraphunit.c
> @@ -203,6 +203,7 @@ along with GCC; see the file COPYING3.  If not see
>  #include "dbgcnt.h"
>  #include "tree-chkp.h"
>  #include "lto-section-names.h"
> +#include "demangle.h"
>
>  /* Queue of cgraph nodes scheduled to be added into cgraph.  This is a
>     secondary queue used during optimization to accommodate passes that
> @@ -1635,6 +1636,12 @@ cgraph_node::expand_thunk (bool output_asm_thunks, bool force_gimple_thunk)
>        assemble_end_function (thunk_fndecl, fnname);
>        insn_locations_finalize ();
>        init_insn_lengths ();
> +
> +      timevar_push (TV_SYMOUT);
> +      if (!DECL_IGNORED_P (thunk_fndecl))
> +       (*debug_hooks->function_decl) (thunk_fndecl);
> +      timevar_pop (TV_SYMOUT);
> +
>        free_after_compilation (cfun);
>        TREE_ASM_WRITTEN (thunk_fndecl) = 1;
>        thunk.thunk_p = false;
> @@ -1676,7 +1683,6 @@ cgraph_node::expand_thunk (bool output_asm_thunks, bool force_gimple_thunk)
>        resolve_unique_section (thunk_fndecl, 0,
>                               flag_function_sections);
>
> -      DECL_IGNORED_P (thunk_fndecl) = 1;
>        bitmap_obstack_initialize (NULL);
>
>        if (thunk.virtual_offset_p)
> @@ -1889,6 +1895,92 @@ cgraph_node::expand_thunk (bool output_asm_thunks, bool force_gimple_thunk)
>    return true;
>  }
>
> +/* Return true if DECL is a cdtor trampoline for unified cdtor
> +   TARGET.  */
> +
> +static bool
> +cxx_cdtor_trampoline_p (tree decl, tree target)
> +{
> +  if (DECL_ABSTRACT_ORIGIN (decl))
> +    return false;
> +
> +  if (!DECL_CXX_CONSTRUCTOR_P (decl) && !DECL_CXX_DESTRUCTOR_P (decl))
> +    return false;
> +
> +  if (DECL_CXX_CONSTRUCTOR_P (decl) != DECL_CXX_CONSTRUCTOR_P (target))
> +    return false;
> +
> +  if (DECL_CXX_DESTRUCTOR_P (decl) != DECL_CXX_DESTRUCTOR_P (target))
> +    return false;
> +
> +  gcc_assert (DECL_ASSEMBLER_NAME_SET_P (decl));
> +  gcc_assert (DECL_ASSEMBLER_NAME_SET_P (target));
> +
> +  const char *dname = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
> +  const char *tname = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (target));
> +
> +  unsigned int i = strlen (dname);
> +  if (i != strlen (tname))
> +    return false;
> +
> +  gcc_assert (i);
> +
> +  /* C1 and C2 ctors may be trampolines to C4; D0, D1 and D2 dtors may
> +     be trampolines to D4.  Check their mangled names, so that the
> +     test will work even during LTO compilations, when the cdtor
> +     clones retrofitted into trampolines might not be right after the
> +     unified one in the DECL_CHAIN, and we don't have C++-specific
> +     data structures or lang hooks to check that the cdtors are of
> +     different kinds and belong to the same class.
> +
> +     Alas, just checking that the assembler name has e.g. C2 vs C4 as
> +     the only difference could find false positives, e.g., if there
> +     are cdtors with the same signature (aside from the THIS pointer)
> +     in classes whose names contain C2 and C4, say _ZN2C2C1Ev AKA
> +     C2::C2() and _ZN2C4C1Ev AKA C4::C4().
> +
> +     So, after checking that we found viable distinguishing characters
> +     at the expected place, we check that the cdtors are of different
> +     kinds using the demangler.  Yuck.  */
> +  bool found = false;
> +  while (i--)
> +    if (dname[i] != tname[i])
> +      {
> +       if (!found
> +           && tname[i] == '4' && i && tname[i-1] == dname[i-1]
> +           && (((dname[i-1] == 'C' || dname[i-1] == 'D')
> +                && (dname[i] == '1' || dname[i] == '2'))
> +               || (dname[i-1] == 'D' && dname[i] == '0')))
> +         found = true;
> +       else
> +         return false;
> +      }
> +
> +  if (DECL_CXX_CONSTRUCTOR_P (decl))
> +    return is_gnu_v3_mangled_ctor (tname) == gnu_v3_unified_ctor
> +      && is_gnu_v3_mangled_ctor (dname) != gnu_v3_unified_ctor;
> +  else if (DECL_CXX_DESTRUCTOR_P (decl))
> +    return is_gnu_v3_mangled_dtor (tname) == gnu_v3_unified_dtor
> +      && is_gnu_v3_mangled_dtor (dname) != gnu_v3_unified_dtor;
> +  else
> +    gcc_unreachable ();
> +}
> +
> +/* Return true when function is as a language-defined trampoline,
> +   e.g., C++ ctor and dtor "thunks" that just call the unified
> +   cdtor.  */
> +
> +bool
> +cgraph_node::is_lang_trampoline (void)
> +{
> +  if (!callees || callees->next_callee)
> +    return false;
> +
> +  tree target = callees->callee->decl;
> +
> +  return (cxx_cdtor_trampoline_p (decl, target));
> +}
> +
>  /* Assemble thunks and aliases associated to node.  */
>
>  void
> @@ -1906,9 +1998,17 @@ cgraph_node::assemble_thunks_and_aliases (void)
>         e = e->next_caller;
>         thunk->expand_thunk (true, false);
>         thunk->assemble_thunks_and_aliases ();
> +       if (!DECL_IGNORED_P (thunk->decl) && !DECL_IGNORED_P (decl))
> +         (*debug_hooks->trampoline_decl) (thunk->decl, decl);
>        }
>      else
> -      e = e->next_caller;
> +      {
> +       if (e->caller->is_lang_trampoline ()
> +           && !DECL_IGNORED_P (e->caller->decl) && !DECL_IGNORED_P (decl))
> +         (*debug_hooks->trampoline_decl) (e->caller->decl, decl);
> +
> +       e = e->next_caller;
> +      }
>
>    FOR_EACH_ALIAS (this, ref)
>      {
> @@ -1922,6 +2022,8 @@ cgraph_node::assemble_thunks_and_aliases (void)
>           TREE_ASM_WRITTEN (decl) = 1;
>           do_assemble_alias (alias->decl,
>                              DECL_ASSEMBLER_NAME (decl));
> +         if (!DECL_IGNORED_P (alias->decl) && !DECL_IGNORED_P (decl))
> +           (*debug_hooks->aliased_decl) (alias->decl, decl);
>           alias->assemble_thunks_and_aliases ();
>           TREE_ASM_WRITTEN (decl) = saved_written;
>         }
> @@ -2341,7 +2443,7 @@ symbol_table::output_weakrefs (void)
>             || !TREE_ASM_WRITTEN (cnode->instrumented_version->decl))
>         && node->weakref)
>        {
> -       tree target;
> +       tree target, target_decl;
>
>         /* Weakrefs are special by not requiring target definition in current
>            compilation unit.  It is thus bit hard to work out what we want to
> @@ -2349,17 +2451,33 @@ symbol_table::output_weakrefs (void)
>            When alias target is defined, we need to fetch it from symtab reference,
>            otherwise it is pointed to by alias_target.  */
>         if (node->alias_target)
> -         target = (DECL_P (node->alias_target)
> -                   ? DECL_ASSEMBLER_NAME (node->alias_target)
> -                   : node->alias_target);
> +         {
> +           if (DECL_P (node->alias_target))
> +             {
> +               target_decl = node->alias_target;
> +               target = DECL_ASSEMBLER_NAME (target_decl);
> +             }
> +           else
> +             {
> +               target_decl = NULL_TREE;
> +               target = node->alias_target;
> +             }
> +         }
>         else if (node->analyzed)
> -         target = DECL_ASSEMBLER_NAME (node->get_alias_target ()->decl);
> +         {
> +           target_decl = node->get_alias_target ()->decl;
> +           target = DECL_ASSEMBLER_NAME (target_decl);
> +         }
>         else
>           {
>             gcc_unreachable ();
> -           target = get_alias_symbol (node->decl);
> +           target_decl = node->decl;
> +           target = get_alias_symbol (target_decl);
>           }
>          do_assemble_alias (node->decl, target);
> +       if (target_decl && !DECL_IGNORED_P (node->decl)
> +           && !DECL_IGNORED_P (target_decl))
> +         (*debug_hooks->aliased_decl) (node->decl, target_decl);
>        }
>  }
>
> diff --git a/gcc/cp/method.c b/gcc/cp/method.c
> index e358ebd..24872d1 100644
> --- a/gcc/cp/method.c
> +++ b/gcc/cp/method.c
> @@ -219,6 +219,7 @@ make_alias_for (tree target, tree newid)
>      }
>    DECL_EXTERNAL (alias) = 0;
>    DECL_ARTIFICIAL (alias) = 1;
> +  DECL_IGNORED_P (alias) = DECL_IGNORED_P (target);
>    DECL_TEMPLATE_INSTANTIATED (alias) = 0;
>    if (TREE_CODE (alias) == FUNCTION_DECL)
>      {
> diff --git a/gcc/dbxout.c b/gcc/dbxout.c
> index 25a03ef..8da8eb0 100644
> --- a/gcc/dbxout.c
> +++ b/gcc/dbxout.c
> @@ -372,6 +372,8 @@ const struct gcc_debug_hooks dbx_debug_hooks =
>    debug_nothing_tree_tree_tree_bool,    /* imported_module_or_decl */
>    debug_nothing_tree,                   /* deferred_inline_function */
>    debug_nothing_tree,                   /* outlining_inline_function */
> +  debug_nothing_tree_tree,              /* aliased_decl */
> +  debug_nothing_tree_tree,              /* trampoline_decl */
>    debug_nothing_rtx_code_label,                 /* label */
>    dbxout_handle_pch,                    /* handle_pch */
>    debug_nothing_rtx_insn,               /* var_location */
> @@ -412,6 +414,8 @@ const struct gcc_debug_hooks xcoff_debug_hooks =
>    debug_nothing_tree_tree_tree_bool,    /* imported_module_or_decl */
>    debug_nothing_tree,                   /* deferred_inline_function */
>    debug_nothing_tree,                   /* outlining_inline_function */
> +  debug_nothing_tree_tree,              /* aliased_decl */
> +  debug_nothing_tree_tree,              /* trampoline_decl */
>    debug_nothing_rtx_code_label,                 /* label */
>    dbxout_handle_pch,                    /* handle_pch */
>    debug_nothing_rtx_insn,               /* var_location */
> diff --git a/gcc/debug.c b/gcc/debug.c
> index 9c2caae..c9495c9a 100644
> --- a/gcc/debug.c
> +++ b/gcc/debug.c
> @@ -50,6 +50,8 @@ const struct gcc_debug_hooks do_nothing_debug_hooks =
>    debug_nothing_tree_tree_tree_bool,    /* imported_module_or_decl */
>    debug_nothing_tree,                   /* deferred_inline_function */
>    debug_nothing_tree,                   /* outlining_inline_function */
> +  debug_nothing_tree_tree,              /* aliased_decl */
> +  debug_nothing_tree_tree,              /* trampoline_decl */
>    debug_nothing_rtx_code_label,                 /* label */
>    debug_nothing_int,                    /* handle_pch */
>    debug_nothing_rtx_insn,               /* var_location */
> diff --git a/gcc/debug.h b/gcc/debug.h
> index 6711f8b..cb6218f 100644
> --- a/gcc/debug.h
> +++ b/gcc/debug.h
> @@ -155,6 +155,14 @@ struct gcc_debug_hooks
>       the inline before it gets mangled by optimization.  */
>    void (* outlining_inline_function) (tree decl);
>
> +  /* ALIAS is a declaration whose symbol was defined as an alias to
> +     DECL's symbol.  Called right after outputting the alias
> +     definition.  */
> +  void (* aliased_decl) (tree alias, tree decl);
> +
> +  /* TRAMPOLINE is a function defined as a trampoline to DECL.  */
> +  void (* trampoline_decl) (tree trampoline, tree decl);
> +
>    /* Called from final_scan_insn for any CODE_LABEL insn whose
>       LABEL_NAME is non-null.  */
>    void (* label) (rtx_code_label *);
> diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c
> index d8ca1b7..cba37f9 100644
> --- a/gcc/dwarf2out.c
> +++ b/gcc/dwarf2out.c
> @@ -2506,6 +2506,8 @@ static void dwarf2out_begin_function (tree);
>  static void dwarf2out_end_function (unsigned int);
>  static void dwarf2out_register_main_translation_unit (tree unit);
>  static void dwarf2out_set_name (tree, tree);
> +static void dwarf2out_aliased_decl (tree, tree);
> +static void dwarf2out_trampoline_decl (tree, tree);
>
>  /* The debug hooks structure.  */
>
> @@ -2545,6 +2547,8 @@ const struct gcc_debug_hooks dwarf2_debug_hooks =
>       emitting the abstract description of inline functions until
>       something tries to reference them.  */
>    dwarf2out_abstract_function, /* outlining_inline_function */
> +  dwarf2out_aliased_decl,      /* aliased_decl */
> +  dwarf2out_trampoline_decl,   /* trampoline_decl */
>    debug_nothing_rtx_code_label,        /* label */
>    debug_nothing_int,           /* handle_pch */
>    dwarf2out_var_location,
> @@ -2583,6 +2587,8 @@ const struct gcc_debug_hooks dwarf2_lineno_debug_hooks =
>    debug_nothing_tree_tree_tree_bool,    /* imported_module_or_decl */
>    debug_nothing_tree,                   /* deferred_inline_function */
>    debug_nothing_tree,                   /* outlining_inline_function */
> +  debug_nothing_tree_tree,              /* aliased_decl */
> +  debug_nothing_tree_tree,              /* trampoline_decl */
>    debug_nothing_rtx_code_label,                 /* label */
>    debug_nothing_int,                    /* handle_pch */
>    debug_nothing_rtx_insn,               /* var_location */
> @@ -9755,7 +9761,10 @@ dwarf2_name (tree decl, int scope)
>  {
>    if (DECL_NAMELESS (decl))
>      return NULL;
> -  return lang_hooks.dwarf_name (decl, scope ? 1 : 0);
> +  const char *name = lang_hooks.dwarf_name (decl, scope ? 1 : 0);
> +  if (name && name[0] == '*')
> +    name++;
> +  return name;
>  }
>
>  /* Add a new entry to .debug_pubnames if appropriate.  */
> @@ -23797,6 +23806,95 @@ dwarf2out_imported_module_or_decl (tree decl, tree name, tree context,
>    dwarf2out_imported_module_or_decl_1 (decl, name, context, scope_die);
>  }
>
> +/* Output debug info indicating that ALIAS is an alias to DECL.  */
> +
> +static void
> +dwarf2out_aliased_decl (tree alias, tree decl)
> +{
> +  if (debug_info_level <= DINFO_LEVEL_TERSE)
> +    return;
> +
> +  if (!(dwarf_version >= 3 || !dwarf_strict))
> +    return;
> +
> +  if (DECL_IGNORED_P (decl) || DECL_IGNORED_P (alias))
> +    return;
> +
> +  dw_die_ref decl_die = lookup_decl_die (decl);
> +
> +  if (!decl_die)
> +    return;
> +
> +  dw_die_ref old_alias_die = lookup_decl_die (alias);
> +
> +  if (old_alias_die && TREE_CODE (alias) == FUNCTION_DECL)
> +    /* FIXME: we have a specification and probably a definition that
> +       turned into an alias.  Location information of the aliased
> +       definition is most certainly not suitable for this alias.  */
> +    return;
> +
> +  dw_die_ref alias_die = new_die (DW_TAG_imported_declaration,
> +                                 comp_unit_die (), NULL_TREE);
> +
> +  add_AT_die_ref (alias_die, DW_AT_import, decl_die);
> +
> +  /* ??? It would be nice if we could just link back to the symbol
> +     declaration, but DW_AT_specification is not a welcome attribute
> +     for a DW_TAG_imported_declaration.  */
> +  if (0 && old_alias_die)
> +    {
> +      add_AT_die_ref (alias_die, DW_AT_specification, old_alias_die);
> +      return;
> +    }
> +
> +  equate_decl_number_to_die (alias, alias_die);
> +
> +  if (TREE_PUBLIC (alias))
> +    add_AT_flag (alias_die, DW_AT_external, 1);
> +
> +  {
> +    bool save_artificial = DECL_ARTIFICIAL (alias);
> +    /* Temporarily set DECL_ARTIFICIAL so that we don't emit src coords
> +       attributes.  */
> +    DECL_ARTIFICIAL (alias) = true;
> +    add_name_and_src_coords_attributes (alias_die, alias);
> +    DECL_ARTIFICIAL (alias) = save_artificial;
> +  }
> +
> +  add_pubname (alias, alias_die);
> +  if (DECL_ARTIFICIAL (alias))
> +    add_AT_flag (alias_die, DW_AT_artificial, 1);
> +  add_accessibility_attribute (alias_die, alias);
> +}
> +
> +/* Output debug info indicating that TRAMPOLINE is a trampoline to
> +   DECL.  */
> +
> +static void
> +dwarf2out_trampoline_decl (tree trampoline, tree decl)
> +{
> +  if (debug_info_level <= DINFO_LEVEL_TERSE)
> +    return;
> +
> +  if (!(dwarf_version >= 3 || !dwarf_strict))
> +    return;
> +
> +  if (DECL_IGNORED_P (decl) || DECL_IGNORED_P (trampoline))
> +    return;
> +
> +  dw_die_ref decl_die = lookup_decl_die (decl);
> +
> +  if (!decl_die)
> +    return;
> +
> +  dw_die_ref trampoline_die = lookup_decl_die (trampoline);
> +
> +  if (!trampoline_die)
> +    return;
> +
> +  add_AT_die_ref (trampoline_die, DW_AT_trampoline, decl_die);
> +}
> +
>  /* Output debug information for namelists.   */
>
>  static dw_die_ref
> diff --git a/gcc/sdbout.c b/gcc/sdbout.c
> index dc52716..df26ad8 100644
> --- a/gcc/sdbout.c
> +++ b/gcc/sdbout.c
> @@ -301,6 +301,8 @@ const struct gcc_debug_hooks sdb_debug_hooks =
>    debug_nothing_tree_tree_tree_bool,    /* imported_module_or_decl */
>    debug_nothing_tree,                   /* deferred_inline_function */
>    debug_nothing_tree,                   /* outlining_inline_function */
> +  debug_nothing_tree_tree,              /* aliased_decl */
> +  debug_nothing_tree_tree,              /* trampoline_decl */
>    sdbout_label,                                 /* label */
>    debug_nothing_int,                    /* handle_pch */
>    debug_nothing_rtx_insn,               /* var_location */
> diff --git a/gcc/testsuite/g++.dg/debug/dwarf2/cdtor-1.C b/gcc/testsuite/g++.dg/debug/dwarf2/cdtor-1.C
> index c0d3d22..71efae8 100644
> --- a/gcc/testsuite/g++.dg/debug/dwarf2/cdtor-1.C
> +++ b/gcc/testsuite/g++.dg/debug/dwarf2/cdtor-1.C
> @@ -14,4 +14,4 @@ main()
>    K k;
>  }
>
> -// { dg-final {scan-assembler-times " DW_AT_\[MIPS_\]*linkage_name" 4 } }
> +// { dg-final {scan-assembler-times " DW_AT_\[MIPS_\]*linkage_name" 6 } }
> diff --git a/gcc/testsuite/g++.dg/debug/dwarf2/cdtor-2.C b/gcc/testsuite/g++.dg/debug/dwarf2/cdtor-2.C
> new file mode 100644
> index 0000000..0737e43
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/debug/dwarf2/cdtor-2.C
> @@ -0,0 +1,13 @@
> +// { dg-options "-gdwarf-2 -dA" }
> +/* { dg-require-alias "" } */
> +// { dg-do compile }
> +
> +struct foo {
> +  foo ();
> +  ~foo ();
> +};
> +
> +foo::foo () {}
> +foo::~foo () {}
> +
> +// { dg-final { scan-assembler-times " DW_AT_import" 2 } }
> diff --git a/gcc/testsuite/g++.dg/debug/dwarf2/cdtor-3.C b/gcc/testsuite/g++.dg/debug/dwarf2/cdtor-3.C
> new file mode 100644
> index 0000000..d500e82
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/debug/dwarf2/cdtor-3.C
> @@ -0,0 +1,17 @@
> +// { dg-options "-gdwarf-2 -fdeclone-ctor-dtor -dA" }
> +// { dg-do compile }
> +
> +struct bar {
> +  bar ();
> +  ~bar ();
> +};
> +
> +struct foo : virtual bar {
> +  foo ();
> +  ~foo ();
> +};
> +
> +foo::foo () {}
> +foo::~foo () {}
> +
> +// { dg-final { scan-assembler-times " DW_AT_trampoline" 4 } }
> diff --git a/gcc/testsuite/g++.dg/debug/dwarf2/covariant-1.C b/gcc/testsuite/g++.dg/debug/dwarf2/covariant-1.C
> new file mode 100644
> index 0000000..1f4326a
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/debug/dwarf2/covariant-1.C
> @@ -0,0 +1,24 @@
> +// { dg-options "-gdwarf-2 -dA" }
> +/* { dg-require-alias "" } */
> +// { dg-do compile }
> +
> +class A {
> +public:
> +  virtual A* getThis();
> +};
> +
> +class B {
> +  int a;
> +public:
> +  virtual B* getThis();
> +};
> +
> +class AB : public A, public B {
> +public:
> +  virtual AB* getThis();
> +};
> +
> +AB* AB::getThis() { return this; }
> +
> +// { dg-final { scan-assembler-times " DW_AT_import" 2 } }
> +// { dg-final { scan-assembler-times " DW_AT_trampoline" 1 } }
> diff --git a/gcc/testsuite/gcc.dg/debug/dwarf2/attr-alias-1.c b/gcc/testsuite/gcc.dg/debug/dwarf2/attr-alias-1.c
> new file mode 100644
> index 0000000..9968856
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/debug/dwarf2/attr-alias-1.c
> @@ -0,0 +1,10 @@
> +/* { dg-do compile } */
> +/* { dg-require-alias "" } */
> +/* { dg-options "-gdwarf-2 -dA" } */
> +
> +static int f1 (void) { return 0; }
> +extern int g1 (void) __attribute__((__alias__("f1")));
> +
> +int f () { return g1 (); }
> +
> +// { dg-final { scan-assembler-times " DW_AT_import" 1 } }
> diff --git a/gcc/testsuite/gcc.dg/debug/dwarf2/attr-alias-2.c b/gcc/testsuite/gcc.dg/debug/dwarf2/attr-alias-2.c
> new file mode 100644
> index 0000000..27201d4
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/debug/dwarf2/attr-alias-2.c
> @@ -0,0 +1,10 @@
> +/* { dg-do compile } */
> +/* { dg-require-alias "" } */
> +/* { dg-options "-gdwarf-2 -dA" } */
> +
> +static int i1 = 0;
> +extern int i2 __attribute__((__alias__("i1")));
> +
> +int f () { return i2; }
> +
> +// { dg-final { scan-assembler-times " DW_AT_import" 1 } }
> diff --git a/gcc/testsuite/gcc.dg/debug/dwarf2/attr-weakref-1.c b/gcc/testsuite/gcc.dg/debug/dwarf2/attr-weakref-1.c
> new file mode 100644
> index 0000000..b53bd05
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/debug/dwarf2/attr-weakref-1.c
> @@ -0,0 +1,10 @@
> +/* { dg-do compile } */
> +/* { dg-require-weak "" } */
> +/* { dg-options "-gdwarf-2 -dA" } */
> +
> +int f1 (void) { return 0; }
> +static int g1 (void) __attribute__((__weakref__("f1")));
> +
> +int f () { return g1 (); }
> +
> +// { dg-final { scan-assembler-times " DW_AT_import" 1 } }
> diff --git a/gcc/testsuite/gcc.dg/debug/dwarf2/attr-weakref-2.c b/gcc/testsuite/gcc.dg/debug/dwarf2/attr-weakref-2.c
> new file mode 100644
> index 0000000..6020202
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/debug/dwarf2/attr-weakref-2.c
> @@ -0,0 +1,10 @@
> +/* { dg-do compile } */
> +/* { dg-require-weak "" } */
> +/* { dg-options "-gdwarf-2 -dA" } */
> +
> +int i1 = 0;
> +static int i2 __attribute__((__weakref__("i1")));
> +
> +int f () { return i2; }
> +
> +// { dg-final { scan-assembler-times " DW_AT_import" 1 } }
> diff --git a/gcc/varpool.c b/gcc/varpool.c
> index cbbdda4..878aaee 100644
> --- a/gcc/varpool.c
> +++ b/gcc/varpool.c
> @@ -538,8 +538,12 @@ varpool_node::assemble_aliases (void)
>      {
>        varpool_node *alias = dyn_cast <varpool_node *> (ref->referring);
>        if (!alias->transparent_alias)
> -       do_assemble_alias (alias->decl,
> -                          DECL_ASSEMBLER_NAME (decl));
> +       {
> +         do_assemble_alias (alias->decl,
> +                            DECL_ASSEMBLER_NAME (decl));
> +         if (!DECL_IGNORED_P (alias->decl) && !DECL_IGNORED_P (decl))
> +           (*debug_hooks->aliased_decl) (alias->decl, decl);
> +       }
>        alias->assemble_aliases ();
>      }
>  }
> diff --git a/gcc/vmsdbgout.c b/gcc/vmsdbgout.c
> index 7c6d64d..fc87828 100644
> --- a/gcc/vmsdbgout.c
> +++ b/gcc/vmsdbgout.c
> @@ -198,6 +198,8 @@ const struct gcc_debug_hooks vmsdbg_debug_hooks
>     debug_nothing_tree_tree_tree_bool, /* imported_module_or_decl */
>     debug_nothing_tree,           /* deferred_inline_function */
>     vmsdbgout_abstract_function,
> +   debug_nothing_tree_tree,      /* aliased_decl */
> +   debug_nothing_tree_tree,      /* trampoline_decl */
>     debug_nothing_rtx_code_label,  /* label */
>     debug_nothing_int,            /* handle_pch */
>     debug_nothing_rtx_insn,       /* var_location */
>
>
> --
> Alexandre Oliva, freedom fighter    http://FSFLA.org/~lxoliva/
> You must be the change you wish to see in the world. -- Gandhi
> Be Free! -- http://FSFLA.org/   FSF Latin America board member
> Free Software Evangelist|Red Hat Brasil GNU Toolchain Engineer



More information about the Gcc-patches mailing list