aboutsummaryrefslogtreecommitdiff
path: root/gdb/cp-namespace.c
diff options
context:
space:
mode:
authorKeith Seitz <keiths@redhat.com>2012-11-16 20:54:30 +0000
committerKeith Seitz <keiths@redhat.com>2012-11-16 20:54:30 +0000
commit8dea366bbed7986295681c101dcfbd35aeb6dfc4 (patch)
tree93ea9e7541e15d6a5701533e7854dc346863854e /gdb/cp-namespace.c
parente64e03922ca4da2d3da887a467076eda615c62bd (diff)
downloadgdb-8dea366bbed7986295681c101dcfbd35aeb6dfc4.zip
gdb-8dea366bbed7986295681c101dcfbd35aeb6dfc4.tar.gz
gdb-8dea366bbed7986295681c101dcfbd35aeb6dfc4.tar.bz2
PR c++/13615
* cp-namespace.c (cp_lookup_symbol_in_namespace): Add SEARCH parameter and pass it to lookup_symbol_file. (cp_lookup_symbol_imports): Tell cp_lookup_symbol_in_namespace to search base classes. (cp_lookup_symbol_namespace): Likewise. (lookup_namespace_scope): Likewise. (lookup_symbol_file): Add SEARCH parameter. If SEARCH is non-zero and no symbol is found, lookup the class and call cp_lookup_nested_symbol. (find_symbol_in_baseclass): New function. (cp_lookup_nested_symbol): Do not let cp_lookup_symbol_in_namespace search through base classes. Do that later when there is no global symbol match. PR c++/13615 * gdb.cp/baseenum.cc: New file. * gdb.cp/baseenum.exp: New file. * gdb.cp/derivation.cc (A): Add copyright. Add a typedef. (B): Use A::value_type instead of int. Change all references. (D): Use value_type instead of int. Change all references. (E): Likewise. (F); Likewise. (Z): New class. (ZZ): New class. (N, Base, Derived): New namespace and classes. (main): Add instances of Z and ZZ. Make sure all symbols from N are kept. * gdb.cp/derivation.exp: Update typedef changes in tests. Add tests for class typedefs both before and after starting the inferior. Add tests for searching for a typedef while stopped in a method.
Diffstat (limited to 'gdb/cp-namespace.c')
-rw-r--r--gdb/cp-namespace.c156
1 files changed, 141 insertions, 15 deletions
diff --git a/gdb/cp-namespace.c b/gdb/cp-namespace.c
index 1a69402..7f291b9 100644
--- a/gdb/cp-namespace.c
+++ b/gdb/cp-namespace.c
@@ -42,7 +42,8 @@ static struct symbol *lookup_namespace_scope (const char *name,
static struct symbol *lookup_symbol_file (const char *name,
const struct block *block,
const domain_enum domain,
- int anonymous_namespace);
+ int anonymous_namespace,
+ int search);
static struct type *cp_lookup_transparent_type_loop (const char *name,
const char *scope,
@@ -264,17 +265,18 @@ cp_lookup_symbol_nonlocal (const char *name,
}
/* Look up NAME in the C++ namespace NAMESPACE. Other arguments are
- as in cp_lookup_symbol_nonlocal. */
+ as in cp_lookup_symbol_nonlocal. If SEARCH is non-zero, search
+ through base classes for a matching symbol. */
static struct symbol *
cp_lookup_symbol_in_namespace (const char *namespace,
const char *name,
const struct block *block,
- const domain_enum domain)
+ const domain_enum domain, int search)
{
if (namespace[0] == '\0')
{
- return lookup_symbol_file (name, block, domain, 0);
+ return lookup_symbol_file (name, block, domain, 0, search);
}
else
{
@@ -285,7 +287,7 @@ cp_lookup_symbol_in_namespace (const char *namespace,
strcat (concatenated_name, "::");
strcat (concatenated_name, name);
return lookup_symbol_file (concatenated_name, block, domain,
- cp_is_anonymous (namespace));
+ cp_is_anonymous (namespace), search);
}
}
@@ -341,7 +343,7 @@ cp_lookup_symbol_imports (const char *scope,
/* First, try to find the symbol in the given namespace. */
if (!declaration_only)
sym = cp_lookup_symbol_in_namespace (scope, name,
- block, domain);
+ block, domain, 1);
if (sym != NULL)
return sym;
@@ -385,7 +387,7 @@ cp_lookup_symbol_imports (const char *scope,
? current->alias : current->declaration) == 0)
sym = cp_lookup_symbol_in_namespace (current->import_src,
current->declaration,
- block, domain);
+ block, domain, 1);
/* If this is a DECLARATION_ONLY search or a symbol was found
or this import statement was an import declaration, the
@@ -419,7 +421,7 @@ cp_lookup_symbol_imports (const char *scope,
{
sym = cp_lookup_symbol_in_namespace (scope,
current->import_src,
- block, domain);
+ block, domain, 1);
}
else if (current->alias == NULL)
{
@@ -550,7 +552,7 @@ cp_lookup_symbol_namespace (const char *scope,
/* First, try to find the symbol in the given namespace. */
sym = cp_lookup_symbol_in_namespace (scope, name,
- block, domain);
+ block, domain, 1);
if (sym != NULL)
return sym;
@@ -621,19 +623,20 @@ lookup_namespace_scope (const char *name,
strncpy (namespace, scope, scope_len);
namespace[scope_len] = '\0';
return cp_lookup_symbol_in_namespace (namespace, name,
- block, domain);
+ block, domain, 1);
}
/* Look up NAME in BLOCK's static block and in global blocks. If
ANONYMOUS_NAMESPACE is nonzero, the symbol in question is located
- within an anonymous namespace. Other arguments are as in
+ within an anonymous namespace. If SEARCH is non-zero, search through
+ base classes for a matching symbol. Other arguments are as in
cp_lookup_symbol_nonlocal. */
static struct symbol *
lookup_symbol_file (const char *name,
const struct block *block,
const domain_enum domain,
- int anonymous_namespace)
+ int anonymous_namespace, int search)
{
struct symbol *sym = NULL;
@@ -657,6 +660,127 @@ lookup_symbol_file (const char *name,
sym = lookup_symbol_global (name, block, domain);
}
+ if (sym != NULL)
+ return sym;
+
+ if (search)
+ {
+ char *klass, *nested;
+ unsigned int prefix_len;
+ struct cleanup *cleanup;
+ struct symbol *klass_sym;
+
+ /* A simple lookup failed. Check if the symbol was defined in
+ a base class. */
+
+ cleanup = make_cleanup (null_cleanup, NULL);
+
+ /* Find the name of the class and the name of the method,
+ variable, etc. */
+ prefix_len = cp_entire_prefix_len (name);
+
+ /* If no prefix was found, search "this". */
+ if (prefix_len == 0)
+ {
+ struct type *type;
+ struct symbol *this;
+
+ this = lookup_language_this (language_def (language_cplus), block);
+ if (this == NULL)
+ {
+ do_cleanups (cleanup);
+ return NULL;
+ }
+
+ type = check_typedef (TYPE_TARGET_TYPE (SYMBOL_TYPE (this)));
+ klass = xstrdup (TYPE_NAME (type));
+ nested = xstrdup (name);
+ }
+ else
+ {
+ /* The class name is everything up to and including PREFIX_LEN. */
+ klass = savestring (name, prefix_len);
+
+ /* The rest of the name is everything else past the initial scope
+ operator. */
+ nested = xstrdup (name + prefix_len + 2);
+ }
+
+ /* Add cleanups to free memory for these strings. */
+ make_cleanup (xfree, klass);
+ make_cleanup (xfree, nested);
+
+ /* Lookup a class named KLASS. If none is found, there is nothing
+ more that can be done. */
+ klass_sym = lookup_symbol_global (klass, block, domain);
+ if (klass_sym == NULL)
+ {
+ do_cleanups (cleanup);
+ return NULL;
+ }
+
+ /* Look for a symbol named NESTED in this class. */
+ sym = cp_lookup_nested_symbol (SYMBOL_TYPE (klass_sym), nested, block);
+ do_cleanups (cleanup);
+ }
+
+ return sym;
+}
+
+/* Search through the base classes of PARENT_TYPE for a symbol named
+ NAME in block BLOCK. */
+
+static struct symbol *
+find_symbol_in_baseclass (struct type *parent_type, const char *name,
+ const struct block *block)
+{
+ int i;
+ struct symbol *sym;
+ struct cleanup *cleanup;
+ char *concatenated_name;
+
+ sym = NULL;
+ concatenated_name = NULL;
+ cleanup = make_cleanup (free_current_contents, &concatenated_name);
+ for (i = 0; i < TYPE_N_BASECLASSES (parent_type); ++i)
+ {
+ size_t len;
+ const char *base_name = TYPE_BASECLASS_NAME (parent_type, i);
+
+ if (base_name == NULL)
+ continue;
+
+ /* Search this particular base class. */
+ sym = cp_lookup_symbol_namespace (base_name, name, block, VAR_DOMAIN);
+ if (sym != NULL)
+ break;
+
+ len = strlen (base_name) + 2 + strlen (name) + 1;
+ concatenated_name = xrealloc (concatenated_name, len);
+ xsnprintf (concatenated_name, len, "%s::%s", base_name, name);
+ sym = lookup_symbol_static (concatenated_name, block, VAR_DOMAIN);
+
+ /* If there is currently no BLOCK, e.g., the inferior hasn't yet
+ been started, then try searching all STATIC_BLOCK symbols in
+ all objfiles. */
+ if (block == NULL)
+ {
+ sym = lookup_static_symbol_aux (concatenated_name, VAR_DOMAIN);
+ if (sym != NULL)
+ break;
+ }
+
+ /* If this class has base classes, search them next. */
+ if (TYPE_N_BASECLASSES (TYPE_BASECLASS (parent_type, i)) > 0)
+ {
+ sym = find_symbol_in_baseclass (TYPE_BASECLASS (parent_type, i),
+ name, block);
+ if (sym != NULL)
+ break;
+ }
+ }
+
+ do_cleanups (cleanup);
return sym;
}
@@ -692,7 +816,7 @@ cp_lookup_nested_symbol (struct type *parent_type,
const char *parent_name = type_name_no_tag_or_error (saved_parent_type);
struct symbol *sym
= cp_lookup_symbol_in_namespace (parent_name, nested_name,
- block, VAR_DOMAIN);
+ block, VAR_DOMAIN, 0);
char *concatenated_name;
if (sym != NULL)
@@ -701,7 +825,7 @@ cp_lookup_nested_symbol (struct type *parent_type,
/* Now search all static file-level symbols. Not strictly
correct, but more useful than an error. We do not try to
guess any imported namespace as even the fully specified
- namespace seach is is already not C++ compliant and more
+ namespace search is already not C++ compliant and more
assumptions could make it too magic. */
size = strlen (parent_name) + 2 + strlen (nested_name) + 1;
@@ -712,7 +836,9 @@ cp_lookup_nested_symbol (struct type *parent_type,
if (sym != NULL)
return sym;
- return NULL;
+ /* If no matching symbols were found, try searching any
+ base classes. */
+ return find_symbol_in_baseclass (parent_type, nested_name, block);
}
default:
internal_error (__FILE__, __LINE__,