On Sat, Feb 20, 2016 at 3:19 AM, Alexandre Oliva <[email protected]> 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