Re: [rfa] teach lookup_symbol about namespace scope

Elena Zannoni
2003-05-16T14:48:20Z

OK, here it goes. I have been ruminating on this patch a long time,
and I have really mixed feelings about it, no that's not accurate, I
am completely torn about it.

On one hand, I really like the algorithm to do the search recursively.
It is very clean and elegant. I have to admit that it took me a long
time to understand what it did, but it may just be me, lacking
concentration these days. Only after I applied the patch and stepped
through the code, I could see how it worked. Probably adding comments
would solve the problem, though.

On the other hand, the generic flow of control of the symbol search
gets pulled into c++ territory. This worries me because other
languages have other requirements, and it would be nice if we could
integrate language specific search portions into the generic lookup
code. We have right now C++, ObjC, Ada, each with their own specific
rules. For instance ada-lang.c "resolves" the problem by doing an
almost total rewrite of the symbol lookup to suit the Ada scope rules.
With ObjC we have a couple of points where the control flow does
additional extra steps, and I think this is the right model, because
those points can become, in a not too distant future, points of entry
into language vectors functions. I would like to have a similar
structure for the C++ specific code. Sadly, doing this means to
disrupt your algorithm, and would require building list(s) of possible
scopes to be searched, and search each in turn, instead of using the
local state of the recursive calls as a list of items to check.
Unless of course, you can think of something else.

I would like to hear other people's opinions as well, on this issue.

Anyway, here is the symtab.c portion of the patch updated to reflect
the namespace-->domain changes. Block.c and block.h changes are ok.

(about the test changes: do you use namespace1.cc at all? I don't see
you hooking that up to anything).

elena

--- symtab.c Fri May 16 10:49:23 2003
+++ symtab.c.dc Thu May 15 13:44:22 2003
@@ -53,6 +53,8 @@
#include "gdb_stat.h"
#include <ctype.h>
#include "cp-abi.h"
+#include "cp-support.h"
+#include "gdb_assert.h"

/* Prototypes for local functions */

@@ -93,8 +95,7 @@
const char *mangled_name,
const struct block *block,
const domain_enum domain,
- struct symtab **symtab,
- const struct block **static_block);
+ struct symtab **symtab);

static
struct symbol *lookup_symbol_aux_block (const char *name,
@@ -126,6 +127,22 @@
struct symtab **symtab);
#endif

+static
+struct symbol *lookup_symbol_aux_namespace_scope (const char *name,
+ const char *linkage_name,
+ const struct block *block,
+ domain_enum domain,
+ struct symtab **symtab,
+ const char *scope,
+ int scope_len);
+
+static struct symbol *lookup_symbol_aux_file (const char *name,
+ const char *linkage_name,
+ const struct block *block,
+ const domain_enum domain,
+ struct symtab **symtab,
+ int anonymous_namespace);
+
static struct symbol *find_active_alias (struct symbol *sym, CORE_ADDR addr);

/* This flag is used in hppa-tdep.c, and set in hp-symtab-read.c */
@@ -959,7 +976,7 @@
STATIC_BLOCK or GLOBAL_BLOCK. */

sym = lookup_symbol_aux_local (name, mangled_name, block, domain,
- symtab, &static_block);
+ symtab);
if (sym != NULL)
return sym;

@@ -1025,50 +1042,10 @@
}
}

- /* If there's a static block to search, search it next. */
-
- /* NOTE: carlton/2002-12-05: There is a question as to whether or
- not it would be appropriate to search the current global block
- here as well. (That's what this code used to do before the
- is_a_field_of_this check was moved up.) On the one hand, it's
- redundant with the lookup_symbol_aux_symtabs search that happens
- next. On the other hand, if decode_line_1 is passed an argument
- like filename:var, then the user presumably wants 'var' to be
- searched for in filename. On the third hand, there shouldn't be
- multiple global variables all of which are named 'var', and it's
- not like decode_line_1 has ever restricted its search to only
- global variables in a single filename. All in all, only
- searching the static block here seems best: it's correct and it's
- cleanest. */
-
- /* NOTE: carlton/2002-12-05: There's also a possible performance
- issue here: if you usually search for global symbols in the
- current file, then it would be slightly better to search the
- current global block before searching all the symtabs. But there
- are other factors that have a much greater effect on performance
- than that one, so I don't think we should worry about that for
- now. */
-
- if (static_block != NULL)
- {
- sym = lookup_symbol_aux_block (name, mangled_name, static_block,
- domain, symtab);
- if (sym != NULL)
- return sym;
- }
+ sym = lookup_symbol_aux_namespace_scope (name, mangled_name, block,
+ domain, symtab,
+ block_scope (block), 0);

- /* Now search all global blocks. Do the symtab's first, then
- check the psymtab's. If a psymtab indicates the existence
- of the desired name as a global, then do psymtab-to-symtab
- conversion on the fly and return the found symbol. */
-
- sym = lookup_symbol_aux_symtabs (GLOBAL_BLOCK, name, mangled_name,
- domain, symtab);
- if (sym != NULL)
- return sym;
-
- sym = lookup_symbol_aux_psymtabs (GLOBAL_BLOCK, name, mangled_name,
- domain, symtab);
if (sym != NULL)
return sym;

@@ -1094,27 +1071,24 @@
}

/* Check to see if the symbol is defined in BLOCK or its superiors.
- Don't search STATIC_BLOCK or GLOBAL_BLOCK. If we don't find a
- match, store the address of STATIC_BLOCK in static_block. */
+ Don't search STATIC_BLOCK or GLOBAL_BLOCK. */

