From 96553a0cffb30d2ac6068eb71bed38ea7432073b Mon Sep 17 00:00:00 2001 From: Doug Evans Date: Sat, 21 Feb 2015 21:58:31 -0800 Subject: [PATCH] PR c++/17976, symtab/17821 This patch addresses two issues. The basic problem is that "(anonymous namespace)" doesn't get entered into the symbol table because when dwarf2read.c:new_symbol_full is called the DIE has no name (dwarf2_name returns NULL). PR 17976: ptype '(anonymous namespace)' should work like any namespace PR 17821: perf issue looking up (anonymous namespace) bash$ gdb monster-program (gdb) mt set per on (gdb) mt set symbol-cache-size 0 (gdb) break (anonymous namespace)::foo Before: Command execution time: 3.266289 (cpu), 6.169030 (wall) Space used: 811429888 (+12910592 for this command) After: Command execution time: 1.264076 (cpu), 4.057408 (wall) Space used: 798781440 (+0 for this command) gdb/ChangeLog: PR c++/17976, symtab/17821 * cp-namespace.c (cp_search_static_and_baseclasses): New parameter is_in_anonymous. All callers updated. (find_symbol_in_baseclass): Ditto. (cp_lookup_nested_symbol_1): Ditto. Don't search all static blocks for symbols in an anonymous namespace. * dwarf2read.c (namespace_name): Don't call dwarf2_name, fetch DW_AT_name directly. (dwarf2_name): Convert missing namespace name to CP_ANONYMOUS_NAMESPACE_STR. gdeb/testsuite/ChangeLog: * gdb.cp/anon-ns.exp: Add test for ptype '(anonymous namespace)'. --- gdb/ChangeLog | 13 ++++++++++++ gdb/cp-namespace.c | 43 ++++++++++++++++++++++++++-------------- gdb/dwarf2read.c | 16 +++++++++++++-- gdb/testsuite/ChangeLog | 4 ++++ gdb/testsuite/gdb.cp/anon-ns.exp | 4 ++++ 5 files changed, 63 insertions(+), 17 deletions(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index b7a72d9..faccd5f 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,16 @@ +2015-02-21 Doug Evans + + PR c++/17976, symtab/17821 + * cp-namespace.c (cp_search_static_and_baseclasses): New parameter + is_in_anonymous. All callers updated. + (find_symbol_in_baseclass): Ditto. + (cp_lookup_nested_symbol_1): Ditto. Don't search all static blocks + for symbols in an anonymous namespace. + * dwarf2read.c (namespace_name): Don't call dwarf2_name, fetch + DW_AT_name directly. + (dwarf2_name): Convert missing namespace name to + CP_ANONYMOUS_NAMESPACE_STR. + 2015-02-20 Pedro Alves * linux-nat.c (linux_handle_extended_wait): Call diff --git a/gdb/cp-namespace.c b/gdb/cp-namespace.c index 2cc2ea9..e278189 100644 --- a/gdb/cp-namespace.c +++ b/gdb/cp-namespace.c @@ -37,7 +37,7 @@ static struct symbol * const char *nested_name, const char *concatenated_name, const struct block *block, - int basic_lookup); + int basic_lookup, int is_in_anonymous); static struct type *cp_lookup_transparent_type_loop (const char *name, const char *scope, @@ -327,7 +327,8 @@ static struct symbol * cp_search_static_and_baseclasses (const char *name, const struct block *block, const domain_enum domain, - unsigned int prefix_len) + unsigned int prefix_len, + int is_in_anonymous) { struct symbol *sym; char *klass, *nested; @@ -366,7 +367,8 @@ cp_search_static_and_baseclasses (const char *name, /* Look for a symbol named NESTED in this class. The caller is assumed to have already have done a basic lookup of NAME. So we pass zero for BASIC_LOOKUP to cp_lookup_nested_symbol_1 here. */ - sym = cp_lookup_nested_symbol_1 (klass_type, nested, name, block, 0); + sym = cp_lookup_nested_symbol_1 (klass_type, nested, name, block, 0, + is_in_anonymous); do_cleanups (cleanup); return sym; @@ -416,7 +418,8 @@ cp_lookup_symbol_in_namespace (const char *namespace, const char *name, return sym; if (search) - sym = cp_search_static_and_baseclasses (name, block, domain, prefix_len); + sym = cp_search_static_and_baseclasses (name, block, domain, prefix_len, + is_in_anonymous); return sym; } @@ -900,7 +903,7 @@ cp_find_type_baseclass_by_name (struct type *parent_type, const char *name) static struct symbol * find_symbol_in_baseclass (struct type *parent_type, const char *name, - const struct block *block) + const struct block *block, int is_in_anonymous) { int i; struct symbol *sym; @@ -925,7 +928,7 @@ find_symbol_in_baseclass (struct type *parent_type, const char *name, xsnprintf (concatenated_name, len, "%s::%s", base_name, name); sym = cp_lookup_nested_symbol_1 (base_type, name, concatenated_name, - block, 1); + block, 1, is_in_anonymous); if (sym != NULL) break; } @@ -942,16 +945,17 @@ find_symbol_in_baseclass (struct type *parent_type, const char *name, passed as an argument so that callers can control how space for it is allocated. If BASIC_LOOKUP is non-zero then perform a basic lookup of - CONCATENATED_NAME. See cp_basic_lookup_symbol for details. */ + CONCATENATED_NAME. See cp_basic_lookup_symbol for details. + If IS_IN_ANONYMOUS is non-zero then CONCATENATED_NAME is in an anonymous + namespace. */ static struct symbol * cp_lookup_nested_symbol_1 (struct type *container_type, const char *nested_name, const char *concatenated_name, const struct block *block, - int basic_lookup) + int basic_lookup, int is_in_anonymous) { - int is_in_anonymous = cp_is_in_anonymous (concatenated_name); struct symbol *sym; /* NOTE: carlton/2003-11-10: We don't treat C++ class members @@ -981,16 +985,22 @@ cp_lookup_nested_symbol_1 (struct type *container_type, /* Nope. We now have to search all static blocks in all objfiles, even if block != NULL, because there's no guarantees as to which - symtab the symbol we want is in. */ - sym = lookup_static_symbol (concatenated_name, VAR_DOMAIN); - if (sym != NULL) - return sym; + symtab the symbol we want is in. Except for symbols defined in + anonymous namespaces should be treated as local to a single file, + which we just searched. */ + if (!is_in_anonymous) + { + sym = lookup_static_symbol (concatenated_name, VAR_DOMAIN); + if (sym != NULL) + return sym; + } /* If this is a class with baseclasses, search them next. */ CHECK_TYPEDEF (container_type); if (TYPE_N_BASECLASSES (container_type) > 0) { - sym = find_symbol_in_baseclass (container_type, nested_name, block); + sym = find_symbol_in_baseclass (container_type, nested_name, block, + is_in_anonymous); if (sym != NULL) return sym; } @@ -1038,14 +1048,17 @@ cp_lookup_nested_symbol (struct type *parent_type, const char *parent_name = type_name_no_tag_or_error (saved_parent_type); struct symbol *sym; char *concatenated_name; + int is_in_anonymous; size = strlen (parent_name) + 2 + strlen (nested_name) + 1; concatenated_name = alloca (size); xsnprintf (concatenated_name, size, "%s::%s", parent_name, nested_name); + is_in_anonymous = cp_is_in_anonymous (concatenated_name); sym = cp_lookup_nested_symbol_1 (parent_type, nested_name, - concatenated_name, block, 1); + concatenated_name, block, 1, + is_in_anonymous); if (symbol_lookup_debug) { diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c index a764389..ac78165 100644 --- a/gdb/dwarf2read.c +++ b/gdb/dwarf2read.c @@ -14109,7 +14109,12 @@ namespace_name (struct die_info *die, int *is_anonymous, struct dwarf2_cu *cu) current_die != NULL; current_die = dwarf2_extension (die, &cu)) { - name = dwarf2_name (current_die, cu); + /* We don't use dwarf2_name here so that we can detect the absence + of a name -> anonymous namespace. */ + struct attribute *attr = dwarf2_attr (die, DW_AT_name, cu); + + if (attr != NULL) + name = DW_STRING (attr); if (name != NULL) break; } @@ -19253,7 +19258,8 @@ dwarf2_canonicalize_name (const char *name, struct dwarf2_cu *cu, return name; } -/* Get name of a die, return NULL if not found. */ +/* Get name of a die, return NULL if not found. + Anonymous namespaces are converted to their magic string. */ static const char * dwarf2_name (struct die_info *die, struct dwarf2_cu *cu) @@ -19262,6 +19268,7 @@ dwarf2_name (struct die_info *die, struct dwarf2_cu *cu) attr = dwarf2_attr (die, DW_AT_name, cu); if ((!attr || !DW_STRING (attr)) + && die->tag != DW_TAG_namespace && die->tag != DW_TAG_class_type && die->tag != DW_TAG_interface_type && die->tag != DW_TAG_structure_type @@ -19280,6 +19287,11 @@ dwarf2_name (struct die_info *die, struct dwarf2_cu *cu) to canonicalize them. */ return DW_STRING (attr); + case DW_TAG_namespace: + if (attr != NULL && DW_STRING (attr) != NULL) + return DW_STRING (attr); + return CP_ANONYMOUS_NAMESPACE_STR; + case DW_TAG_subprogram: /* Java constructors will all be named "", so return the class name when we see this special case. */ diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog index dbcc4f6..bc3bdd9 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2015-02-21 Doug Evans + + * gdb.cp/anon-ns.exp: Add test for ptype '(anonymous namespace)'. + 2015-02-21 Jan Kratochvil PR corefiles/17808 diff --git a/gdb/testsuite/gdb.cp/anon-ns.exp b/gdb/testsuite/gdb.cp/anon-ns.exp index ab9da14..d817435 100644 --- a/gdb/testsuite/gdb.cp/anon-ns.exp +++ b/gdb/testsuite/gdb.cp/anon-ns.exp @@ -64,5 +64,9 @@ foreach test $methods { } } +# PR c++/17976 +gdb_test "ptype '(anonymous namespace)'" \ + "type = namespace \\\(anonymous namespace\\\)" + gdb_exit return 0 -- 2.7.4