Re: [patch] Perform a namespace lookup at every block level

Sami Wagiaalla
2009-07-23T19:26:36Z

>
> 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"