static struct symbol *
lookup_symbol_aux_local (const char *name, const char *mangled_name,
const struct block *block,
const domain_enum domain,
- struct symtab **symtab,
- const struct block **static_block)
+ struct symtab **symtab)
{
struct symbol *sym;
-
- /* Check if either no block is specified or it's a global block. */
+ const struct block *static_block = block_static_block (block);

- if (block == NULL || BLOCK_SUPERBLOCK (block) == NULL)
- {
- *static_block = NULL;
- return NULL;
- }
+ /* Either no block is specified or it's a global block. */
+
+ if (static_block == NULL)
+ return NULL;

- while (BLOCK_SUPERBLOCK (BLOCK_SUPERBLOCK (block)) != NULL)
+
+ while (block != static_block)
{
sym = lookup_symbol_aux_block (name, mangled_name, block, domain,
symtab);
@@ -1123,9 +1097,8 @@
block = BLOCK_SUPERBLOCK (block);
}

- /* We've reached the static block. */
+ /* We've reached the static block without finding a result. */

- *static_block = block;
return NULL;
}

@@ -1390,6 +1363,157 @@
}
#endif /* 0 */

+/* Lookup NAME at namespace scope (or, in C terms, in static and
+ global variables). SCOPE is the namespace that the current
+ function is defined within; only consider namespaces whose length
+ is at least SCOPE_LEN. (This is to make the recursion easier.) */
+
+static struct symbol *
+lookup_symbol_aux_namespace_scope (const char *name,
+ const char *linkage_name,
+ const struct block *block,
+ domain_enum domain,
+ struct symtab **symtab,
+ const char *scope,
+ int scope_len)
+{
+ char *cp_namespace;
+
+ if (scope[scope_len] != '\0')
+ {
+ struct symbol *sym;
+ int new_scope_len = scope_len;
+
+ /* If the current scope is followed by "::", skip past that. */
+ if (new_scope_len != 0)
+ {
+ gdb_assert (scope[new_scope_len] == ':');
+ new_scope_len += 2;
+ }
+ new_scope_len += cp_find_first_component (scope + new_scope_len);
+ sym = lookup_symbol_aux_namespace_scope (name, linkage_name, block,
+ domain, symtab,
+ scope, new_scope_len);
+ if (sym != NULL)
+ return sym;
+ }
+
+ cp_namespace = alloca (scope_len + 1);
+ strncpy (cp_namespace, scope, scope_len);
+ cp_namespace[scope_len] = '\0';
+ return lookup_symbol_namespace (cp_namespace, name, linkage_name,
+ block, domain, symtab);
+}
+
+/* Look up NAME in the C++ namespace CP_NAMESPACE, applying the using
+ directives that are active in BLOCK. Otherwise, arguments are as
+ in lookup_symbol_aux. */
+
+struct symbol *
+lookup_symbol_namespace (const char *cp_namespace,
+ const char *name,
+ const char *linkage_name,
+ const struct block *block,
+ domain_enum domain,
+ struct symtab **symtab)
+{
+ 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 (cp_namespace, current->outer) == 0)
+ {
+ sym = lookup_symbol_namespace (current->inner,
+ name,
+ linkage_name,
+ block,
+ domain,
+ symtab);
+ 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 (cp_namespace[0] == '\0')
+ {
+ return lookup_symbol_aux_file (name, linkage_name, block,
+ domain, symtab,
+ 0);
+ }
+ else
+ {
+ char *concatenated_name
+ = alloca (strlen (cp_namespace) + 2 + strlen (name) + 1);
+ strcpy (concatenated_name, cp_namespace);
+ strcat (concatenated_name, "::");
+ strcat (concatenated_name, name);
+ sym = lookup_symbol_aux_file (concatenated_name, linkage_name,
+ block, domain, symtab,
+ cp_is_anonymous (cp_namespace));
+ return sym;
+ }
+}
+
+/* Look up NAME in BLOCK's static block and in global blocks. If
+ ANONYMOUS_NAMESPACE is nonzero, don't look in other files' global
+ blocks, just in the one belonging to this file. */
+
+static struct symbol *
+lookup_symbol_aux_file (const char *name,
+ const char *linkage_name,
+ const struct block *block,
+ const domain_enum domain,
+ struct symtab **symtab,
+ int anonymous_namespace)
+{
+ struct symbol *sym = NULL;
+ const struct block *static_block = block_static_block (block);
+
+ if (static_block != NULL)
+ {
+ sym = lookup_symbol_aux_block (name, linkage_name, static_block,
+ domain, symtab);
+ if (sym != NULL)
+ return sym;
+ }
+
+ if (anonymous_namespace)
+ {
+ const struct block *global_block = NULL;
+ if (static_block != NULL)
+ global_block = BLOCK_SUPERBLOCK (static_block);
+ else if (block != NULL)
+ global_block = block;
+
+ if (global_block != NULL)
+ return lookup_symbol_aux_block (name, linkage_name, global_block,
+ domain, symtab);
+ else
+ return NULL;
+ }
+ else
+ {
+ sym = lookup_symbol_aux_symtabs (GLOBAL_BLOCK, name, linkage_name,
+ domain, symtab);
+ if (sym != NULL)
+ return sym;
+ else
+ return lookup_symbol_aux_psymtabs (GLOBAL_BLOCK, name, linkage_name,
+ domain, symtab);
+ }
+}
+
/* Look, in partial_symtab PST, for symbol whose natural name is NAME.
If LINKAGE_NAME is non-NULL, check in addition that the symbol's
linkage name matches it. Check the global symbols if GLOBAL, the