* [patch] Perform a namespace lookup at every block level @ 2009-07-10 15:10 Sami Wagiaalla 2009-07-10 20:16 ` Daniel Jacobowitz 0 siblings, 1 reply; 28+ messages in thread From: Sami Wagiaalla @ 2009-07-10 15:10 UTC (permalink / raw) To: GDB Patches Now that import information is stored in the nearest block, this patch changes things so that a namespace lookup is correctly performed at every block level. 2009-07-09 Sami Wagiaalla <swagiaal@redhat.com> * symtab.c: Import cp-support.h. (lookup_symbol_aux_local): Continue lookup through static block and stop at global block. Do a namespace at each block level via lookup_namespace_scope. Now takes 'enum language' argument. * cp-support.h: Added extern lookup_namespace_scope prototype. * cp-namespace.c (lookup_namespace_scope): Removed static qualifier. (cp_lookup_symbol_nonlocal): Calls lookup_symbol_file if call to lookup_namespace_scope fails. (cp_lookup_symbol_namespace): Return NULL if no namespace is specified. 2009-07-09 Sami Wagiaalla <swagiaal@redhat.com> * gdb.cp/namespace-using.exp: Add test for printing of namespaces imported into file scope. * gdb.cp/namespace-using.cc (marker5): New function. diff --git a/gdb/cp-namespace.c b/gdb/cp-namespace.c index d2d8f2e..75cac01 100644 --- a/gdb/cp-namespace.c +++ b/gdb/cp-namespace.c @@ -35,13 +35,6 @@ static struct using_direct *cp_copy_usings (struct using_direct *using, struct obstack *obstack); -static struct symbol *lookup_namespace_scope (const char *name, - const char *linkage_name, - const struct block *block, - const domain_enum domain, - const char *scope, - int scope_len); - static struct symbol *lookup_symbol_file (const char *name, const char *linkage_name, const struct block *block, @@ -265,8 +258,15 @@ cp_lookup_symbol_nonlocal (const char *name, const struct block *block, const domain_enum domain) { - return lookup_namespace_scope (name, linkage_name, block, domain, + struct symbol *sym; + + sym = lookup_namespace_scope (name, linkage_name, block, domain, block_scope (block), 0); + if ( sym != NULL) + return sym; + + return lookup_symbol_file (name, linkage_name, block, + domain, 0); } /* Lookup NAME at namespace scope (or, in C terms, in static and @@ -284,7 +284,7 @@ cp_lookup_symbol_nonlocal (const char *name, "A::x", and if that call fails, then the first call looks for "x". */ -static struct symbol * +struct symbol * lookup_namespace_scope (const char *name, const char *linkage_name, const struct block *block, @@ -364,8 +364,7 @@ cp_lookup_symbol_namespace (const char *namespace, if (namespace[0] == '\0') { - return lookup_symbol_file (name, linkage_name, block, - domain, 0); + return NULL; } else { diff --git a/gdb/cp-support.h b/gdb/cp-support.h index b5a5c5f..2016024 100644 --- a/gdb/cp-support.h +++ b/gdb/cp-support.h @@ -101,6 +101,13 @@ extern struct symbol *cp_lookup_symbol_nonlocal (const char *name, const struct block *block, const domain_enum domain); +extern struct symbol *lookup_namespace_scope (const char *name, + const char *linkage_name, + const struct block *block, + const domain_enum domain, + const char *scope, + int scope_len); + extern struct symbol *cp_lookup_symbol_namespace (const char *namespace, const char *name, const char *linkage_name, diff --git a/gdb/symtab.c b/gdb/symtab.c index 009c52d..ca6a476 100644 --- a/gdb/symtab.c +++ b/gdb/symtab.c @@ -42,6 +42,7 @@ #include "ada-lang.h" #include "p-lang.h" #include "addrmap.h" +#include "cp-support.h" #include "hashtab.h" @@ -95,7 +96,8 @@ static struct symbol *lookup_symbol_aux_local (const char *name, const char *linkage_name, const struct block *block, - const domain_enum domain); + const domain_enum domain, + enum language language); static struct symbol *lookup_symbol_aux_symtabs (int block_index, @@ -1291,7 +1293,7 @@ lookup_symbol_aux (const char *name, const char *linkage_name, /* Search specified block and its superiors. Don't search STATIC_BLOCK or GLOBAL_BLOCK. */ - sym = lookup_symbol_aux_local (name, linkage_name, block, domain); + sym = lookup_symbol_aux_local (name, linkage_name, block, domain, language); if (sym != NULL) return sym; @@ -1361,27 +1363,41 @@ lookup_symbol_aux (const char *name, const char *linkage_name, } /* Check to see if the symbol is defined in BLOCK or its superiors. - Don't search STATIC_BLOCK or GLOBAL_BLOCK. */ + Don't search GLOBAL_BLOCK. + In the case of C++ perform a namespace lookup and every block. */ static struct symbol * lookup_symbol_aux_local (const char *name, const char *linkage_name, const struct block *block, - const domain_enum domain) + const domain_enum domain, + enum language language) { struct symbol *sym; - const struct block *static_block = block_static_block (block); + const struct block *global_block = block_global_block (block); + const struct language_defn *langdef; + + langdef = language_def (language); /* Check if either no block is specified or it's a global block. */ - if (static_block == NULL) + if (global_block == NULL) return NULL; - while (block != static_block) + while (block != global_block) { sym = lookup_symbol_aux_block (name, linkage_name, block, domain); if (sym != NULL) return sym; + if ( language == language_cplus ) + { + sym = lookup_namespace_scope (name, linkage_name, block, domain, + block_scope (block), 0); + + if (sym != NULL) + return sym; + } + if (BLOCK_FUNCTION (block) != NULL && block_inlined_p (block)) break; block = BLOCK_SUPERBLOCK (block); diff --git a/gdb/testsuite/gdb.cp/namespace-using.cc b/gdb/testsuite/gdb.cp/namespace-using.cc index 4786fd5..00fd47f 100644 --- a/gdb/testsuite/gdb.cp/namespace-using.cc +++ b/gdb/testsuite/gdb.cp/namespace-using.cc @@ -4,12 +4,26 @@ namespace A int x = 2; } -int marker4(){ - using A::x; - return 0; +namespace C +{ + int cc = 3; +} + +using namespace C; +int marker5() +{ + cc; + return 0; } -int marker3(){ +int marker4() +{ + using A::x; + return marker5(); +} + +int marker3() +{ return marker4(); } diff --git a/gdb/testsuite/gdb.cp/namespace-using.exp b/gdb/testsuite/gdb.cp/namespace-using.exp index f24973f..210bfd7 100644 --- a/gdb/testsuite/gdb.cp/namespace-using.exp +++ b/gdb/testsuite/gdb.cp/namespace-using.exp @@ -28,6 +28,10 @@ if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {deb return -1 } +if [get_compiler_info ${binfile}] { + return -1; +} + # Get things started. gdb_exit @@ -73,7 +77,13 @@ gdb_test "print B::a" "= 1" gdb_breakpoint "marker3" gdb_continue_to_breakpoint "marker3" -gdb_test "print _a" "No symbol \"_a\" in current context." "Print a without import" +# gcc-4-3 puts import statements for aliases in +# the global scope instead of the corresponding +# function scope. These wrong import statements throw +# this test off. This is fixed in gcc-4-4. +if [test_compiler_info gcc-4-3-*] then { setup_xfail *-*-* } + +gdb_test "print _a" "No symbol \"_a\" in current context." "Print _a without import" ############################################ # Test printing of individually imported elements @@ -85,3 +95,15 @@ if ![runto marker4] then { } gdb_test "print x" "= 2" + + +############################################ +# test printing of namespace imported into +# file scope. + +if ![runto marker5] then { + perror "couldn't run to marker5" + continue +} + +gdb_test "print cc" "= 3" ^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [patch] Perform a namespace lookup at every block level 2009-07-10 15:10 [patch] Perform a namespace lookup at every block level Sami Wagiaalla @ 2009-07-10 20:16 ` Daniel Jacobowitz 2009-07-13 17:55 ` Sami Wagiaalla 0 siblings, 1 reply; 28+ messages in thread From: Daniel Jacobowitz @ 2009-07-10 20:16 UTC (permalink / raw) To: Sami Wagiaalla; +Cc: GDB Patches On Fri, Jul 10, 2009 at 10:33:14AM -0400, Sami Wagiaalla wrote: > Now that import information is stored in the nearest block, > this patch changes things so that a namespace lookup is correctly > performed at every block level. Where in the overall search order are block-level using directives supposed to fall according to the standard? And where does this patch put them? It looks to me like this change causes the global scope to be searched too early (and too often). Given this: int a; int foo() { int a; if (...) { breakpoint_here; } } If we do a namespace scope search for a in the inner block, we'll find the copy in this file instead of the enclosing local. -- Daniel Jacobowitz CodeSourcery ^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [patch] Perform a namespace lookup at every block level 2009-07-10 20:16 ` Daniel Jacobowitz @ 2009-07-13 17:55 ` Sami Wagiaalla 2009-07-23 19:46 ` Sami Wagiaalla 0 siblings, 1 reply; 28+ messages in thread From: Sami Wagiaalla @ 2009-07-13 17:55 UTC (permalink / raw) To: Sami Wagiaalla, GDB Patches > Where in the overall search order are block-level using directives > supposed to fall according to the standard? And where does this patch > put them? > > It looks to me like this change causes the global scope to be searched > too early (and too often). Given this: > Yes, it is searched too early. imports such as: using namespace A should not be applied until the function level lookup fails. However, imports of type: using A::a are applied at the block level and take priority over higher lexical scope variables. So they will require per-block lookup, but that is another patch for another feature. I will correct this patch. Sami ^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [patch] Perform a namespace lookup at every block level 2009-07-13 17:55 ` Sami Wagiaalla @ 2009-07-23 19:46 ` Sami Wagiaalla 2009-07-23 22:19 ` Sami Wagiaalla ` (3 more replies) 0 siblings, 4 replies; 28+ messages in thread From: Sami Wagiaalla @ 2009-07-23 19:46 UTC (permalink / raw) To: Sami Wagiaalla, GDB Patches > > I will correct this patch. > I started correcting the patch by changing cp_lookup_symbol_nonlocal to iterate over blocks outwards calling lookup_namespace_scope which in turn calls cp_lookup_symbol_namespace. cp_lookup_symbol_namespace did two things look in the current namespace as well as examine applicable imports. I realized that we didnt need to examine imports at each scope level. We can simply look at the import destination. This patch separates the two kinds of lookups (imports and scopes) and performs the import lookup at every block level. Thoughts ? 2009-07-23 Sami Wagiaalla <swagiaal@redhat.com> * symtab.c (lookup_symbol_aux): Pass lowest level block to la_lookup_symbol_nonlocal. * cp-namespace.c (lookup_namespace_scope): Rename to cp_lookup_namespace_scope. Remove 'static' qualifier. (cp_lookup_symbol_nonlocal): Separate scope lookup from import lookup. Perform import lookup at every block level. (cp_lookup_symbol_namespace): Remove import search. (cp_lookup_symbol_imports): New function. * dwarf2read.c (read_lexical_block_scope): Create blocks for scopes which contain only import statements. 2009-07-22 Sami Wagiaalla <swagiaal@redhat.com> * gdb.cp/namespace-using.exp: Add test for printing of namespaces imported into file scope. Marked test as xfail. * gdb.cp/namespace-using.cc (marker5): New function. diff --git a/gdb/cp-namespace.c b/gdb/cp-namespace.c index d2d8f2e..5d82172 100644 --- a/gdb/cp-namespace.c +++ b/gdb/cp-namespace.c @@ -42,6 +42,12 @@ static struct symbol *lookup_namespace_scope (const char *name, const char *scope, int scope_len); +static struct symbol *cp_lookup_symbol_imports (const char *scope, + const char *name, + const char *linkage_name, + const struct block *block, + const domain_enum domain); + static struct symbol *lookup_symbol_file (const char *name, const char *linkage_name, const struct block *block, @@ -265,8 +271,26 @@ cp_lookup_symbol_nonlocal (const char *name, const struct block *block, const domain_enum domain) { - return lookup_namespace_scope (name, linkage_name, block, domain, + struct symbol *sym; + + sym = lookup_namespace_scope (name, linkage_name, block, domain, block_scope (block), 0); + if (sym) + return sym; + + while (block != NULL) + { + sym = cp_lookup_symbol_imports(block_scope (block), + name, linkage_name, + block, domain); + + if (sym) + return sym; + + block = BLOCK_SUPERBLOCK(block); + } + + return NULL; } /* Lookup NAME at namespace scope (or, in C terms, in static and @@ -324,8 +348,7 @@ lookup_namespace_scope (const char *name, block, domain); } -/* Look up NAME in the C++ namespace NAMESPACE, applying the using - directives that are active in BLOCK. Other arguments are as in +/* Look up NAME in the C++ namespace NAMESPACE. Other arguments are as in cp_lookup_symbol_nonlocal. */ struct symbol * @@ -335,10 +358,39 @@ cp_lookup_symbol_namespace (const char *namespace, const struct block *block, const domain_enum domain) { + + if (namespace[0] == '\0') + { + return lookup_symbol_file (name, linkage_name, block, + domain, 0); + } + else + { + char *concatenated_name + = alloca (strlen (namespace) + 2 + strlen (name) + 1); + strcpy (concatenated_name, namespace); + strcat (concatenated_name, "::"); + strcat (concatenated_name, name); + return lookup_symbol_file (concatenated_name, linkage_name, + block, domain, + cp_is_anonymous (namespace)); + } +} + +/* Search for NAME by applying all import statements belonging + to BLOCK which are applicable in SCOPE. */ + +static struct symbol * +cp_lookup_symbol_imports (const char *scope, + const char *name, + const char *linkage_name, + const struct block *block, + const domain_enum domain) +{ const struct using_direct *current; struct symbol *sym; - /* First, go through the using directives. If any of them add new + /* Go through the using directives. If any of them add new names to the namespace we're searching in, see if we can find a match by applying them. */ @@ -346,7 +398,10 @@ cp_lookup_symbol_namespace (const char *namespace, current != NULL; current = current->next) { - if (strcmp (namespace, current->import_dest) == 0) + + /* If the import destination is the current scope or one of its ancestors then + it is applicable. */ + if (strncmp (scope, current->import_dest, strlen(current->import_dest)) == 0) { sym = cp_lookup_symbol_namespace (current->import_src, name, @@ -358,27 +413,7 @@ cp_lookup_symbol_namespace (const char *namespace, } } - /* We didn't find anything by applying any of the using directives - that are still applicable; so let's see if we've got a match - using the current namespace. */ - - if (namespace[0] == '\0') - { - return lookup_symbol_file (name, linkage_name, block, - domain, 0); - } - else - { - char *concatenated_name - = alloca (strlen (namespace) + 2 + strlen (name) + 1); - strcpy (concatenated_name, namespace); - strcat (concatenated_name, "::"); - strcat (concatenated_name, name); - sym = lookup_symbol_file (concatenated_name, linkage_name, - block, domain, - cp_is_anonymous (namespace)); - return sym; - } + return NULL; } /* Look up NAME in BLOCK's static block and in global blocks. If diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c index 445bab8..f18d804 100644 --- a/gdb/dwarf2read.c +++ b/gdb/dwarf2read.c @@ -3922,7 +3922,7 @@ read_lexical_block_scope (struct die_info *die, struct dwarf2_cu *cu) } new = pop_context (); - if (local_symbols != NULL) + if (local_symbols != NULL || using_directives != NULL) { struct block *block = finish_block (0, &local_symbols, new->old_blocks, new->start_addr, diff --git a/gdb/symtab.c b/gdb/symtab.c index 009c52d..16ca673 100644 --- a/gdb/symtab.c +++ b/gdb/symtab.c @@ -1304,13 +1304,14 @@ lookup_symbol_aux (const char *name, const char *linkage_name, && block != NULL) { struct symbol *sym = NULL; + const struct block *function_block = block; /* 'this' is only defined in the function's block, so find the enclosing function block. */ - for (; block && !BLOCK_FUNCTION (block); - block = BLOCK_SUPERBLOCK (block)); + for (; function_block && !BLOCK_FUNCTION (function_block); + function_block = BLOCK_SUPERBLOCK (function_block)); - if (block && !dict_empty (BLOCK_DICT (block))) - sym = lookup_block_symbol (block, langdef->la_name_of_this, + if (function_block && !dict_empty (BLOCK_DICT (function_block))) + sym = lookup_block_symbol (function_block, langdef->la_name_of_this, NULL, VAR_DOMAIN); if (sym) { @@ -1334,11 +1335,14 @@ lookup_symbol_aux (const char *name, const char *linkage_name, return NULL; } } - } - /* Now do whatever is appropriate for LANGUAGE to look - up static and global variables. */ + /* C++ language specific lookup requires the lowest block level. */ + if (language != language_cplus) + block = function_block; + + } + /* Now do whatever is appropriate for LANGUAGE specific lookup. */ sym = langdef->la_lookup_symbol_nonlocal (name, linkage_name, block, domain); if (sym != NULL) return sym; diff --git a/gdb/testsuite/gdb.cp/namespace-using.cc b/gdb/testsuite/gdb.cp/namespace-using.cc index 4786fd5..091b4cc 100644 --- a/gdb/testsuite/gdb.cp/namespace-using.cc +++ b/gdb/testsuite/gdb.cp/namespace-using.cc @@ -1,3 +1,16 @@ +namespace C +{ + int cc = 3; +} + +using namespace C; +int marker5() +{ + cc; + return 0; +} + + namespace A { int _a = 1; @@ -6,7 +19,7 @@ namespace A int marker4(){ using A::x; - return 0; + return marker5(); } int marker3(){ diff --git a/gdb/testsuite/gdb.cp/namespace-using.exp b/gdb/testsuite/gdb.cp/namespace-using.exp index f24973f..bd1016b 100644 --- a/gdb/testsuite/gdb.cp/namespace-using.exp +++ b/gdb/testsuite/gdb.cp/namespace-using.exp @@ -28,6 +28,11 @@ if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {deb return -1 } +if [get_compiler_info ${binfile}] { + return -1; +} + + # Get things started. gdb_exit @@ -73,7 +78,13 @@ gdb_test "print B::a" "= 1" gdb_breakpoint "marker3" gdb_continue_to_breakpoint "marker3" -gdb_test "print _a" "No symbol \"_a\" in current context." "Print a without import" +# gcc-4-3 puts import statements for aliases in +# the global scope instead of the corresponding +# function scope. These wrong import statements throw +# this test off. This is fixed in gcc-4-4. +if [test_compiler_info gcc-4-3-*] then { setup_xfail *-*-* } + +gdb_test "print _a" "No symbol \"_a\" in current context." "Print _a without import" ############################################ # Test printing of individually imported elements @@ -85,3 +96,14 @@ if ![runto marker4] then { } gdb_test "print x" "= 2" + +############################################ +# test printing of namespace imported into +# file scope. + +if ![runto marker5] then { + perror "couldn't run to marker5" + continue +} + +gdb_test "print cc" "= 3" ^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [patch] Perform a namespace lookup at every block level 2009-07-23 19:46 ` Sami Wagiaalla @ 2009-07-23 22:19 ` Sami Wagiaalla 2009-07-29 22:12 ` Tom Tromey ` (2 subsequent siblings) 3 siblings, 0 replies; 28+ messages in thread From: Sami Wagiaalla @ 2009-07-23 22:19 UTC (permalink / raw) To: Sami Wagiaalla, GDB Patches > + /* C++ language specific lookup requires the lowest block level. */ > + if (language != language_cplus) > + block = function_block; > + > + } I dont know if resetting the pointer is needed by other languages. I saw no test failures without it. I just did it to preserve the code for other languages in case I am missing something. Sami ^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [patch] Perform a namespace lookup at every block level 2009-07-23 19:46 ` Sami Wagiaalla 2009-07-23 22:19 ` Sami Wagiaalla @ 2009-07-29 22:12 ` Tom Tromey 2009-08-18 20:34 ` [patch 1/2] " Sami Wagiaalla 2009-08-18 20:46 ` [patch 2/2] " Sami Wagiaalla 3 siblings, 0 replies; 28+ messages in thread From: Tom Tromey @ 2009-07-29 22:12 UTC (permalink / raw) To: Sami Wagiaalla; +Cc: GDB Patches >>>>> "Sami" == Sami Wagiaalla <swagiaal@redhat.com> writes: Sami> This patch separates the two kinds of lookups (imports and scopes) and Sami> performs the import lookup at every block level. Just FYI, Sami said that he's found some bugs in this patch and he'll be sending a new one soon. So, if you were thinking of reviewing it, don't :-) Tom ^ permalink raw reply [flat|nested] 28+ messages in thread
* [patch 1/2] Perform a namespace lookup at every block level 2009-07-23 19:46 ` Sami Wagiaalla 2009-07-23 22:19 ` Sami Wagiaalla 2009-07-29 22:12 ` Tom Tromey @ 2009-08-18 20:34 ` Sami Wagiaalla 2009-10-13 19:47 ` Tom Tromey 2009-08-18 20:46 ` [patch 2/2] " Sami Wagiaalla 3 siblings, 1 reply; 28+ messages in thread From: Sami Wagiaalla @ 2009-08-18 20:34 UTC (permalink / raw) To: Sami Wagiaalla, GDB Patches > cp_lookup_symbol_namespace did two things look in the current namespace > as well as examine applicable imports. I realized that we didnt need to > examine imports at each scope level. We can simply look at the import > destination. > > This patch separates the two kinds of lookups (imports and scopes) and > performs the import lookup at every block level. > Same as above, but I fixed a couple of issues with the previous patch. The first issue is that even while we iterate over blocks the original scope should be used. Secondly, the call to lookup_symbol_name space in valops.c must also perform a per block search. The final issue is recursive search which is discussed in part 2 of this patch. ---- 2009-08-11 Sami Wagiaalla <swagiaal@redhat.com> * dwarf2read.c (read_lexical_block_scope): Create blocks for scopes which contain using directives even if they contain no declarations. * symtab.c (lookup_symbol_aux): Pass lowest level block to la_lookup_symbol_nonlocal. * cp-namespace.c (cp_lookup_symbol_nonlocal): call cp_lookup_symbol_namespace. (cp_lookup_symbol_namespace): Perform an import lookup at every block level. (cp_lookup_symbol_imports): New function. (cp_lookup_symbol_in_namespace): New function. 2009-08-11 Sami Wagiaalla <swagiaal@redhat.com> * gdb.cp/namespace-using.exp: Add test for printing of namespaces imported into file scope. Marked test as xfail. * gdb.cp/namespace-using.cc (marker5): New function. diff --git a/gdb/cp-namespace.c b/gdb/cp-namespace.c index d2d8f2e..a0ccd7f 100644 --- a/gdb/cp-namespace.c +++ b/gdb/cp-namespace.c @@ -42,6 +42,18 @@ static struct symbol *lookup_namespace_scope (const char *name, const char *scope, int scope_len); +static struct symbol *cp_lookup_symbol_imports (const char *scope, + const char *name, + const char *linkage_name, + const struct block *block, + const domain_enum domain); + +static struct symbol *cp_lookup_symbol_in_namespace (const char *namespace, + const char *name, + const char *linkage_name, + const struct block *block, + const domain_enum domain); + static struct symbol *lookup_symbol_file (const char *name, const char *linkage_name, const struct block *block, @@ -265,8 +277,41 @@ cp_lookup_symbol_nonlocal (const char *name, const struct block *block, const domain_enum domain) { - return lookup_namespace_scope (name, linkage_name, block, domain, - block_scope (block), 0); + struct symbol *sym; + const char *scope = block_scope (block); + + sym = lookup_namespace_scope (name, linkage_name, block, domain, scope, 0); + if ( sym != NULL) + return sym; + + return cp_lookup_symbol_namespace(scope, name, linkage_name, block, domain); +} + +/* Searches for NAME in the current namespace, and by applying relevant import + statements belonging to BLOCK and its parents. SCOPE is the namespace scope + of the context in which the search is being evaluated. */ + +struct symbol* +cp_lookup_symbol_namespace (const char *scope, + const char *name, + const char *linkage_name, + const struct block *block, + const domain_enum domain) +{ + struct symbol *sym; + + /* Search for name in namespaces imported to this and parent blocks. */ + while (block != NULL) + { + sym = cp_lookup_symbol_imports(scope,name, linkage_name, block, domain); + + if (sym) + return sym; + + block = BLOCK_SUPERBLOCK(block); + } + + return NULL; } /* Lookup NAME at namespace scope (or, in C terms, in static and @@ -320,25 +365,59 @@ lookup_namespace_scope (const char *name, namespace = alloca (scope_len + 1); strncpy (namespace, scope, scope_len); namespace[scope_len] = '\0'; - return cp_lookup_symbol_namespace (namespace, name, linkage_name, + return cp_lookup_symbol_in_namespace (namespace, name, linkage_name, block, domain); } -/* Look up NAME in the C++ namespace NAMESPACE, applying the using - directives that are active in BLOCK. Other arguments are as in +/* Look up NAME in the C++ namespace NAMESPACE. Other arguments are as in cp_lookup_symbol_nonlocal. */ -struct symbol * -cp_lookup_symbol_namespace (const char *namespace, - const char *name, - const char *linkage_name, - const struct block *block, - const domain_enum domain) +static struct symbol * +cp_lookup_symbol_in_namespace (const char *namespace, + const char *name, + const char *linkage_name, + const struct block *block, + const domain_enum domain) +{ + + if (namespace[0] == '\0') + { + return lookup_symbol_file (name, linkage_name, block, + domain, 0); + } + else + { + char *concatenated_name + = alloca (strlen (namespace) + 2 + strlen (name) + 1); + strcpy (concatenated_name, namespace); + strcat (concatenated_name, "::"); + strcat (concatenated_name, name); + return lookup_symbol_file (concatenated_name, linkage_name, + block, domain, + cp_is_anonymous (namespace)); + } +} + +/* Search for NAME by applying all import statements belonging + to BLOCK which are applicable in SCOPE. */ + +static struct symbol * +cp_lookup_symbol_imports (const char *scope, + const char *name, + const char *linkage_name, + const struct block *block, + const domain_enum domain) { const struct using_direct *current; struct symbol *sym; - /* First, go through the using directives. If any of them add new + /* First, try to find the symbol in the given namespace. */ + sym = cp_lookup_symbol_in_namespace (scope, name, linkage_name, block, + domain); + if ( sym != NULL) + return sym; + + /* Go through the using directives. If any of them add new names to the namespace we're searching in, see if we can find a match by applying them. */ @@ -346,9 +425,12 @@ cp_lookup_symbol_namespace (const char *namespace, current != NULL; current = current->next) { - if (strcmp (namespace, current->import_dest) == 0) + + /* If the import destination is the current scope or one of its ancestors then + it is applicable. */ + if (strncmp (scope, current->import_dest, strlen(current->import_dest)) == 0) { - sym = cp_lookup_symbol_namespace (current->import_src, + sym = cp_lookup_symbol_in_namespace (current->import_src, name, linkage_name, block, @@ -358,27 +440,7 @@ cp_lookup_symbol_namespace (const char *namespace, } } - /* We didn't find anything by applying any of the using directives - that are still applicable; so let's see if we've got a match - using the current namespace. */ - - if (namespace[0] == '\0') - { - return lookup_symbol_file (name, linkage_name, block, - domain, 0); - } - else - { - char *concatenated_name - = alloca (strlen (namespace) + 2 + strlen (name) + 1); - strcpy (concatenated_name, namespace); - strcat (concatenated_name, "::"); - strcat (concatenated_name, name); - sym = lookup_symbol_file (concatenated_name, linkage_name, - block, domain, - cp_is_anonymous (namespace)); - return sym; - } + return NULL; } /* Look up NAME in BLOCK's static block and in global blocks. If @@ -461,7 +523,7 @@ cp_lookup_nested_type (struct type *parent_type, lookup_symbol_namespace works when looking them up. */ const char *parent_name = TYPE_TAG_NAME (parent_type); - struct symbol *sym = cp_lookup_symbol_namespace (parent_name, + struct symbol *sym = cp_lookup_symbol_in_namespace (parent_name, nested_name, NULL, block, diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c index 445bab8..f18d804 100644 --- a/gdb/dwarf2read.c +++ b/gdb/dwarf2read.c @@ -3922,7 +3922,7 @@ read_lexical_block_scope (struct die_info *die, struct dwarf2_cu *cu) } new = pop_context (); - if (local_symbols != NULL) + if (local_symbols != NULL || using_directives != NULL) { struct block *block = finish_block (0, &local_symbols, new->old_blocks, new->start_addr, diff --git a/gdb/symtab.c b/gdb/symtab.c index c88156a..cebbb4b 100644 --- a/gdb/symtab.c +++ b/gdb/symtab.c @@ -1304,13 +1304,14 @@ lookup_symbol_aux (const char *name, const char *linkage_name, && block != NULL) { struct symbol *sym = NULL; + const struct block *function_block = block; /* 'this' is only defined in the function's block, so find the enclosing function block. */ - for (; block && !BLOCK_FUNCTION (block); - block = BLOCK_SUPERBLOCK (block)); + for (; function_block && !BLOCK_FUNCTION (function_block); + function_block = BLOCK_SUPERBLOCK (function_block)); - if (block && !dict_empty (BLOCK_DICT (block))) - sym = lookup_block_symbol (block, langdef->la_name_of_this, + if (function_block && !dict_empty (BLOCK_DICT (function_block))) + sym = lookup_block_symbol (function_block, langdef->la_name_of_this, NULL, VAR_DOMAIN); if (sym) { @@ -1334,11 +1335,14 @@ lookup_symbol_aux (const char *name, const char *linkage_name, return NULL; } } - } - /* Now do whatever is appropriate for LANGUAGE to look - up static and global variables. */ + /* C++ language specific lookup requires the lowest block level. */ + if (language != language_cplus) + block = function_block; + + } + /* Now do whatever is appropriate for LANGUAGE specific lookup. */ sym = langdef->la_lookup_symbol_nonlocal (name, linkage_name, block, domain); if (sym != NULL) return sym; diff --git a/gdb/testsuite/gdb.cp/namespace-using.cc b/gdb/testsuite/gdb.cp/namespace-using.cc index 4786fd5..091b4cc 100644 --- a/gdb/testsuite/gdb.cp/namespace-using.cc +++ b/gdb/testsuite/gdb.cp/namespace-using.cc @@ -1,3 +1,16 @@ +namespace C +{ + int cc = 3; +} + +using namespace C; +int marker5() +{ + cc; + return 0; +} + + namespace A { int _a = 1; @@ -6,7 +19,7 @@ namespace A int marker4(){ using A::x; - return 0; + return marker5(); } int marker3(){ diff --git a/gdb/testsuite/gdb.cp/namespace-using.exp b/gdb/testsuite/gdb.cp/namespace-using.exp index f24973f..bd1016b 100644 --- a/gdb/testsuite/gdb.cp/namespace-using.exp +++ b/gdb/testsuite/gdb.cp/namespace-using.exp @@ -28,6 +28,11 @@ if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {deb return -1 } +if [get_compiler_info ${binfile}] { + return -1; +} + + # Get things started. gdb_exit @@ -73,7 +78,13 @@ gdb_test "print B::a" "= 1" gdb_breakpoint "marker3" gdb_continue_to_breakpoint "marker3" -gdb_test "print _a" "No symbol \"_a\" in current context." "Print a without import" +# gcc-4-3 puts import statements for aliases in +# the global scope instead of the corresponding +# function scope. These wrong import statements throw +# this test off. This is fixed in gcc-4-4. +if [test_compiler_info gcc-4-3-*] then { setup_xfail *-*-* } + +gdb_test "print _a" "No symbol \"_a\" in current context." "Print _a without import" ############################################ # Test printing of individually imported elements @@ -85,3 +96,14 @@ if ![runto marker4] then { } gdb_test "print x" "= 2" + +############################################ +# test printing of namespace imported into +# file scope. + +if ![runto marker5] then { + perror "couldn't run to marker5" + continue +} + +gdb_test "print cc" "= 3" ^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [patch 1/2] Perform a namespace lookup at every block level 2009-08-18 20:34 ` [patch 1/2] " Sami Wagiaalla @ 2009-10-13 19:47 ` Tom Tromey 2009-10-20 20:50 ` Sami Wagiaalla 0 siblings, 1 reply; 28+ messages in thread From: Tom Tromey @ 2009-10-13 19:47 UTC (permalink / raw) To: Sami Wagiaalla; +Cc: GDB Patches >>>>> "Sami" == Sami Wagiaalla <swagiaal@redhat.com> writes: Sami> Same as above, but I fixed a couple of issues with the previous patch. Sami> The first issue is that even while we iterate over blocks the original Sami> scope should be used. Secondly, the call to lookup_symbol_name space Sami> in valops.c must also perform a per block search. The final issue is Sami> recursive search which is discussed in part 2 of this patch. Sorry about the delay on this. For best results, ping a pending patch every week or two -- the lack of a response can mean either that everybody is busy or that everybody somehow missed the posting entirely, and there's no way to tell the difference. Sami> @@ -265,8 +277,41 @@ cp_lookup_symbol_nonlocal (const char *name, [...] Sami> + if ( sym != NULL) Extra space after the "(". Sami> + return cp_lookup_symbol_namespace(scope, name, linkage_name, block, domain); Missing a space before "(". There are several of these. Sami> +static struct symbol * Sami> +cp_lookup_symbol_imports (const char *scope, Sami> + const char *name, Sami> + const char *linkage_name, Sami> + const struct block *block, Sami> + const domain_enum domain) [...] Sami> + if ( sym != NULL) The extra space again :) Sami> @@ -1304,13 +1304,14 @@ lookup_symbol_aux (const char *name, const char *linkage_name, [...] Sami> + /* C++ language specific lookup requires the lowest block level. */ Sami> + if (language != language_cplus) Sami> + block = function_block; I like to avoid special cases for a specific language in the generic code. These make gdb more brittle over time; also they make it harder to understand. One alternative approach would be to pass `block' as an argument to the la_lookup_symbol_nonlocal method. This would mean adding an ignored parameter to most of the implementations of this method, but that is no big deal, we've done that sort of thing before. Sami> diff --git a/gdb/testsuite/gdb.cp/namespace-using.cc b/gdb/testsuite/gdb.cp/namespace-using.cc I think this needs more tests. At the very least it should have a test case for the bug Daniel pointed out upthread, but I think it would be good to have tests for other confounding cases. Tom ^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [patch 1/2] Perform a namespace lookup at every block level 2009-10-13 19:47 ` Tom Tromey @ 2009-10-20 20:50 ` Sami Wagiaalla 2009-11-10 22:23 ` Tom Tromey 0 siblings, 1 reply; 28+ messages in thread From: Sami Wagiaalla @ 2009-10-20 20:50 UTC (permalink / raw) To: tromey; +Cc: GDB Patches > Sorry about the delay on this. Thanks for the review. I fixed the mentioned formatting issues. I also got rid of the static prototypes in the patch and rearranged the functions as needed. > Sami> @@ -1304,13 +1304,14 @@ lookup_symbol_aux (const char *name, const char *linkage_name, > [...] > Sami> + /* C++ language specific lookup requires the lowest block level. */ > Sami> + if (language != language_cplus) > Sami> + block = function_block; > > I like to avoid special cases for a specific language in the generic > code. These make gdb more brittle over time; also they make it harder > to understand. > This is actually not needed. As I mentioned up-thread I put it there to preserve the status quo for languages other than c++. I looked further into it. All languages with the exception of c++ and ADA use basic_lookup_symbol_nonlocal, cp_lookup_symbol_nonlocal, and ada_lookup_symbol_nonlocal. cp_lookup_symbol_nonlocal is the only function which makes an assumption about which block is passed to it. The other functions retrieve the desired block explicitly via block_static_block (block) or block_global_block (block). So it is gone! > Sami> diff --git a/gdb/testsuite/gdb.cp/namespace-using.cc b/gdb/testsuite/gdb.cp/namespace-using.cc > > I think this needs more tests. At the very least it should have a test > case for the bug Daniel pointed out upthread, but I think it would be > good to have tests for other confounding cases. I have added shadowing.exp to the patch which belongs to a future patch but has some good tests, and it tests for the problem pointed out by Daniel. I also added namespace-multiple-imports.exp. Excuse the kfails; they will be fixed by a future patch. 2009-10-20 Sami Wagiaalla <swagiaal@redhat.com> * dwarf2read.c (read_lexical_block_scope): Create blocks for scopes which contain using directives even if they contain no declarations. * symtab.c (lookup_symbol_aux): Pass lowest level block to la_lookup_symbol_nonlocal. * cp-namespace.c (cp_lookup_symbol_nonlocal): call cp_lookup_symbol_namespace. (cp_lookup_symbol_namespace): Perform an import lookup at every block level. (cp_lookup_symbol_imports): New function. (cp_lookup_symbol_in_namespace): New function. 2009-10-20 Sami Wagiaalla <swagiaal@redhat.com> * gdb.cp/namespace-using.exp: Add test for printing of namespaces imported into file scope. Marked test as xfail. * gdb.cp/namespace-using.cc (marker5): New function. * gdb.cp/shadowing.exp: New test. * gdb.cp/shadowing.cc: New test program. diff --git a/gdb/cp-namespace.c b/gdb/cp-namespace.c index d2d8f2e..06a5486 100644 --- a/gdb/cp-namespace.c +++ b/gdb/cp-namespace.c @@ -265,8 +265,115 @@ cp_lookup_symbol_nonlocal (const char *name, const struct block *block, const domain_enum domain) { - return lookup_namespace_scope (name, linkage_name, block, domain, - block_scope (block), 0); + struct symbol *sym; + const char *scope = block_scope (block); + + sym = lookup_namespace_scope (name, linkage_name, block, domain, scope, 0); + if (sym != NULL) + return sym; + + return cp_lookup_symbol_namespace (scope, name, linkage_name, block, domain); +} + +/* Look up NAME in the C++ namespace NAMESPACE. Other arguments are as in + cp_lookup_symbol_nonlocal. */ + +static struct symbol * +cp_lookup_symbol_in_namespace (const char *namespace, + const char *name, + const char *linkage_name, + const struct block *block, + const domain_enum domain) +{ + + if (namespace[0] == '\0') + { + return lookup_symbol_file (name, linkage_name, block, + domain, 0); + } + else + { + char *concatenated_name = alloca (strlen (namespace) + 2 + + strlen (name+ 1)); + strcpy (concatenated_name, namespace); + strcat (concatenated_name, "::"); + strcat (concatenated_name, name); + return lookup_symbol_file (concatenated_name, linkage_name, + block, domain,cp_is_anonymous (namespace)); + } +} + +/* Search for NAME by applying all import statements belonging + to BLOCK which are applicable in SCOPE. */ + +static struct symbol * +cp_lookup_symbol_imports (const char *scope, + const char *name, + const char *linkage_name, + const struct block *block, + const domain_enum domain) +{ + const struct using_direct *current; + struct symbol *sym; + + /* First, try to find the symbol in the given namespace. */ + sym = cp_lookup_symbol_in_namespace (scope, name, linkage_name, block, + domain); + if (sym != NULL) + return sym; + + /* Go through the using directives. If any of them add new + names to the namespace we're searching in, see if we can find a + match by applying them. */ + + for (current = block_using (block); + current != NULL; + current = current->next) + { + + /* If the import destination is the current scope or one of its ancestors then + it is applicable. */ + if (strncmp (scope, current->import_dest, strlen (current->import_dest)) == 0) + { + sym = cp_lookup_symbol_in_namespace (current->import_src, + name, + linkage_name, + block, + domain); + if (sym != NULL) + return sym; + } + } + + return NULL; +} + + + /* Searches for NAME in the current namespace, and by applying relevant import + statements belonging to BLOCK and its parents. SCOPE is the namespace scope + of the context in which the search is being evaluated. */ + +struct symbol* +cp_lookup_symbol_namespace (const char *scope, + const char *name, + const char *linkage_name, + const struct block *block, + const domain_enum domain) +{ + struct symbol *sym; + + /* Search for name in namespaces imported to this and parent blocks. */ + while (block != NULL) + { + sym = cp_lookup_symbol_imports (scope,name, linkage_name, block, domain); + + if (sym) + return sym; + + block = BLOCK_SUPERBLOCK (block); + } + + return NULL; } /* Lookup NAME at namespace scope (or, in C terms, in static and @@ -320,65 +427,8 @@ lookup_namespace_scope (const char *name, namespace = alloca (scope_len + 1); strncpy (namespace, scope, scope_len); namespace[scope_len] = '\0'; - return cp_lookup_symbol_namespace (namespace, name, linkage_name, - block, domain); -} - -/* Look up NAME in the C++ namespace NAMESPACE, applying the using - directives that are active in BLOCK. Other arguments are as in - cp_lookup_symbol_nonlocal. */ - -struct symbol * -cp_lookup_symbol_namespace (const char *namespace, - const char *name, - const char *linkage_name, - const struct block *block, - const domain_enum domain) -{ - const struct using_direct *current; - struct symbol *sym; - - /* First, go through the using directives. If any of them add new - names to the namespace we're searching in, see if we can find a - match by applying them. */ - - for (current = block_using (block); - current != NULL; - current = current->next) - { - if (strcmp (namespace, current->import_dest) == 0) - { - sym = cp_lookup_symbol_namespace (current->import_src, - name, - linkage_name, - block, - domain); - if (sym != NULL) - return sym; - } - } - - /* We didn't find anything by applying any of the using directives - that are still applicable; so let's see if we've got a match - using the current namespace. */ - - if (namespace[0] == '\0') - { - return lookup_symbol_file (name, linkage_name, block, - domain, 0); - } - else - { - char *concatenated_name - = alloca (strlen (namespace) + 2 + strlen (name) + 1); - strcpy (concatenated_name, namespace); - strcat (concatenated_name, "::"); - strcat (concatenated_name, name); - sym = lookup_symbol_file (concatenated_name, linkage_name, - block, domain, - cp_is_anonymous (namespace)); - return sym; - } + return cp_lookup_symbol_in_namespace (namespace, name, linkage_name, + block, domain); } /* Look up NAME in BLOCK's static block and in global blocks. If @@ -461,11 +511,11 @@ cp_lookup_nested_type (struct type *parent_type, lookup_symbol_namespace works when looking them up. */ const char *parent_name = TYPE_TAG_NAME (parent_type); - struct symbol *sym = cp_lookup_symbol_namespace (parent_name, - nested_name, - NULL, - block, - VAR_DOMAIN); + struct symbol *sym = cp_lookup_symbol_in_namespace (parent_name, + nested_name, + NULL, + block, + VAR_DOMAIN); if (sym == NULL || SYMBOL_CLASS (sym) != LOC_TYPEDEF) return NULL; else diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c index 69a7242..c2b2e3c 100644 --- a/gdb/dwarf2read.c +++ b/gdb/dwarf2read.c @@ -3920,7 +3920,7 @@ read_lexical_block_scope (struct die_info *die, struct dwarf2_cu *cu) } new = pop_context (); - if (local_symbols != NULL) + if (local_symbols != NULL || using_directives != NULL) { struct block *block = finish_block (0, &local_symbols, new->old_blocks, new->start_addr, diff --git a/gdb/symtab.c b/gdb/symtab.c index 8d9d72c..dfa8f48 100644 --- a/gdb/symtab.c +++ b/gdb/symtab.c @@ -1304,13 +1304,14 @@ lookup_symbol_aux (const char *name, const char *linkage_name, && block != NULL) { struct symbol *sym = NULL; + const struct block *function_block = block; /* 'this' is only defined in the function's block, so find the enclosing function block. */ - for (; block && !BLOCK_FUNCTION (block); - block = BLOCK_SUPERBLOCK (block)); + for (; function_block && !BLOCK_FUNCTION (function_block); + function_block = BLOCK_SUPERBLOCK (function_block)); - if (block && !dict_empty (BLOCK_DICT (block))) - sym = lookup_block_symbol (block, langdef->la_name_of_this, + if (function_block && !dict_empty (BLOCK_DICT (function_block))) + sym = lookup_block_symbol (function_block, langdef->la_name_of_this, NULL, VAR_DOMAIN); if (sym) { diff --git a/gdb/testsuite/gdb.cp/namespace-using.cc b/gdb/testsuite/gdb.cp/namespace-using.cc index 4786fd5..762a508 100644 --- a/gdb/testsuite/gdb.cp/namespace-using.cc +++ b/gdb/testsuite/gdb.cp/namespace-using.cc @@ -1,3 +1,16 @@ +namespace C +{ + int cc = 3; +} + +using namespace C; +int marker5 () +{ + cc; + return 0; +} + + namespace A { int _a = 1; @@ -6,7 +19,7 @@ namespace A int marker4(){ using A::x; - return 0; + return marker5 (); } int marker3(){ diff --git a/gdb/testsuite/gdb.cp/namespace-using.cc.orig b/gdb/testsuite/gdb.cp/namespace-using.cc.orig new file mode 100644 index 0000000..4786fd5 --- /dev/null +++ b/gdb/testsuite/gdb.cp/namespace-using.cc.orig @@ -0,0 +1,45 @@ +namespace A +{ + int _a = 1; + int x = 2; +} + +int marker4(){ + using A::x; + return 0; +} + +int marker3(){ + return marker4(); +} + +int marker2() +{ + namespace B = A; + B::_a; + return marker3(); +} + +int marker1() +{ + int total = 0; + { + int b = 1; + { + using namespace A; + int c = 2; + { + int d = 3; + total = _a + b + c + d + marker2(); // marker1 stop + } + } + } + return total; +} + +int main() +{ + using namespace A; + _a; + return marker1(); +} diff --git a/gdb/testsuite/gdb.cp/namespace-using.exp b/gdb/testsuite/gdb.cp/namespace-using.exp index f24973f..bd1016b 100644 --- a/gdb/testsuite/gdb.cp/namespace-using.exp +++ b/gdb/testsuite/gdb.cp/namespace-using.exp @@ -28,6 +28,11 @@ if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {deb return -1 } +if [get_compiler_info ${binfile}] { + return -1; +} + + # Get things started. gdb_exit @@ -73,7 +78,13 @@ gdb_test "print B::a" "= 1" gdb_breakpoint "marker3" gdb_continue_to_breakpoint "marker3" -gdb_test "print _a" "No symbol \"_a\" in current context." "Print a without import" +# gcc-4-3 puts import statements for aliases in +# the global scope instead of the corresponding +# function scope. These wrong import statements throw +# this test off. This is fixed in gcc-4-4. +if [test_compiler_info gcc-4-3-*] then { setup_xfail *-*-* } + +gdb_test "print _a" "No symbol \"_a\" in current context." "Print _a without import" ############################################ # Test printing of individually imported elements @@ -85,3 +96,14 @@ if ![runto marker4] then { } gdb_test "print x" "= 2" + +############################################ +# test printing of namespace imported into +# file scope. + +if ![runto marker5] then { + perror "couldn't run to marker5" + continue +} + +gdb_test "print cc" "= 3" diff --git a/gdb/testsuite/gdb.cp/shadowing.cc b/gdb/testsuite/gdb.cp/shadowing.cc new file mode 100644 index 0000000..1651510 --- /dev/null +++ b/gdb/testsuite/gdb.cp/shadowing.cc @@ -0,0 +1,45 @@ +namespace A +{ + int x = 11; +} + +int x = 22; +int y = 0; + +class B +{ +public: + int x; + + int + func() + { + x = 33; + y++; // marker1 + + { + int x = 44; + y++; // marker2 + + { + int x = 55; + y++; // marker3 + + { + using namespace A; + y++; // marker4 + + using A::x; + y++; // marker5 + } + } + } + } +}; + +int +main() +{ + B theB; + return theB.func(); +} diff --git a/gdb/testsuite/gdb.cp/shadowing.exp b/gdb/testsuite/gdb.cp/shadowing.exp new file mode 100644 index 0000000..443881e --- /dev/null +++ b/gdb/testsuite/gdb.cp/shadowing.exp @@ -0,0 +1,86 @@ +# Copyright 2008 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +if $tracelevel then { + strace $tracelevel +} + +set prms_id 0 +set bug_id 0 + +set testfile shadowing +set srcfile ${testfile}.cc +set binfile ${objdir}/${subdir}/${testfile} +if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug c++}] != "" } { + untested "Couldn't compile test program" + return -1 +} + +# Get things started. + +gdb_exit +gdb_start +gdb_reinitialize_dir $srcdir/$subdir +gdb_load ${binfile} + +if ![runto_main] then { + perror "couldn't run to breakpoint main" + continue +} + +############################################ +# Test printing of class variable is not shadowed +# by global variable + +gdb_breakpoint [gdb_get_line_number "marker1"] +gdb_continue_to_breakpoint "marker1" + +gdb_test "print x" "= 33" "Print class x shadowing global x" + + +############################################ +# Test printing local variable is not shadowed +# by class variable + +gdb_breakpoint [gdb_get_line_number "marker2"] +gdb_continue_to_breakpoint "marker2" + +gdb_test "print x" "= 44" "Print local x shadowing class x" + +############################################ +# Test inner scope x is printed not outer scope + +gdb_breakpoint [gdb_get_line_number "marker3"] +gdb_continue_to_breakpoint "marker3" + +gdb_test "print x" "= 55" "Print inner scope x" + +############################################ +# Test printing local variable is not shadowed +# by namespace variable + +gdb_breakpoint [gdb_get_line_number "marker4"] +gdb_continue_to_breakpoint "marker4" + +gdb_test "print x" "= 55" "Print local x not namespace x" + +############################################ +# Test imported namespace element is printed + +gdb_breakpoint [gdb_get_line_number "marker5"] +gdb_continue_to_breakpoint "marker5" + +setup_kfail "gdb/7936" "*-*-*" +gdb_test "print x" "= 11" "Print imported namespace x" ^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [patch 1/2] Perform a namespace lookup at every block level 2009-10-20 20:50 ` Sami Wagiaalla @ 2009-11-10 22:23 ` Tom Tromey 2009-11-10 22:26 ` Tom Tromey 0 siblings, 1 reply; 28+ messages in thread From: Tom Tromey @ 2009-11-10 22:23 UTC (permalink / raw) To: Sami Wagiaalla; +Cc: GDB Patches >>>>> "Sami" == Sami Wagiaalla <swagiaal@redhat.com> writes: Sami> I have added shadowing.exp to the patch which belongs to a future Sami> patch but has some good tests, and it tests for the problem Sami> pointed out by Daniel. I also added Sami> namespace-multiple-imports.exp. Excuse the kfails; they will be Sami> fixed by a future patch. Thanks. Sami> +static struct symbol * Sami> +cp_lookup_symbol_in_namespace (const char *namespace, Sami> + const char *name, Sami> + const char *linkage_name, Sami> + const struct block *block, Sami> + const domain_enum domain) Sami> +{ Sami> + Extra blank line. Sami> +static struct symbol * Sami> +cp_lookup_symbol_imports (const char *scope, Sami> + const char *name, Sami> + const char *linkage_name, Sami> + const struct block *block, Sami> + const domain_enum domain) [...] Sami> + /* If the import destination is the current scope or one of its ancestors then Does this line go past column 80? It looks like it. Sami> + it is applicable. */ Sami> + if (strncmp (scope, current->import_dest, strlen (current->import_dest)) == 0) From my reading this doesn't exactly match the comment -- can current->import_dest be an extension of scope? Like, if scope is "x" and import_dest is "xyz"? Sami> diff --git a/gdb/testsuite/gdb.cp/namespace-using.exp b/gdb/testsuite/gdb.cp/namespace-using.exp Sami> + return -1; No ";" here. Otherwise this looks good. Tom ^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [patch 1/2] Perform a namespace lookup at every block level 2009-11-10 22:23 ` Tom Tromey @ 2009-11-10 22:26 ` Tom Tromey 2009-11-16 15:32 ` Sami Wagiaalla 0 siblings, 1 reply; 28+ messages in thread From: Tom Tromey @ 2009-11-10 22:26 UTC (permalink / raw) To: Sami Wagiaalla; +Cc: GDB Patches >>>>> "Tom" == Tom Tromey <tromey@redhat.com> writes: Sami> + it is applicable. */ Sami> + if (strncmp (scope, current->import_dest, strlen (current->import_dest)) == 0) Tom> From my reading this doesn't exactly match the comment -- can Tom> current-> import_dest be an extension of scope? Like, if scope is "x" Tom> and import_dest is "xyz"? So, I sent that and then immediately realized I have no idea what I was thinking, since it doesn't make sense. This patch is ok with the few minor lexical fixes I pointed out. Thanks. Tom ^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [patch 1/2] Perform a namespace lookup at every block level 2009-11-10 22:26 ` Tom Tromey @ 2009-11-16 15:32 ` Sami Wagiaalla 2009-11-16 19:16 ` Sami Wagiaalla 2009-11-24 19:06 ` Sami Wagiaalla 0 siblings, 2 replies; 28+ messages in thread From: Sami Wagiaalla @ 2009-11-16 15:32 UTC (permalink / raw) To: Tom Tromey; +Cc: GDB Patches Tom Tromey wrote: >>>>>> "Tom" == Tom Tromey <tromey@redhat.com> writes: > > Sami> + it is applicable. */ > Sami> + if (strncmp (scope, current->import_dest, strlen (current->import_dest)) == 0) > > Tom> From my reading this doesn't exactly match the comment -- can > Tom> current-> import_dest be an extension of scope? Like, if scope is "x" > Tom> and import_dest is "xyz"? > > So, I sent that and then immediately realized I have no idea what I was > thinking, since it doesn't make sense. > So the above situation is not possible but the reverse is; scope = "xyz" and import_dest = "x" as is the case in this example if we are stopped at 'foo': namespace A { int x; } namespace XYZ { int foo (){ return 1; } } namespace X{ using namespace A; } I fixed that like by adding this: + len = strlen (current->import_dest); + if (strncmp (scope, current->import_dest, len) == 0 + && (scope[len] == ':' || scope[len] == '\0')) + { I also added a test case. New patch: 2009-11-16 Sami Wagiaalla <swagiaal@redhat.com> * dwarf2read.c (read_lexical_block_scope): Create blocks for scopes which contain using directives even if they contain no declarations. * symtab.c (lookup_symbol_aux): Pass lowest level block to la_lookup_symbol_nonlocal. * cp-namespace.c (cp_lookup_symbol_nonlocal): call cp_lookup_symbol_namespace. (cp_lookup_symbol_namespace): Perform an import lookup at every block level. (cp_lookup_symbol_imports): New function. (cp_lookup_symbol_in_namespace): New function. 2009-11-16 Sami Wagiaalla <swagiaal@redhat.com> * gdb.cp/namespace-using.exp: Add test for printing of namespaces imported into file scope. Marked test as xfail. * gdb.cp/namespace-using.cc (marker5): New function. * gdb.cp/shadowing.exp: New test. * gdb.cp/shadowing.cc: New test program. * gdb.cp/namespace-multiple-imports.exp: New test. * gdb.cp/namespace-multiple-imports.cc: New test program. diff --git a/gdb/cp-namespace.c b/gdb/cp-namespace.c index d2d8f2e..1980681 100644 --- a/gdb/cp-namespace.c +++ b/gdb/cp-namespace.c @@ -265,8 +265,114 @@ cp_lookup_symbol_nonlocal (const char *name, const struct block *block, const domain_enum domain) { - return lookup_namespace_scope (name, linkage_name, block, domain, - block_scope (block), 0); + struct symbol *sym; + const char *scope = block_scope (block); + + sym = lookup_namespace_scope (name, linkage_name, block, domain, scope, 0); + if (sym != NULL) + return sym; + + return cp_lookup_symbol_namespace (scope, name, linkage_name, block, domain); +} + +/* Look up NAME in the C++ namespace NAMESPACE. Other arguments are as in + cp_lookup_symbol_nonlocal. */ + +static struct symbol * +cp_lookup_symbol_in_namespace (const char *namespace, + const char *name, + const char *linkage_name, + const struct block *block, + const domain_enum domain) +{ + if (namespace[0] == '\0') + { + return lookup_symbol_file (name, linkage_name, block, + domain, 0); + } + else + { + char *concatenated_name = alloca (strlen (namespace) + 2 + + strlen (name+ 1)); + strcpy (concatenated_name, namespace); + strcat (concatenated_name, "::"); + strcat (concatenated_name, name); + return lookup_symbol_file (concatenated_name, linkage_name, + block, domain,cp_is_anonymous (namespace)); + } +} + +/* Search for NAME by applying all import statements belonging + to BLOCK which are applicable in SCOPE. */ + +static struct symbol * +cp_lookup_symbol_imports (const char *scope, + const char *name, + const char *linkage_name, + const struct block *block, + const domain_enum domain) +{ + const struct using_direct *current; + struct symbol *sym; + int len; + + /* First, try to find the symbol in the given namespace. */ + sym = cp_lookup_symbol_in_namespace (scope, name, linkage_name, block, + domain); + if (sym != NULL) + return sym; + + /* Go through the using directives. If any of them add new + names to the namespace we're searching in, see if we can find a + match by applying them. */ + + for (current = block_using (block); + current != NULL; + current = current->next) + { + + /* If the import destination is the current scope or one of its ancestors then + it is applicable. */ + len = strlen (current->import_dest); + if (strncmp (scope, current->import_dest, len) == 0 + && (scope[len] == ':' || scope[len] == '\0')) + { + sym = cp_lookup_symbol_in_namespace (current->import_src, name, + linkage_name, block, domain); + if (sym != NULL) + return sym; + } + } + + return NULL; +} + + + /* Searches for NAME in the current namespace, and by applying relevant import + statements belonging to BLOCK and its parents. SCOPE is the namespace scope + of the context in which the search is being evaluated. */ + +struct symbol* +cp_lookup_symbol_namespace (const char *scope, + const char *name, + const char *linkage_name, + const struct block *block, + const domain_enum domain) +{ + struct symbol *sym; + + /* Search for name in namespaces imported to this and parent blocks. */ + while (block != NULL) + { + sym = cp_lookup_symbol_imports (scope,name, linkage_name, block, domain); + + if (sym) + return sym; + + block = BLOCK_SUPERBLOCK (block); + } + + return NULL; } /* Lookup NAME at namespace scope (or, in C terms, in static and @@ -320,65 +426,8 @@ lookup_namespace_scope (const char *name, namespace = alloca (scope_len + 1); strncpy (namespace, scope, scope_len); namespace[scope_len] = '\0'; - return cp_lookup_symbol_namespace (namespace, name, linkage_name, - block, domain); -} - -/* Look up NAME in the C++ namespace NAMESPACE, applying the using - directives that are active in BLOCK. Other arguments are as in - cp_lookup_symbol_nonlocal. */ - -struct symbol * -cp_lookup_symbol_namespace (const char *namespace, - const char *name, - const char *linkage_name, - const struct block *block, - const domain_enum domain) -{ - const struct using_direct *current; - struct symbol *sym; - - /* First, go through the using directives. If any of them add new - names to the namespace we're searching in, see if we can find a - match by applying them. */ - - for (current = block_using (block); - current != NULL; - current = current->next) - { - if (strcmp (namespace, current->import_dest) == 0) - { - sym = cp_lookup_symbol_namespace (current->import_src, - name, - linkage_name, - block, - domain); - if (sym != NULL) - return sym; - } - } - - /* We didn't find anything by applying any of the using directives - that are still applicable; so let's see if we've got a match - using the current namespace. */ - - if (namespace[0] == '\0') - { - return lookup_symbol_file (name, linkage_name, block, - domain, 0); - } - else - { - char *concatenated_name - = alloca (strlen (namespace) + 2 + strlen (name) + 1); - strcpy (concatenated_name, namespace); - strcat (concatenated_name, "::"); - strcat (concatenated_name, name); - sym = lookup_symbol_file (concatenated_name, linkage_name, - block, domain, - cp_is_anonymous (namespace)); - return sym; - } + return cp_lookup_symbol_in_namespace (namespace, name, linkage_name, + block, domain); } /* Look up NAME in BLOCK's static block and in global blocks. If @@ -461,11 +510,11 @@ cp_lookup_nested_type (struct type *parent_type, lookup_symbol_namespace works when looking them up. */ const char *parent_name = TYPE_TAG_NAME (parent_type); - struct symbol *sym = cp_lookup_symbol_namespace (parent_name, - nested_name, - NULL, - block, - VAR_DOMAIN); + struct symbol *sym = cp_lookup_symbol_in_namespace (parent_name, + nested_name, + NULL, + block, + VAR_DOMAIN); if (sym == NULL || SYMBOL_CLASS (sym) != LOC_TYPEDEF) return NULL; else diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c index 69a7242..c2b2e3c 100644 --- a/gdb/dwarf2read.c +++ b/gdb/dwarf2read.c @@ -3920,7 +3920,7 @@ read_lexical_block_scope (struct die_info *die, struct dwarf2_cu *cu) } new = pop_context (); - if (local_symbols != NULL) + if (local_symbols != NULL || using_directives != NULL) { struct block *block = finish_block (0, &local_symbols, new->old_blocks, new->start_addr, diff --git a/gdb/symtab.c b/gdb/symtab.c index 8d9d72c..dfa8f48 100644 --- a/gdb/symtab.c +++ b/gdb/symtab.c @@ -1304,13 +1304,14 @@ lookup_symbol_aux (const char *name, const char *linkage_name, && block != NULL) { struct symbol *sym = NULL; + const struct block *function_block = block; /* 'this' is only defined in the function's block, so find the enclosing function block. */ - for (; block && !BLOCK_FUNCTION (block); - block = BLOCK_SUPERBLOCK (block)); + for (; function_block && !BLOCK_FUNCTION (function_block); + function_block = BLOCK_SUPERBLOCK (function_block)); - if (block && !dict_empty (BLOCK_DICT (block))) - sym = lookup_block_symbol (block, langdef->la_name_of_this, + if (function_block && !dict_empty (BLOCK_DICT (function_block))) + sym = lookup_block_symbol (function_block, langdef->la_name_of_this, NULL, VAR_DOMAIN); if (sym) { diff --git a/gdb/testsuite/gdb.cp/namespace-multiple-imports.cc b/gdb/testsuite/gdb.cp/namespace-multiple-imports.cc new file mode 100644 index 0000000..6b180d6 --- /dev/null +++ b/gdb/testsuite/gdb.cp/namespace-multiple-imports.cc @@ -0,0 +1,20 @@ +namespace A { + int x = 11; + namespace{ + int xx = 22; + } +} + +using namespace A; + +namespace{ + int xxx = 33; +}; + +int main() +{ + x; + xx; + xxx; + return 0; +} diff --git a/gdb/testsuite/gdb.cp/namespace-multiple-imports.exp b/gdb/testsuite/gdb.cp/namespace-multiple-imports.exp new file mode 100644 index 0000000..e4bb9f8 --- /dev/null +++ b/gdb/testsuite/gdb.cp/namespace-multiple-imports.exp @@ -0,0 +1,49 @@ +# Copyright 2008 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +if $tracelevel then { + strace $tracelevel +} + +set prms_id 0 +set bug_id 0 + +set testfile namespace-multiple-imports +set srcfile ${testfile}.cc +set binfile ${objdir}/${subdir}/${testfile} +if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug c++}] != "" } { + untested "Couldn't compile test program" + return -1 +} + +# Get things started. + +gdb_exit +gdb_start +gdb_reinitialize_dir $srcdir/$subdir +gdb_load ${binfile} + +############################################ +# test printing of namespace imported within +# the function. + +if ![runto_main] then { + perror "couldn't run to breakpoint main" + continue +} + +gdb_test "print x" "\\$\[0-9\].* = 11" +gdb_test "print xx" "\\$\[0-9\].* = 22" +gdb_test "print xxx" "\\$\[0-9\].* = 33" diff --git a/gdb/testsuite/gdb.cp/namespace-using.cc b/gdb/testsuite/gdb.cp/namespace-using.cc index 4786fd5..8d9ea67 100644 --- a/gdb/testsuite/gdb.cp/namespace-using.cc +++ b/gdb/testsuite/gdb.cp/namespace-using.cc @@ -1,3 +1,35 @@ +namespace O +{ + int ox = 4; +} + +namespace PQ +{ + int marker6 () + { + return 0; + } +} + +namespace P +{ + using namespace O; +} + +//-------------- +namespace C +{ + int cc = 3; +} + +using namespace C; +int marker5 () +{ + cc; + return PQ::marker6 (); +} + + namespace A { int _a = 1; @@ -6,7 +38,7 @@ namespace A int marker4(){ using A::x; - return 0; + return marker5 (); } int marker3(){ diff --git a/gdb/testsuite/gdb.cp/namespace-using.cc.orig b/gdb/testsuite/gdb.cp/namespace-using.cc.orig new file mode 100644 index 0000000..4786fd5 --- /dev/null +++ b/gdb/testsuite/gdb.cp/namespace-using.cc.orig @@ -0,0 +1,45 @@ +namespace A +{ + int _a = 1; + int x = 2; +} + +int marker4(){ + using A::x; + return 0; +} + +int marker3(){ + return marker4(); +} + +int marker2() +{ + namespace B = A; + B::_a; + return marker3(); +} + +int marker1() +{ + int total = 0; + { + int b = 1; + { + using namespace A; + int c = 2; + { + int d = 3; + total = _a + b + c + d + marker2(); // marker1 stop + } + } + } + return total; +} + +int main() +{ + using namespace A; + _a; + return marker1(); +} diff --git a/gdb/testsuite/gdb.cp/namespace-using.exp b/gdb/testsuite/gdb.cp/namespace-using.exp index f24973f..0dd2067 100644 --- a/gdb/testsuite/gdb.cp/namespace-using.exp +++ b/gdb/testsuite/gdb.cp/namespace-using.exp @@ -28,6 +28,11 @@ if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {deb return -1 } +if [get_compiler_info ${binfile}] { + return -1 +} + + # Get things started. gdb_exit @@ -73,7 +78,13 @@ gdb_test "print B::a" "= 1" gdb_breakpoint "marker3" gdb_continue_to_breakpoint "marker3" -gdb_test "print _a" "No symbol \"_a\" in current context." "Print a without import" +# gcc-4-3 puts import statements for aliases in +# the global scope instead of the corresponding +# function scope. These wrong import statements throw +# this test off. This is fixed in gcc-4-4. +if [test_compiler_info gcc-4-3-*] then { setup_xfail *-*-* } + +gdb_test "print _a" "No symbol \"_a\" in current context." "Print _a without import" ############################################ # Test printing of individually imported elements @@ -85,3 +96,25 @@ if ![runto marker4] then { } gdb_test "print x" "= 2" + +############################################ +# test printing of namespace imported into +# file scope. + +if ![runto marker5] then { + perror "couldn't run to marker5" + continue +} + +gdb_test "print cc" "= 3" + +############################################ +# test printing of namespace imported into +# file scope. + +if ![runto PQ::marker6] then { + perror "couldn't run to PQ::marker6" + continue +} + +gdb_test "print ox" "No symbol \"ox\" in current context." diff --git a/gdb/testsuite/gdb.cp/shadowing.cc b/gdb/testsuite/gdb.cp/shadowing.cc new file mode 100644 index 0000000..1651510 --- /dev/null +++ b/gdb/testsuite/gdb.cp/shadowing.cc @@ -0,0 +1,45 @@ +namespace A +{ + int x = 11; +} + +int x = 22; +int y = 0; + +class B +{ +public: + int x; + + int + func() + { + x = 33; + y++; // marker1 + + { + int x = 44; + y++; // marker2 + + { + int x = 55; + y++; // marker3 + + { + using namespace A; + y++; // marker4 + + using A::x; + y++; // marker5 + } + } + } + } +}; + +int +main() +{ + B theB; + return theB.func(); +} diff --git a/gdb/testsuite/gdb.cp/shadowing.exp b/gdb/testsuite/gdb.cp/shadowing.exp new file mode 100644 index 0000000..443881e --- /dev/null +++ b/gdb/testsuite/gdb.cp/shadowing.exp @@ -0,0 +1,86 @@ +# Copyright 2008 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +if $tracelevel then { + strace $tracelevel +} + +set prms_id 0 +set bug_id 0 + +set testfile shadowing +set srcfile ${testfile}.cc +set binfile ${objdir}/${subdir}/${testfile} +if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug c++}] != "" } { + untested "Couldn't compile test program" + return -1 +} + +# Get things started. + +gdb_exit +gdb_start +gdb_reinitialize_dir $srcdir/$subdir +gdb_load ${binfile} + +if ![runto_main] then { + perror "couldn't run to breakpoint main" + continue +} + +############################################ +# Test printing of class variable is not shadowed +# by global variable + +gdb_breakpoint [gdb_get_line_number "marker1"] +gdb_continue_to_breakpoint "marker1" + +gdb_test "print x" "= 33" "Print class x shadowing global x" + + +############################################ +# Test printing local variable is not shadowed +# by class variable + +gdb_breakpoint [gdb_get_line_number "marker2"] +gdb_continue_to_breakpoint "marker2" + +gdb_test "print x" "= 44" "Print local x shadowing class x" + +############################################ +# Test inner scope x is printed not outer scope + +gdb_breakpoint [gdb_get_line_number "marker3"] +gdb_continue_to_breakpoint "marker3" + +gdb_test "print x" "= 55" "Print inner scope x" + +############################################ +# Test printing local variable is not shadowed +# by namespace variable + +gdb_breakpoint [gdb_get_line_number "marker4"] +gdb_continue_to_breakpoint "marker4" + +gdb_test "print x" "= 55" "Print local x not namespace x" + +############################################ +# Test imported namespace element is printed + +gdb_breakpoint [gdb_get_line_number "marker5"] +gdb_continue_to_breakpoint "marker5" + +setup_kfail "gdb/7936" "*-*-*" +gdb_test "print x" "= 11" "Print imported namespace x" ^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [patch 1/2] Perform a namespace lookup at every block level 2009-11-16 15:32 ` Sami Wagiaalla @ 2009-11-16 19:16 ` Sami Wagiaalla 2009-11-24 19:06 ` Sami Wagiaalla 1 sibling, 0 replies; 28+ messages in thread From: Sami Wagiaalla @ 2009-11-16 19:16 UTC (permalink / raw) To: Tom Tromey; +Cc: GDB Patches This patch also fixes PR gdb/10929 Sami ^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [patch 1/2] Perform a namespace lookup at every block level 2009-11-16 15:32 ` Sami Wagiaalla 2009-11-16 19:16 ` Sami Wagiaalla @ 2009-11-24 19:06 ` Sami Wagiaalla 2009-12-21 21:44 ` Tom Tromey 1 sibling, 1 reply; 28+ messages in thread From: Sami Wagiaalla @ 2009-11-24 19:06 UTC (permalink / raw) To: gdb-patches [-- Attachment #1: Type: text/plain, Size: 18215 bytes --] Minor fix + if (strncmp (scope, current->import_dest, len) == 0 + && (len == 0 || scope[len] == ':' || scope[len] == '\0')) + { added len == 0 Patch: 2009-11-24 Sami Wagiaalla <swagiaal@redhat.com> * dwarf2read.c (read_lexical_block_scope): Create blocks for scopes which contain using directives even if they contain no declarations. * symtab.c (lookup_symbol_aux): Pass lowest level block to la_lookup_symbol_nonlocal. * cp-namespace.c (cp_lookup_symbol_nonlocal): call cp_lookup_symbol_namespace. (cp_lookup_symbol_namespace): Perform an import lookup at every block level. (cp_lookup_symbol_imports): New function. (cp_lookup_symbol_in_namespace): New function. 2009-11-24 Sami Wagiaalla <swagiaal@redhat.com> * gdb.cp/namespace-using.exp: Add test for printing of namespaces imported into file scope. Marked test as xfail. * gdb.cp/namespace-using.cc (marker5): New function. * gdb.cp/shadowing.exp: New test. * gdb.cp/shadowing.cc: New test program. * gdb.cp/namespace-multiple-imports.exp: New test. * gdb.cp/namespace-multiple-imports.cc: New test program. diff --git a/gdb/cp-namespace.c b/gdb/cp-namespace.c index d2d8f2e..f63cf8a 100644 --- a/gdb/cp-namespace.c +++ b/gdb/cp-namespace.c @@ -265,8 +265,114 @@ cp_lookup_symbol_nonlocal (const char *name, const struct block *block, const domain_enum domain) { - return lookup_namespace_scope (name, linkage_name, block, domain, - block_scope (block), 0); + struct symbol *sym; + const char *scope = block_scope (block); + + sym = lookup_namespace_scope (name, linkage_name, block, domain, scope, 0); + if (sym != NULL) + return sym; + + return cp_lookup_symbol_namespace (scope, name, linkage_name, block, domain); +} + +/* Look up NAME in the C++ namespace NAMESPACE. Other arguments are as in + cp_lookup_symbol_nonlocal. */ + +static struct symbol * +cp_lookup_symbol_in_namespace (const char *namespace, + const char *name, + const char *linkage_name, + const struct block *block, + const domain_enum domain) +{ + if (namespace[0] == '\0') + { + return lookup_symbol_file (name, linkage_name, block, + domain, 0); + } + else + { + char *concatenated_name = alloca (strlen (namespace) + 2 + + strlen (name+ 1)); + strcpy (concatenated_name, namespace); + strcat (concatenated_name, "::"); + strcat (concatenated_name, name); + return lookup_symbol_file (concatenated_name, linkage_name, + block, domain,cp_is_anonymous (namespace)); + } +} + +/* Search for NAME by applying all import statements belonging + to BLOCK which are applicable in SCOPE. */ + +static struct symbol * +cp_lookup_symbol_imports (const char *scope, + const char *name, + const char *linkage_name, + const struct block *block, + const domain_enum domain) +{ + const struct using_direct *current; + struct symbol *sym; + int len; + + /* First, try to find the symbol in the given namespace. */ + sym = cp_lookup_symbol_in_namespace (scope, name, linkage_name, block, + domain); + if (sym != NULL) + return sym; + + /* Go through the using directives. If any of them add new + names to the namespace we're searching in, see if we can find a + match by applying them. */ + + for (current = block_using (block); + current != NULL; + current = current->next) + { + + /* If the import destination is the current scope or one of its ancestors then + it is applicable. */ + len = strlen (current->import_dest); + if (strncmp (scope, current->import_dest, len) == 0 + && (len == 0 || scope[len] == ':' || scope[len] == '\0')) + { + sym = cp_lookup_symbol_in_namespace (current->import_src, name, + linkage_name, block, domain); + if (sym != NULL) + return sym; + } + } + + return NULL; +} + + + /* Searches for NAME in the current namespace, and by applying relevant import + statements belonging to BLOCK and its parents. SCOPE is the namespace scope + of the context in which the search is being evaluated. */ + +struct symbol* +cp_lookup_symbol_namespace (const char *scope, + const char *name, + const char *linkage_name, + const struct block *block, + const domain_enum domain) +{ + struct symbol *sym; + + /* Search for name in namespaces imported to this and parent blocks. */ + while (block != NULL) + { + sym = cp_lookup_symbol_imports (scope,name, linkage_name, block, domain); + + if (sym) + return sym; + + block = BLOCK_SUPERBLOCK (block); + } + + return NULL; } /* Lookup NAME at namespace scope (or, in C terms, in static and @@ -320,65 +426,8 @@ lookup_namespace_scope (const char *name, namespace = alloca (scope_len + 1); strncpy (namespace, scope, scope_len); namespace[scope_len] = '\0'; - return cp_lookup_symbol_namespace (namespace, name, linkage_name, - block, domain); -} - -/* Look up NAME in the C++ namespace NAMESPACE, applying the using - directives that are active in BLOCK. Other arguments are as in - cp_lookup_symbol_nonlocal. */ - -struct symbol * -cp_lookup_symbol_namespace (const char *namespace, - const char *name, - const char *linkage_name, - const struct block *block, - const domain_enum domain) -{ - const struct using_direct *current; - struct symbol *sym; - - /* First, go through the using directives. If any of them add new - names to the namespace we're searching in, see if we can find a - match by applying them. */ - - for (current = block_using (block); - current != NULL; - current = current->next) - { - if (strcmp (namespace, current->import_dest) == 0) - { - sym = cp_lookup_symbol_namespace (current->import_src, - name, - linkage_name, - block, - domain); - if (sym != NULL) - return sym; - } - } - - /* We didn't find anything by applying any of the using directives - that are still applicable; so let's see if we've got a match - using the current namespace. */ - - if (namespace[0] == '\0') - { - return lookup_symbol_file (name, linkage_name, block, - domain, 0); - } - else - { - char *concatenated_name - = alloca (strlen (namespace) + 2 + strlen (name) + 1); - strcpy (concatenated_name, namespace); - strcat (concatenated_name, "::"); - strcat (concatenated_name, name); - sym = lookup_symbol_file (concatenated_name, linkage_name, - block, domain, - cp_is_anonymous (namespace)); - return sym; - } + return cp_lookup_symbol_in_namespace (namespace, name, linkage_name, + block, domain); } /* Look up NAME in BLOCK's static block and in global blocks. If @@ -461,11 +510,11 @@ cp_lookup_nested_type (struct type *parent_type, lookup_symbol_namespace works when looking them up. */ const char *parent_name = TYPE_TAG_NAME (parent_type); - struct symbol *sym = cp_lookup_symbol_namespace (parent_name, - nested_name, - NULL, - block, - VAR_DOMAIN); + struct symbol *sym = cp_lookup_symbol_in_namespace (parent_name, + nested_name, + NULL, + block, + VAR_DOMAIN); if (sym == NULL || SYMBOL_CLASS (sym) != LOC_TYPEDEF) return NULL; else diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c index 69a7242..c2b2e3c 100644 --- a/gdb/dwarf2read.c +++ b/gdb/dwarf2read.c @@ -3920,7 +3920,7 @@ read_lexical_block_scope (struct die_info *die, struct dwarf2_cu *cu) } new = pop_context (); - if (local_symbols != NULL) + if (local_symbols != NULL || using_directives != NULL) { struct block *block = finish_block (0, &local_symbols, new->old_blocks, new->start_addr, diff --git a/gdb/symtab.c b/gdb/symtab.c index 8d9d72c..dfa8f48 100644 --- a/gdb/symtab.c +++ b/gdb/symtab.c @@ -1304,13 +1304,14 @@ lookup_symbol_aux (const char *name, const char *linkage_name, && block != NULL) { struct symbol *sym = NULL; + const struct block *function_block = block; /* 'this' is only defined in the function's block, so find the enclosing function block. */ - for (; block && !BLOCK_FUNCTION (block); - block = BLOCK_SUPERBLOCK (block)); + for (; function_block && !BLOCK_FUNCTION (function_block); + function_block = BLOCK_SUPERBLOCK (function_block)); - if (block && !dict_empty (BLOCK_DICT (block))) - sym = lookup_block_symbol (block, langdef->la_name_of_this, + if (function_block && !dict_empty (BLOCK_DICT (function_block))) + sym = lookup_block_symbol (function_block, langdef->la_name_of_this, NULL, VAR_DOMAIN); if (sym) { diff --git a/gdb/testsuite/gdb.cp/namespace-multiple-imports.cc b/gdb/testsuite/gdb.cp/namespace-multiple-imports.cc new file mode 100644 index 0000000..6b180d6 --- /dev/null +++ b/gdb/testsuite/gdb.cp/namespace-multiple-imports.cc @@ -0,0 +1,20 @@ +namespace A { + int x = 11; + namespace{ + int xx = 22; + } +} + +using namespace A; + +namespace{ + int xxx = 33; +}; + +int main() +{ + x; + xx; + xxx; + return 0; +} diff --git a/gdb/testsuite/gdb.cp/namespace-multiple-imports.exp b/gdb/testsuite/gdb.cp/namespace-multiple-imports.exp new file mode 100644 index 0000000..e4bb9f8 --- /dev/null +++ b/gdb/testsuite/gdb.cp/namespace-multiple-imports.exp @@ -0,0 +1,49 @@ +# Copyright 2008 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +if $tracelevel then { + strace $tracelevel +} + +set prms_id 0 +set bug_id 0 + +set testfile namespace-multiple-imports +set srcfile ${testfile}.cc +set binfile ${objdir}/${subdir}/${testfile} +if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug c++}] != "" } { + untested "Couldn't compile test program" + return -1 +} + +# Get things started. + +gdb_exit +gdb_start +gdb_reinitialize_dir $srcdir/$subdir +gdb_load ${binfile} + +############################################ +# test printing of namespace imported within +# the function. + +if ![runto_main] then { + perror "couldn't run to breakpoint main" + continue +} + +gdb_test "print x" "\\$\[0-9\].* = 11" +gdb_test "print xx" "\\$\[0-9\].* = 22" +gdb_test "print xxx" "\\$\[0-9\].* = 33" diff --git a/gdb/testsuite/gdb.cp/namespace-using.cc b/gdb/testsuite/gdb.cp/namespace-using.cc index 4786fd5..8d9ea67 100644 --- a/gdb/testsuite/gdb.cp/namespace-using.cc +++ b/gdb/testsuite/gdb.cp/namespace-using.cc @@ -1,3 +1,35 @@ +namespace O +{ + int ox = 4; +} + +namespace PQ +{ + int marker6 () + { + return 0; + } +} + +namespace P +{ + using namespace O; +} + +//-------------- +namespace C +{ + int cc = 3; +} + +using namespace C; +int marker5 () +{ + cc; + return PQ::marker6 (); +} + + namespace A { int _a = 1; @@ -6,7 +38,7 @@ namespace A int marker4(){ using A::x; - return 0; + return marker5 (); } int marker3(){ diff --git a/gdb/testsuite/gdb.cp/namespace-using.cc.orig b/gdb/testsuite/gdb.cp/namespace-using.cc.orig new file mode 100644 index 0000000..4786fd5 --- /dev/null +++ b/gdb/testsuite/gdb.cp/namespace-using.cc.orig @@ -0,0 +1,45 @@ +namespace A +{ + int _a = 1; + int x = 2; +} + +int marker4(){ + using A::x; + return 0; +} + +int marker3(){ + return marker4(); +} + +int marker2() +{ + namespace B = A; + B::_a; + return marker3(); +} + +int marker1() +{ + int total = 0; + { + int b = 1; + { + using namespace A; + int c = 2; + { + int d = 3; + total = _a + b + c + d + marker2(); // marker1 stop + } + } + } + return total; +} + +int main() +{ + using namespace A; + _a; + return marker1(); +} diff --git a/gdb/testsuite/gdb.cp/namespace-using.exp b/gdb/testsuite/gdb.cp/namespace-using.exp index f24973f..0dd2067 100644 --- a/gdb/testsuite/gdb.cp/namespace-using.exp +++ b/gdb/testsuite/gdb.cp/namespace-using.exp @@ -28,6 +28,11 @@ if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {deb return -1 } +if [get_compiler_info ${binfile}] { + return -1 +} + + # Get things started. gdb_exit @@ -73,7 +78,13 @@ gdb_test "print B::a" "= 1" gdb_breakpoint "marker3" gdb_continue_to_breakpoint "marker3" -gdb_test "print _a" "No symbol \"_a\" in current context." "Print a without import" +# gcc-4-3 puts import statements for aliases in +# the global scope instead of the corresponding +# function scope. These wrong import statements throw +# this test off. This is fixed in gcc-4-4. +if [test_compiler_info gcc-4-3-*] then { setup_xfail *-*-* } + +gdb_test "print _a" "No symbol \"_a\" in current context." "Print _a without import" ############################################ # Test printing of individually imported elements @@ -85,3 +96,25 @@ if ![runto marker4] then { } gdb_test "print x" "= 2" + +############################################ +# test printing of namespace imported into +# file scope. + +if ![runto marker5] then { + perror "couldn't run to marker5" + continue +} + +gdb_test "print cc" "= 3" + +############################################ +# test printing of namespace imported into +# file scope. + +if ![runto PQ::marker6] then { + perror "couldn't run to PQ::marker6" + continue +} + +gdb_test "print ox" "No symbol \"ox\" in current context." diff --git a/gdb/testsuite/gdb.cp/shadowing.cc b/gdb/testsuite/gdb.cp/shadowing.cc new file mode 100644 index 0000000..1651510 --- /dev/null +++ b/gdb/testsuite/gdb.cp/shadowing.cc @@ -0,0 +1,45 @@ +namespace A +{ + int x = 11; +} + +int x = 22; +int y = 0; + +class B +{ +public: + int x; + + int + func() + { + x = 33; + y++; // marker1 + + { + int x = 44; + y++; // marker2 + + { + int x = 55; + y++; // marker3 + + { + using namespace A; + y++; // marker4 + + using A::x; + y++; // marker5 + } + } + } + } +}; + +int +main() +{ + B theB; + return theB.func(); +} diff --git a/gdb/testsuite/gdb.cp/shadowing.exp b/gdb/testsuite/gdb.cp/shadowing.exp new file mode 100644 index 0000000..443881e --- /dev/null +++ b/gdb/testsuite/gdb.cp/shadowing.exp @@ -0,0 +1,86 @@ +# Copyright 2008 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +if $tracelevel then { + strace $tracelevel +} + +set prms_id 0 +set bug_id 0 + +set testfile shadowing +set srcfile ${testfile}.cc +set binfile ${objdir}/${subdir}/${testfile} +if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug c++}] != "" } { + untested "Couldn't compile test program" + return -1 +} + +# Get things started. + +gdb_exit +gdb_start +gdb_reinitialize_dir $srcdir/$subdir +gdb_load ${binfile} + +if ![runto_main] then { + perror "couldn't run to breakpoint main" + continue +} + +############################################ +# Test printing of class variable is not shadowed +# by global variable + +gdb_breakpoint [gdb_get_line_number "marker1"] +gdb_continue_to_breakpoint "marker1" + +gdb_test "print x" "= 33" "Print class x shadowing global x" + + +############################################ +# Test printing local variable is not shadowed +# by class variable + +gdb_breakpoint [gdb_get_line_number "marker2"] +gdb_continue_to_breakpoint "marker2" + +gdb_test "print x" "= 44" "Print local x shadowing class x" + +############################################ +# Test inner scope x is printed not outer scope + +gdb_breakpoint [gdb_get_line_number "marker3"] +gdb_continue_to_breakpoint "marker3" + +gdb_test "print x" "= 55" "Print inner scope x" + +############################################ +# Test printing local variable is not shadowed +# by namespace variable + +gdb_breakpoint [gdb_get_line_number "marker4"] +gdb_continue_to_breakpoint "marker4" + +gdb_test "print x" "= 55" "Print local x not namespace x" + +############################################ +# Test imported namespace element is printed + +gdb_breakpoint [gdb_get_line_number "marker5"] +gdb_continue_to_breakpoint "marker5" + +setup_kfail "gdb/7936" "*-*-*" +gdb_test "print x" "= 11" "Print imported namespace x" [-- Attachment #2: sami1-ns-search-per-block.patch --] [-- Type: text/plain, Size: 17982 bytes --] 2009-11-24 Sami Wagiaalla <swagiaal@redhat.com> * dwarf2read.c (read_lexical_block_scope): Create blocks for scopes which contain using directives even if they contain no declarations. * symtab.c (lookup_symbol_aux): Pass lowest level block to la_lookup_symbol_nonlocal. * cp-namespace.c (cp_lookup_symbol_nonlocal): call cp_lookup_symbol_namespace. (cp_lookup_symbol_namespace): Perform an import lookup at every block level. (cp_lookup_symbol_imports): New function. (cp_lookup_symbol_in_namespace): New function. 2009-11-24 Sami Wagiaalla <swagiaal@redhat.com> * gdb.cp/namespace-using.exp: Add test for printing of namespaces imported into file scope. Marked test as xfail. * gdb.cp/namespace-using.cc (marker5): New function. * gdb.cp/shadowing.exp: New test. * gdb.cp/shadowing.cc: New test program. * gdb.cp/namespace-multiple-imports.exp: New test. * gdb.cp/namespace-multiple-imports.cc: New test program. diff --git a/gdb/cp-namespace.c b/gdb/cp-namespace.c index d2d8f2e..f63cf8a 100644 --- a/gdb/cp-namespace.c +++ b/gdb/cp-namespace.c @@ -265,8 +265,114 @@ cp_lookup_symbol_nonlocal (const char *name, const struct block *block, const domain_enum domain) { - return lookup_namespace_scope (name, linkage_name, block, domain, - block_scope (block), 0); + struct symbol *sym; + const char *scope = block_scope (block); + + sym = lookup_namespace_scope (name, linkage_name, block, domain, scope, 0); + if (sym != NULL) + return sym; + + return cp_lookup_symbol_namespace (scope, name, linkage_name, block, domain); +} + +/* Look up NAME in the C++ namespace NAMESPACE. Other arguments are as in + cp_lookup_symbol_nonlocal. */ + +static struct symbol * +cp_lookup_symbol_in_namespace (const char *namespace, + const char *name, + const char *linkage_name, + const struct block *block, + const domain_enum domain) +{ + if (namespace[0] == '\0') + { + return lookup_symbol_file (name, linkage_name, block, + domain, 0); + } + else + { + char *concatenated_name = alloca (strlen (namespace) + 2 + + strlen (name+ 1)); + strcpy (concatenated_name, namespace); + strcat (concatenated_name, "::"); + strcat (concatenated_name, name); + return lookup_symbol_file (concatenated_name, linkage_name, + block, domain,cp_is_anonymous (namespace)); + } +} + +/* Search for NAME by applying all import statements belonging + to BLOCK which are applicable in SCOPE. */ + +static struct symbol * +cp_lookup_symbol_imports (const char *scope, + const char *name, + const char *linkage_name, + const struct block *block, + const domain_enum domain) +{ + const struct using_direct *current; + struct symbol *sym; + int len; + + /* First, try to find the symbol in the given namespace. */ + sym = cp_lookup_symbol_in_namespace (scope, name, linkage_name, block, + domain); + if (sym != NULL) + return sym; + + /* Go through the using directives. If any of them add new + names to the namespace we're searching in, see if we can find a + match by applying them. */ + + for (current = block_using (block); + current != NULL; + current = current->next) + { + + /* If the import destination is the current scope or one of its ancestors then + it is applicable. */ + len = strlen (current->import_dest); + if (strncmp (scope, current->import_dest, len) == 0 + && (len == 0 || scope[len] == ':' || scope[len] == '\0')) + { + sym = cp_lookup_symbol_in_namespace (current->import_src, name, + linkage_name, block, domain); + if (sym != NULL) + return sym; + } + } + + return NULL; +} + + + /* Searches for NAME in the current namespace, and by applying relevant import + statements belonging to BLOCK and its parents. SCOPE is the namespace scope + of the context in which the search is being evaluated. */ + +struct symbol* +cp_lookup_symbol_namespace (const char *scope, + const char *name, + const char *linkage_name, + const struct block *block, + const domain_enum domain) +{ + struct symbol *sym; + + /* Search for name in namespaces imported to this and parent blocks. */ + while (block != NULL) + { + sym = cp_lookup_symbol_imports (scope,name, linkage_name, block, domain); + + if (sym) + return sym; + + block = BLOCK_SUPERBLOCK (block); + } + + return NULL; } /* Lookup NAME at namespace scope (or, in C terms, in static and @@ -320,65 +426,8 @@ lookup_namespace_scope (const char *name, namespace = alloca (scope_len + 1); strncpy (namespace, scope, scope_len); namespace[scope_len] = '\0'; - return cp_lookup_symbol_namespace (namespace, name, linkage_name, - block, domain); -} - -/* Look up NAME in the C++ namespace NAMESPACE, applying the using - directives that are active in BLOCK. Other arguments are as in - cp_lookup_symbol_nonlocal. */ - -struct symbol * -cp_lookup_symbol_namespace (const char *namespace, - const char *name, - const char *linkage_name, - const struct block *block, - const domain_enum domain) -{ - const struct using_direct *current; - struct symbol *sym; - - /* First, go through the using directives. If any of them add new - names to the namespace we're searching in, see if we can find a - match by applying them. */ - - for (current = block_using (block); - current != NULL; - current = current->next) - { - if (strcmp (namespace, current->import_dest) == 0) - { - sym = cp_lookup_symbol_namespace (current->import_src, - name, - linkage_name, - block, - domain); - if (sym != NULL) - return sym; - } - } - - /* We didn't find anything by applying any of the using directives - that are still applicable; so let's see if we've got a match - using the current namespace. */ - - if (namespace[0] == '\0') - { - return lookup_symbol_file (name, linkage_name, block, - domain, 0); - } - else - { - char *concatenated_name - = alloca (strlen (namespace) + 2 + strlen (name) + 1); - strcpy (concatenated_name, namespace); - strcat (concatenated_name, "::"); - strcat (concatenated_name, name); - sym = lookup_symbol_file (concatenated_name, linkage_name, - block, domain, - cp_is_anonymous (namespace)); - return sym; - } + return cp_lookup_symbol_in_namespace (namespace, name, linkage_name, + block, domain); } /* Look up NAME in BLOCK's static block and in global blocks. If @@ -461,11 +510,11 @@ cp_lookup_nested_type (struct type *parent_type, lookup_symbol_namespace works when looking them up. */ const char *parent_name = TYPE_TAG_NAME (parent_type); - struct symbol *sym = cp_lookup_symbol_namespace (parent_name, - nested_name, - NULL, - block, - VAR_DOMAIN); + struct symbol *sym = cp_lookup_symbol_in_namespace (parent_name, + nested_name, + NULL, + block, + VAR_DOMAIN); if (sym == NULL || SYMBOL_CLASS (sym) != LOC_TYPEDEF) return NULL; else diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c index 69a7242..c2b2e3c 100644 --- a/gdb/dwarf2read.c +++ b/gdb/dwarf2read.c @@ -3920,7 +3920,7 @@ read_lexical_block_scope (struct die_info *die, struct dwarf2_cu *cu) } new = pop_context (); - if (local_symbols != NULL) + if (local_symbols != NULL || using_directives != NULL) { struct block *block = finish_block (0, &local_symbols, new->old_blocks, new->start_addr, diff --git a/gdb/symtab.c b/gdb/symtab.c index 8d9d72c..dfa8f48 100644 --- a/gdb/symtab.c +++ b/gdb/symtab.c @@ -1304,13 +1304,14 @@ lookup_symbol_aux (const char *name, const char *linkage_name, && block != NULL) { struct symbol *sym = NULL; + const struct block *function_block = block; /* 'this' is only defined in the function's block, so find the enclosing function block. */ - for (; block && !BLOCK_FUNCTION (block); - block = BLOCK_SUPERBLOCK (block)); + for (; function_block && !BLOCK_FUNCTION (function_block); + function_block = BLOCK_SUPERBLOCK (function_block)); - if (block && !dict_empty (BLOCK_DICT (block))) - sym = lookup_block_symbol (block, langdef->la_name_of_this, + if (function_block && !dict_empty (BLOCK_DICT (function_block))) + sym = lookup_block_symbol (function_block, langdef->la_name_of_this, NULL, VAR_DOMAIN); if (sym) { diff --git a/gdb/testsuite/gdb.cp/namespace-multiple-imports.cc b/gdb/testsuite/gdb.cp/namespace-multiple-imports.cc new file mode 100644 index 0000000..6b180d6 --- /dev/null +++ b/gdb/testsuite/gdb.cp/namespace-multiple-imports.cc @@ -0,0 +1,20 @@ +namespace A { + int x = 11; + namespace{ + int xx = 22; + } +} + +using namespace A; + +namespace{ + int xxx = 33; +}; + +int main() +{ + x; + xx; + xxx; + return 0; +} diff --git a/gdb/testsuite/gdb.cp/namespace-multiple-imports.exp b/gdb/testsuite/gdb.cp/namespace-multiple-imports.exp new file mode 100644 index 0000000..e4bb9f8 --- /dev/null +++ b/gdb/testsuite/gdb.cp/namespace-multiple-imports.exp @@ -0,0 +1,49 @@ +# Copyright 2008 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +if $tracelevel then { + strace $tracelevel +} + +set prms_id 0 +set bug_id 0 + +set testfile namespace-multiple-imports +set srcfile ${testfile}.cc +set binfile ${objdir}/${subdir}/${testfile} +if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug c++}] != "" } { + untested "Couldn't compile test program" + return -1 +} + +# Get things started. + +gdb_exit +gdb_start +gdb_reinitialize_dir $srcdir/$subdir +gdb_load ${binfile} + +############################################ +# test printing of namespace imported within +# the function. + +if ![runto_main] then { + perror "couldn't run to breakpoint main" + continue +} + +gdb_test "print x" "\\$\[0-9\].* = 11" +gdb_test "print xx" "\\$\[0-9\].* = 22" +gdb_test "print xxx" "\\$\[0-9\].* = 33" diff --git a/gdb/testsuite/gdb.cp/namespace-using.cc b/gdb/testsuite/gdb.cp/namespace-using.cc index 4786fd5..8d9ea67 100644 --- a/gdb/testsuite/gdb.cp/namespace-using.cc +++ b/gdb/testsuite/gdb.cp/namespace-using.cc @@ -1,3 +1,35 @@ +namespace O +{ + int ox = 4; +} + +namespace PQ +{ + int marker6 () + { + return 0; + } +} + +namespace P +{ + using namespace O; +} + +//-------------- +namespace C +{ + int cc = 3; +} + +using namespace C; +int marker5 () +{ + cc; + return PQ::marker6 (); +} + + namespace A { int _a = 1; @@ -6,7 +38,7 @@ namespace A int marker4(){ using A::x; - return 0; + return marker5 (); } int marker3(){ diff --git a/gdb/testsuite/gdb.cp/namespace-using.cc.orig b/gdb/testsuite/gdb.cp/namespace-using.cc.orig new file mode 100644 index 0000000..4786fd5 --- /dev/null +++ b/gdb/testsuite/gdb.cp/namespace-using.cc.orig @@ -0,0 +1,45 @@ +namespace A +{ + int _a = 1; + int x = 2; +} + +int marker4(){ + using A::x; + return 0; +} + +int marker3(){ + return marker4(); +} + +int marker2() +{ + namespace B = A; + B::_a; + return marker3(); +} + +int marker1() +{ + int total = 0; + { + int b = 1; + { + using namespace A; + int c = 2; + { + int d = 3; + total = _a + b + c + d + marker2(); // marker1 stop + } + } + } + return total; +} + +int main() +{ + using namespace A; + _a; + return marker1(); +} diff --git a/gdb/testsuite/gdb.cp/namespace-using.exp b/gdb/testsuite/gdb.cp/namespace-using.exp index f24973f..0dd2067 100644 --- a/gdb/testsuite/gdb.cp/namespace-using.exp +++ b/gdb/testsuite/gdb.cp/namespace-using.exp @@ -28,6 +28,11 @@ if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {deb return -1 } +if [get_compiler_info ${binfile}] { + return -1 +} + + # Get things started. gdb_exit @@ -73,7 +78,13 @@ gdb_test "print B::a" "= 1" gdb_breakpoint "marker3" gdb_continue_to_breakpoint "marker3" -gdb_test "print _a" "No symbol \"_a\" in current context." "Print a without import" +# gcc-4-3 puts import statements for aliases in +# the global scope instead of the corresponding +# function scope. These wrong import statements throw +# this test off. This is fixed in gcc-4-4. +if [test_compiler_info gcc-4-3-*] then { setup_xfail *-*-* } + +gdb_test "print _a" "No symbol \"_a\" in current context." "Print _a without import" ############################################ # Test printing of individually imported elements @@ -85,3 +96,25 @@ if ![runto marker4] then { } gdb_test "print x" "= 2" + +############################################ +# test printing of namespace imported into +# file scope. + +if ![runto marker5] then { + perror "couldn't run to marker5" + continue +} + +gdb_test "print cc" "= 3" + +############################################ +# test printing of namespace imported into +# file scope. + +if ![runto PQ::marker6] then { + perror "couldn't run to PQ::marker6" + continue +} + +gdb_test "print ox" "No symbol \"ox\" in current context." diff --git a/gdb/testsuite/gdb.cp/shadowing.cc b/gdb/testsuite/gdb.cp/shadowing.cc new file mode 100644 index 0000000..1651510 --- /dev/null +++ b/gdb/testsuite/gdb.cp/shadowing.cc @@ -0,0 +1,45 @@ +namespace A +{ + int x = 11; +} + +int x = 22; +int y = 0; + +class B +{ +public: + int x; + + int + func() + { + x = 33; + y++; // marker1 + + { + int x = 44; + y++; // marker2 + + { + int x = 55; + y++; // marker3 + + { + using namespace A; + y++; // marker4 + + using A::x; + y++; // marker5 + } + } + } + } +}; + +int +main() +{ + B theB; + return theB.func(); +} diff --git a/gdb/testsuite/gdb.cp/shadowing.exp b/gdb/testsuite/gdb.cp/shadowing.exp new file mode 100644 index 0000000..443881e --- /dev/null +++ b/gdb/testsuite/gdb.cp/shadowing.exp @@ -0,0 +1,86 @@ +# Copyright 2008 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +if $tracelevel then { + strace $tracelevel +} + +set prms_id 0 +set bug_id 0 + +set testfile shadowing +set srcfile ${testfile}.cc +set binfile ${objdir}/${subdir}/${testfile} +if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug c++}] != "" } { + untested "Couldn't compile test program" + return -1 +} + +# Get things started. + +gdb_exit +gdb_start +gdb_reinitialize_dir $srcdir/$subdir +gdb_load ${binfile} + +if ![runto_main] then { + perror "couldn't run to breakpoint main" + continue +} + +############################################ +# Test printing of class variable is not shadowed +# by global variable + +gdb_breakpoint [gdb_get_line_number "marker1"] +gdb_continue_to_breakpoint "marker1" + +gdb_test "print x" "= 33" "Print class x shadowing global x" + + +############################################ +# Test printing local variable is not shadowed +# by class variable + +gdb_breakpoint [gdb_get_line_number "marker2"] +gdb_continue_to_breakpoint "marker2" + +gdb_test "print x" "= 44" "Print local x shadowing class x" + +############################################ +# Test inner scope x is printed not outer scope + +gdb_breakpoint [gdb_get_line_number "marker3"] +gdb_continue_to_breakpoint "marker3" + +gdb_test "print x" "= 55" "Print inner scope x" + +############################################ +# Test printing local variable is not shadowed +# by namespace variable + +gdb_breakpoint [gdb_get_line_number "marker4"] +gdb_continue_to_breakpoint "marker4" + +gdb_test "print x" "= 55" "Print local x not namespace x" + +############################################ +# Test imported namespace element is printed + +gdb_breakpoint [gdb_get_line_number "marker5"] +gdb_continue_to_breakpoint "marker5" + +setup_kfail "gdb/7936" "*-*-*" +gdb_test "print x" "= 11" "Print imported namespace x" ^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [patch 1/2] Perform a namespace lookup at every block level 2009-11-24 19:06 ` Sami Wagiaalla @ 2009-12-21 21:44 ` Tom Tromey 0 siblings, 0 replies; 28+ messages in thread From: Tom Tromey @ 2009-12-21 21:44 UTC (permalink / raw) To: Sami Wagiaalla; +Cc: gdb-patches >>>>> "Sami" == Sami Wagiaalla <swagiaal@redhat.com> writes: Sami> This patch also fixes PR gdb/10929 Please put this in the ChangeLog and the commit message, so it shows up in bugzilla. Sami> 2009-11-24 Sami Wagiaalla <swagiaal@redhat.com> Sami> * dwarf2read.c (read_lexical_block_scope): Create blocks for scopes Sami> which contain using directives even if they contain no declarations. Sami> * symtab.c (lookup_symbol_aux): Pass lowest level Sami> block to la_lookup_symbol_nonlocal. Sami> * cp-namespace.c (cp_lookup_symbol_nonlocal): call Sami> cp_lookup_symbol_namespace. Sami> (cp_lookup_symbol_namespace): Perform an import lookup at every block Sami> level. Sami> (cp_lookup_symbol_imports): New function. Sami> (cp_lookup_symbol_in_namespace): New function. This is ok. Thanks. Tom ^ permalink raw reply [flat|nested] 28+ messages in thread
* [patch 2/2] Perform a namespace lookup at every block level 2009-07-23 19:46 ` Sami Wagiaalla ` (2 preceding siblings ...) 2009-08-18 20:34 ` [patch 1/2] " Sami Wagiaalla @ 2009-08-18 20:46 ` Sami Wagiaalla 2009-09-04 16:57 ` Sami Wagiaalla 3 siblings, 1 reply; 28+ messages in thread From: Sami Wagiaalla @ 2009-08-18 20:46 UTC (permalink / raw) To: Sami Wagiaalla, GDB Patches In cases like this namespace A{ int ax; } namespace B{ using namespace A; } namespace C{ using namespace B; } using namespace A void foo(){ C::ax; } And this: namespace{ namespace{ in xx; } } void foo(){ xx; } A recursive search must be performed. This patch provides that functionality: 2009-08-14 Sami Wagiaalla <swagiaal@redhat.com> * cp-support.h: Add 'searched' feild to using_direct struct. * cp-namespace.c (cp_lookup_symbol_imports): Perform recursive search. (cp_add_using): Initialize 'searched' feild. (cp_copy_usings): Copy searched feild. diff --git a/gdb/cp-namespace.c b/gdb/cp-namespace.c index a0ccd7f..909ec2c 100644 --- a/gdb/cp-namespace.c +++ b/gdb/cp-namespace.c @@ -229,6 +229,7 @@ cp_add_using (const char *dest, retval->import_src = savestring (src, strlen(src)); retval->import_dest = savestring (dest, strlen(dest)); retval->next = next; + retval->searched = 0; return retval; } @@ -255,6 +256,8 @@ cp_copy_usings (struct using_direct *using, obstack); retval->next = cp_copy_usings (using->next, obstack); + retval->searched = using->searched; + xfree (using->import_src); xfree (using->import_dest); xfree (using); @@ -408,7 +411,7 @@ cp_lookup_symbol_imports (const char *scope, const struct block *block, const domain_enum domain) { - const struct using_direct *current; + struct using_direct *current; struct symbol *sym; /* First, try to find the symbol in the given namespace. */ @@ -428,13 +431,20 @@ cp_lookup_symbol_imports (const char *scope, /* If the import destination is the current scope or one of its ancestors then it is applicable. */ - if (strncmp (scope, current->import_dest, strlen(current->import_dest)) == 0) + if (strncmp (scope, current->import_dest, + strlen(current->import_dest)) == 0 && + !current->searched ) { - sym = cp_lookup_symbol_in_namespace (current->import_src, + /* Mark this import as searched so that the recursive call does not + search it again. */ + current->searched = 1; + sym = cp_lookup_symbol_namespace (current->import_src, name, linkage_name, block, domain); + + current->searched = 0; if (sym != NULL) return sym; } diff --git a/gdb/cp-support.h b/gdb/cp-support.h index b5a5c5f..c9d53e5 100644 --- a/gdb/cp-support.h +++ b/gdb/cp-support.h @@ -47,6 +47,9 @@ struct using_direct char *import_src; char *import_dest; struct using_direct *next; + + /* Used during import search to temporarly mark this node as searced. */ + int searched; }; diff --git a/gdb/testsuite/gdb.cp/namespace-recursive.cc b/gdb/testsuite/gdb.cp/namespace-recursive.cc new file mode 100644 index 0000000..9368ad8 --- /dev/null +++ b/gdb/testsuite/gdb.cp/namespace-recursive.cc @@ -0,0 +1,30 @@ +namespace A{ + int ax = 9; +} + +namespace B{ + using namespace A; +} + +namespace C{ + using namespace B; +} + +//--------------- +namespace D{ + using namespace D; + int dx = 99; +} +using namespace C; + +//--------------- +namespace{ + namespace{ + int xx = 999; + } +} + +int main(){ + using namespace D; + return ax + dx + xx; +} \ No newline at end of file diff --git a/gdb/testsuite/gdb.cp/namespace-recursive.exp b/gdb/testsuite/gdb.cp/namespace-recursive.exp new file mode 100644 index 0000000..ebc898f --- /dev/null +++ b/gdb/testsuite/gdb.cp/namespace-recursive.exp @@ -0,0 +1,66 @@ +# Copyright 2008 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +if $tracelevel then { + strace $tracelevel +} + +set prms_id 0 +set bug_id 0 + +set testfile namespace-recursive +set srcfile ${testfile}.cc +set binfile ${objdir}/${subdir}/${testfile} +if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug c++}] != "" } { + untested "Couldn't compile test program" + return -1 +} + +if [get_compiler_info ${binfile}] { + return -1; +} + + +# Get things started. + +gdb_exit +gdb_start +gdb_reinitialize_dir $srcdir/$subdir +gdb_load ${binfile} + +if ![runto_main] then { + perror "couldn't run to breakpoint main" + continue +} + +############################################ +# test printing from namespace imported into +# imported namespace + +gdb_test "print ax" "= 9" + +############################################ +# test that gdb can print without falling +# into search loop + +gdb_test "print dx" "= 99" + +############################################ +# test printing from namespace imported into +# imported namespace where imports are implicit +# anonymous namespace imports. + +gdb_test "print xx" "= 999" + ^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [patch 2/2] Perform a namespace lookup at every block level 2009-08-18 20:46 ` [patch 2/2] " Sami Wagiaalla @ 2009-09-04 16:57 ` Sami Wagiaalla 2009-10-13 20:22 ` Tom Tromey 0 siblings, 1 reply; 28+ messages in thread From: Sami Wagiaalla @ 2009-09-04 16:57 UTC (permalink / raw) To: Sami Wagiaalla, GDB Patches > A recursive search must be performed. This patch provides that > functionality: > That implementation performed redundant searches. This problem is fixed by this patch. 2009-09-04 Sami Wagiaalla <swagiaal@redhat.com> * cp-namespace.c (cp_lookup_symbol_namespace): Added search_parent argument. * cp-support.h (cp_lookup_symbol_imports): Ditto. * cp-namespace.c (cp_lookup_symbol_imports): Ditto. Implement non parent search. * valops.c (value_maybe_namespace_elt): Updated. 2009-09-04 Sami Wagiaalla <swagiaal@redhat.com> * gdb.cp/namespace-stress.exp: New test. * gdb.cp/namespace-stress.cc: New test file. diff --git a/gdb/cp-namespace.c b/gdb/cp-namespace.c index 909ec2c..eeaf851 100644 --- a/gdb/cp-namespace.c +++ b/gdb/cp-namespace.c @@ -46,7 +46,8 @@ static struct symbol *cp_lookup_symbol_imports (const char *scope, const char *name, const char *linkage_name, const struct block *block, - const domain_enum domain); + const domain_enum domain, + const int search_parents); static struct symbol *cp_lookup_symbol_in_namespace (const char *namespace, const char *name, @@ -287,7 +288,7 @@ cp_lookup_symbol_nonlocal (const char *name, if ( sym != NULL) return sym; - return cp_lookup_symbol_namespace(scope, name, linkage_name, block, domain); + return cp_lookup_symbol_namespace(scope, name, linkage_name, block, domain, 1); } /* Searches for NAME in the current namespace, and by applying relevant import @@ -299,14 +300,16 @@ cp_lookup_symbol_namespace (const char *scope, const char *name, const char *linkage_name, const struct block *block, - const domain_enum domain) + const domain_enum domain, + const int search_parents) { struct symbol *sym; /* Search for name in namespaces imported to this and parent blocks. */ while (block != NULL) { - sym = cp_lookup_symbol_imports(scope,name, linkage_name, block, domain); + sym = cp_lookup_symbol_imports(scope,name, linkage_name, block, domain, + search_parents ); if (sym) return sym; @@ -402,17 +405,33 @@ cp_lookup_symbol_in_namespace (const char *namespace, } /* Search for NAME by applying all import statements belonging - to BLOCK which are applicable in SCOPE. */ + to BLOCK which are applicable in SCOPE. + If SEARCH_PARENTS the search will include imports which are applicable in + parents of scopes. + Example: + + namespace A{ + using namespace X; + namespace B{ + using namespace Y; + } + } + + If SCOPE is "A::B" and SEARCH_PARENTS is true the imports of namespaces X + and Y will be considered. If SEARCH_PARENTS is false only the import of Y + is considered. */ static struct symbol * cp_lookup_symbol_imports (const char *scope, const char *name, const char *linkage_name, const struct block *block, - const domain_enum domain) + const domain_enum domain, + const int search_parents) { struct using_direct *current; struct symbol *sym; + int directive_match; /* First, try to find the symbol in the given namespace. */ sym = cp_lookup_symbol_in_namespace (scope, name, linkage_name, block, @@ -429,9 +448,15 @@ cp_lookup_symbol_imports (const char *scope, current = current->next) { + directive_match = search_parents ? + strncmp (scope, current->import_dest, + strlen(current->import_dest)) == 0 : + strcmp (scope, current->import_dest) == 0; + /* If the import destination is the current scope or one of its ancestors then it is applicable. */ - if (strncmp (scope, current->import_dest, + if (directive_match && + strncmp (scope, current->import_dest, strlen(current->import_dest)) == 0 && !current->searched ) { @@ -442,8 +467,8 @@ cp_lookup_symbol_imports (const char *scope, name, linkage_name, block, - domain); - + domain, 0); + current->searched = 0; if (sym != NULL) return sym; diff --git a/gdb/cp-support.h b/gdb/cp-support.h index c9d53e5..348d7c9 100644 --- a/gdb/cp-support.h +++ b/gdb/cp-support.h @@ -108,7 +108,8 @@ extern struct symbol *cp_lookup_symbol_namespace (const char *namespace, const char *name, const char *linkage_name, const struct block *block, - const domain_enum domain); + const domain_enum domain, + const int search_parents); extern struct type *cp_lookup_nested_type (struct type *parent_type, const char *nested_name, diff --git a/gdb/testsuite/gdb.cp/namespace-stress.cc b/gdb/testsuite/gdb.cp/namespace-stress.cc new file mode 100644 index 0000000..f34083e --- /dev/null +++ b/gdb/testsuite/gdb.cp/namespace-stress.cc @@ -0,0 +1,60 @@ + +namespace A{ int x; } +namespace B{ int x; } +namespace C{ int x; } +namespace D{ int x; } +namespace E{ int x; } +namespace F{ int x; } +namespace G{ int x; } +namespace H{ int x; } +namespace I{ int x; } +namespace J{ int x; } +namespace K{ int x; } +namespace L{ int x; } +namespace M{ int x; } +namespace N{ int x; } +namespace O{ int x; } +namespace P{ int x; } +namespace Q{ int x; } +namespace R{ int x; } +namespace S{ int x; } +namespace T{ int x; } +namespace U{ int x; } +namespace V{ int x; } +namespace W{ int x; } +namespace X{ int x; } +namespace Y{ int x; } +namespace Z{ int x; } + + +int main(){ + + using namespace A; + using namespace B; + using namespace C; + using namespace D; + using namespace E; + using namespace F; + using namespace G; + using namespace H; + using namespace I; + using namespace J; + using namespace K; + using namespace L; + using namespace M; + using namespace N; + using namespace O; + using namespace P; + using namespace Q; + using namespace R; + using namespace S; + using namespace T; + using namespace U; + using namespace V; + using namespace W; + using namespace X; + using namespace Y; + using namespace Z; + + return 0; +} \ No newline at end of file diff --git a/gdb/testsuite/gdb.cp/namespace-stress.exp b/gdb/testsuite/gdb.cp/namespace-stress.exp new file mode 100644 index 0000000..36e0628 --- /dev/null +++ b/gdb/testsuite/gdb.cp/namespace-stress.exp @@ -0,0 +1,50 @@ +# Copyright 2008 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +if $tracelevel then { + strace $tracelevel +} + +set prms_id 0 +set bug_id 0 + +set testfile namespace-stress +set srcfile ${testfile}.cc +set binfile ${objdir}/${subdir}/${testfile} +if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug c++}] != "" } { + untested "Couldn't compile test program" + return -1 +} + +if [get_compiler_info ${binfile}] { + return -1; +} + +# Get things started. + +gdb_exit +gdb_start +gdb_reinitialize_dir $srcdir/$subdir +gdb_load ${binfile} + +if ![runto_main] then { + perror "couldn't run to breakpoint main" + continue +} + +############################################ +# Test that the search can fail efficiently + +gdb_test "print y" "No symbol \"y\" in current context." diff --git a/gdb/valops.c b/gdb/valops.c index 5e5c4ed..3448b4a 100644 --- a/gdb/valops.c +++ b/gdb/valops.c @@ -2754,7 +2754,7 @@ value_maybe_namespace_elt (const struct type *curtype, sym = cp_lookup_symbol_namespace (namespace_name, name, NULL, get_selected_block (0), - VAR_DOMAIN); + VAR_DOMAIN,1); if (sym == NULL) return NULL; ^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [patch 2/2] Perform a namespace lookup at every block level 2009-09-04 16:57 ` Sami Wagiaalla @ 2009-10-13 20:22 ` Tom Tromey 2009-10-22 17:47 ` Sami Wagiaalla 0 siblings, 1 reply; 28+ messages in thread From: Tom Tromey @ 2009-10-13 20:22 UTC (permalink / raw) To: Sami Wagiaalla; +Cc: GDB Patches >>>>> "Sami" == Sami Wagiaalla <swagiaal@redhat.com> writes: Sami> + return cp_lookup_symbol_namespace(scope, name, linkage_name, block, domain, 1); Missing space before "(". There are a few of these. Sami> + search_parents ); Extra space. Sami> + directive_match = search_parents ? Sami> + strncmp (scope, current->import_dest, Sami> + strlen(current->import_dest)) == 0 : Sami> + strcmp (scope, current->import_dest) == 0; GNU style is to line break before an operator, not after. There are several instances of this. Sami> +############################################ Sami> +# Test that the search can fail efficiently Sami> + Sami> +gdb_test "print y" "No symbol \"y\" in current context." I like the test case :) Sami> - VAR_DOMAIN); Sami> + VAR_DOMAIN,1); Missing space after the ",". Tom ^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [patch 2/2] Perform a namespace lookup at every block level 2009-10-13 20:22 ` Tom Tromey @ 2009-10-22 17:47 ` Sami Wagiaalla 2009-11-10 22:52 ` Tom Tromey 0 siblings, 1 reply; 28+ messages in thread From: Sami Wagiaalla @ 2009-10-22 17:47 UTC (permalink / raw) To: tromey; +Cc: GDB Patches Sorry, that patch was meant to go at the end of the series. I should have change the subject to [patch 3/3] or something. Anyhow I have made the changes you asked for and combined the patch you missed with this one. Thanks. Here is the new patch: 2009-10-22 Sami Wagiaalla <swagiaal@redhat.com> * cp-namespace.c (cp_lookup_symbol_namespace): Added search_parent argument. (cp_add_using): Initialize 'searched' feild. (cp_copy_usings): Copy searched feild. * cp-support.h: Add 'searched' feild to using_direct struct. (cp_lookup_symbol_imports): Ditto. * cp-namespace.c (cp_lookup_symbol_imports): Ditto. Perform recursive search. Implement non parent search. * valops.c (value_maybe_namespace_elt): Updated. 2009-10-22 Sami Wagiaalla <swagiaal@redhat.com> * gdb.cp/namespace-stress.exp: New test. * gdb.cp/namespace-stress.cc: New test program. * gdb.cp/namespace-recursive.exp: New test. * gdb.cp/namespace-recursive.cc: New test program. * gdb.cp/namespace-stress.exp: New test. * gdb.cp/namespace-stress.cc: New test program. diff --git a/gdb/cp-namespace.c b/gdb/cp-namespace.c index 06a5486..857e485 100644 --- a/gdb/cp-namespace.c +++ b/gdb/cp-namespace.c @@ -217,6 +217,7 @@ cp_add_using (const char *dest, retval->import_src = savestring (src, strlen(src)); retval->import_dest = savestring (dest, strlen(dest)); retval->next = next; + retval->searched = 0; return retval; } @@ -243,6 +244,8 @@ cp_copy_usings (struct using_direct *using, obstack); retval->next = cp_copy_usings (using->next, obstack); + retval->searched = using->searched; + xfree (using->import_src); xfree (using->import_dest); xfree (using); @@ -272,7 +275,8 @@ cp_lookup_symbol_nonlocal (const char *name, if (sym != NULL) return sym; - return cp_lookup_symbol_namespace (scope, name, linkage_name, block, domain); + return cp_lookup_symbol_namespace (scope, name, linkage_name, block, domain, + 1); } /* Look up NAME in the C++ namespace NAMESPACE. Other arguments are as in @@ -304,17 +308,33 @@ cp_lookup_symbol_in_namespace (const char *namespace, } /* Search for NAME by applying all import statements belonging - to BLOCK which are applicable in SCOPE. */ + to BLOCK which are applicable in SCOPE. + If SEARCH_PARENTS the search will include imports which are applicable in + parents of SCOPE. + Example: + + namespace A{ + using namespace X; + namespace B{ + using namespace Y; + } + } + + If SCOPE is "A::B" and SEARCH_PARENTS is true the imports of namespaces X + and Y will be considered. If SEARCH_PARENTS is false only the import of Y + is considered. */ static struct symbol * cp_lookup_symbol_imports (const char *scope, const char *name, const char *linkage_name, const struct block *block, - const domain_enum domain) + const domain_enum domain, + const int search_parents) { - const struct using_direct *current; + struct using_direct *current; struct symbol *sym; + int directive_match; /* First, try to find the symbol in the given namespace. */ sym = cp_lookup_symbol_in_namespace (scope, name, linkage_name, block, @@ -331,15 +351,29 @@ cp_lookup_symbol_imports (const char *scope, current = current->next) { + directive_match = search_parents + ? strncmp (scope, current->import_dest, + strlen(current->import_dest)) == 0 + : strcmp (scope, current->import_dest) == 0; + /* If the import destination is the current scope or one of its ancestors then it is applicable. */ - if (strncmp (scope, current->import_dest, strlen (current->import_dest)) == 0) + if (directive_match + && strncmp (scope, current->import_dest, + strlen (current->import_dest)) == 0 + && !current->searched) { - sym = cp_lookup_symbol_in_namespace (current->import_src, - name, - linkage_name, - block, - domain); + /* Mark this import as searched so that the recursive call does not + search it again. */ + current->searched = 1; + sym = cp_lookup_symbol_namespace (current->import_src, + name, + linkage_name, + block, + domain, + 0); + + current->searched = 0; if (sym != NULL) return sym; } @@ -348,7 +382,6 @@ cp_lookup_symbol_imports (const char *scope, return NULL; } - /* Searches for NAME in the current namespace, and by applying relevant import statements belonging to BLOCK and its parents. SCOPE is the namespace scope of the context in which the search is being evaluated. */ @@ -358,14 +391,16 @@ cp_lookup_symbol_namespace (const char *scope, const char *name, const char *linkage_name, const struct block *block, - const domain_enum domain) + const domain_enum domain, + const int search_parents) { struct symbol *sym; /* Search for name in namespaces imported to this and parent blocks. */ while (block != NULL) { - sym = cp_lookup_symbol_imports (scope,name, linkage_name, block, domain); + sym = cp_lookup_symbol_imports (scope, name, linkage_name, block, domain, + search_parents); if (sym) return sym; diff --git a/gdb/cp-support.h b/gdb/cp-support.h index 7ecd201..9400469 100644 --- a/gdb/cp-support.h +++ b/gdb/cp-support.h @@ -47,6 +47,9 @@ struct using_direct char *import_src; char *import_dest; struct using_direct *next; + + /* Used during import search to temporarily mark this node as searched. */ + int searched; }; @@ -107,7 +110,8 @@ extern struct symbol *cp_lookup_symbol_namespace (const char *namespace, const char *name, const char *linkage_name, const struct block *block, - const domain_enum domain); + const domain_enum domain, + const int search_parents); extern struct type *cp_lookup_nested_type (struct type *parent_type, const char *nested_name, diff --git a/gdb/testsuite/gdb.cp/namespace-recursive.cc b/gdb/testsuite/gdb.cp/namespace-recursive.cc new file mode 100644 index 0000000..9368ad8 --- /dev/null +++ b/gdb/testsuite/gdb.cp/namespace-recursive.cc @@ -0,0 +1,30 @@ +namespace A{ + int ax = 9; +} + +namespace B{ + using namespace A; +} + +namespace C{ + using namespace B; +} + +//--------------- +namespace D{ + using namespace D; + int dx = 99; +} +using namespace C; + +//--------------- +namespace{ + namespace{ + int xx = 999; + } +} + +int main(){ + using namespace D; + return ax + dx + xx; +} \ No newline at end of file diff --git a/gdb/testsuite/gdb.cp/namespace-recursive.exp b/gdb/testsuite/gdb.cp/namespace-recursive.exp new file mode 100644 index 0000000..e9dc004 --- /dev/null +++ b/gdb/testsuite/gdb.cp/namespace-recursive.exp @@ -0,0 +1,66 @@ +# Copyright 2008 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +if $tracelevel then { + strace $tracelevel +} + +set prms_id 0 +set bug_id 0 + +set testfile namespace-recursive +set srcfile ${testfile}.cc +set binfile ${objdir}/${subdir}/${testfile} +if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug c++}] != "" } { + untested "Couldn't compile test program" + return -1 +} + +if [get_compiler_info ${binfile}] { + return -1; +} + + +# Get things started. + +gdb_exit +gdb_start +gdb_reinitialize_dir $srcdir/$subdir +gdb_load ${binfile} + +if ![runto_main] then { + perror "couldn't run to breakpoint main" + continue +} + +############################################ +# test printing from namespace imported into +# imported namespace + +gdb_test "print ax" "= 9" + +############################################ +# test that gdb can print without falling +# into search loop + +gdb_test "print dx" "= 99" + +############################################ +# test printing from namespace imported into +# imported namespace where imports are implicit +# anonymous namespace imports. + +gdb_test "print xx" "= 999" + diff --git a/gdb/testsuite/gdb.cp/namespace-stress.cc b/gdb/testsuite/gdb.cp/namespace-stress.cc new file mode 100644 index 0000000..f34083e --- /dev/null +++ b/gdb/testsuite/gdb.cp/namespace-stress.cc @@ -0,0 +1,60 @@ + +namespace A{ int x; } +namespace B{ int x; } +namespace C{ int x; } +namespace D{ int x; } +namespace E{ int x; } +namespace F{ int x; } +namespace G{ int x; } +namespace H{ int x; } +namespace I{ int x; } +namespace J{ int x; } +namespace K{ int x; } +namespace L{ int x; } +namespace M{ int x; } +namespace N{ int x; } +namespace O{ int x; } +namespace P{ int x; } +namespace Q{ int x; } +namespace R{ int x; } +namespace S{ int x; } +namespace T{ int x; } +namespace U{ int x; } +namespace V{ int x; } +namespace W{ int x; } +namespace X{ int x; } +namespace Y{ int x; } +namespace Z{ int x; } + + +int main(){ + + using namespace A; + using namespace B; + using namespace C; + using namespace D; + using namespace E; + using namespace F; + using namespace G; + using namespace H; + using namespace I; + using namespace J; + using namespace K; + using namespace L; + using namespace M; + using namespace N; + using namespace O; + using namespace P; + using namespace Q; + using namespace R; + using namespace S; + using namespace T; + using namespace U; + using namespace V; + using namespace W; + using namespace X; + using namespace Y; + using namespace Z; + + return 0; +} \ No newline at end of file diff --git a/gdb/testsuite/gdb.cp/namespace-stress.exp b/gdb/testsuite/gdb.cp/namespace-stress.exp new file mode 100644 index 0000000..36e0628 --- /dev/null +++ b/gdb/testsuite/gdb.cp/namespace-stress.exp @@ -0,0 +1,50 @@ +# Copyright 2008 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +if $tracelevel then { + strace $tracelevel +} + +set prms_id 0 +set bug_id 0 + +set testfile namespace-stress +set srcfile ${testfile}.cc +set binfile ${objdir}/${subdir}/${testfile} +if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug c++}] != "" } { + untested "Couldn't compile test program" + return -1 +} + +if [get_compiler_info ${binfile}] { + return -1; +} + +# Get things started. + +gdb_exit +gdb_start +gdb_reinitialize_dir $srcdir/$subdir +gdb_load ${binfile} + +if ![runto_main] then { + perror "couldn't run to breakpoint main" + continue +} + +############################################ +# Test that the search can fail efficiently + +gdb_test "print y" "No symbol \"y\" in current context." diff --git a/gdb/valops.c b/gdb/valops.c index 012ea6a..6fdea95 100644 --- a/gdb/valops.c +++ b/gdb/valops.c @@ -2765,7 +2765,7 @@ value_maybe_namespace_elt (const struct type *curtype, sym = cp_lookup_symbol_namespace (namespace_name, name, NULL, get_selected_block (0), - VAR_DOMAIN); + VAR_DOMAIN, 1); if (sym == NULL) return NULL; ^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [patch 2/2] Perform a namespace lookup at every block level 2009-10-22 17:47 ` Sami Wagiaalla @ 2009-11-10 22:52 ` Tom Tromey 2009-11-16 17:55 ` Sami Wagiaalla 0 siblings, 1 reply; 28+ messages in thread From: Tom Tromey @ 2009-11-10 22:52 UTC (permalink / raw) To: Sami Wagiaalla; +Cc: GDB Patches >>>>> "Sami" == Sami Wagiaalla <swagiaal@redhat.com> writes: Sami> + directive_match = search_parents Sami> + ? strncmp (scope, current->import_dest, Sami> + strlen(current->import_dest)) == 0 Sami> + : strcmp (scope, current->import_dest) == 0; In the GNU style a multi-line expression like this has to be surrounded by parens. Put one before 'search_parents' and then another before ';'. Also this is missing a space after 'strlen'. Sami> + /* Mark this import as searched so that the recursive call does not Sami> + search it again. */ Sami> + current->searched = 1; Sami> + sym = cp_lookup_symbol_namespace (current->import_src, Sami> + name, Sami> + linkage_name, Sami> + block, Sami> + domain, Sami> + 0); Sami> + Sami> + current->searched = 0; If cp_lookup_symbol_namespace can throw an exception, then it can leave the wrong setting of 'searched' here. I don't know whether cp_lookup_symbol_namespace can in fact throw, but I tend to assume that most things in GDB can and defensively use cleanups. Do the new tests include a case which exercises this? Sami> diff --git a/gdb/testsuite/gdb.cp/namespace-recursive.exp b/gdb/testsuite/gdb.cp/namespace-recursive.exp Sami> + return -1; s/;// Sami> diff --git a/gdb/testsuite/gdb.cp/namespace-stress.exp b/gdb/testsuite/gdb.cp/namespace-stress.exp Sami> + return -1; Likewise. Tom ^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [patch 2/2] Perform a namespace lookup at every block level 2009-11-10 22:52 ` Tom Tromey @ 2009-11-16 17:55 ` Sami Wagiaalla 2009-11-24 19:12 ` Sami Wagiaalla 0 siblings, 1 reply; 28+ messages in thread From: Sami Wagiaalla @ 2009-11-16 17:55 UTC (permalink / raw) To: tromey; +Cc: GDB Patches > Sami> + /* Mark this import as searched so that the recursive call does not > Sami> + search it again. */ > Sami> + current->searched = 1; > Sami> + sym = cp_lookup_symbol_namespace (current->import_src, > Sami> + name, > Sami> + linkage_name, > Sami> + block, > Sami> + domain, > Sami> + 0); > Sami> + > Sami> + current->searched = 0; > > If cp_lookup_symbol_namespace can throw an exception, then it can leave > the wrong setting of 'searched' here. > > I don't know whether cp_lookup_symbol_namespace can in fact throw, but I > tend to assume that most things in GDB can and defensively use cleanups. > > Do the new tests include a case which exercises this? > I don't know how to test for this. There is no immediately obvious 'throw' that I can try to provoke, but I have added cleanups to be safe: 2009-11-16 Sami Wagiaalla <swagiaal@redhat.com> * cp-namespace.c (cp_lookup_symbol_namespace): Added search_parent argument. (cp_add_using): Initialize 'searched' field. (cp_copy_usings): Copy searched field. * cp-support.h: Add 'searched' field to using_direct struct. (cp_lookup_symbol_imports): Ditto. * cp-namespace.c (cp_lookup_symbol_imports): Ditto. Perform recursive search. Implement non parent search. * valops.c (value_maybe_namespace_elt): Updated. 2009-11-16 Sami Wagiaalla <swagiaal@redhat.com> * gdb.cp/namespace-stress.exp: New test. * gdb.cp/namespace-stress.cc: New test program. * gdb.cp/namespace-recursive.exp: New test. * gdb.cp/namespace-recursive.cc: New test program. * gdb.cp/namespace-stress.exp: New test. * gdb.cp/namespace-stress.cc: New test program. diff --git a/gdb/cp-namespace.c b/gdb/cp-namespace.c index 1980681..fc067f1 100644 --- a/gdb/cp-namespace.c +++ b/gdb/cp-namespace.c @@ -217,6 +217,7 @@ cp_add_using (const char *dest, retval->import_src = savestring (src, strlen(src)); retval->import_dest = savestring (dest, strlen(dest)); retval->next = next; + retval->searched = 0; return retval; } @@ -243,6 +244,8 @@ cp_copy_usings (struct using_direct *using, obstack); retval->next = cp_copy_usings (using->next, obstack); + retval->searched = using->searched; + xfree (using->import_src); xfree (using->import_dest); xfree (using); @@ -272,7 +275,8 @@ cp_lookup_symbol_nonlocal (const char *name, if (sym != NULL) return sym; - return cp_lookup_symbol_namespace (scope, name, linkage_name, block, domain); + return cp_lookup_symbol_namespace (scope, name, linkage_name, block, domain, + 1); } /* Look up NAME in the C++ namespace NAMESPACE. Other arguments are as in @@ -302,19 +306,46 @@ cp_lookup_symbol_in_namespace (const char *namespace, } } +/* Used for cleanups to reset the "searched" flag incase + of an error. */ + +static void +reset_directive_searched (void *data) +{ + struct using_direct *direct = data; + direct->searched = 0; +} + /* Search for NAME by applying all import statements belonging - to BLOCK which are applicable in SCOPE. */ + to BLOCK which are applicable in SCOPE. + If SEARCH_PARENTS the search will include imports which are applicable in + parents of SCOPE. + Example: + + namespace A{ + using namespace X; + namespace B{ + using namespace Y; + } + } + + If SCOPE is "A::B" and SEARCH_PARENTS is true the imports of namespaces X + and Y will be considered. If SEARCH_PARENTS is false only the import of Y + is considered. */ static struct symbol * cp_lookup_symbol_imports (const char *scope, const char *name, const char *linkage_name, const struct block *block, - const domain_enum domain) + const domain_enum domain, + const int search_parents) { - const struct using_direct *current; + struct using_direct *current; struct symbol *sym; int len; + int directive_match; + struct cleanup *searched_cleanup; /* First, try to find the symbol in the given namespace. */ sym = cp_lookup_symbol_in_namespace (scope, name, linkage_name, block, @@ -331,14 +362,32 @@ cp_lookup_symbol_imports (const char *scope, current = current->next) { + directive_match = (search_parents + ? (strncmp (scope, current->import_dest, + strlen (current->import_dest)) == 0 + && (scope[len] == ':' || scope[len] == '\0')) + : strcmp (scope, current->import_dest) == 0); + /* If the import destination is the current scope or one of its ancestors then it is applicable. */ len = strlen (current->import_dest); - if (strncmp (scope, current->import_dest, len) == 0 - && (scope[len] == ':' || scope[len] == '\0')) + if (directive_match && !current->searched) { - sym = cp_lookup_symbol_in_namespace (current->import_src, name, - linkage_name, block, domain); + /* Mark this import as searched so that the recursive call does not + search it again. */ + current->searched = 1; + searched_cleanup = make_cleanup (reset_directive_searched, current); + + sym = cp_lookup_symbol_namespace (current->import_src, + name, + linkage_name, + block, + domain, + 0); + + current->searched = 0; + discard_cleanups (searched_cleanup); + if (sym != NULL) return sym; } @@ -347,7 +396,6 @@ cp_lookup_symbol_imports (const char *scope, return NULL; } - /* Searches for NAME in the current namespace, and by applying relevant import statements belonging to BLOCK and its parents. SCOPE is the namespace scope of the context in which the search is being evaluated. */ @@ -357,14 +405,16 @@ cp_lookup_symbol_namespace (const char *scope, const char *name, const char *linkage_name, const struct block *block, - const domain_enum domain) + const domain_enum domain, + const int search_parents) { struct symbol *sym; /* Search for name in namespaces imported to this and parent blocks. */ while (block != NULL) { - sym = cp_lookup_symbol_imports (scope,name, linkage_name, block, domain); + sym = cp_lookup_symbol_imports (scope, name, linkage_name, block, domain, + search_parents); if (sym) return sym; diff --git a/gdb/cp-support.h b/gdb/cp-support.h index 7ecd201..9400469 100644 --- a/gdb/cp-support.h +++ b/gdb/cp-support.h @@ -47,6 +47,9 @@ struct using_direct char *import_src; char *import_dest; struct using_direct *next; + + /* Used during import search to temporarily mark this node as searched. */ + int searched; }; @@ -107,7 +110,8 @@ extern struct symbol *cp_lookup_symbol_namespace (const char *namespace, const char *name, const char *linkage_name, const struct block *block, - const domain_enum domain); + const domain_enum domain, + const int search_parents); extern struct type *cp_lookup_nested_type (struct type *parent_type, const char *nested_name, diff --git a/gdb/testsuite/gdb.cp/namespace-recursive.cc b/gdb/testsuite/gdb.cp/namespace-recursive.cc new file mode 100644 index 0000000..9368ad8 --- /dev/null +++ b/gdb/testsuite/gdb.cp/namespace-recursive.cc @@ -0,0 +1,30 @@ +namespace A{ + int ax = 9; +} + +namespace B{ + using namespace A; +} + +namespace C{ + using namespace B; +} + +//--------------- +namespace D{ + using namespace D; + int dx = 99; +} +using namespace C; + +//--------------- +namespace{ + namespace{ + int xx = 999; + } +} + +int main(){ + using namespace D; + return ax + dx + xx; +} \ No newline at end of file diff --git a/gdb/testsuite/gdb.cp/namespace-recursive.exp b/gdb/testsuite/gdb.cp/namespace-recursive.exp new file mode 100644 index 0000000..7fa6bd1 --- /dev/null +++ b/gdb/testsuite/gdb.cp/namespace-recursive.exp @@ -0,0 +1,65 @@ +# Copyright 2008 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +if $tracelevel then { + strace $tracelevel +} + +set prms_id 0 +set bug_id 0 + +set testfile namespace-recursive +set srcfile ${testfile}.cc +set binfile ${objdir}/${subdir}/${testfile} +if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug c++}] != "" } { + untested "Couldn't compile test program" + return -1 +} + +if [get_compiler_info ${binfile}] { + return -1 +} + + +# Get things started. + +gdb_exit +gdb_start +gdb_reinitialize_dir $srcdir/$subdir +gdb_load ${binfile} + +if ![runto_main] then { + perror "couldn't run to breakpoint main" + continue +} + +############################################ +# test printing from namespace imported into +# imported namespace + +gdb_test "print ax" "= 9" + +############################################ +# test that gdb can print without falling +# into search loop + +gdb_test "print dx" "= 99" + +############################################ +# test printing from namespace imported into +# imported namespace where imports are implicit +# anonymous namespace imports. + +gdb_test "print xx" "= 999" diff --git a/gdb/testsuite/gdb.cp/namespace-stress.cc b/gdb/testsuite/gdb.cp/namespace-stress.cc new file mode 100644 index 0000000..f34083e --- /dev/null +++ b/gdb/testsuite/gdb.cp/namespace-stress.cc @@ -0,0 +1,60 @@ + +namespace A{ int x; } +namespace B{ int x; } +namespace C{ int x; } +namespace D{ int x; } +namespace E{ int x; } +namespace F{ int x; } +namespace G{ int x; } +namespace H{ int x; } +namespace I{ int x; } +namespace J{ int x; } +namespace K{ int x; } +namespace L{ int x; } +namespace M{ int x; } +namespace N{ int x; } +namespace O{ int x; } +namespace P{ int x; } +namespace Q{ int x; } +namespace R{ int x; } +namespace S{ int x; } +namespace T{ int x; } +namespace U{ int x; } +namespace V{ int x; } +namespace W{ int x; } +namespace X{ int x; } +namespace Y{ int x; } +namespace Z{ int x; } + + +int main(){ + + using namespace A; + using namespace B; + using namespace C; + using namespace D; + using namespace E; + using namespace F; + using namespace G; + using namespace H; + using namespace I; + using namespace J; + using namespace K; + using namespace L; + using namespace M; + using namespace N; + using namespace O; + using namespace P; + using namespace Q; + using namespace R; + using namespace S; + using namespace T; + using namespace U; + using namespace V; + using namespace W; + using namespace X; + using namespace Y; + using namespace Z; + + return 0; +} \ No newline at end of file diff --git a/gdb/testsuite/gdb.cp/namespace-stress.exp b/gdb/testsuite/gdb.cp/namespace-stress.exp new file mode 100644 index 0000000..64da6df --- /dev/null +++ b/gdb/testsuite/gdb.cp/namespace-stress.exp @@ -0,0 +1,50 @@ +# Copyright 2008 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +if $tracelevel then { + strace $tracelevel +} + +set prms_id 0 +set bug_id 0 + +set testfile namespace-stress +set srcfile ${testfile}.cc +set binfile ${objdir}/${subdir}/${testfile} +if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug c++}] != "" } { + untested "Couldn't compile test program" + return -1 +} + +if [get_compiler_info ${binfile}] { + return -1 +} + +# Get things started. + +gdb_exit +gdb_start +gdb_reinitialize_dir $srcdir/$subdir +gdb_load ${binfile} + +if ![runto_main] then { + perror "couldn't run to breakpoint main" + continue +} + +############################################ +# Test that the search can fail efficiently + +gdb_test "print y" "No symbol \"y\" in current context." diff --git a/gdb/valops.c b/gdb/valops.c index 012ea6a..6fdea95 100644 --- a/gdb/valops.c +++ b/gdb/valops.c @@ -2765,7 +2765,7 @@ value_maybe_namespace_elt (const struct type *curtype, sym = cp_lookup_symbol_namespace (namespace_name, name, NULL, get_selected_block (0), - VAR_DOMAIN); + VAR_DOMAIN, 1); if (sym == NULL) return NULL; ^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [patch 2/2] Perform a namespace lookup at every block level 2009-11-16 17:55 ` Sami Wagiaalla @ 2009-11-24 19:12 ` Sami Wagiaalla 2009-12-21 21:55 ` Tom Tromey 0 siblings, 1 reply; 28+ messages in thread From: Sami Wagiaalla @ 2009-11-24 19:12 UTC (permalink / raw) To: gdb-patches [-- Attachment #1: Type: text/plain, Size: 7456 bytes --] Updating patch because of changes in patch 1/2 2009-11-16 Sami Wagiaalla <swagiaal@redhat.com> * cp-namespace.c (cp_lookup_symbol_namespace): Added search_parent argument. (cp_add_using): Initialize 'searched' field. (cp_copy_usings): Copy searched field. * cp-support.h: Add 'searched' field to using_direct struct. (cp_lookup_symbol_imports): Ditto. * cp-namespace.c (cp_lookup_symbol_imports): Ditto. Perform recursive search. Implement non parent search. * valops.c (value_maybe_namespace_elt): Updated. 2009-11-16 Sami Wagiaalla <swagiaal@redhat.com> * gdb.cp/namespace-stress.exp: New test. * gdb.cp/namespace-stress.cc: New test program. * gdb.cp/namespace-recursive.exp: New test. * gdb.cp/namespace-recursive.cc: New test program. * gdb.cp/namespace-stress.exp: New test. * gdb.cp/namespace-stress.cc: New test program. diff --git a/gdb/cp-namespace.c b/gdb/cp-namespace.c index f63cf8a..e2f1d43 100644 --- a/gdb/cp-namespace.c +++ b/gdb/cp-namespace.c @@ -217,6 +217,7 @@ cp_add_using (const char *dest, retval->import_src = savestring (src, strlen(src)); retval->import_dest = savestring (dest, strlen(dest)); retval->next = next; + retval->searched = 0; return retval; } @@ -243,6 +244,8 @@ cp_copy_usings (struct using_direct *using, obstack); retval->next = cp_copy_usings (using->next, obstack); + retval->searched = using->searched; + xfree (using->import_src); xfree (using->import_dest); xfree (using); @@ -272,7 +275,8 @@ cp_lookup_symbol_nonlocal (const char *name, if (sym != NULL) return sym; - return cp_lookup_symbol_namespace (scope, name, linkage_name, block, domain); + return cp_lookup_symbol_namespace (scope, name, linkage_name, block, domain, + 1); } /* Look up NAME in the C++ namespace NAMESPACE. Other arguments are as in @@ -302,19 +306,46 @@ cp_lookup_symbol_in_namespace (const char *namespace, } } -/* Search for NAME by applying all import statements belonging - to BLOCK which are applicable in SCOPE. */ +/* Used for cleanups to reset the "searched" flag incase + of an error. */ + +static void +reset_directive_searched (void *data) +{ + struct using_direct *direct = data; + direct->searched = 0; +} +/* Search for NAME by applying all import statements belonging + to BLOCK which are applicable in SCOPE. + If SEARCH_PARENTS the search will include imports which are applicable in + parents of SCOPE. + Example: + + namespace A{ + using namespace X; + namespace B{ + using namespace Y; + } + } + + If SCOPE is "A::B" and SEARCH_PARENTS is true the imports of namespaces X + and Y will be considered. If SEARCH_PARENTS is false only the import of Y + is considered. */ + static struct symbol * cp_lookup_symbol_imports (const char *scope, const char *name, const char *linkage_name, const struct block *block, - const domain_enum domain) + const domain_enum domain, + const int search_parents) { - const struct using_direct *current; + struct using_direct *current; struct symbol *sym; int len; + int directive_match; + struct cleanup *searched_cleanup; /* First, try to find the symbol in the given namespace. */ sym = cp_lookup_symbol_in_namespace (scope, name, linkage_name, block, @@ -330,24 +361,41 @@ cp_lookup_symbol_imports (const char *scope, current != NULL; current = current->next) { + len = strlen (current->import_dest); + directive_match = (search_parents + ? (strncmp (scope, current->import_dest, + strlen (current->import_dest)) == 0 + && (len == 0 + || scope[len] == ':' || scope[len] == '\0')) + : strcmp (scope, current->import_dest) == 0); /* If the import destination is the current scope or one of its ancestors then it is applicable. */ - len = strlen (current->import_dest); - if (strncmp (scope, current->import_dest, len) == 0 - && (len == 0 || scope[len] == ':' || scope[len] == '\0')) + if (directive_match && !current->searched) { - sym = cp_lookup_symbol_in_namespace (current->import_src, name, - linkage_name, block, domain); - if (sym != NULL) - return sym; + /* Mark this import as searched so that the recursive call does not + search it again. */ + current->searched = 1; + searched_cleanup = make_cleanup (reset_directive_searched, current); + + sym = cp_lookup_symbol_namespace (current->import_src, + name, + linkage_name, + block, + domain, + 0); + + current->searched = 0; + discard_cleanups (searched_cleanup); + + if (sym != NULL) + return sym; } } return NULL; } - /* Searches for NAME in the current namespace, and by applying relevant import statements belonging to BLOCK and its parents. SCOPE is the namespace scope of the context in which the search is being evaluated. */ @@ -357,14 +405,16 @@ cp_lookup_symbol_namespace (const char *scope, const char *name, const char *linkage_name, const struct block *block, - const domain_enum domain) + const domain_enum domain, + const int search_parents) { struct symbol *sym; /* Search for name in namespaces imported to this and parent blocks. */ while (block != NULL) { - sym = cp_lookup_symbol_imports (scope,name, linkage_name, block, domain); + sym = cp_lookup_symbol_imports (scope, name, linkage_name, block, domain, + search_parents); if (sym) return sym; diff --git a/gdb/cp-support.h b/gdb/cp-support.h index 7ecd201..9400469 100644 --- a/gdb/cp-support.h +++ b/gdb/cp-support.h @@ -47,6 +47,9 @@ struct using_direct char *import_src; char *import_dest; struct using_direct *next; + + /* Used during import search to temporarily mark this node as searched. */ + int searched; }; @@ -107,7 +110,8 @@ extern struct symbol *cp_lookup_symbol_namespace (const char *namespace, const char *name, const char *linkage_name, const struct block *block, - const domain_enum domain); + const domain_enum domain, + const int search_parents); extern struct type *cp_lookup_nested_type (struct type *parent_type, const char *nested_name, diff --git a/gdb/valops.c b/gdb/valops.c index 012ea6a..6fdea95 100644 --- a/gdb/valops.c +++ b/gdb/valops.c @@ -2765,7 +2765,7 @@ value_maybe_namespace_elt (const struct type *curtype, sym = cp_lookup_symbol_namespace (namespace_name, name, NULL, get_selected_block (0), - VAR_DOMAIN); + VAR_DOMAIN, 1); if (sym == NULL) return NULL; [-- Attachment #2: sami2-recursive-search.patch --] [-- Type: text/plain, Size: 7316 bytes --] 2009-11-16 Sami Wagiaalla <swagiaal@redhat.com> * cp-namespace.c (cp_lookup_symbol_namespace): Added search_parent argument. (cp_add_using): Initialize 'searched' field. (cp_copy_usings): Copy searched field. * cp-support.h: Add 'searched' field to using_direct struct. (cp_lookup_symbol_imports): Ditto. * cp-namespace.c (cp_lookup_symbol_imports): Ditto. Perform recursive search. Implement non parent search. * valops.c (value_maybe_namespace_elt): Updated. 2009-11-16 Sami Wagiaalla <swagiaal@redhat.com> * gdb.cp/namespace-stress.exp: New test. * gdb.cp/namespace-stress.cc: New test program. * gdb.cp/namespace-recursive.exp: New test. * gdb.cp/namespace-recursive.cc: New test program. * gdb.cp/namespace-stress.exp: New test. * gdb.cp/namespace-stress.cc: New test program. diff --git a/gdb/cp-namespace.c b/gdb/cp-namespace.c index f63cf8a..e2f1d43 100644 --- a/gdb/cp-namespace.c +++ b/gdb/cp-namespace.c @@ -217,6 +217,7 @@ cp_add_using (const char *dest, retval->import_src = savestring (src, strlen(src)); retval->import_dest = savestring (dest, strlen(dest)); retval->next = next; + retval->searched = 0; return retval; } @@ -243,6 +244,8 @@ cp_copy_usings (struct using_direct *using, obstack); retval->next = cp_copy_usings (using->next, obstack); + retval->searched = using->searched; + xfree (using->import_src); xfree (using->import_dest); xfree (using); @@ -272,7 +275,8 @@ cp_lookup_symbol_nonlocal (const char *name, if (sym != NULL) return sym; - return cp_lookup_symbol_namespace (scope, name, linkage_name, block, domain); + return cp_lookup_symbol_namespace (scope, name, linkage_name, block, domain, + 1); } /* Look up NAME in the C++ namespace NAMESPACE. Other arguments are as in @@ -302,19 +306,46 @@ cp_lookup_symbol_in_namespace (const char *namespace, } } -/* Search for NAME by applying all import statements belonging - to BLOCK which are applicable in SCOPE. */ +/* Used for cleanups to reset the "searched" flag incase + of an error. */ + +static void +reset_directive_searched (void *data) +{ + struct using_direct *direct = data; + direct->searched = 0; +} +/* Search for NAME by applying all import statements belonging + to BLOCK which are applicable in SCOPE. + If SEARCH_PARENTS the search will include imports which are applicable in + parents of SCOPE. + Example: + + namespace A{ + using namespace X; + namespace B{ + using namespace Y; + } + } + + If SCOPE is "A::B" and SEARCH_PARENTS is true the imports of namespaces X + and Y will be considered. If SEARCH_PARENTS is false only the import of Y + is considered. */ + static struct symbol * cp_lookup_symbol_imports (const char *scope, const char *name, const char *linkage_name, const struct block *block, - const domain_enum domain) + const domain_enum domain, + const int search_parents) { - const struct using_direct *current; + struct using_direct *current; struct symbol *sym; int len; + int directive_match; + struct cleanup *searched_cleanup; /* First, try to find the symbol in the given namespace. */ sym = cp_lookup_symbol_in_namespace (scope, name, linkage_name, block, @@ -330,24 +361,41 @@ cp_lookup_symbol_imports (const char *scope, current != NULL; current = current->next) { + len = strlen (current->import_dest); + directive_match = (search_parents + ? (strncmp (scope, current->import_dest, + strlen (current->import_dest)) == 0 + && (len == 0 + || scope[len] == ':' || scope[len] == '\0')) + : strcmp (scope, current->import_dest) == 0); /* If the import destination is the current scope or one of its ancestors then it is applicable. */ - len = strlen (current->import_dest); - if (strncmp (scope, current->import_dest, len) == 0 - && (len == 0 || scope[len] == ':' || scope[len] == '\0')) + if (directive_match && !current->searched) { - sym = cp_lookup_symbol_in_namespace (current->import_src, name, - linkage_name, block, domain); - if (sym != NULL) - return sym; + /* Mark this import as searched so that the recursive call does not + search it again. */ + current->searched = 1; + searched_cleanup = make_cleanup (reset_directive_searched, current); + + sym = cp_lookup_symbol_namespace (current->import_src, + name, + linkage_name, + block, + domain, + 0); + + current->searched = 0; + discard_cleanups (searched_cleanup); + + if (sym != NULL) + return sym; } } return NULL; } - /* Searches for NAME in the current namespace, and by applying relevant import statements belonging to BLOCK and its parents. SCOPE is the namespace scope of the context in which the search is being evaluated. */ @@ -357,14 +405,16 @@ cp_lookup_symbol_namespace (const char *scope, const char *name, const char *linkage_name, const struct block *block, - const domain_enum domain) + const domain_enum domain, + const int search_parents) { struct symbol *sym; /* Search for name in namespaces imported to this and parent blocks. */ while (block != NULL) { - sym = cp_lookup_symbol_imports (scope,name, linkage_name, block, domain); + sym = cp_lookup_symbol_imports (scope, name, linkage_name, block, domain, + search_parents); if (sym) return sym; diff --git a/gdb/cp-support.h b/gdb/cp-support.h index 7ecd201..9400469 100644 --- a/gdb/cp-support.h +++ b/gdb/cp-support.h @@ -47,6 +47,9 @@ struct using_direct char *import_src; char *import_dest; struct using_direct *next; + + /* Used during import search to temporarily mark this node as searched. */ + int searched; }; @@ -107,7 +110,8 @@ extern struct symbol *cp_lookup_symbol_namespace (const char *namespace, const char *name, const char *linkage_name, const struct block *block, - const domain_enum domain); + const domain_enum domain, + const int search_parents); extern struct type *cp_lookup_nested_type (struct type *parent_type, const char *nested_name, diff --git a/gdb/valops.c b/gdb/valops.c index 012ea6a..6fdea95 100644 --- a/gdb/valops.c +++ b/gdb/valops.c @@ -2765,7 +2765,7 @@ value_maybe_namespace_elt (const struct type *curtype, sym = cp_lookup_symbol_namespace (namespace_name, name, NULL, get_selected_block (0), - VAR_DOMAIN); + VAR_DOMAIN, 1); if (sym == NULL) return NULL; ^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [patch 2/2] Perform a namespace lookup at every block level 2009-11-24 19:12 ` Sami Wagiaalla @ 2009-12-21 21:55 ` Tom Tromey 2010-01-11 21:24 ` Sami Wagiaalla 0 siblings, 1 reply; 28+ messages in thread From: Tom Tromey @ 2009-12-21 21:55 UTC (permalink / raw) To: Sami Wagiaalla; +Cc: gdb-patches >>>>> "Sami" == Sami Wagiaalla <swagiaal@redhat.com> writes: Sami> Updating patch because of changes in patch 1/2 Sami> 2009-11-16 Sami Wagiaalla <swagiaal@redhat.com> Sami> * cp-namespace.c (cp_lookup_symbol_namespace): Added Sami> search_parent argument. Sami> (cp_add_using): Initialize 'searched' field. Sami> (cp_copy_usings): Copy searched field. Sami> * cp-support.h: Add 'searched' field to using_direct struct. Sami> (cp_lookup_symbol_imports): Ditto. Sami> * cp-namespace.c (cp_lookup_symbol_imports): Ditto. Sami> Perform recursive search. Sami> Implement non parent search. Sami> * valops.c (value_maybe_namespace_elt): Updated. This is nearly ok. Note that the patch got a little mangled, and this resubmission was missing the changes in testsuite/. Sami> 2009-11-16 Sami Wagiaalla <swagiaal@redhat.com> Sami> * gdb.cp/namespace-stress.exp: New test. Sami> * gdb.cp/namespace-stress.cc: New test program. Sami> * gdb.cp/namespace-recursive.exp: New test. Sami> * gdb.cp/namespace-recursive.cc: New test program. Sami> * gdb.cp/namespace-stress.exp: New test. Sami> * gdb.cp/namespace-stress.cc: New test program. We're mostly following 8.3 rules, so I would suggest renaming these to "ns-*". Also, in an archer fix you had namespace-stress-declaration... what happened to that? The corresponding code patch seems to include reset_directive_searched: http://sourceware.org/ml/archer-commits/2009-q4/msg00094.html Speaking of which, reset_directive_searched is not mentioned in the ChangeLog. Tom ^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [patch 2/2] Perform a namespace lookup at every block level 2009-12-21 21:55 ` Tom Tromey @ 2010-01-11 21:24 ` Sami Wagiaalla 2010-01-12 17:43 ` Tom Tromey 0 siblings, 1 reply; 28+ messages in thread From: Sami Wagiaalla @ 2010-01-11 21:24 UTC (permalink / raw) To: tromey; +Cc: gdb-patches [-- Attachment #1: Type: text/plain, Size: 17074 bytes --] I have added the missing tests, and corrected the Changelog > > Sami> 2009-11-16 Sami Wagiaalla<swagiaal@redhat.com> > Sami> * gdb.cp/namespace-stress.exp: New test. > Sami> * gdb.cp/namespace-stress.cc: New test program. > Sami> * gdb.cp/namespace-recursive.exp: New test. > Sami> * gdb.cp/namespace-recursive.cc: New test program. > Sami> * gdb.cp/namespace-stress.exp: New test. > Sami> * gdb.cp/namespace-stress.cc: New test program. > > We're mostly following 8.3 rules, so I would suggest renaming these to > "ns-*". > Can I do this in a separate patch ? There are more files to rename, so I would like to do the renaming in one patch 2010-01-11 Sami Wagiaalla <swagiaal@redhat.com> * cp-namespace.c (cp_lookup_symbol_namespace): Added search_parent argument. (cp_add_using): Initialize 'searched' field. (cp_copy_usings): Copy searched field. (reset_directive_searched): New function. * cp-support.h: Add 'searched' field to using_direct struct. (cp_lookup_symbol_imports): Ditto. * cp-namespace.c (cp_lookup_symbol_imports): Ditto. Perform recursive search. Implement non parent search. * valops.c (value_maybe_namespace_elt): Updated. 2010-01-11 Sami Wagiaalla <swagiaal@redhat.com> * gdb.cp/namespace-stress.exp: New test. * gdb.cp/namespace-stress.cc: New test program. * gdb.cp/namespace-recursive.exp: New test. * gdb.cp/namespace-recursive.cc: New test program. * gdb.cp/namespace-stress.exp: New test. * gdb.cp/namespace-stress.cc: New test program. * gdb.cp/namespace-stress-declarations.exp: New test. * gdb.cp/namespace-stress-declarations.cc: New test program. diff --git a/gdb/cp-namespace.c b/gdb/cp-namespace.c index f63cf8a..e2f1d43 100644 --- a/gdb/cp-namespace.c +++ b/gdb/cp-namespace.c @@ -217,6 +217,7 @@ cp_add_using (const char *dest, retval->import_src = savestring (src, strlen(src)); retval->import_dest = savestring (dest, strlen(dest)); retval->next = next; + retval->searched = 0; return retval; } @@ -243,6 +244,8 @@ cp_copy_usings (struct using_direct *using, obstack); retval->next = cp_copy_usings (using->next, obstack); + retval->searched = using->searched; + xfree (using->import_src); xfree (using->import_dest); xfree (using); @@ -272,7 +275,8 @@ cp_lookup_symbol_nonlocal (const char *name, if (sym != NULL) return sym; - return cp_lookup_symbol_namespace (scope, name, linkage_name, block, domain); + return cp_lookup_symbol_namespace (scope, name, linkage_name, block, domain, + 1); } /* Look up NAME in the C++ namespace NAMESPACE. Other arguments are as in @@ -302,19 +306,46 @@ cp_lookup_symbol_in_namespace (const char *namespace, } } -/* Search for NAME by applying all import statements belonging - to BLOCK which are applicable in SCOPE. */ +/* Used for cleanups to reset the "searched" flag incase + of an error. */ + +static void +reset_directive_searched (void *data) +{ + struct using_direct *direct = data; + direct->searched = 0; +} +/* Search for NAME by applying all import statements belonging + to BLOCK which are applicable in SCOPE. + If SEARCH_PARENTS the search will include imports which are applicable in + parents of SCOPE. + Example: + + namespace A{ + using namespace X; + namespace B{ + using namespace Y; + } + } + + If SCOPE is "A::B" and SEARCH_PARENTS is true the imports of namespaces X + and Y will be considered. If SEARCH_PARENTS is false only the import of Y + is considered. */ + static struct symbol * cp_lookup_symbol_imports (const char *scope, const char *name, const char *linkage_name, const struct block *block, - const domain_enum domain) + const domain_enum domain, + const int search_parents) { - const struct using_direct *current; + struct using_direct *current; struct symbol *sym; int len; + int directive_match; + struct cleanup *searched_cleanup; /* First, try to find the symbol in the given namespace. */ sym = cp_lookup_symbol_in_namespace (scope, name, linkage_name, block, @@ -330,24 +361,41 @@ cp_lookup_symbol_imports (const char *scope, current != NULL; current = current->next) { + len = strlen (current->import_dest); + directive_match = (search_parents + ? (strncmp (scope, current->import_dest, + strlen (current->import_dest)) == 0 + && (len == 0 + || scope[len] == ':' || scope[len] == '\0')) + : strcmp (scope, current->import_dest) == 0); /* If the import destination is the current scope or one of its ancestors then it is applicable. */ - len = strlen (current->import_dest); - if (strncmp (scope, current->import_dest, len) == 0 - && (len == 0 || scope[len] == ':' || scope[len] == '\0')) + if (directive_match && !current->searched) { - sym = cp_lookup_symbol_in_namespace (current->import_src, name, - linkage_name, block, domain); - if (sym != NULL) - return sym; + /* Mark this import as searched so that the recursive call does not + search it again. */ + current->searched = 1; + searched_cleanup = make_cleanup (reset_directive_searched, current); + + sym = cp_lookup_symbol_namespace (current->import_src, + name, + linkage_name, + block, + domain, + 0); + + current->searched = 0; + discard_cleanups (searched_cleanup); + + if (sym != NULL) + return sym; } } return NULL; } - /* Searches for NAME in the current namespace, and by applying relevant import statements belonging to BLOCK and its parents. SCOPE is the namespace scope of the context in which the search is being evaluated. */ @@ -357,14 +405,16 @@ cp_lookup_symbol_namespace (const char *scope, const char *name, const char *linkage_name, const struct block *block, - const domain_enum domain) + const domain_enum domain, + const int search_parents) { struct symbol *sym; /* Search for name in namespaces imported to this and parent blocks. */ while (block != NULL) { - sym = cp_lookup_symbol_imports (scope,name, linkage_name, block, domain); + sym = cp_lookup_symbol_imports (scope, name, linkage_name, block, domain, + search_parents); if (sym) return sym; diff --git a/gdb/cp-support.h b/gdb/cp-support.h index 7ecd201..9400469 100644 --- a/gdb/cp-support.h +++ b/gdb/cp-support.h @@ -47,6 +47,9 @@ struct using_direct char *import_src; char *import_dest; struct using_direct *next; + + /* Used during import search to temporarily mark this node as searched. */ + int searched; }; @@ -107,7 +110,8 @@ extern struct symbol *cp_lookup_symbol_namespace (const char *namespace, const char *name, const char *linkage_name, const struct block *block, - const domain_enum domain); + const domain_enum domain, + const int search_parents); extern struct type *cp_lookup_nested_type (struct type *parent_type, const char *nested_name, diff --git a/gdb/testsuite/gdb.cp/namespace-recursive.cc b/gdb/testsuite/gdb.cp/namespace-recursive.cc new file mode 100644 index 0000000..9368ad8 --- /dev/null +++ b/gdb/testsuite/gdb.cp/namespace-recursive.cc @@ -0,0 +1,30 @@ +namespace A{ + int ax = 9; +} + +namespace B{ + using namespace A; +} + +namespace C{ + using namespace B; +} + +//--------------- +namespace D{ + using namespace D; + int dx = 99; +} +using namespace C; + +//--------------- +namespace{ + namespace{ + int xx = 999; + } +} + +int main(){ + using namespace D; + return ax + dx + xx; +} \ No newline at end of file diff --git a/gdb/testsuite/gdb.cp/namespace-recursive.exp b/gdb/testsuite/gdb.cp/namespace-recursive.exp new file mode 100644 index 0000000..7fa6bd1 --- /dev/null +++ b/gdb/testsuite/gdb.cp/namespace-recursive.exp @@ -0,0 +1,65 @@ +# Copyright 2008 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +if $tracelevel then { + strace $tracelevel +} + +set prms_id 0 +set bug_id 0 + +set testfile namespace-recursive +set srcfile ${testfile}.cc +set binfile ${objdir}/${subdir}/${testfile} +if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug c++}] != "" } { + untested "Couldn't compile test program" + return -1 +} + +if [get_compiler_info ${binfile}] { + return -1 +} + + +# Get things started. + +gdb_exit +gdb_start +gdb_reinitialize_dir $srcdir/$subdir +gdb_load ${binfile} + +if ![runto_main] then { + perror "couldn't run to breakpoint main" + continue +} + +############################################ +# test printing from namespace imported into +# imported namespace + +gdb_test "print ax" "= 9" + +############################################ +# test that gdb can print without falling +# into search loop + +gdb_test "print dx" "= 99" + +############################################ +# test printing from namespace imported into +# imported namespace where imports are implicit +# anonymous namespace imports. + +gdb_test "print xx" "= 999" diff --git a/gdb/testsuite/gdb.cp/namespace-stress-declarations.cc b/gdb/testsuite/gdb.cp/namespace-stress-declarations.cc new file mode 100644 index 0000000..173e49b --- /dev/null +++ b/gdb/testsuite/gdb.cp/namespace-stress-declarations.cc @@ -0,0 +1,93 @@ +int a; +int b; +int c; +int d; +int e; +int f; +int g; +int h; +int i; +int j; +int k; +int l; +int m; +int n; +int o; +int p; +int q; +int r; +int s; +int t; +int u; +int v; +int w; +int x; +int y; +int z; + +namespace A +{ + int xyz; + + using ::a; + using ::b; + using ::c; + using ::d; + using ::e; + using ::f; + using ::g; + using ::h; + using ::i; + using ::j; + using ::k; + using ::l; + using ::m; + using ::n; + using ::o; + using ::p; + using ::q; + using ::r; + using ::s; + using ::t; + using ::u; + using ::v; + using ::w; + using ::x; + using ::y; + using ::z; + +} + +using A::a; +using A::b; +using A::c; +using A::d; +using A::e; +using A::f; +using A::g; +using A::h; +using A::i; +using A::j; +using A::k; +using A::l; +using A::m; +using A::n; +using A::o; +using A::p; +using A::q; +using A::r; +using A::s; +using A::t; +using A::u; +using A::v; +using A::w; +using A::x; +using A::y; +using A::z; + +using namespace A; + +int main () +{ + return 0; +} \ No newline at end of file diff --git a/gdb/testsuite/gdb.cp/namespace-stress-declarations.exp b/gdb/testsuite/gdb.cp/namespace-stress-declarations.exp new file mode 100644 index 0000000..f22a14e --- /dev/null +++ b/gdb/testsuite/gdb.cp/namespace-stress-declarations.exp @@ -0,0 +1,50 @@ +# Copyright 2008 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +if $tracelevel then { + strace $tracelevel +} + +set prms_id 0 +set bug_id 0 + +set testfile namespace-stress-declarations +set srcfile ${testfile}.cc +set binfile ${objdir}/${subdir}/${testfile} +if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug c++}] != "" } { + untested "Couldn't compile test program" + return -1 +} + +if [get_compiler_info ${binfile}] { + return -1; +} + +# Get things started. + +gdb_exit +gdb_start +gdb_reinitialize_dir $srcdir/$subdir +gdb_load ${binfile} + +if ![runto_main] then { + perror "couldn't run to breakpoint main" + continue +} + +############################################ +# Test that the search can fail efficiently + +gdb_test "print fakex" "No symbol \"fakex\" in current context." diff --git a/gdb/testsuite/gdb.cp/namespace-stress.cc b/gdb/testsuite/gdb.cp/namespace-stress.cc new file mode 100644 index 0000000..f34083e --- /dev/null +++ b/gdb/testsuite/gdb.cp/namespace-stress.cc @@ -0,0 +1,60 @@ + +namespace A{ int x; } +namespace B{ int x; } +namespace C{ int x; } +namespace D{ int x; } +namespace E{ int x; } +namespace F{ int x; } +namespace G{ int x; } +namespace H{ int x; } +namespace I{ int x; } +namespace J{ int x; } +namespace K{ int x; } +namespace L{ int x; } +namespace M{ int x; } +namespace N{ int x; } +namespace O{ int x; } +namespace P{ int x; } +namespace Q{ int x; } +namespace R{ int x; } +namespace S{ int x; } +namespace T{ int x; } +namespace U{ int x; } +namespace V{ int x; } +namespace W{ int x; } +namespace X{ int x; } +namespace Y{ int x; } +namespace Z{ int x; } + + +int main(){ + + using namespace A; + using namespace B; + using namespace C; + using namespace D; + using namespace E; + using namespace F; + using namespace G; + using namespace H; + using namespace I; + using namespace J; + using namespace K; + using namespace L; + using namespace M; + using namespace N; + using namespace O; + using namespace P; + using namespace Q; + using namespace R; + using namespace S; + using namespace T; + using namespace U; + using namespace V; + using namespace W; + using namespace X; + using namespace Y; + using namespace Z; + + return 0; +} \ No newline at end of file diff --git a/gdb/testsuite/gdb.cp/namespace-stress.exp b/gdb/testsuite/gdb.cp/namespace-stress.exp new file mode 100644 index 0000000..64da6df --- /dev/null +++ b/gdb/testsuite/gdb.cp/namespace-stress.exp @@ -0,0 +1,50 @@ +# Copyright 2008 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +if $tracelevel then { + strace $tracelevel +} + +set prms_id 0 +set bug_id 0 + +set testfile namespace-stress +set srcfile ${testfile}.cc +set binfile ${objdir}/${subdir}/${testfile} +if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug c++}] != "" } { + untested "Couldn't compile test program" + return -1 +} + +if [get_compiler_info ${binfile}] { + return -1 +} + +# Get things started. + +gdb_exit +gdb_start +gdb_reinitialize_dir $srcdir/$subdir +gdb_load ${binfile} + +if ![runto_main] then { + perror "couldn't run to breakpoint main" + continue +} + +############################################ +# Test that the search can fail efficiently + +gdb_test "print y" "No symbol \"y\" in current context." diff --git a/gdb/valops.c b/gdb/valops.c index 012ea6a..6fdea95 100644 --- a/gdb/valops.c +++ b/gdb/valops.c @@ -2765,7 +2765,7 @@ value_maybe_namespace_elt (const struct type *curtype, sym = cp_lookup_symbol_namespace (namespace_name, name, NULL, get_selected_block (0), - VAR_DOMAIN); + VAR_DOMAIN, 1); if (sym == NULL) return NULL; [-- Attachment #2: sami2-recursive-search.patch --] [-- Type: text/plain, Size: 15234 bytes --] diff --git a/gdb/cp-namespace.c b/gdb/cp-namespace.c index f63cf8a..e2f1d43 100644 --- a/gdb/cp-namespace.c +++ b/gdb/cp-namespace.c @@ -217,6 +217,7 @@ cp_add_using (const char *dest, retval->import_src = savestring (src, strlen(src)); retval->import_dest = savestring (dest, strlen(dest)); retval->next = next; + retval->searched = 0; return retval; } @@ -243,6 +244,8 @@ cp_copy_usings (struct using_direct *using, obstack); retval->next = cp_copy_usings (using->next, obstack); + retval->searched = using->searched; + xfree (using->import_src); xfree (using->import_dest); xfree (using); @@ -272,7 +275,8 @@ cp_lookup_symbol_nonlocal (const char *name, if (sym != NULL) return sym; - return cp_lookup_symbol_namespace (scope, name, linkage_name, block, domain); + return cp_lookup_symbol_namespace (scope, name, linkage_name, block, domain, + 1); } /* Look up NAME in the C++ namespace NAMESPACE. Other arguments are as in @@ -302,19 +306,46 @@ cp_lookup_symbol_in_namespace (const char *namespace, } } -/* Search for NAME by applying all import statements belonging - to BLOCK which are applicable in SCOPE. */ +/* Used for cleanups to reset the "searched" flag incase + of an error. */ + +static void +reset_directive_searched (void *data) +{ + struct using_direct *direct = data; + direct->searched = 0; +} +/* Search for NAME by applying all import statements belonging + to BLOCK which are applicable in SCOPE. + If SEARCH_PARENTS the search will include imports which are applicable in + parents of SCOPE. + Example: + + namespace A{ + using namespace X; + namespace B{ + using namespace Y; + } + } + + If SCOPE is "A::B" and SEARCH_PARENTS is true the imports of namespaces X + and Y will be considered. If SEARCH_PARENTS is false only the import of Y + is considered. */ + static struct symbol * cp_lookup_symbol_imports (const char *scope, const char *name, const char *linkage_name, const struct block *block, - const domain_enum domain) + const domain_enum domain, + const int search_parents) { - const struct using_direct *current; + struct using_direct *current; struct symbol *sym; int len; + int directive_match; + struct cleanup *searched_cleanup; /* First, try to find the symbol in the given namespace. */ sym = cp_lookup_symbol_in_namespace (scope, name, linkage_name, block, @@ -330,24 +361,41 @@ cp_lookup_symbol_imports (const char *scope, current != NULL; current = current->next) { + len = strlen (current->import_dest); + directive_match = (search_parents + ? (strncmp (scope, current->import_dest, + strlen (current->import_dest)) == 0 + && (len == 0 + || scope[len] == ':' || scope[len] == '\0')) + : strcmp (scope, current->import_dest) == 0); /* If the import destination is the current scope or one of its ancestors then it is applicable. */ - len = strlen (current->import_dest); - if (strncmp (scope, current->import_dest, len) == 0 - && (len == 0 || scope[len] == ':' || scope[len] == '\0')) + if (directive_match && !current->searched) { - sym = cp_lookup_symbol_in_namespace (current->import_src, name, - linkage_name, block, domain); - if (sym != NULL) - return sym; + /* Mark this import as searched so that the recursive call does not + search it again. */ + current->searched = 1; + searched_cleanup = make_cleanup (reset_directive_searched, current); + + sym = cp_lookup_symbol_namespace (current->import_src, + name, + linkage_name, + block, + domain, + 0); + + current->searched = 0; + discard_cleanups (searched_cleanup); + + if (sym != NULL) + return sym; } } return NULL; } - /* Searches for NAME in the current namespace, and by applying relevant import statements belonging to BLOCK and its parents. SCOPE is the namespace scope of the context in which the search is being evaluated. */ @@ -357,14 +405,16 @@ cp_lookup_symbol_namespace (const char *scope, const char *name, const char *linkage_name, const struct block *block, - const domain_enum domain) + const domain_enum domain, + const int search_parents) { struct symbol *sym; /* Search for name in namespaces imported to this and parent blocks. */ while (block != NULL) { - sym = cp_lookup_symbol_imports (scope,name, linkage_name, block, domain); + sym = cp_lookup_symbol_imports (scope, name, linkage_name, block, domain, + search_parents); if (sym) return sym; diff --git a/gdb/cp-support.h b/gdb/cp-support.h index 7ecd201..9400469 100644 --- a/gdb/cp-support.h +++ b/gdb/cp-support.h @@ -47,6 +47,9 @@ struct using_direct char *import_src; char *import_dest; struct using_direct *next; + + /* Used during import search to temporarily mark this node as searched. */ + int searched; }; @@ -107,7 +110,8 @@ extern struct symbol *cp_lookup_symbol_namespace (const char *namespace, const char *name, const char *linkage_name, const struct block *block, - const domain_enum domain); + const domain_enum domain, + const int search_parents); extern struct type *cp_lookup_nested_type (struct type *parent_type, const char *nested_name, diff --git a/gdb/testsuite/gdb.cp/namespace-recursive.cc b/gdb/testsuite/gdb.cp/namespace-recursive.cc new file mode 100644 index 0000000..9368ad8 --- /dev/null +++ b/gdb/testsuite/gdb.cp/namespace-recursive.cc @@ -0,0 +1,30 @@ +namespace A{ + int ax = 9; +} + +namespace B{ + using namespace A; +} + +namespace C{ + using namespace B; +} + +//--------------- +namespace D{ + using namespace D; + int dx = 99; +} +using namespace C; + +//--------------- +namespace{ + namespace{ + int xx = 999; + } +} + +int main(){ + using namespace D; + return ax + dx + xx; +} \ No newline at end of file diff --git a/gdb/testsuite/gdb.cp/namespace-recursive.exp b/gdb/testsuite/gdb.cp/namespace-recursive.exp new file mode 100644 index 0000000..7fa6bd1 --- /dev/null +++ b/gdb/testsuite/gdb.cp/namespace-recursive.exp @@ -0,0 +1,65 @@ +# Copyright 2008 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +if $tracelevel then { + strace $tracelevel +} + +set prms_id 0 +set bug_id 0 + +set testfile namespace-recursive +set srcfile ${testfile}.cc +set binfile ${objdir}/${subdir}/${testfile} +if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug c++}] != "" } { + untested "Couldn't compile test program" + return -1 +} + +if [get_compiler_info ${binfile}] { + return -1 +} + + +# Get things started. + +gdb_exit +gdb_start +gdb_reinitialize_dir $srcdir/$subdir +gdb_load ${binfile} + +if ![runto_main] then { + perror "couldn't run to breakpoint main" + continue +} + +############################################ +# test printing from namespace imported into +# imported namespace + +gdb_test "print ax" "= 9" + +############################################ +# test that gdb can print without falling +# into search loop + +gdb_test "print dx" "= 99" + +############################################ +# test printing from namespace imported into +# imported namespace where imports are implicit +# anonymous namespace imports. + +gdb_test "print xx" "= 999" diff --git a/gdb/testsuite/gdb.cp/namespace-stress-declarations.cc b/gdb/testsuite/gdb.cp/namespace-stress-declarations.cc new file mode 100644 index 0000000..173e49b --- /dev/null +++ b/gdb/testsuite/gdb.cp/namespace-stress-declarations.cc @@ -0,0 +1,93 @@ +int a; +int b; +int c; +int d; +int e; +int f; +int g; +int h; +int i; +int j; +int k; +int l; +int m; +int n; +int o; +int p; +int q; +int r; +int s; +int t; +int u; +int v; +int w; +int x; +int y; +int z; + +namespace A +{ + int xyz; + + using ::a; + using ::b; + using ::c; + using ::d; + using ::e; + using ::f; + using ::g; + using ::h; + using ::i; + using ::j; + using ::k; + using ::l; + using ::m; + using ::n; + using ::o; + using ::p; + using ::q; + using ::r; + using ::s; + using ::t; + using ::u; + using ::v; + using ::w; + using ::x; + using ::y; + using ::z; + +} + +using A::a; +using A::b; +using A::c; +using A::d; +using A::e; +using A::f; +using A::g; +using A::h; +using A::i; +using A::j; +using A::k; +using A::l; +using A::m; +using A::n; +using A::o; +using A::p; +using A::q; +using A::r; +using A::s; +using A::t; +using A::u; +using A::v; +using A::w; +using A::x; +using A::y; +using A::z; + +using namespace A; + +int main () +{ + return 0; +} \ No newline at end of file diff --git a/gdb/testsuite/gdb.cp/namespace-stress-declarations.exp b/gdb/testsuite/gdb.cp/namespace-stress-declarations.exp new file mode 100644 index 0000000..f22a14e --- /dev/null +++ b/gdb/testsuite/gdb.cp/namespace-stress-declarations.exp @@ -0,0 +1,50 @@ +# Copyright 2008 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +if $tracelevel then { + strace $tracelevel +} + +set prms_id 0 +set bug_id 0 + +set testfile namespace-stress-declarations +set srcfile ${testfile}.cc +set binfile ${objdir}/${subdir}/${testfile} +if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug c++}] != "" } { + untested "Couldn't compile test program" + return -1 +} + +if [get_compiler_info ${binfile}] { + return -1; +} + +# Get things started. + +gdb_exit +gdb_start +gdb_reinitialize_dir $srcdir/$subdir +gdb_load ${binfile} + +if ![runto_main] then { + perror "couldn't run to breakpoint main" + continue +} + +############################################ +# Test that the search can fail efficiently + +gdb_test "print fakex" "No symbol \"fakex\" in current context." diff --git a/gdb/testsuite/gdb.cp/namespace-stress.cc b/gdb/testsuite/gdb.cp/namespace-stress.cc new file mode 100644 index 0000000..f34083e --- /dev/null +++ b/gdb/testsuite/gdb.cp/namespace-stress.cc @@ -0,0 +1,60 @@ + +namespace A{ int x; } +namespace B{ int x; } +namespace C{ int x; } +namespace D{ int x; } +namespace E{ int x; } +namespace F{ int x; } +namespace G{ int x; } +namespace H{ int x; } +namespace I{ int x; } +namespace J{ int x; } +namespace K{ int x; } +namespace L{ int x; } +namespace M{ int x; } +namespace N{ int x; } +namespace O{ int x; } +namespace P{ int x; } +namespace Q{ int x; } +namespace R{ int x; } +namespace S{ int x; } +namespace T{ int x; } +namespace U{ int x; } +namespace V{ int x; } +namespace W{ int x; } +namespace X{ int x; } +namespace Y{ int x; } +namespace Z{ int x; } + + +int main(){ + + using namespace A; + using namespace B; + using namespace C; + using namespace D; + using namespace E; + using namespace F; + using namespace G; + using namespace H; + using namespace I; + using namespace J; + using namespace K; + using namespace L; + using namespace M; + using namespace N; + using namespace O; + using namespace P; + using namespace Q; + using namespace R; + using namespace S; + using namespace T; + using namespace U; + using namespace V; + using namespace W; + using namespace X; + using namespace Y; + using namespace Z; + + return 0; +} \ No newline at end of file diff --git a/gdb/testsuite/gdb.cp/namespace-stress.exp b/gdb/testsuite/gdb.cp/namespace-stress.exp new file mode 100644 index 0000000..64da6df --- /dev/null +++ b/gdb/testsuite/gdb.cp/namespace-stress.exp @@ -0,0 +1,50 @@ +# Copyright 2008 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +if $tracelevel then { + strace $tracelevel +} + +set prms_id 0 +set bug_id 0 + +set testfile namespace-stress +set srcfile ${testfile}.cc +set binfile ${objdir}/${subdir}/${testfile} +if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug c++}] != "" } { + untested "Couldn't compile test program" + return -1 +} + +if [get_compiler_info ${binfile}] { + return -1 +} + +# Get things started. + +gdb_exit +gdb_start +gdb_reinitialize_dir $srcdir/$subdir +gdb_load ${binfile} + +if ![runto_main] then { + perror "couldn't run to breakpoint main" + continue +} + +############################################ +# Test that the search can fail efficiently + +gdb_test "print y" "No symbol \"y\" in current context." diff --git a/gdb/valops.c b/gdb/valops.c index 012ea6a..6fdea95 100644 --- a/gdb/valops.c +++ b/gdb/valops.c @@ -2765,7 +2765,7 @@ value_maybe_namespace_elt (const struct type *curtype, sym = cp_lookup_symbol_namespace (namespace_name, name, NULL, get_selected_block (0), - VAR_DOMAIN); + VAR_DOMAIN, 1); if (sym == NULL) return NULL; ^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [patch 2/2] Perform a namespace lookup at every block level 2010-01-11 21:24 ` Sami Wagiaalla @ 2010-01-12 17:43 ` Tom Tromey 2010-01-14 16:47 ` Sami Wagiaalla 0 siblings, 1 reply; 28+ messages in thread From: Tom Tromey @ 2010-01-12 17:43 UTC (permalink / raw) To: Sami Wagiaalla; +Cc: gdb-patches >>>>> "Sami" == Sami Wagiaalla <swagiaal@redhat.com> writes: Tom> We're mostly following 8.3 rules, so I would suggest renaming these to Tom> "ns-*". Sami> Can I do this in a separate patch ? There are more files to rename, Sami> so I would like to do the renaming in one patch No, it is really preferable to do this from the first checkin to CVS. Sami> \ No newline at end of file A few of the new files are missing newlines at the end. Tom ^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [patch 2/2] Perform a namespace lookup at every block level 2010-01-12 17:43 ` Tom Tromey @ 2010-01-14 16:47 ` Sami Wagiaalla 2010-01-14 20:18 ` Sami Wagiaalla 0 siblings, 1 reply; 28+ messages in thread From: Sami Wagiaalla @ 2010-01-14 16:47 UTC (permalink / raw) To: gdb-patches [-- Attachment #1: Type: text/plain, Size: 16712 bytes --] On 01/12/2010 12:43 PM, Tom Tromey wrote: >>>>>> "Sami" == Sami Wagiaalla<swagiaal@redhat.com> writes: > > Tom> We're mostly following 8.3 rules, so I would suggest renaming these to > Tom> "ns-*". > > Sami> Can I do this in a separate patch ? There are more files to rename, > Sami> so I would like to do the renaming in one patch > > No, it is really preferable to do this from the first checkin to CVS. > > Sami> \ No newline at end of file > > A few of the new files are missing newlines at the end. > > Tom Renamed test files to fit 8.3, and added comments in the beginning of the files to compensate for the loss of readability. 2010-01-11 Sami Wagiaalla <swagiaal@redhat.com> * cp-namespace.c (cp_lookup_symbol_namespace): Added search_parent argument. (cp_add_using): Initialize 'searched' field. (cp_copy_usings): Copy searched field. (reset_directive_searched): New function. * cp-support.h: Add 'searched' field to using_direct struct. (cp_lookup_symbol_imports): Ditto. * cp-namespace.c (cp_lookup_symbol_imports): Ditto. Perform recursive search. Implement non parent search. * valops.c (value_maybe_namespace_elt): Updated. 2010-01-11 Sami Wagiaalla <swagiaal@redhat.com> * gdb.cp/namespace-stress.exp: New test. * gdb.cp/namespace-stress.cc: New test program. * gdb.cp/namespace-recursive.exp: New test. * gdb.cp/namespace-recursive.cc: New test program. * gdb.cp/namespace-stress.exp: New test. * gdb.cp/namespace-stress.cc: New test program. * gdb.cp/namespace-stress-declarations.exp: New test. * gdb.cp/namespace-stress-declarations.cc: New test program. diff --git a/gdb/cp-namespace.c b/gdb/cp-namespace.c index f63cf8a..5790ebf 100644 --- a/gdb/cp-namespace.c +++ b/gdb/cp-namespace.c @@ -217,6 +217,7 @@ cp_add_using (const char *dest, retval->import_src = savestring (src, strlen(src)); retval->import_dest = savestring (dest, strlen(dest)); retval->next = next; + retval->searched = 0; return retval; } @@ -243,6 +244,8 @@ cp_copy_usings (struct using_direct *using, obstack); retval->next = cp_copy_usings (using->next, obstack); + retval->searched = using->searched; + xfree (using->import_src); xfree (using->import_dest); xfree (using); @@ -272,7 +275,8 @@ cp_lookup_symbol_nonlocal (const char *name, if (sym != NULL) return sym; - return cp_lookup_symbol_namespace (scope, name, linkage_name, block, domain); + return cp_lookup_symbol_namespace (scope, name, linkage_name, block, domain, + 1); } /* Look up NAME in the C++ namespace NAMESPACE. Other arguments are as in @@ -302,19 +306,46 @@ cp_lookup_symbol_in_namespace (const char *namespace, } } +/* Used for cleanups to reset the "searched" flag incase + of an error. */ + +static void +reset_directive_searched (void *data) +{ + struct using_direct *direct = data; + direct->searched = 0; +} + /* Search for NAME by applying all import statements belonging - to BLOCK which are applicable in SCOPE. */ + to BLOCK which are applicable in SCOPE. + If SEARCH_PARENTS the search will include imports which are applicable in + parents of SCOPE. + Example: + + namespace A{ + using namespace X; + namespace B{ + using namespace Y; + } + } + + If SCOPE is "A::B" and SEARCH_PARENTS is true the imports of namespaces X + and Y will be considered. If SEARCH_PARENTS is false only the import of Y + is considered. */ static struct symbol * cp_lookup_symbol_imports (const char *scope, const char *name, const char *linkage_name, const struct block *block, - const domain_enum domain) + const domain_enum domain, + const int search_parents) { - const struct using_direct *current; + struct using_direct *current; struct symbol *sym; int len; + int directive_match; + struct cleanup *searched_cleanup; /* First, try to find the symbol in the given namespace. */ sym = cp_lookup_symbol_in_namespace (scope, name, linkage_name, block, @@ -330,24 +361,41 @@ cp_lookup_symbol_imports (const char *scope, current != NULL; current = current->next) { + len = strlen (current->import_dest); + directive_match = (search_parents + ? (strncmp (scope, current->import_dest, + strlen (current->import_dest)) == 0 + && (len == 0 + || scope[len] == ':' || scope[len] == '\0')) + : strcmp (scope, current->import_dest) == 0); /* If the import destination is the current scope or one of its ancestors then it is applicable. */ - len = strlen (current->import_dest); - if (strncmp (scope, current->import_dest, len) == 0 - && (len == 0 || scope[len] == ':' || scope[len] == '\0')) + if (directive_match && !current->searched) { - sym = cp_lookup_symbol_in_namespace (current->import_src, name, - linkage_name, block, domain); - if (sym != NULL) - return sym; + /* Mark this import as searched so that the recursive call does not + search it again. */ + current->searched = 1; + searched_cleanup = make_cleanup (reset_directive_searched, current); + + sym = cp_lookup_symbol_namespace (current->import_src, + name, + linkage_name, + block, + domain, + 0); + + current->searched = 0; + discard_cleanups (searched_cleanup); + + if (sym != NULL) + return sym; } } return NULL; } - /* Searches for NAME in the current namespace, and by applying relevant import statements belonging to BLOCK and its parents. SCOPE is the namespace scope of the context in which the search is being evaluated. */ @@ -357,14 +405,16 @@ cp_lookup_symbol_namespace (const char *scope, const char *name, const char *linkage_name, const struct block *block, - const domain_enum domain) + const domain_enum domain, + const int search_parents) { struct symbol *sym; /* Search for name in namespaces imported to this and parent blocks. */ while (block != NULL) { - sym = cp_lookup_symbol_imports (scope,name, linkage_name, block, domain); + sym = cp_lookup_symbol_imports (scope, name, linkage_name, block, domain, + search_parents); if (sym) return sym; diff --git a/gdb/cp-support.h b/gdb/cp-support.h index 7ecd201..9400469 100644 --- a/gdb/cp-support.h +++ b/gdb/cp-support.h @@ -47,6 +47,9 @@ struct using_direct char *import_src; char *import_dest; struct using_direct *next; + + /* Used during import search to temporarily mark this node as searched. */ + int searched; }; @@ -107,7 +110,8 @@ extern struct symbol *cp_lookup_symbol_namespace (const char *namespace, const char *name, const char *linkage_name, const struct block *block, - const domain_enum domain); + const domain_enum domain, + const int search_parents); extern struct type *cp_lookup_nested_type (struct type *parent_type, const char *nested_name, diff --git a/gdb/testsuite/gdb.cp/nsdecl.cc b/gdb/testsuite/gdb.cp/nsdecl.cc new file mode 100644 index 0000000..01a9c75 --- /dev/null +++ b/gdb/testsuite/gdb.cp/nsdecl.cc @@ -0,0 +1,93 @@ +int a; +int b; +int c; +int d; +int e; +int f; +int g; +int h; +int i; +int j; +int k; +int l; +int m; +int n; +int o; +int p; +int q; +int r; +int s; +int t; +int u; +int v; +int w; +int x; +int y; +int z; + +namespace A +{ + int xyz; + + using ::a; + using ::b; + using ::c; + using ::d; + using ::e; + using ::f; + using ::g; + using ::h; + using ::i; + using ::j; + using ::k; + using ::l; + using ::m; + using ::n; + using ::o; + using ::p; + using ::q; + using ::r; + using ::s; + using ::t; + using ::u; + using ::v; + using ::w; + using ::x; + using ::y; + using ::z; + +} + +using A::a; +using A::b; +using A::c; +using A::d; +using A::e; +using A::f; +using A::g; +using A::h; +using A::i; +using A::j; +using A::k; +using A::l; +using A::m; +using A::n; +using A::o; +using A::p; +using A::q; +using A::r; +using A::s; +using A::t; +using A::u; +using A::v; +using A::w; +using A::x; +using A::y; +using A::z; + +using namespace A; + +int main () +{ + return 0; +} diff --git a/gdb/testsuite/gdb.cp/nsdecl.exp b/gdb/testsuite/gdb.cp/nsdecl.exp new file mode 100644 index 0000000..6e0d875 --- /dev/null +++ b/gdb/testsuite/gdb.cp/nsdecl.exp @@ -0,0 +1,52 @@ +# Copyright 2008 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +# Stress test the lookup of declarations + +if $tracelevel then { + strace $tracelevel +} + +set prms_id 0 +set bug_id 0 + +set testfile nsdecl +set srcfile ${testfile}.cc +set binfile ${objdir}/${subdir}/${testfile} +if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug c++}] != "" } { + untested "Couldn't compile test program" + return -1 +} + +if [get_compiler_info ${binfile}] { + return -1; +} + +# Get things started. + +gdb_exit +gdb_start +gdb_reinitialize_dir $srcdir/$subdir +gdb_load ${binfile} + +if ![runto_main] then { + perror "couldn't run to breakpoint main" + continue +} + +############################################ +# Test that the search can fail efficiently + +gdb_test "print fakex" "No symbol \"fakex\" in current context." diff --git a/gdb/testsuite/gdb.cp/nsrecurs.cc b/gdb/testsuite/gdb.cp/nsrecurs.cc new file mode 100644 index 0000000..84605a6 --- /dev/null +++ b/gdb/testsuite/gdb.cp/nsrecurs.cc @@ -0,0 +1,30 @@ +namespace A{ + int ax = 9; +} + +namespace B{ + using namespace A; +} + +namespace C{ + using namespace B; +} + +//--------------- +namespace D{ + using namespace D; + int dx = 99; +} +using namespace C; + +//--------------- +namespace{ + namespace{ + int xx = 999; + } +} + +int main(){ + using namespace D; + return ax + dx + xx; +} diff --git a/gdb/testsuite/gdb.cp/nsrecurs.exp b/gdb/testsuite/gdb.cp/nsrecurs.exp new file mode 100644 index 0000000..9939a9f --- /dev/null +++ b/gdb/testsuite/gdb.cp/nsrecurs.exp @@ -0,0 +1,67 @@ +# Copyright 2008 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +# Test recursive namespace lookup + +if $tracelevel then { + strace $tracelevel +} + +set prms_id 0 +set bug_id 0 + +set testfile nsrecurs +set srcfile ${testfile}.cc +set binfile ${objdir}/${subdir}/${testfile} +if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug c++}] != "" } { + untested "Couldn't compile test program" + return -1 +} + +if [get_compiler_info ${binfile}] { + return -1 +} + + +# Get things started. + +gdb_exit +gdb_start +gdb_reinitialize_dir $srcdir/$subdir +gdb_load ${binfile} + +if ![runto_main] then { + perror "couldn't run to breakpoint main" + continue +} + +############################################ +# test printing from namespace imported into +# imported namespace + +gdb_test "print ax" "= 9" + +############################################ +# test that gdb can print without falling +# into search loop + +gdb_test "print dx" "= 99" + +############################################ +# test printing from namespace imported into +# imported namespace where imports are implicit +# anonymous namespace imports. + +gdb_test "print xx" "= 999" diff --git a/gdb/testsuite/gdb.cp/nsstress.cc b/gdb/testsuite/gdb.cp/nsstress.cc new file mode 100644 index 0000000..de84ab1 --- /dev/null +++ b/gdb/testsuite/gdb.cp/nsstress.cc @@ -0,0 +1,60 @@ + +namespace A{ int x; } +namespace B{ int x; } +namespace C{ int x; } +namespace D{ int x; } +namespace E{ int x; } +namespace F{ int x; } +namespace G{ int x; } +namespace H{ int x; } +namespace I{ int x; } +namespace J{ int x; } +namespace K{ int x; } +namespace L{ int x; } +namespace M{ int x; } +namespace N{ int x; } +namespace O{ int x; } +namespace P{ int x; } +namespace Q{ int x; } +namespace R{ int x; } +namespace S{ int x; } +namespace T{ int x; } +namespace U{ int x; } +namespace V{ int x; } +namespace W{ int x; } +namespace X{ int x; } +namespace Y{ int x; } +namespace Z{ int x; } + + +int main(){ + + using namespace A; + using namespace B; + using namespace C; + using namespace D; + using namespace E; + using namespace F; + using namespace G; + using namespace H; + using namespace I; + using namespace J; + using namespace K; + using namespace L; + using namespace M; + using namespace N; + using namespace O; + using namespace P; + using namespace Q; + using namespace R; + using namespace S; + using namespace T; + using namespace U; + using namespace V; + using namespace W; + using namespace X; + using namespace Y; + using namespace Z; + + return 0; +} diff --git a/gdb/testsuite/gdb.cp/nsstress.exp b/gdb/testsuite/gdb.cp/nsstress.exp new file mode 100644 index 0000000..afe1bb0 --- /dev/null +++ b/gdb/testsuite/gdb.cp/nsstress.exp @@ -0,0 +1,52 @@ +# Copyright 2008 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +# Stress test namespace lookup + +if $tracelevel then { + strace $tracelevel +} + +set prms_id 0 +set bug_id 0 + +set testfile nsstress +set srcfile ${testfile}.cc +set binfile ${objdir}/${subdir}/${testfile} +if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug c++}] != "" } { + untested "Couldn't compile test program" + return -1 +} + +if [get_compiler_info ${binfile}] { + return -1 +} + +# Get things started. + +gdb_exit +gdb_start +gdb_reinitialize_dir $srcdir/$subdir +gdb_load ${binfile} + +if ![runto_main] then { + perror "couldn't run to breakpoint main" + continue +} + +############################################ +# Test that the search can fail efficiently + +gdb_test "print y" "No symbol \"y\" in current context." diff --git a/gdb/valops.c b/gdb/valops.c index 012ea6a..6fdea95 100644 --- a/gdb/valops.c +++ b/gdb/valops.c @@ -2765,7 +2765,7 @@ value_maybe_namespace_elt (const struct type *curtype, sym = cp_lookup_symbol_namespace (namespace_name, name, NULL, get_selected_block (0), - VAR_DOMAIN); + VAR_DOMAIN, 1); if (sym == NULL) return NULL; [-- Attachment #2: sami2-recursive-search.patch --] [-- Type: text/plain, Size: 14910 bytes --] diff --git a/gdb/cp-namespace.c b/gdb/cp-namespace.c index f63cf8a..5790ebf 100644 --- a/gdb/cp-namespace.c +++ b/gdb/cp-namespace.c @@ -217,6 +217,7 @@ cp_add_using (const char *dest, retval->import_src = savestring (src, strlen(src)); retval->import_dest = savestring (dest, strlen(dest)); retval->next = next; + retval->searched = 0; return retval; } @@ -243,6 +244,8 @@ cp_copy_usings (struct using_direct *using, obstack); retval->next = cp_copy_usings (using->next, obstack); + retval->searched = using->searched; + xfree (using->import_src); xfree (using->import_dest); xfree (using); @@ -272,7 +275,8 @@ cp_lookup_symbol_nonlocal (const char *name, if (sym != NULL) return sym; - return cp_lookup_symbol_namespace (scope, name, linkage_name, block, domain); + return cp_lookup_symbol_namespace (scope, name, linkage_name, block, domain, + 1); } /* Look up NAME in the C++ namespace NAMESPACE. Other arguments are as in @@ -302,19 +306,46 @@ cp_lookup_symbol_in_namespace (const char *namespace, } } +/* Used for cleanups to reset the "searched" flag incase + of an error. */ + +static void +reset_directive_searched (void *data) +{ + struct using_direct *direct = data; + direct->searched = 0; +} + /* Search for NAME by applying all import statements belonging - to BLOCK which are applicable in SCOPE. */ + to BLOCK which are applicable in SCOPE. + If SEARCH_PARENTS the search will include imports which are applicable in + parents of SCOPE. + Example: + + namespace A{ + using namespace X; + namespace B{ + using namespace Y; + } + } + + If SCOPE is "A::B" and SEARCH_PARENTS is true the imports of namespaces X + and Y will be considered. If SEARCH_PARENTS is false only the import of Y + is considered. */ static struct symbol * cp_lookup_symbol_imports (const char *scope, const char *name, const char *linkage_name, const struct block *block, - const domain_enum domain) + const domain_enum domain, + const int search_parents) { - const struct using_direct *current; + struct using_direct *current; struct symbol *sym; int len; + int directive_match; + struct cleanup *searched_cleanup; /* First, try to find the symbol in the given namespace. */ sym = cp_lookup_symbol_in_namespace (scope, name, linkage_name, block, @@ -330,24 +361,41 @@ cp_lookup_symbol_imports (const char *scope, current != NULL; current = current->next) { + len = strlen (current->import_dest); + directive_match = (search_parents + ? (strncmp (scope, current->import_dest, + strlen (current->import_dest)) == 0 + && (len == 0 + || scope[len] == ':' || scope[len] == '\0')) + : strcmp (scope, current->import_dest) == 0); /* If the import destination is the current scope or one of its ancestors then it is applicable. */ - len = strlen (current->import_dest); - if (strncmp (scope, current->import_dest, len) == 0 - && (len == 0 || scope[len] == ':' || scope[len] == '\0')) + if (directive_match && !current->searched) { - sym = cp_lookup_symbol_in_namespace (current->import_src, name, - linkage_name, block, domain); - if (sym != NULL) - return sym; + /* Mark this import as searched so that the recursive call does not + search it again. */ + current->searched = 1; + searched_cleanup = make_cleanup (reset_directive_searched, current); + + sym = cp_lookup_symbol_namespace (current->import_src, + name, + linkage_name, + block, + domain, + 0); + + current->searched = 0; + discard_cleanups (searched_cleanup); + + if (sym != NULL) + return sym; } } return NULL; } - /* Searches for NAME in the current namespace, and by applying relevant import statements belonging to BLOCK and its parents. SCOPE is the namespace scope of the context in which the search is being evaluated. */ @@ -357,14 +405,16 @@ cp_lookup_symbol_namespace (const char *scope, const char *name, const char *linkage_name, const struct block *block, - const domain_enum domain) + const domain_enum domain, + const int search_parents) { struct symbol *sym; /* Search for name in namespaces imported to this and parent blocks. */ while (block != NULL) { - sym = cp_lookup_symbol_imports (scope,name, linkage_name, block, domain); + sym = cp_lookup_symbol_imports (scope, name, linkage_name, block, domain, + search_parents); if (sym) return sym; diff --git a/gdb/cp-support.h b/gdb/cp-support.h index 7ecd201..9400469 100644 --- a/gdb/cp-support.h +++ b/gdb/cp-support.h @@ -47,6 +47,9 @@ struct using_direct char *import_src; char *import_dest; struct using_direct *next; + + /* Used during import search to temporarily mark this node as searched. */ + int searched; }; @@ -107,7 +110,8 @@ extern struct symbol *cp_lookup_symbol_namespace (const char *namespace, const char *name, const char *linkage_name, const struct block *block, - const domain_enum domain); + const domain_enum domain, + const int search_parents); extern struct type *cp_lookup_nested_type (struct type *parent_type, const char *nested_name, diff --git a/gdb/testsuite/gdb.cp/nsdecl.cc b/gdb/testsuite/gdb.cp/nsdecl.cc new file mode 100644 index 0000000..01a9c75 --- /dev/null +++ b/gdb/testsuite/gdb.cp/nsdecl.cc @@ -0,0 +1,93 @@ +int a; +int b; +int c; +int d; +int e; +int f; +int g; +int h; +int i; +int j; +int k; +int l; +int m; +int n; +int o; +int p; +int q; +int r; +int s; +int t; +int u; +int v; +int w; +int x; +int y; +int z; + +namespace A +{ + int xyz; + + using ::a; + using ::b; + using ::c; + using ::d; + using ::e; + using ::f; + using ::g; + using ::h; + using ::i; + using ::j; + using ::k; + using ::l; + using ::m; + using ::n; + using ::o; + using ::p; + using ::q; + using ::r; + using ::s; + using ::t; + using ::u; + using ::v; + using ::w; + using ::x; + using ::y; + using ::z; + +} + +using A::a; +using A::b; +using A::c; +using A::d; +using A::e; +using A::f; +using A::g; +using A::h; +using A::i; +using A::j; +using A::k; +using A::l; +using A::m; +using A::n; +using A::o; +using A::p; +using A::q; +using A::r; +using A::s; +using A::t; +using A::u; +using A::v; +using A::w; +using A::x; +using A::y; +using A::z; + +using namespace A; + +int main () +{ + return 0; +} diff --git a/gdb/testsuite/gdb.cp/nsdecl.exp b/gdb/testsuite/gdb.cp/nsdecl.exp new file mode 100644 index 0000000..6e0d875 --- /dev/null +++ b/gdb/testsuite/gdb.cp/nsdecl.exp @@ -0,0 +1,52 @@ +# Copyright 2008 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +# Stress test the lookup of declarations + +if $tracelevel then { + strace $tracelevel +} + +set prms_id 0 +set bug_id 0 + +set testfile nsdecl +set srcfile ${testfile}.cc +set binfile ${objdir}/${subdir}/${testfile} +if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug c++}] != "" } { + untested "Couldn't compile test program" + return -1 +} + +if [get_compiler_info ${binfile}] { + return -1; +} + +# Get things started. + +gdb_exit +gdb_start +gdb_reinitialize_dir $srcdir/$subdir +gdb_load ${binfile} + +if ![runto_main] then { + perror "couldn't run to breakpoint main" + continue +} + +############################################ +# Test that the search can fail efficiently + +gdb_test "print fakex" "No symbol \"fakex\" in current context." diff --git a/gdb/testsuite/gdb.cp/nsrecurs.cc b/gdb/testsuite/gdb.cp/nsrecurs.cc new file mode 100644 index 0000000..84605a6 --- /dev/null +++ b/gdb/testsuite/gdb.cp/nsrecurs.cc @@ -0,0 +1,30 @@ +namespace A{ + int ax = 9; +} + +namespace B{ + using namespace A; +} + +namespace C{ + using namespace B; +} + +//--------------- +namespace D{ + using namespace D; + int dx = 99; +} +using namespace C; + +//--------------- +namespace{ + namespace{ + int xx = 999; + } +} + +int main(){ + using namespace D; + return ax + dx + xx; +} diff --git a/gdb/testsuite/gdb.cp/nsrecurs.exp b/gdb/testsuite/gdb.cp/nsrecurs.exp new file mode 100644 index 0000000..9939a9f --- /dev/null +++ b/gdb/testsuite/gdb.cp/nsrecurs.exp @@ -0,0 +1,67 @@ +# Copyright 2008 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +# Test recursive namespace lookup + +if $tracelevel then { + strace $tracelevel +} + +set prms_id 0 +set bug_id 0 + +set testfile nsrecurs +set srcfile ${testfile}.cc +set binfile ${objdir}/${subdir}/${testfile} +if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug c++}] != "" } { + untested "Couldn't compile test program" + return -1 +} + +if [get_compiler_info ${binfile}] { + return -1 +} + + +# Get things started. + +gdb_exit +gdb_start +gdb_reinitialize_dir $srcdir/$subdir +gdb_load ${binfile} + +if ![runto_main] then { + perror "couldn't run to breakpoint main" + continue +} + +############################################ +# test printing from namespace imported into +# imported namespace + +gdb_test "print ax" "= 9" + +############################################ +# test that gdb can print without falling +# into search loop + +gdb_test "print dx" "= 99" + +############################################ +# test printing from namespace imported into +# imported namespace where imports are implicit +# anonymous namespace imports. + +gdb_test "print xx" "= 999" diff --git a/gdb/testsuite/gdb.cp/nsstress.cc b/gdb/testsuite/gdb.cp/nsstress.cc new file mode 100644 index 0000000..de84ab1 --- /dev/null +++ b/gdb/testsuite/gdb.cp/nsstress.cc @@ -0,0 +1,60 @@ + +namespace A{ int x; } +namespace B{ int x; } +namespace C{ int x; } +namespace D{ int x; } +namespace E{ int x; } +namespace F{ int x; } +namespace G{ int x; } +namespace H{ int x; } +namespace I{ int x; } +namespace J{ int x; } +namespace K{ int x; } +namespace L{ int x; } +namespace M{ int x; } +namespace N{ int x; } +namespace O{ int x; } +namespace P{ int x; } +namespace Q{ int x; } +namespace R{ int x; } +namespace S{ int x; } +namespace T{ int x; } +namespace U{ int x; } +namespace V{ int x; } +namespace W{ int x; } +namespace X{ int x; } +namespace Y{ int x; } +namespace Z{ int x; } + + +int main(){ + + using namespace A; + using namespace B; + using namespace C; + using namespace D; + using namespace E; + using namespace F; + using namespace G; + using namespace H; + using namespace I; + using namespace J; + using namespace K; + using namespace L; + using namespace M; + using namespace N; + using namespace O; + using namespace P; + using namespace Q; + using namespace R; + using namespace S; + using namespace T; + using namespace U; + using namespace V; + using namespace W; + using namespace X; + using namespace Y; + using namespace Z; + + return 0; +} diff --git a/gdb/testsuite/gdb.cp/nsstress.exp b/gdb/testsuite/gdb.cp/nsstress.exp new file mode 100644 index 0000000..afe1bb0 --- /dev/null +++ b/gdb/testsuite/gdb.cp/nsstress.exp @@ -0,0 +1,52 @@ +# Copyright 2008 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +# Stress test namespace lookup + +if $tracelevel then { + strace $tracelevel +} + +set prms_id 0 +set bug_id 0 + +set testfile nsstress +set srcfile ${testfile}.cc +set binfile ${objdir}/${subdir}/${testfile} +if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug c++}] != "" } { + untested "Couldn't compile test program" + return -1 +} + +if [get_compiler_info ${binfile}] { + return -1 +} + +# Get things started. + +gdb_exit +gdb_start +gdb_reinitialize_dir $srcdir/$subdir +gdb_load ${binfile} + +if ![runto_main] then { + perror "couldn't run to breakpoint main" + continue +} + +############################################ +# Test that the search can fail efficiently + +gdb_test "print y" "No symbol \"y\" in current context." diff --git a/gdb/valops.c b/gdb/valops.c index 012ea6a..6fdea95 100644 --- a/gdb/valops.c +++ b/gdb/valops.c @@ -2765,7 +2765,7 @@ value_maybe_namespace_elt (const struct type *curtype, sym = cp_lookup_symbol_namespace (namespace_name, name, NULL, get_selected_block (0), - VAR_DOMAIN); + VAR_DOMAIN, 1); if (sym == NULL) return NULL; ^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [patch 2/2] Perform a namespace lookup at every block level 2010-01-14 16:47 ` Sami Wagiaalla @ 2010-01-14 20:18 ` Sami Wagiaalla 2010-01-15 18:06 ` Tom Tromey 0 siblings, 1 reply; 28+ messages in thread From: Sami Wagiaalla @ 2010-01-14 20:18 UTC (permalink / raw) To: gdb-patches [-- Attachment #1: Type: text/plain, Size: 16717 bytes --] On 01/14/2010 11:51 AM, Sami Wagiaalla wrote: > On 01/12/2010 12:43 PM, Tom Tromey wrote: >>>>>>> "Sami" == Sami Wagiaalla<swagiaal@redhat.com> writes: >> >> Tom> We're mostly following 8.3 rules, so I would suggest renaming >> these to >> Tom> "ns-*". >> >> Sami> Can I do this in a separate patch ? There are more files to rename, >> Sami> so I would like to do the renaming in one patch >> >> No, it is really preferable to do this from the first checkin to CVS. >> >> Sami> \ No newline at end of file >> >> A few of the new files are missing newlines at the end. >> >> Tom > > Renamed test files to fit 8.3, and added comments in the beginning of > the files to compensate for the loss of readability. > > Corrected Changelog 2010-01-14 Sami Wagiaalla <swagiaal@redhat.com> * cp-namespace.c (cp_lookup_symbol_namespace): Added search_parent argument. (cp_add_using): Initialize 'searched' field. (cp_copy_usings): Copy searched field. (reset_directive_searched): New function. * cp-support.h: Add 'searched' field to using_direct struct. (cp_lookup_symbol_imports): Ditto. * cp-namespace.c (cp_lookup_symbol_imports): Ditto. Perform recursive search. Implement non parent search. * valops.c (value_maybe_namespace_elt): Updated. 2010-01-14 Sami Wagiaalla <swagiaal@redhat.com> * gdb.cp/namespace-stress.exp: New test. * gdb.cp/namespace-stress.cc: New test program. * gdb.cp/nsrecurs.exp: New test. * gdb.cp/nsrecurs.cc: New test program. * gdb.cp/nsstress.exp: New test. * gdb.cp/nsstress.cc: New test program. * gdb.cp/nsdecl.exp: New test. * gdb.cp/nsdecl.cc: New test program. diff --git a/gdb/cp-namespace.c b/gdb/cp-namespace.c index f63cf8a..5790ebf 100644 --- a/gdb/cp-namespace.c +++ b/gdb/cp-namespace.c @@ -217,6 +217,7 @@ cp_add_using (const char *dest, retval->import_src = savestring (src, strlen(src)); retval->import_dest = savestring (dest, strlen(dest)); retval->next = next; + retval->searched = 0; return retval; } @@ -243,6 +244,8 @@ cp_copy_usings (struct using_direct *using, obstack); retval->next = cp_copy_usings (using->next, obstack); + retval->searched = using->searched; + xfree (using->import_src); xfree (using->import_dest); xfree (using); @@ -272,7 +275,8 @@ cp_lookup_symbol_nonlocal (const char *name, if (sym != NULL) return sym; - return cp_lookup_symbol_namespace (scope, name, linkage_name, block, domain); + return cp_lookup_symbol_namespace (scope, name, linkage_name, block, domain, + 1); } /* Look up NAME in the C++ namespace NAMESPACE. Other arguments are as in @@ -302,19 +306,46 @@ cp_lookup_symbol_in_namespace (const char *namespace, } } +/* Used for cleanups to reset the "searched" flag incase + of an error. */ + +static void +reset_directive_searched (void *data) +{ + struct using_direct *direct = data; + direct->searched = 0; +} + /* Search for NAME by applying all import statements belonging - to BLOCK which are applicable in SCOPE. */ + to BLOCK which are applicable in SCOPE. + If SEARCH_PARENTS the search will include imports which are applicable in + parents of SCOPE. + Example: + + namespace A{ + using namespace X; + namespace B{ + using namespace Y; + } + } + + If SCOPE is "A::B" and SEARCH_PARENTS is true the imports of namespaces X + and Y will be considered. If SEARCH_PARENTS is false only the import of Y + is considered. */ static struct symbol * cp_lookup_symbol_imports (const char *scope, const char *name, const char *linkage_name, const struct block *block, - const domain_enum domain) + const domain_enum domain, + const int search_parents) { - const struct using_direct *current; + struct using_direct *current; struct symbol *sym; int len; + int directive_match; + struct cleanup *searched_cleanup; /* First, try to find the symbol in the given namespace. */ sym = cp_lookup_symbol_in_namespace (scope, name, linkage_name, block, @@ -330,24 +361,41 @@ cp_lookup_symbol_imports (const char *scope, current != NULL; current = current->next) { + len = strlen (current->import_dest); + directive_match = (search_parents + ? (strncmp (scope, current->import_dest, + strlen (current->import_dest)) == 0 + && (len == 0 + || scope[len] == ':' || scope[len] == '\0')) + : strcmp (scope, current->import_dest) == 0); /* If the import destination is the current scope or one of its ancestors then it is applicable. */ - len = strlen (current->import_dest); - if (strncmp (scope, current->import_dest, len) == 0 - && (len == 0 || scope[len] == ':' || scope[len] == '\0')) + if (directive_match && !current->searched) { - sym = cp_lookup_symbol_in_namespace (current->import_src, name, - linkage_name, block, domain); - if (sym != NULL) - return sym; + /* Mark this import as searched so that the recursive call does not + search it again. */ + current->searched = 1; + searched_cleanup = make_cleanup (reset_directive_searched, current); + + sym = cp_lookup_symbol_namespace (current->import_src, + name, + linkage_name, + block, + domain, + 0); + + current->searched = 0; + discard_cleanups (searched_cleanup); + + if (sym != NULL) + return sym; } } return NULL; } - /* Searches for NAME in the current namespace, and by applying relevant import statements belonging to BLOCK and its parents. SCOPE is the namespace scope of the context in which the search is being evaluated. */ @@ -357,14 +405,16 @@ cp_lookup_symbol_namespace (const char *scope, const char *name, const char *linkage_name, const struct block *block, - const domain_enum domain) + const domain_enum domain, + const int search_parents) { struct symbol *sym; /* Search for name in namespaces imported to this and parent blocks. */ while (block != NULL) { - sym = cp_lookup_symbol_imports (scope,name, linkage_name, block, domain); + sym = cp_lookup_symbol_imports (scope, name, linkage_name, block, domain, + search_parents); if (sym) return sym; diff --git a/gdb/cp-support.h b/gdb/cp-support.h index 7ecd201..9400469 100644 --- a/gdb/cp-support.h +++ b/gdb/cp-support.h @@ -47,6 +47,9 @@ struct using_direct char *import_src; char *import_dest; struct using_direct *next; + + /* Used during import search to temporarily mark this node as searched. */ + int searched; }; @@ -107,7 +110,8 @@ extern struct symbol *cp_lookup_symbol_namespace (const char *namespace, const char *name, const char *linkage_name, const struct block *block, - const domain_enum domain); + const domain_enum domain, + const int search_parents); extern struct type *cp_lookup_nested_type (struct type *parent_type, const char *nested_name, diff --git a/gdb/testsuite/gdb.cp/nsdecl.cc b/gdb/testsuite/gdb.cp/nsdecl.cc new file mode 100644 index 0000000..01a9c75 --- /dev/null +++ b/gdb/testsuite/gdb.cp/nsdecl.cc @@ -0,0 +1,93 @@ +int a; +int b; +int c; +int d; +int e; +int f; +int g; +int h; +int i; +int j; +int k; +int l; +int m; +int n; +int o; +int p; +int q; +int r; +int s; +int t; +int u; +int v; +int w; +int x; +int y; +int z; + +namespace A +{ + int xyz; + + using ::a; + using ::b; + using ::c; + using ::d; + using ::e; + using ::f; + using ::g; + using ::h; + using ::i; + using ::j; + using ::k; + using ::l; + using ::m; + using ::n; + using ::o; + using ::p; + using ::q; + using ::r; + using ::s; + using ::t; + using ::u; + using ::v; + using ::w; + using ::x; + using ::y; + using ::z; + +} + +using A::a; +using A::b; +using A::c; +using A::d; +using A::e; +using A::f; +using A::g; +using A::h; +using A::i; +using A::j; +using A::k; +using A::l; +using A::m; +using A::n; +using A::o; +using A::p; +using A::q; +using A::r; +using A::s; +using A::t; +using A::u; +using A::v; +using A::w; +using A::x; +using A::y; +using A::z; + +using namespace A; + +int main () +{ + return 0; +} diff --git a/gdb/testsuite/gdb.cp/nsdecl.exp b/gdb/testsuite/gdb.cp/nsdecl.exp new file mode 100644 index 0000000..6e0d875 --- /dev/null +++ b/gdb/testsuite/gdb.cp/nsdecl.exp @@ -0,0 +1,52 @@ +# Copyright 2008 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +# Stress test the lookup of declarations + +if $tracelevel then { + strace $tracelevel +} + +set prms_id 0 +set bug_id 0 + +set testfile nsdecl +set srcfile ${testfile}.cc +set binfile ${objdir}/${subdir}/${testfile} +if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug c++}] != "" } { + untested "Couldn't compile test program" + return -1 +} + +if [get_compiler_info ${binfile}] { + return -1; +} + +# Get things started. + +gdb_exit +gdb_start +gdb_reinitialize_dir $srcdir/$subdir +gdb_load ${binfile} + +if ![runto_main] then { + perror "couldn't run to breakpoint main" + continue +} + +############################################ +# Test that the search can fail efficiently + +gdb_test "print fakex" "No symbol \"fakex\" in current context." diff --git a/gdb/testsuite/gdb.cp/nsrecurs.cc b/gdb/testsuite/gdb.cp/nsrecurs.cc new file mode 100644 index 0000000..84605a6 --- /dev/null +++ b/gdb/testsuite/gdb.cp/nsrecurs.cc @@ -0,0 +1,30 @@ +namespace A{ + int ax = 9; +} + +namespace B{ + using namespace A; +} + +namespace C{ + using namespace B; +} + +//--------------- +namespace D{ + using namespace D; + int dx = 99; +} +using namespace C; + +//--------------- +namespace{ + namespace{ + int xx = 999; + } +} + +int main(){ + using namespace D; + return ax + dx + xx; +} diff --git a/gdb/testsuite/gdb.cp/nsrecurs.exp b/gdb/testsuite/gdb.cp/nsrecurs.exp new file mode 100644 index 0000000..9939a9f --- /dev/null +++ b/gdb/testsuite/gdb.cp/nsrecurs.exp @@ -0,0 +1,67 @@ +# Copyright 2008 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +# Test recursive namespace lookup + +if $tracelevel then { + strace $tracelevel +} + +set prms_id 0 +set bug_id 0 + +set testfile nsrecurs +set srcfile ${testfile}.cc +set binfile ${objdir}/${subdir}/${testfile} +if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug c++}] != "" } { + untested "Couldn't compile test program" + return -1 +} + +if [get_compiler_info ${binfile}] { + return -1 +} + + +# Get things started. + +gdb_exit +gdb_start +gdb_reinitialize_dir $srcdir/$subdir +gdb_load ${binfile} + +if ![runto_main] then { + perror "couldn't run to breakpoint main" + continue +} + +############################################ +# test printing from namespace imported into +# imported namespace + +gdb_test "print ax" "= 9" + +############################################ +# test that gdb can print without falling +# into search loop + +gdb_test "print dx" "= 99" + +############################################ +# test printing from namespace imported into +# imported namespace where imports are implicit +# anonymous namespace imports. + +gdb_test "print xx" "= 999" diff --git a/gdb/testsuite/gdb.cp/nsstress.cc b/gdb/testsuite/gdb.cp/nsstress.cc new file mode 100644 index 0000000..de84ab1 --- /dev/null +++ b/gdb/testsuite/gdb.cp/nsstress.cc @@ -0,0 +1,60 @@ + +namespace A{ int x; } +namespace B{ int x; } +namespace C{ int x; } +namespace D{ int x; } +namespace E{ int x; } +namespace F{ int x; } +namespace G{ int x; } +namespace H{ int x; } +namespace I{ int x; } +namespace J{ int x; } +namespace K{ int x; } +namespace L{ int x; } +namespace M{ int x; } +namespace N{ int x; } +namespace O{ int x; } +namespace P{ int x; } +namespace Q{ int x; } +namespace R{ int x; } +namespace S{ int x; } +namespace T{ int x; } +namespace U{ int x; } +namespace V{ int x; } +namespace W{ int x; } +namespace X{ int x; } +namespace Y{ int x; } +namespace Z{ int x; } + + +int main(){ + + using namespace A; + using namespace B; + using namespace C; + using namespace D; + using namespace E; + using namespace F; + using namespace G; + using namespace H; + using namespace I; + using namespace J; + using namespace K; + using namespace L; + using namespace M; + using namespace N; + using namespace O; + using namespace P; + using namespace Q; + using namespace R; + using namespace S; + using namespace T; + using namespace U; + using namespace V; + using namespace W; + using namespace X; + using namespace Y; + using namespace Z; + + return 0; +} diff --git a/gdb/testsuite/gdb.cp/nsstress.exp b/gdb/testsuite/gdb.cp/nsstress.exp new file mode 100644 index 0000000..afe1bb0 --- /dev/null +++ b/gdb/testsuite/gdb.cp/nsstress.exp @@ -0,0 +1,52 @@ +# Copyright 2008 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +# Stress test namespace lookup + +if $tracelevel then { + strace $tracelevel +} + +set prms_id 0 +set bug_id 0 + +set testfile nsstress +set srcfile ${testfile}.cc +set binfile ${objdir}/${subdir}/${testfile} +if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug c++}] != "" } { + untested "Couldn't compile test program" + return -1 +} + +if [get_compiler_info ${binfile}] { + return -1 +} + +# Get things started. + +gdb_exit +gdb_start +gdb_reinitialize_dir $srcdir/$subdir +gdb_load ${binfile} + +if ![runto_main] then { + perror "couldn't run to breakpoint main" + continue +} + +############################################ +# Test that the search can fail efficiently + +gdb_test "print y" "No symbol \"y\" in current context." diff --git a/gdb/valops.c b/gdb/valops.c index 012ea6a..6fdea95 100644 --- a/gdb/valops.c +++ b/gdb/valops.c @@ -2765,7 +2765,7 @@ value_maybe_namespace_elt (const struct type *curtype, sym = cp_lookup_symbol_namespace (namespace_name, name, NULL, get_selected_block (0), - VAR_DOMAIN); + VAR_DOMAIN, 1); if (sym == NULL) return NULL; [-- Attachment #2: sami2-recursive-search.patch --] [-- Type: text/plain, Size: 14910 bytes --] diff --git a/gdb/cp-namespace.c b/gdb/cp-namespace.c index f63cf8a..5790ebf 100644 --- a/gdb/cp-namespace.c +++ b/gdb/cp-namespace.c @@ -217,6 +217,7 @@ cp_add_using (const char *dest, retval->import_src = savestring (src, strlen(src)); retval->import_dest = savestring (dest, strlen(dest)); retval->next = next; + retval->searched = 0; return retval; } @@ -243,6 +244,8 @@ cp_copy_usings (struct using_direct *using, obstack); retval->next = cp_copy_usings (using->next, obstack); + retval->searched = using->searched; + xfree (using->import_src); xfree (using->import_dest); xfree (using); @@ -272,7 +275,8 @@ cp_lookup_symbol_nonlocal (const char *name, if (sym != NULL) return sym; - return cp_lookup_symbol_namespace (scope, name, linkage_name, block, domain); + return cp_lookup_symbol_namespace (scope, name, linkage_name, block, domain, + 1); } /* Look up NAME in the C++ namespace NAMESPACE. Other arguments are as in @@ -302,19 +306,46 @@ cp_lookup_symbol_in_namespace (const char *namespace, } } +/* Used for cleanups to reset the "searched" flag incase + of an error. */ + +static void +reset_directive_searched (void *data) +{ + struct using_direct *direct = data; + direct->searched = 0; +} + /* Search for NAME by applying all import statements belonging - to BLOCK which are applicable in SCOPE. */ + to BLOCK which are applicable in SCOPE. + If SEARCH_PARENTS the search will include imports which are applicable in + parents of SCOPE. + Example: + + namespace A{ + using namespace X; + namespace B{ + using namespace Y; + } + } + + If SCOPE is "A::B" and SEARCH_PARENTS is true the imports of namespaces X + and Y will be considered. If SEARCH_PARENTS is false only the import of Y + is considered. */ static struct symbol * cp_lookup_symbol_imports (const char *scope, const char *name, const char *linkage_name, const struct block *block, - const domain_enum domain) + const domain_enum domain, + const int search_parents) { - const struct using_direct *current; + struct using_direct *current; struct symbol *sym; int len; + int directive_match; + struct cleanup *searched_cleanup; /* First, try to find the symbol in the given namespace. */ sym = cp_lookup_symbol_in_namespace (scope, name, linkage_name, block, @@ -330,24 +361,41 @@ cp_lookup_symbol_imports (const char *scope, current != NULL; current = current->next) { + len = strlen (current->import_dest); + directive_match = (search_parents + ? (strncmp (scope, current->import_dest, + strlen (current->import_dest)) == 0 + && (len == 0 + || scope[len] == ':' || scope[len] == '\0')) + : strcmp (scope, current->import_dest) == 0); /* If the import destination is the current scope or one of its ancestors then it is applicable. */ - len = strlen (current->import_dest); - if (strncmp (scope, current->import_dest, len) == 0 - && (len == 0 || scope[len] == ':' || scope[len] == '\0')) + if (directive_match && !current->searched) { - sym = cp_lookup_symbol_in_namespace (current->import_src, name, - linkage_name, block, domain); - if (sym != NULL) - return sym; + /* Mark this import as searched so that the recursive call does not + search it again. */ + current->searched = 1; + searched_cleanup = make_cleanup (reset_directive_searched, current); + + sym = cp_lookup_symbol_namespace (current->import_src, + name, + linkage_name, + block, + domain, + 0); + + current->searched = 0; + discard_cleanups (searched_cleanup); + + if (sym != NULL) + return sym; } } return NULL; } - /* Searches for NAME in the current namespace, and by applying relevant import statements belonging to BLOCK and its parents. SCOPE is the namespace scope of the context in which the search is being evaluated. */ @@ -357,14 +405,16 @@ cp_lookup_symbol_namespace (const char *scope, const char *name, const char *linkage_name, const struct block *block, - const domain_enum domain) + const domain_enum domain, + const int search_parents) { struct symbol *sym; /* Search for name in namespaces imported to this and parent blocks. */ while (block != NULL) { - sym = cp_lookup_symbol_imports (scope,name, linkage_name, block, domain); + sym = cp_lookup_symbol_imports (scope, name, linkage_name, block, domain, + search_parents); if (sym) return sym; diff --git a/gdb/cp-support.h b/gdb/cp-support.h index 7ecd201..9400469 100644 --- a/gdb/cp-support.h +++ b/gdb/cp-support.h @@ -47,6 +47,9 @@ struct using_direct char *import_src; char *import_dest; struct using_direct *next; + + /* Used during import search to temporarily mark this node as searched. */ + int searched; }; @@ -107,7 +110,8 @@ extern struct symbol *cp_lookup_symbol_namespace (const char *namespace, const char *name, const char *linkage_name, const struct block *block, - const domain_enum domain); + const domain_enum domain, + const int search_parents); extern struct type *cp_lookup_nested_type (struct type *parent_type, const char *nested_name, diff --git a/gdb/testsuite/gdb.cp/nsdecl.cc b/gdb/testsuite/gdb.cp/nsdecl.cc new file mode 100644 index 0000000..01a9c75 --- /dev/null +++ b/gdb/testsuite/gdb.cp/nsdecl.cc @@ -0,0 +1,93 @@ +int a; +int b; +int c; +int d; +int e; +int f; +int g; +int h; +int i; +int j; +int k; +int l; +int m; +int n; +int o; +int p; +int q; +int r; +int s; +int t; +int u; +int v; +int w; +int x; +int y; +int z; + +namespace A +{ + int xyz; + + using ::a; + using ::b; + using ::c; + using ::d; + using ::e; + using ::f; + using ::g; + using ::h; + using ::i; + using ::j; + using ::k; + using ::l; + using ::m; + using ::n; + using ::o; + using ::p; + using ::q; + using ::r; + using ::s; + using ::t; + using ::u; + using ::v; + using ::w; + using ::x; + using ::y; + using ::z; + +} + +using A::a; +using A::b; +using A::c; +using A::d; +using A::e; +using A::f; +using A::g; +using A::h; +using A::i; +using A::j; +using A::k; +using A::l; +using A::m; +using A::n; +using A::o; +using A::p; +using A::q; +using A::r; +using A::s; +using A::t; +using A::u; +using A::v; +using A::w; +using A::x; +using A::y; +using A::z; + +using namespace A; + +int main () +{ + return 0; +} diff --git a/gdb/testsuite/gdb.cp/nsdecl.exp b/gdb/testsuite/gdb.cp/nsdecl.exp new file mode 100644 index 0000000..6e0d875 --- /dev/null +++ b/gdb/testsuite/gdb.cp/nsdecl.exp @@ -0,0 +1,52 @@ +# Copyright 2008 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +# Stress test the lookup of declarations + +if $tracelevel then { + strace $tracelevel +} + +set prms_id 0 +set bug_id 0 + +set testfile nsdecl +set srcfile ${testfile}.cc +set binfile ${objdir}/${subdir}/${testfile} +if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug c++}] != "" } { + untested "Couldn't compile test program" + return -1 +} + +if [get_compiler_info ${binfile}] { + return -1; +} + +# Get things started. + +gdb_exit +gdb_start +gdb_reinitialize_dir $srcdir/$subdir +gdb_load ${binfile} + +if ![runto_main] then { + perror "couldn't run to breakpoint main" + continue +} + +############################################ +# Test that the search can fail efficiently + +gdb_test "print fakex" "No symbol \"fakex\" in current context." diff --git a/gdb/testsuite/gdb.cp/nsrecurs.cc b/gdb/testsuite/gdb.cp/nsrecurs.cc new file mode 100644 index 0000000..84605a6 --- /dev/null +++ b/gdb/testsuite/gdb.cp/nsrecurs.cc @@ -0,0 +1,30 @@ +namespace A{ + int ax = 9; +} + +namespace B{ + using namespace A; +} + +namespace C{ + using namespace B; +} + +//--------------- +namespace D{ + using namespace D; + int dx = 99; +} +using namespace C; + +//--------------- +namespace{ + namespace{ + int xx = 999; + } +} + +int main(){ + using namespace D; + return ax + dx + xx; +} diff --git a/gdb/testsuite/gdb.cp/nsrecurs.exp b/gdb/testsuite/gdb.cp/nsrecurs.exp new file mode 100644 index 0000000..9939a9f --- /dev/null +++ b/gdb/testsuite/gdb.cp/nsrecurs.exp @@ -0,0 +1,67 @@ +# Copyright 2008 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +# Test recursive namespace lookup + +if $tracelevel then { + strace $tracelevel +} + +set prms_id 0 +set bug_id 0 + +set testfile nsrecurs +set srcfile ${testfile}.cc +set binfile ${objdir}/${subdir}/${testfile} +if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug c++}] != "" } { + untested "Couldn't compile test program" + return -1 +} + +if [get_compiler_info ${binfile}] { + return -1 +} + + +# Get things started. + +gdb_exit +gdb_start +gdb_reinitialize_dir $srcdir/$subdir +gdb_load ${binfile} + +if ![runto_main] then { + perror "couldn't run to breakpoint main" + continue +} + +############################################ +# test printing from namespace imported into +# imported namespace + +gdb_test "print ax" "= 9" + +############################################ +# test that gdb can print without falling +# into search loop + +gdb_test "print dx" "= 99" + +############################################ +# test printing from namespace imported into +# imported namespace where imports are implicit +# anonymous namespace imports. + +gdb_test "print xx" "= 999" diff --git a/gdb/testsuite/gdb.cp/nsstress.cc b/gdb/testsuite/gdb.cp/nsstress.cc new file mode 100644 index 0000000..de84ab1 --- /dev/null +++ b/gdb/testsuite/gdb.cp/nsstress.cc @@ -0,0 +1,60 @@ + +namespace A{ int x; } +namespace B{ int x; } +namespace C{ int x; } +namespace D{ int x; } +namespace E{ int x; } +namespace F{ int x; } +namespace G{ int x; } +namespace H{ int x; } +namespace I{ int x; } +namespace J{ int x; } +namespace K{ int x; } +namespace L{ int x; } +namespace M{ int x; } +namespace N{ int x; } +namespace O{ int x; } +namespace P{ int x; } +namespace Q{ int x; } +namespace R{ int x; } +namespace S{ int x; } +namespace T{ int x; } +namespace U{ int x; } +namespace V{ int x; } +namespace W{ int x; } +namespace X{ int x; } +namespace Y{ int x; } +namespace Z{ int x; } + + +int main(){ + + using namespace A; + using namespace B; + using namespace C; + using namespace D; + using namespace E; + using namespace F; + using namespace G; + using namespace H; + using namespace I; + using namespace J; + using namespace K; + using namespace L; + using namespace M; + using namespace N; + using namespace O; + using namespace P; + using namespace Q; + using namespace R; + using namespace S; + using namespace T; + using namespace U; + using namespace V; + using namespace W; + using namespace X; + using namespace Y; + using namespace Z; + + return 0; +} diff --git a/gdb/testsuite/gdb.cp/nsstress.exp b/gdb/testsuite/gdb.cp/nsstress.exp new file mode 100644 index 0000000..afe1bb0 --- /dev/null +++ b/gdb/testsuite/gdb.cp/nsstress.exp @@ -0,0 +1,52 @@ +# Copyright 2008 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +# Stress test namespace lookup + +if $tracelevel then { + strace $tracelevel +} + +set prms_id 0 +set bug_id 0 + +set testfile nsstress +set srcfile ${testfile}.cc +set binfile ${objdir}/${subdir}/${testfile} +if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug c++}] != "" } { + untested "Couldn't compile test program" + return -1 +} + +if [get_compiler_info ${binfile}] { + return -1 +} + +# Get things started. + +gdb_exit +gdb_start +gdb_reinitialize_dir $srcdir/$subdir +gdb_load ${binfile} + +if ![runto_main] then { + perror "couldn't run to breakpoint main" + continue +} + +############################################ +# Test that the search can fail efficiently + +gdb_test "print y" "No symbol \"y\" in current context." diff --git a/gdb/valops.c b/gdb/valops.c index 012ea6a..6fdea95 100644 --- a/gdb/valops.c +++ b/gdb/valops.c @@ -2765,7 +2765,7 @@ value_maybe_namespace_elt (const struct type *curtype, sym = cp_lookup_symbol_namespace (namespace_name, name, NULL, get_selected_block (0), - VAR_DOMAIN); + VAR_DOMAIN, 1); if (sym == NULL) return NULL; ^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [patch 2/2] Perform a namespace lookup at every block level 2010-01-14 20:18 ` Sami Wagiaalla @ 2010-01-15 18:06 ` Tom Tromey 0 siblings, 0 replies; 28+ messages in thread From: Tom Tromey @ 2010-01-15 18:06 UTC (permalink / raw) To: Sami Wagiaalla; +Cc: gdb-patches >>>>> "Sami" == Sami Wagiaalla <swagiaal@redhat.com> writes: >> Renamed test files to fit 8.3, and added comments in the beginning of >> the files to compensate for the loss of readability. Sami> Corrected Changelog This is ok. Thanks. Tom ^ permalink raw reply [flat|nested] 28+ messages in thread
end of thread, other threads:[~2010-01-15 18:06 UTC | newest] Thread overview: 28+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2009-07-10 15:10 [patch] Perform a namespace lookup at every block level Sami Wagiaalla 2009-07-10 20:16 ` Daniel Jacobowitz 2009-07-13 17:55 ` Sami Wagiaalla 2009-07-23 19:46 ` Sami Wagiaalla 2009-07-23 22:19 ` Sami Wagiaalla 2009-07-29 22:12 ` Tom Tromey 2009-08-18 20:34 ` [patch 1/2] " Sami Wagiaalla 2009-10-13 19:47 ` Tom Tromey 2009-10-20 20:50 ` Sami Wagiaalla 2009-11-10 22:23 ` Tom Tromey 2009-11-10 22:26 ` Tom Tromey 2009-11-16 15:32 ` Sami Wagiaalla 2009-11-16 19:16 ` Sami Wagiaalla 2009-11-24 19:06 ` Sami Wagiaalla 2009-12-21 21:44 ` Tom Tromey 2009-08-18 20:46 ` [patch 2/2] " Sami Wagiaalla 2009-09-04 16:57 ` Sami Wagiaalla 2009-10-13 20:22 ` Tom Tromey 2009-10-22 17:47 ` Sami Wagiaalla 2009-11-10 22:52 ` Tom Tromey 2009-11-16 17:55 ` Sami Wagiaalla 2009-11-24 19:12 ` Sami Wagiaalla 2009-12-21 21:55 ` Tom Tromey 2010-01-11 21:24 ` Sami Wagiaalla 2010-01-12 17:43 ` Tom Tromey 2010-01-14 16:47 ` Sami Wagiaalla 2010-01-14 20:18 ` Sami Wagiaalla 2010-01-15 18:06 ` Tom Tromey
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox