From patchwork Mon Jul 23 21:21:27 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Cary Coutant X-Patchwork-Id: 172749 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) by ozlabs.org (Postfix) with SMTP id E08D72C0131 for ; Tue, 24 Jul 2012 07:22:07 +1000 (EST) Comment: DKIM? See http://www.dkim.org DKIM-Signature: v=1; a=rsa-sha1; c=relaxed/relaxed; d=gcc.gnu.org; s=default; x=1343683328; h=Comment: DomainKey-Signature:Received:Received:Received:Received:Received: Received:Received:Received:Received:To:Subject:Message-Id:Date: From:Mailing-List:Precedence:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:Sender:Delivered-To; bh=BBVZ45I lBfVMj4XjAZOZt+N9ah4=; b=jUqqoNt5yq4ZpPHuXpDL37uDgiZCANlnnQY2Jkz jedTVS5n5DQ2kpmib8rqIIu0S0XRJpKSERgEdDEwtvdK5iXBrLIVH0fqwD/PlQIv jsXDW4OZCjPb1zgkziuOdC5C1O0Z+1OAimD2OWJGrOev3wb1yxWkQxqp5ah4VehP 2HfI= Comment: DomainKeys? See http://antispam.yahoo.com/domainkeys DomainKey-Signature: a=rsa-sha1; q=dns; c=nofws; s=default; d=gcc.gnu.org; h=Received:Received:X-SWARE-Spam-Status:X-Spam-Check-By:Received:Received:X-Google-DKIM-Signature:Received:Received:Received:Received:Received:To:Subject:Message-Id:Date:From:X-Gm-Message-State:X-IsSubscribed:Mailing-List:Precedence:List-Id:List-Unsubscribe:List-Archive:List-Post:List-Help:Sender:Delivered-To; b=rcLxEKODuSrCO0q/4U9zcJYfVpmHfyF0V6zFvHyD33JJ+8A1gn+7aA+09aFIQk jFojaKxGG0KBW+Czh9hO2fflAPoX2Ycc+MRK1mDmY7LZjqN/vwiEySkWXrd3wRbO IL8UKSGay5hi+2mFlZI1q5gSQmBGQVU3hyLRXa2gLlkLI=; Received: (qmail 27188 invoked by alias); 23 Jul 2012 21:22:01 -0000 Received: (qmail 27130 invoked by uid 22791); 23 Jul 2012 21:21:55 -0000 X-SWARE-Spam-Status: No, hits=-3.8 required=5.0 tests=AWL, BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, KHOP_RCVD_TRUST, RCVD_IN_DNSWL_LOW, RCVD_IN_HOSTKARMA_YE, TW_CX, TW_GD, T_RP_MATCHES_RCVD, URIBL_DBL_REDIR X-Spam-Check-By: sourceware.org Received: from mail-vc0-f201.google.com (HELO mail-vc0-f201.google.com) (209.85.220.201) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Mon, 23 Jul 2012 21:21:28 +0000 Received: by vcbfo13 with SMTP id fo13so774858vcb.2 for ; Mon, 23 Jul 2012 14:21:28 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20120113; h=to:subject:message-id:date:from:x-gm-message-state; bh=dabGpb57sU3gYkiK/Zjiae4v1PJ0OWYlvU8I0fDJl2Q=; b=pJEEvbe2iJAw83bh0ZgRNDpxClmT23JczvFInfVhQ1LGuGpWBWAnrt1Vya6FfpUx7K FlASodGKEg59nfZJnX8Tg47Ef0+IXb5qvQ3cc0FkAu9vMNhYlqB/ZzGQNgmWImntIekS AqYYbKHVjQ9G+87Ft9Dc8hhKHk6fUk6BcgrsZ/Ac3oODqLs6xu/iKqQUg57iYgW/1Uvn ITyB7RM8KrbV96xjXzFXyuuyWBeuUp3B2MykNJy/5FrYpyArP9vIt/Xm1aCUnqnSqX6x JpPYUBKLepWEkaJi3hCti7sOhEOm7dL9VYguSQ8wa30+DUaFBimYxp4Fr9F0N73+Umb3 1LTw== Received: by 10.236.138.232 with SMTP id a68mr7087884yhj.28.1343078487955; Mon, 23 Jul 2012 14:21:27 -0700 (PDT) Received: by 10.236.138.232 with SMTP id a68mr7087879yhj.28.1343078487909; Mon, 23 Jul 2012 14:21:27 -0700 (PDT) Received: from wpzn3.hot.corp.google.com (216-239-44-65.google.com [216.239.44.65]) by gmr-mx.google.com with ESMTPS id w65si2681710yhi.1.2012.07.23.14.21.27 (version=TLSv1/SSLv3 cipher=AES128-SHA); Mon, 23 Jul 2012 14:21:27 -0700 (PDT) Received: from ccoutant.mtv.corp.google.com (ccoutant.mtv.corp.google.com [172.18.110.42]) by wpzn3.hot.corp.google.com (Postfix) with ESMTP id 9E30A100047; Mon, 23 Jul 2012 14:21:27 -0700 (PDT) Received: by ccoutant.mtv.corp.google.com (Postfix, from userid 62097) id 3FAC0E1504; Mon, 23 Jul 2012 14:21:27 -0700 (PDT) To: reply@codereview.appspotmail.com, saugustine@google.com, gcc-patches@gcc.gnu.org Subject: [google/gcc-4_7] Backport Fission patches from trunk (issue6405076) Message-Id: <20120723212127.3FAC0E1504@ccoutant.mtv.corp.google.com> Date: Mon, 23 Jul 2012 14:21:27 -0700 (PDT) From: ccoutant@google.com (Cary Coutant) X-Gm-Message-State: ALoCoQnarTOCuDChOBW3DOvYaWXoTz0kzjuSphGz1L/m8OK8WovHBDyhRLuJVgWi9QhYppsFSryNl/IBjv8IrvrddXIvd9J1Lt2iZn888D8iuOj3el3O6W7I/sKdWc5p5dlToy1ke0i0ImD804cHiyKqNjywK8wVzu948RbIqXf277cQ/Q9qYMqTFhi40Awv8vcusVMwe6Ut X-IsSubscribed: yes Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org This patch is for the google/gcc-4_7 branch. It backports five Fission patches from trunk, with two minor differences: - The DW_AT_GNU_pubnames and DW_AT_GNU_pubtypes attributes are both generated, and provide the offset to the corresponding pubnames/pubtypes section. This is done for compatibility with the gold linker, which does not yet support the flag form. - Enumerator names are placed in .debug_pubtypes instead of .debug_pubnames. In trunk with -fdebug_types_section enabled, enumerators were missing from the pubnames table. Tested by bootstrap and regression testing. 2012-07-23 Cary Coutant Backport Fission patches from trunk at r188195, r188857, r189084, r189094, and r189392. 2012-07-09 Sterling Augustine cp/ * error.c (lang_decl_name): Use TFF_UNQUALIFIED_NAME flag. testsuite/ * g++.dg/debug/dwarf2/pubnames-2.C: New. 2012-06-29 Cary Coutant * dwarf2out.c (add_pubname_string): Don't check for want_pubnames. (gen_subprogram_die): Don't add pubname if want_pubnames is false. (gen_variable_die): Likewise. (gen_namespace_die): Likewise. 2012-06-29 Sterling Augustine * dwarf2out.c (add_pubname): Add comment. (add_pubtype): Fix indentation. (gen_enumeration_type_die): Likewise. 2012-06-21 Sterling Augustine Cary Coutant * dwarf2out.c (is_cu_die, is_namespace_die, is_class_die, add_AT_pubnames, add_enumerator_pubname, want_pubnames): New functions. (comdat_type_struct): New field 'skeleton_die'. (breakout_comdat_types): Update it. (add_pubname): Rework logic. Call is_class_die, is_cu_die and is_namespace_die. Fix minor style violation. Call want_pubnames. (add_pubname_string): Call want_pubnames. (add_pubtype): Rework logic for calculating type name. Call is_namespace_die. Call want_pubnames. (output_pubnames): Move conditional logic deciding when to produce the section from dwarf2out_finish. Use new skeleton_die field. (base_type_die): Call add_pubtype. (gen_enumeration_type_die): Unconditionally call add_pubtype. (gen_subprogram_die): Adjust calls to add_pubname. (gen_namespace_die): Call add_pubname_string. (dwarf2out_finish): Call add_AT_pubnames; Move logic on when to produce pubnames and pubtypes sections to output_pubnames. (common.opt): New option '-gpubnames'. (invoke.texi): Document it. 2012-06-04 Sterling Augustine c-family/ * c-pretty-print.h (pp_c_flag_gnu_v3): New enumerator. * c-pretty-print.c (pp_c_specifier_qualifier_list): Check it at both the start and end of the function. cp/ * error.c (dump_decl): Check pp_c_flag_gnu_v3. (decl_as_dwarf_string, lang_decl_dwarf_name): New functions. (lang_decl_name): Handle namespace decls. * cp-tree.h: Declare decl_as_dwarf_string, lang_decl_dwarf_name. * cp-lang.c: Call them. --- This patch is available for review at http://codereview.appspot.com/6405076 diff --git a/gcc/c-family/c-pretty-print.c b/gcc/c-family/c-pretty-print.c index dc63f00..b596d3b 100644 --- a/gcc/c-family/c-pretty-print.c +++ b/gcc/c-family/c-pretty-print.c @@ -446,7 +446,7 @@ pp_c_specifier_qualifier_list (c_pretty_printer *pp, tree t) { const enum tree_code code = TREE_CODE (t); - if (TREE_CODE (t) != POINTER_TYPE) + if (!(pp->flags & pp_c_flag_gnu_v3) && code != POINTER_TYPE) pp_c_type_qualifier_list (pp, t); switch (code) { @@ -494,6 +494,8 @@ pp_c_specifier_qualifier_list (c_pretty_printer *pp, tree t) pp_simple_type_specifier (pp, t); break; } + if ((pp->flags & pp_c_flag_gnu_v3) && code != POINTER_TYPE) + pp_c_type_qualifier_list (pp, t); } /* parameter-type-list: diff --git a/gcc/c-family/c-pretty-print.h b/gcc/c-family/c-pretty-print.h index 8d399dd..2f9f94a 100644 --- a/gcc/c-family/c-pretty-print.h +++ b/gcc/c-family/c-pretty-print.h @@ -30,7 +30,8 @@ along with GCC; see the file COPYING3. If not see typedef enum { pp_c_flag_abstract = 1 << 1, - pp_c_flag_last_bit = 2 + pp_c_flag_gnu_v3 = 1 << 2, + pp_c_flag_last_bit = 3 } pp_c_pretty_print_flags; diff --git a/gcc/common.opt b/gcc/common.opt index 747dec9..ec94e86 100644 --- a/gcc/common.opt +++ b/gcc/common.opt @@ -2408,6 +2408,14 @@ gmlt Common RejectNegative Generate debug information at level 1 with minimal line table +gno-pubnames +Common RejectNegative Var(debug_generate_pub_sections, 0) Init(-1) +Don't generate DWARF pubnames and pubtypes sections. + +gpubnames +Common RejectNegative Var(debug_generate_pub_sections, 1) +Generate DWARF pubnames and pubtypes sections. + gno-record-gcc-switches Common RejectNegative Var(dwarf_record_gcc_switches,0) Init(0) Don't record gcc command line switches in DWARF DW_AT_producer. diff --git a/gcc/cp/cp-lang.c b/gcc/cp/cp-lang.c index 6291398..04d24fc 100644 --- a/gcc/cp/cp-lang.c +++ b/gcc/cp/cp-lang.c @@ -164,11 +164,11 @@ cxx_dwarf_name (tree t, int verbosity) && (ANON_AGGRNAME_P (DECL_NAME (t)) || LAMBDANAME_P (DECL_NAME (t)))) return NULL; if (verbosity >= 2) - return decl_as_string (t, - TFF_DECL_SPECIFIERS | TFF_UNQUALIFIED_NAME - | TFF_NO_OMIT_DEFAULT_TEMPLATE_ARGUMENTS); + return decl_as_dwarf_string (t, + TFF_DECL_SPECIFIERS | TFF_UNQUALIFIED_NAME + | TFF_NO_OMIT_DEFAULT_TEMPLATE_ARGUMENTS); - return cxx_printable_name (t, verbosity); + return lang_decl_dwarf_name (t, verbosity, false); } static enum classify_record diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index a94c923..d328904 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -5151,8 +5151,10 @@ extern const char *type_as_string (tree, int); extern const char *type_as_string_translate (tree, int); extern const char *decl_as_string (tree, int); extern const char *decl_as_string_translate (tree, int); +extern const char *decl_as_dwarf_string (tree, int); extern const char *expr_as_string (tree, int); extern const char *lang_decl_name (tree, int, bool); +extern const char *lang_decl_dwarf_name (tree, int, bool); extern const char *language_to_string (enum languages); extern const char *class_key_or_enum_as_string (tree); extern void print_instantiation_context (void); diff --git a/gcc/cp/error.c b/gcc/cp/error.c index 7edfee0..a440962 100644 --- a/gcc/cp/error.c +++ b/gcc/cp/error.c @@ -1028,7 +1028,12 @@ dump_decl (tree t, int flags) dump_scope (CP_DECL_CONTEXT (t), flags); flags &= ~TFF_UNQUALIFIED_NAME; if (DECL_NAME (t) == NULL_TREE) - pp_cxx_ws_string (cxx_pp, M_("{anonymous}")); + { + if (!(pp_c_base (cxx_pp)->flags & pp_c_flag_gnu_v3)) + pp_cxx_ws_string (cxx_pp, M_("{anonymous}")); + else + pp_cxx_ws_string (cxx_pp, M_("(anonymous namespace)")); + } else pp_cxx_tree_identifier (cxx_pp, DECL_NAME (t)); } @@ -2555,6 +2560,21 @@ expr_as_string (tree decl, int flags) return pp_formatted_text (cxx_pp); } +/* Wrap decl_as_string with options appropriate for dwarf. */ + +const char * +decl_as_dwarf_string (tree decl, int flags) +{ + const char *name; + /* Curiously, reinit_cxx_pp doesn't reset the flags field, so setting the flag + here will be adequate to get the desired behaviour. */ + pp_c_base (cxx_pp)->flags |= pp_c_flag_gnu_v3; + name = decl_as_string (decl, flags); + /* Subsequent calls to the pretty printer shouldn't use this style. */ + pp_c_base (cxx_pp)->flags &= ~pp_c_flag_gnu_v3; + return name; +} + const char * decl_as_string (tree decl, int flags) { @@ -2572,6 +2592,21 @@ decl_as_string_translate (tree decl, int flags) return pp_formatted_text (cxx_pp); } +/* Wrap lang_decl_name with options appropriate for dwarf. */ + +const char * +lang_decl_dwarf_name (tree decl, int v, bool translate) +{ + const char *name; + /* Curiously, reinit_cxx_pp doesn't reset the flags field, so setting the flag + here will be adequate to get the desired behaviour. */ + pp_c_base (cxx_pp)->flags |= pp_c_flag_gnu_v3; + name = lang_decl_name (decl, v, translate); + /* Subsequent calls to the pretty printer shouldn't use this style. */ + pp_c_base (cxx_pp)->flags &= ~pp_c_flag_gnu_v3; + return name; +} + /* Generate the three forms of printable names for cxx_printable_name. */ const char * @@ -2595,6 +2630,9 @@ lang_decl_name (tree decl, int v, bool translate) if (TREE_CODE (decl) == FUNCTION_DECL) dump_function_name (decl, TFF_PLAIN_IDENTIFIER); + else if ((DECL_NAME (decl) == NULL_TREE) + && TREE_CODE (decl) == NAMESPACE_DECL) + dump_decl (decl, TFF_PLAIN_IDENTIFIER | TFF_UNQUALIFIED_NAME); else dump_decl (DECL_NAME (decl), TFF_PLAIN_IDENTIFIER); diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index 9e3e66e..8934ab4 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -4954,6 +4954,10 @@ most expressive format available (DWARF 2, stabs, or the native format if neither of those are supported), including GDB extensions if at all possible. +@item -gpubnames +@opindex gpubnames +Generate dwarf .debug_pubnames and .debug_pubtypes sections. + @item -gstabs @opindex gstabs Produce debugging information in stabs format (if that is supported), diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c index 23f6fff..cc91aee 100644 --- a/gcc/dwarf2out.c +++ b/gcc/dwarf2out.c @@ -2879,6 +2879,7 @@ typedef struct GTY(()) comdat_type_struct { dw_die_ref root_die; dw_die_ref type_die; + dw_die_ref skeleton_die; char signature[DWARF_TYPE_SIGNATURE_SIZE]; struct comdat_type_struct *next; } @@ -3353,6 +3354,7 @@ static void output_comp_unit (dw_die_ref, int); static void output_comdat_type_unit (comdat_type_node *); static const char *dwarf2_name (tree, int); static void add_pubname (tree, dw_die_ref); +static void add_enumerator_pubname (const char *, dw_die_ref); static void add_pubname_string (const char *, dw_die_ref); static void add_pubtype (tree, dw_die_ref); static void output_pubnames (VEC (pubname_entry,gc) *); @@ -3482,6 +3484,7 @@ static dw_loc_list_ref new_loc_list (dw_loc_descr_ref, const char *, const char *, const char *); static void output_loc_list (dw_loc_list_ref); static char *gen_internal_sym (const char *); +static bool want_pubnames (void); static void prune_unmark_dies (dw_die_ref); static void prune_unused_types_mark_generic_parms_dies (dw_die_ref); @@ -3556,6 +3559,12 @@ static void gen_scheduled_generic_parms_dies (void); #ifndef COLD_TEXT_SECTION_LABEL #define COLD_TEXT_SECTION_LABEL "Ltext_cold" #endif +#ifndef DEBUG_PUBNAMES_SECTION_LABEL +#define DEBUG_PUBNAMES_SECTION_LABEL "Ldebug_pubnames" +#endif +#ifndef DEBUG_PUBTYPES_SECTION_LABEL +#define DEBUG_PUBTYPES_SECTION_LABEL "Ldebug_pubtypes" +#endif #ifndef DEBUG_LINE_SECTION_LABEL #define DEBUG_LINE_SECTION_LABEL "Ldebug_line" #endif @@ -3592,6 +3601,8 @@ static char cold_end_label[MAX_ARTIFICIAL_LABEL_BYTES]; static char abbrev_section_label[MAX_ARTIFICIAL_LABEL_BYTES]; static char debug_info_section_label[MAX_ARTIFICIAL_LABEL_BYTES]; static char debug_line_section_label[MAX_ARTIFICIAL_LABEL_BYTES]; +static char debug_pubnames_section_label[MAX_ARTIFICIAL_LABEL_BYTES]; +static char debug_pubtypes_section_label[MAX_ARTIFICIAL_LABEL_BYTES]; static char macinfo_section_label[MAX_ARTIFICIAL_LABEL_BYTES]; static char loc_section_label[MAX_ARTIFICIAL_LABEL_BYTES]; static char ranges_section_label[2 * MAX_ARTIFICIAL_LABEL_BYTES]; @@ -6726,6 +6737,23 @@ is_cu_die (dw_die_ref c) return c && c->die_tag == DW_TAG_compile_unit; } +/* Returns true iff C is a namespace DIE. */ + +static inline bool +is_namespace_die (dw_die_ref c) +{ + return c && c->die_tag == DW_TAG_namespace; +} + +/* Returns true iff C is a class or structure DIE. */ + +static inline bool +is_class_die (dw_die_ref c) +{ + return c && (c->die_tag == DW_TAG_class_type + || c->die_tag == DW_TAG_structure_type); +} + static char * gen_internal_sym (const char *prefix) { @@ -7306,6 +7334,7 @@ break_out_comdat_types (dw_die_ref die) declaration into the new type unit DIE, then remove this DIE from the main CU (or replace it with a skeleton if necessary). */ replacement = remove_child_or_replace_with_skeleton (unit, c, prev); + type_node->skeleton_die = replacement; /* Break out nested types into their own type units. */ break_out_comdat_types (c); @@ -8626,6 +8655,34 @@ output_comp_unit (dw_die_ref die, int output_if_empty) } } +/* Whether to generate the DWARF accelerator tables in .debug_pubnames + and .debug_pubtypes. This is configured per-target, but can be + overridden by the -gpubnames or -gno-pubnames options. */ + +static inline bool +want_pubnames (void) +{ + if (GENERATE_MINIMUM_LINE_TABLE) + return false; + return (debug_generate_pub_sections != -1 + ? debug_generate_pub_sections + : targetm.want_debug_pub_sections); +} + +/* Add the DW_AT_GNU_pubnames and DW_AT_GNU_pubtypes attributes. */ + +static void +add_AT_pubnames (dw_die_ref die) +{ + if (want_pubnames ()) + { + /* FIXME: Should use add_AT_pubnamesptr. This works because most targets + don't care what the base section is. */ + add_AT_lineptr (die, DW_AT_GNU_pubnames, debug_pubnames_section_label); + add_AT_lineptr (die, DW_AT_GNU_pubtypes, debug_pubtypes_section_label); + } +} + /* Output a comdat type unit DIE and its children. */ static void @@ -8691,29 +8748,47 @@ dwarf2_name (tree decl, int scope) static void add_pubname_string (const char *str, dw_die_ref die) { - if (!GENERATE_MINIMUM_LINE_TABLE && targetm.want_debug_pub_sections) - { - pubname_entry e; + pubname_entry e; - e.die = die; - e.name = xstrdup (str); - VEC_safe_push (pubname_entry, gc, pubname_table, &e); - } + e.die = die; + e.name = xstrdup (str); + VEC_safe_push (pubname_entry, gc, pubname_table, &e); } static void add_pubname (tree decl, dw_die_ref die) { - if (!GENERATE_MINIMUM_LINE_TABLE - && targetm.want_debug_pub_sections - && TREE_PUBLIC (decl)) + if (!want_pubnames ()) + return; + + /* Don't add items to the table when we expect that the consumer will have + just read the enclosing die. For example, if the consumer is looking at a + class_member, it will either be inside the class already, or will have just + looked up the class to find the member. Either way, searching the class is + faster than searching the index. */ + if ((TREE_PUBLIC (decl) && !is_class_die (die->die_parent)) + || is_cu_die (die->die_parent) || is_namespace_die (die->die_parent)) { const char *name = dwarf2_name (decl, 1); + if (name) add_pubname_string (name, die); } } +/* Add an enumerator to the pubtypes section. */ + +static void +add_enumerator_pubname (const char *scope_name, dw_die_ref die) +{ + pubname_entry e; + + gcc_assert (scope_name); + e.name = concat (scope_name, get_AT_string (die, DW_AT_name), NULL); + e.die = die; + VEC_safe_push (pubname_entry, gc, pubtype_table, &e); +} + /* Add a new entry to .debug_pubtypes if appropriate. */ static void @@ -8721,39 +8796,54 @@ add_pubtype (tree decl, dw_die_ref die) { pubname_entry e; - if (!targetm.want_debug_pub_sections) + if (!want_pubnames ()) return; - e.name = NULL; if ((TREE_PUBLIC (decl) - || is_cu_die (die->die_parent)) + || is_cu_die (die->die_parent) || is_namespace_die (die->die_parent)) && (die->die_tag == DW_TAG_typedef || COMPLETE_TYPE_P (decl))) { - e.die = die; - if (TYPE_P (decl)) - { - if (TYPE_NAME (decl)) - { - if (TREE_CODE (TYPE_NAME (decl)) == IDENTIFIER_NODE) - e.name = IDENTIFIER_POINTER (TYPE_NAME (decl)); - else if (TREE_CODE (TYPE_NAME (decl)) == TYPE_DECL - && DECL_NAME (TYPE_NAME (decl))) - e.name = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (decl))); - else - e.name = xstrdup ((const char *) get_AT_string (die, DW_AT_name)); - } + tree scope = NULL; + const char *scope_name = ""; + const char *sep = is_cxx () ? "::" : "."; + const char *name; + + scope = TYPE_P (decl) ? TYPE_CONTEXT (decl) : NULL; + if (scope && TREE_CODE (scope) == NAMESPACE_DECL) + { + scope_name = lang_hooks.dwarf_name (scope, 1); + if (scope_name != NULL && scope_name[0] != '\0') + scope_name = concat (scope_name, sep, NULL); + else + scope_name = ""; } + + if (TYPE_P (decl)) + name = type_tag (decl); else - { - e.name = dwarf2_name (decl, 1); - if (e.name) - e.name = xstrdup (e.name); - } + name = lang_hooks.dwarf_name (decl, 1); /* If we don't have a name for the type, there's no point in adding it to the table. */ - if (e.name && e.name[0] != '\0') - VEC_safe_push (pubname_entry, gc, pubtype_table, &e); + if (name != NULL && name[0] != '\0') + { + e.die = die; + e.name = concat (scope_name, name, NULL); + VEC_safe_push (pubname_entry, gc, pubtype_table, &e); + } + + /* Although it might be more consistent to add the pubinfo for the + enumerators as their dies are created, they should only be added if the + enum type meets the criteria above. So rather than re-check the parent + enum type whenever an enumerator die is created, just output them all + here. This isn't protected by the name conditional because anonymous + enums don't have names. */ + if (die->die_tag == DW_TAG_enumeration_type) + { + dw_die_ref c; + + FOR_EACH_CHILD (die, c, add_enumerator_pubname (scope_name, c)); + } } } @@ -8767,6 +8857,18 @@ output_pubnames (VEC (pubname_entry, gc) * names) unsigned long pubnames_length = size_of_pubnames (names); pubname_ref pub; + if (!want_pubnames () || !info_section_emitted) + return; + if (names == pubname_table) + { + switch_to_section (debug_pubnames_section); + ASM_OUTPUT_LABEL (asm_out_file, debug_pubnames_section_label); + } + else + { + switch_to_section (debug_pubtypes_section); + ASM_OUTPUT_LABEL (asm_out_file, debug_pubtypes_section_label); + } if (DWARF_INITIAL_LENGTH_SIZE - DWARF_OFFSET_SIZE == 4) dw2_asm_output_data (4, 0xffffffff, "Initial length escape value indicating 64-bit DWARF extension"); @@ -8794,8 +8896,23 @@ output_pubnames (VEC (pubname_entry, gc) * names) || pub->die->die_offset != 0 || !flag_eliminate_unused_debug_types) { - dw2_asm_output_data (DWARF_OFFSET_SIZE, pub->die->die_offset, - "DIE offset"); + dw_offset die_offset = pub->die->die_offset; + + /* If we're putting types in their own .debug_types sections, + the .debug_pubtypes table will still point to the compile + unit (not the type unit), so we want to use the offset of + the skeleton DIE (if there is one). */ + if (use_debug_types && names == pubtype_table) + { + comdat_type_node_ref type_node = pub->die->die_id.die_type_node; + + if (type_node != NULL) + die_offset = (type_node->skeleton_die != NULL + ? type_node->skeleton_die->die_offset + : 0); + } + + dw2_asm_output_data (DWARF_OFFSET_SIZE, die_offset, "DIE offset"); dw2_asm_output_nstring (pub->name, -1, "external name"); } @@ -9678,6 +9795,7 @@ base_type_die (tree type) add_AT_unsigned (base_type_result, DW_AT_byte_size, int_size_in_bytes (type)); add_AT_unsigned (base_type_result, DW_AT_encoding, encoding); + add_pubtype (type, base_type_result); return base_type_result; } @@ -16764,8 +16882,7 @@ gen_enumeration_type_die (tree type, dw_die_ref context_die) else add_AT_flag (type_die, DW_AT_declaration, 1); - if (get_AT (type_die, DW_AT_name)) - add_pubtype (type, type_die); + add_pubtype (type, type_die); return type_die; } @@ -17275,6 +17392,7 @@ gen_subprogram_die (tree decl, dw_die_ref context_die) { subr_die = new_die (DW_TAG_subprogram, context_die, decl); add_AT_specification (subr_die, old_die); + add_pubname (decl, subr_die); if (get_AT_file (old_die, DW_AT_decl_file) != file_index) add_AT_file (subr_die, DW_AT_decl_file, file_index); if (get_AT_unsigned (old_die, DW_AT_decl_line) != (unsigned) s.line) @@ -17289,6 +17407,7 @@ gen_subprogram_die (tree decl, dw_die_ref context_die) add_AT_flag (subr_die, DW_AT_external, 1); add_name_and_src_coords_attributes (subr_die, decl); + add_pubname (decl, subr_die); if (debug_info_level > DINFO_LEVEL_TERSE) { add_prototyped_attribute (subr_die, TREE_TYPE (decl)); @@ -17400,7 +17519,6 @@ gen_subprogram_die (tree decl, dw_die_ref context_die) } #endif - add_pubname (decl, subr_die); } else { @@ -17421,7 +17539,6 @@ gen_subprogram_die (tree decl, dw_die_ref context_die) add_ranges_by_labels (subr_die, fde->dw_fde_second_begin, fde->dw_fde_second_end, &range_list_added); - add_pubname (decl, subr_die); if (range_list_added) add_ranges (NULL); } @@ -17443,8 +17560,6 @@ gen_subprogram_die (tree decl, dw_die_ref context_die) fde->dw_fde_begin); add_AT_lbl_id (subr_die, DW_AT_high_pc, fde->dw_fde_end); - /* Add it. */ - add_pubname (decl, subr_die); /* Build a minimal DIE for the secondary section. */ seg_die = new_die (DW_TAG_subprogram, @@ -17473,14 +17588,14 @@ gen_subprogram_die (tree decl, dw_die_ref context_die) add_AT_lbl_id (seg_die, DW_AT_high_pc, fde->dw_fde_second_end); add_name_attribute (seg_die, name); - add_pubname_string (name, seg_die); + if (want_pubnames ()) + add_pubname_string (name, seg_die); } } else { add_AT_lbl_id (subr_die, DW_AT_low_pc, fde->dw_fde_begin); add_AT_lbl_id (subr_die, DW_AT_high_pc, fde->dw_fde_end); - add_pubname (decl, subr_die); } } @@ -17901,7 +18016,8 @@ gen_variable_die (tree decl, tree origin, dw_die_ref context_die) } else if (DECL_EXTERNAL (decl)) add_AT_flag (com_die, DW_AT_declaration, 1); - add_pubname_string (cnam, com_die); /* ??? needed? */ + if (want_pubnames ()) + add_pubname_string (cnam, com_die); /* ??? needed? */ com_die->decl_id = DECL_UID (com_decl); slot = htab_find_slot (common_block_die_table, com_die, INSERT); *slot = (void *) com_die; @@ -19483,6 +19599,9 @@ gen_namespace_die (tree decl, dw_die_ref context_die) add_AT_die_ref (namespace_die, DW_AT_import, origin_die); equate_decl_number_to_die (decl, namespace_die); } + /* Bypass dwarf2_name's check for DECL_NAMELESS. */ + if (want_pubnames ()) + add_pubname_string (lang_hooks.dwarf_name (decl, 1), namespace_die); } /* Generate Dwarf debug information for a decl described by DECL. @@ -21186,6 +21305,10 @@ dwarf2out_init (const char *filename ATTRIBUTE_UNUSED) ASM_GENERATE_INTERNAL_LABEL (debug_info_section_label, DEBUG_INFO_SECTION_LABEL, 0); + ASM_GENERATE_INTERNAL_LABEL (debug_pubnames_section_label, + DEBUG_PUBNAMES_SECTION_LABEL, 0); + ASM_GENERATE_INTERNAL_LABEL (debug_pubtypes_section_label, + DEBUG_PUBTYPES_SECTION_LABEL, 0); ASM_GENERATE_INTERNAL_LABEL (debug_line_section_label, DEBUG_LINE_SECTION_LABEL, 0); ASM_GENERATE_INTERNAL_LABEL (ranges_section_label, @@ -22788,6 +22911,8 @@ dwarf2out_finish (const char *filename) } htab_delete (comdat_type_table); + add_AT_pubnames (comp_unit_die ()); + /* Output the main compilation unit if non-empty or if .debug_macinfo or .debug_macro will be emitted. */ output_comp_unit (comp_unit_die (), have_macinfo); @@ -22811,42 +22936,12 @@ dwarf2out_finish (const char *filename) output_location_lists (comp_unit_die ()); } - /* Output public names table if necessary. */ - if (!VEC_empty (pubname_entry, pubname_table)) - { - gcc_assert (info_section_emitted); - switch_to_section (debug_pubnames_section); - output_pubnames (pubname_table); - } - - /* Output public types table if necessary. */ + /* Output public names and types tables if necessary. */ + output_pubnames (pubname_table); /* ??? Only defined by DWARF3, but emitted by Darwin for DWARF2. It shouldn't hurt to emit it always, since pure DWARF2 consumers simply won't look for the section. */ - if (!VEC_empty (pubname_entry, pubtype_table)) - { - bool empty = false; - - if (flag_eliminate_unused_debug_types) - { - /* The pubtypes table might be emptied by pruning unused items. */ - unsigned i; - pubname_ref p; - empty = true; - FOR_EACH_VEC_ELT (pubname_entry, pubtype_table, i, p) - if (p->die->die_offset != 0) - { - empty = false; - break; - } - } - if (!empty) - { - gcc_assert (info_section_emitted); - switch_to_section (debug_pubtypes_section); - output_pubnames (pubtype_table); - } - } + output_pubnames (pubtype_table); /* Output the address range information if a CU (.debug_info section) was emitted. We output an empty table even if we had no functions diff --git a/gcc/testsuite/g++.dg/debug/dwarf2/pubnames-2.C b/gcc/testsuite/g++.dg/debug/dwarf2/pubnames-2.C new file mode 100644 index 0000000..eef0336 --- /dev/null +++ b/gcc/testsuite/g++.dg/debug/dwarf2/pubnames-2.C @@ -0,0 +1,194 @@ +// { dg-do compile } +// { dg-options "-gpubnames -gdwarf-4 -std=c++0x -dA" } +// { dg-final { scan-assembler ".section\t.debug_pubnames" } } +// { dg-final { scan-assembler "\"\\(anonymous namespace\\)\\\\0\"+\[ \t\]+\[#;]+\[ \t\]+external name" } } +// { dg-final { scan-assembler "\"one\\\\0\"+\[ \t\]+\[#;]+\[ \t\]+external name" } } +// { dg-final { scan-assembler "\"one::G_A\\\\0\"+\[ \t\]+\[#;]+\[ \t\]+external name" } } +// { dg-final { scan-assembler "\"one::G_B\\\\0\"+\[ \t\]+\[#;]+\[ \t\]+external name" } } +// { dg-final { scan-assembler "\"one::G_C\\\\0\"+\[ \t\]+\[#;]+\[ \t\]+external name" } } +// { dg-final { scan-assembler "\"one::\\(anonymous namespace\\)\\\\0\"+\[ \t\]+\[#;]+\[ \t\]+external name" } } +// { dg-final { scan-assembler "\"two\\\\0\"+\[ \t\]+\[#;]+\[ \t\]+external name" } } +// { dg-final { scan-assembler "\"F_A\\\\0\"+\[ \t\]+\[#;]+\[ \t\]+external name" } } +// { dg-final { scan-assembler "\"F_B\\\\0\"+\[ \t\]+\[#;]+\[ \t\]+external name" } } +// { dg-final { scan-assembler "\"F_C\\\\0\"+\[ \t\]+\[#;]+\[ \t\]+external name" } } +// { dg-final { scan-assembler "\"inline_func_1\\\\0\"+\[ \t\]+\[#;]+\[ \t\]+external name" } } +// { dg-final { scan-assembler "\"one::c1::c1\\\\0\"+\[ \t\]+\[#;]+\[ \t\]+external name" } } +// { dg-final { scan-assembler "\"one::c1::~c1\\\\0\"+\[ \t\]+\[#;]+\[ \t\]+external name" } } +// { dg-final { scan-assembler "\"one::c1::val\\\\0\"+\[ \t\]+\[#;]+\[ \t\]+external name" } } +// { dg-final { scan-assembler "\"check_enum\\\\0\"+\[ \t\]+\[#;]+\[ \t\]+external name" } } +// { dg-final { scan-assembler "\"main\\\\0\"+\[ \t\]+\[#;]+\[ \t\]+external name" } } +// { dg-final { scan-assembler "\"two::c2::c2\\\\0\"+\[ \t\]+\[#;]+\[ \t\]+external name" } } +// { dg-final { scan-assembler "\"two::c2::c2\\\\0\"+\[ \t\]+\[#;]+\[ \t\]+external name" } } +// { dg-final { scan-assembler "\"two::c2::c2\\\\0\"+\[ \t\]+\[#;]+\[ \t\]+external name" } } +// { dg-final { scan-assembler "\"check\\\\0\"+\[ \t\]+\[#;]+\[ \t\]+external name" } } +// { dg-final { scan-assembler "\"check \\>\\\\0\"+\[ \t\]+\[#;]+\[ \t\]+external name" } } +// { dg-final { scan-assembler "\"check \\>\\\\0\"+\[ \t\]+\[#;]+\[ \t\]+external name" } } +// { dg-final { scan-assembler "\"check \\>\\\\0\"+\[ \t\]+\[#;]+\[ \t\]+external name" } } +// { dg-final { scan-assembler "\"two::c2::val\\\\0\"+\[ \t\]+\[#;]+\[ \t\]+external name" } } +// { dg-final { scan-assembler "\"two::c2::val\\\\0\"+\[ \t\]+\[#;]+\[ \t\]+external name" } } +// { dg-final { scan-assembler "\"two::c2::val\\\\0\"+\[ \t\]+\[#;]+\[ \t\]+external name" } } +// { dg-final { scan-assembler "\"__static_initialization_and_destruction_0\\\\0\"+\[ \t\]+\[#;]+\[ \t\]+external name" } } +// { dg-final { scan-assembler "\"two::c2::~c2\\\\0\"+\[ \t\]+\[#;]+\[ \t\]+external name" } } +// { dg-final { scan-assembler "\"two::c2::~c2\\\\0\"+\[ \t\]+\[#;]+\[ \t\]+external name" } } +// { dg-final { scan-assembler "\"two::c2::~c2\\\\0\"+\[ \t\]+\[#;]+\[ \t\]+external name" } } +// { dg-final { scan-assembler "\"_GLOBAL__sub_I__ZN3one3c1vE\\\\0\"+\[ \t\]+\[#;]+\[ \t\]+external name" } } +// { dg-final { scan-assembler "\"anonymous_union_var\\\\0\"+\[ \t\]+\[#;]+\[ \t\]+external name" } } +// { dg-final { scan-assembler "\"two::ci\\\\0\"+\[ \t\]+\[#;]+\[ \t\]+external name" } } +// { dg-final { scan-assembler "\"two::c2v1\\\\0\"+\[ \t\]+\[#;]+\[ \t\]+external name" } } +// { dg-final { scan-assembler "\"two::c2v2\\\\0\"+\[ \t\]+\[#;]+\[ \t\]+external name" } } +// { dg-final { scan-assembler "\"two::c2v3\\\\0\"+\[ \t\]+\[#;]+\[ \t\]+external name" } } +// { dg-final { scan-assembler "\"one::c1v\\\\0\"+\[ \t\]+\[#;]+\[ \t\]+external name" } } +// { dg-final { scan-assembler "\"one::\\(anonymous namespace\\)::one_anonymous_var\\\\0\"+\[ \t\]+\[#;]+\[ \t\]+external name" } } +// { dg-final { scan-assembler "\"\\(anonymous namespace\\)::c1_count\\\\0\"+\[ \t\]+\[#;]+\[ \t\]+external name" } } +// { dg-final { scan-assembler "\"\\(anonymous namespace\\)::c2_count\\\\0\"+\[ \t\]+\[#;]+\[ \t\]+external name" } } +// { dg-final { scan-assembler "\"\\(anonymous namespace\\)::three\\\\0\"+\[ \t\]+\[#;]+\[ \t\]+external name" } } +// { dg-final { scan-assembler "\"\\(anonymous namespace\\)::three::anonymous_three_var\\\\0\"+\[ \t\]+\[#;]+\[ \t\]+external name" } } +// { dg-final { scan-assembler ".section\t.debug_pubtypes" } } +// { dg-final { scan-assembler "\"one::G\\\\0\"+\[ \t\]+\[#;]+\[ \t\]+external name" } } +// { dg-final { scan-assembler "\"one::c1\\\\0\"+\[ \t\]+\[#;]+\[ \t\]+external name" } } +// { dg-final { scan-assembler "\"int\\\\0\"+\[ \t\]+\[#;]+\[ \t\]+external name" } } +// { dg-final { scan-assembler "\"one::c1\\\\0\"+\[ \t\]+\[#;]+\[ \t\]+external name" } } +// { dg-final { scan-assembler "\"two::c2\\\\0\"+\[ \t\]+\[#;]+\[ \t\]+external name" } } +// { dg-final { scan-assembler "\"two::c2\\\\0\"+\[ \t\]+\[#;]+\[ \t\]+external name" } } +// { dg-final { scan-assembler "\"two::c2\\\\0\"+\[ \t\]+\[#;]+\[ \t\]+external name" } } +// { dg-final { scan-assembler "\"double\\\\0\"+\[ \t\]+\[#;]+\[ \t\]+external name" } } +// { dg-final { scan-assembler "\"two::c2\\\\0\"+\[ \t\]+\[#;]+\[ \t\]+external name" } } +// { dg-final { scan-assembler "\"two::c2\\\\0\"+\[ \t\]+\[#;]+\[ \t\]+external name" } } +// { dg-final { scan-assembler "\"two::c2\\\\0\"+\[ \t\]+\[#;]+\[ \t\]+external name" } } +// { dg-final { scan-assembler "\"F\\\\0\"+\[ \t\]+\[#;]+\[ \t\]+external name" } } +// { dg-final { scan-assembler "\"anonymous_union_container\\\\0\"+\[ \t\]+\[#;]+\[ \t\]+external name" } } +// { dg-final { scan-assembler "\"bool\\\\0\"+\[ \t\]+\[#;]+\[ \t\]+external name" } } + +namespace +{ +int c1_count; +int c2_count; + +namespace three +{ +int anonymous_three_var; +} +}; + +namespace one +{ + +enum G +{ + G_A, + G_B, + G_C +}; + +namespace { +int one_anonymous_var; +} + +class c1 +{ + public: + static int count; + + c1() + { ++c1_count; } + + ~c1() + { + --c1_count; + } + + enum E + { + E_A, + E_B, + E_C, + }; + + int + val() + { return E_A; } +}; + +c1 c1v; +}; + +namespace two +{ +const int ci = 3; + +template +class c2 +{ + public: + c2(T t) + : t_(t) + { + ++c2_count; + } + + ~c2() + { --c2_count; } + + T + val() + { return this->t_; } + + T t_; +}; + +c2 c2v1(1); +c2 c2v2(2.0); +c2 c2v3(&ci); +}; + +enum F +{ + F_A, + F_B, + F_C +}; + +template +bool +check(C* c) +{ return c->val() == 0; } + +bool +check_enum(int i) +{ return i > 0; } + +struct anonymous_union_container { + union { + struct astruct { + int a; + }; + int b; + } u; +}; + +anonymous_union_container anonymous_union_var; + +#ifdef __GNUC__ +#define ALWAYS_INLINE __attribute__((always_inline)) +#else +#define ALWAYS_INLINE +#endif + +static inline ALWAYS_INLINE int +inline_func_1(int i) +{ return i * 17; } + +int +main() +{ + F f = F_A; + one::G g = one::G_A; + check_enum(f); + check_enum(g); + check(&one::c1v); + check(&two::c2v1); + check(&two::c2v2); + check(&two::c2v3); + anonymous_union_var.u.b = inline_func_1(3) - 51; + return anonymous_union_var.u.b; +}