Index: gdb/cp-namespace.c |
diff --git a/gdb/cp-namespace.c b/gdb/cp-namespace.c |
index e2291a9938f9118a937d21e67465b0649a4659e1..d0520bd7a6cd928d7e00156cb95966aced1eab11 100644 |
--- a/gdb/cp-namespace.c |
+++ b/gdb/cp-namespace.c |
@@ -1,5 +1,5 @@ |
/* Helper routines for C++ support in GDB. |
- Copyright (C) 2003-2004, 2007-2012 Free Software Foundation, Inc. |
+ Copyright (C) 2003-2013 Free Software Foundation, Inc. |
Contributed by David Carlton and by Kealia, Inc. |
@@ -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, |
@@ -95,7 +96,7 @@ cp_scan_for_anonymous_namespaces (const struct symbol *const symbol, |
anonymous namespace. So add symbols in it to the |
namespace given by the previous component if there is |
one, or to the global namespace if there isn't. */ |
- cp_add_using_directive (dest, src, NULL, NULL, NULL, |
+ cp_add_using_directive (dest, src, NULL, NULL, NULL, 1, |
&objfile->objfile_obstack); |
} |
/* The "+ 2" is for the "::". */ |
@@ -116,9 +117,10 @@ cp_scan_for_anonymous_namespaces (const struct symbol *const symbol, |
in the current scope. If ALIAS is NULL then the namespace is known |
by its original name. DECLARATION is the name if the imported |
varable if this is a declaration import (Eg. using A::x), otherwise |
- it is NULL. EXCLUDES is a list of names not to import from an imported |
- module or NULL. The arguments are copied into newly allocated memory so |
- they can be temporaries. For EXCLUDES the VEC pointers are copied but the |
+ it is NULL. EXCLUDES is a list of names not to import from an |
+ imported module or NULL. If COPY_NAMES is non-zero, then the |
+ arguments are copied into newly allocated memory so they can be |
+ temporaries. For EXCLUDES the VEC pointers are copied but the |
pointed to characters are not copied. */ |
void |
@@ -127,6 +129,7 @@ cp_add_using_directive (const char *dest, |
const char *alias, |
const char *declaration, |
VEC (const_char_ptr) *excludes, |
+ int copy_names, |
struct obstack *obstack) |
{ |
struct using_direct *current; |
@@ -172,15 +175,27 @@ cp_add_using_directive (const char *dest, |
* sizeof (*new->excludes)))); |
memset (new, 0, sizeof (*new)); |
- new->import_src = obsavestring (src, strlen (src), obstack); |
- new->import_dest = obsavestring (dest, strlen (dest), obstack); |
+ if (copy_names) |
+ { |
+ new->import_src = obstack_copy0 (obstack, src, strlen (src)); |
+ new->import_dest = obstack_copy0 (obstack, dest, strlen (dest)); |
+ } |
+ else |
+ { |
+ new->import_src = src; |
+ new->import_dest = dest; |
+ } |
- if (alias != NULL) |
- new->alias = obsavestring (alias, strlen (alias), obstack); |
+ if (alias != NULL && copy_names) |
+ new->alias = obstack_copy0 (obstack, alias, strlen (alias)); |
+ else |
+ new->alias = alias; |
- if (declaration != NULL) |
- new->declaration = obsavestring (declaration, strlen (declaration), |
- obstack); |
+ if (declaration != NULL && copy_names) |
+ new->declaration = obstack_copy0 (obstack, |
+ declaration, strlen (declaration)); |
+ else |
+ new->declaration = declaration; |
memcpy (new->excludes, VEC_address (const_char_ptr, excludes), |
VEC_length (const_char_ptr, excludes) * sizeof (*new->excludes)); |
@@ -190,44 +205,6 @@ cp_add_using_directive (const char *dest, |
using_directives = new; |
} |
-/* Record the namespace that the function defined by SYMBOL was |
- defined in, if necessary. BLOCK is the associated block; use |
- OBSTACK for allocation. */ |
- |
-void |
-cp_set_block_scope (const struct symbol *symbol, |
- struct block *block, |
- struct obstack *obstack, |
- const char *processing_current_prefix, |
- int processing_has_namespace_info) |
-{ |
- if (processing_has_namespace_info) |
- { |
- block_set_scope |
- (block, obsavestring (processing_current_prefix, |
- strlen (processing_current_prefix), |
- obstack), |
- obstack); |
- } |
- else if (SYMBOL_DEMANGLED_NAME (symbol) != NULL) |
- { |
- /* Try to figure out the appropriate namespace from the |
- demangled name. */ |
- |
- /* FIXME: carlton/2003-04-15: If the function in question is |
- a method of a class, the name will actually include the |
- name of the class as well. This should be harmless, but |
- is a little unfortunate. */ |
- |
- const char *name = SYMBOL_DEMANGLED_NAME (symbol); |
- unsigned int prefix_len = cp_entire_prefix_len (name); |
- |
- block_set_scope (block, |
- obsavestring (name, prefix_len, obstack), |
- obstack); |
- } |
-} |
- |
/* Test whether or not NAMESPACE looks like it mentions an anonymous |
namespace; return nonzero if so. */ |
@@ -264,17 +241,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 +263,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 +319,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 +363,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 +397,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) |
{ |
@@ -473,10 +451,6 @@ cp_lookup_symbol_imports_or_template (const char *scope, |
if (function != NULL && SYMBOL_LANGUAGE (function) == language_cplus) |
{ |
- int i; |
- struct cplus_specific *cps |
- = function->ginfo.language_specific.cplus_specific; |
- |
/* Search the function's template parameters. */ |
if (SYMBOL_IS_CPLUS_TEMPLATE_FUNCTION (function)) |
{ |
@@ -499,7 +473,8 @@ cp_lookup_symbol_imports_or_template (const char *scope, |
char *name_copy = xstrdup (SYMBOL_NATURAL_NAME (function)); |
struct cleanup *cleanups = make_cleanup (xfree, name_copy); |
const struct language_defn *lang = language_def (language_cplus); |
- struct gdbarch *arch = SYMBOL_SYMTAB (function)->objfile->gdbarch; |
+ struct gdbarch *arch |
+ = get_objfile_arch (SYMBOL_SYMTAB (function)->objfile); |
const struct block *parent = BLOCK_SUPERBLOCK (block); |
while (1) |
@@ -525,7 +500,10 @@ cp_lookup_symbol_imports_or_template (const char *scope, |
TYPE_N_TEMPLATE_ARGUMENTS (context), |
TYPE_TEMPLATE_ARGUMENTS (context)); |
if (result != NULL) |
- return result; |
+ { |
+ do_cleanups (cleanups); |
+ return result; |
+ } |
} |
do_cleanups (cleanups); |
@@ -550,7 +528,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 +599,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 +636,159 @@ 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 base class |
+ named NAME and return its type. If not found, return NULL. */ |
+ |
+struct type * |
+find_type_baseclass_by_name (struct type *parent_type, const char *name) |
+{ |
+ int i; |
+ |
+ CHECK_TYPEDEF (parent_type); |
+ for (i = 0; i < TYPE_N_BASECLASSES (parent_type); ++i) |
+ { |
+ struct type *type = check_typedef (TYPE_BASECLASS (parent_type, i)); |
+ const char *base_name = TYPE_BASECLASS_NAME (parent_type, i); |
+ |
+ if (base_name == NULL) |
+ continue; |
+ |
+ if (streq (base_name, name)) |
+ return type; |
+ |
+ type = find_type_baseclass_by_name (type, name); |
+ if (type != NULL) |
+ return type; |
+ } |
+ |
+ return NULL; |
+} |
+ |
+/* 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; |
+ struct type *base_type = TYPE_BASECLASS (parent_type, i); |
+ const char *base_name = TYPE_BASECLASS_NAME (parent_type, i); |
+ |
+ if (base_name == NULL) |
+ continue; |
+ |
+ /* Search this particular base class. */ |
+ sym = cp_lookup_symbol_in_namespace (base_name, name, block, |
+ VAR_DOMAIN, 0); |
+ if (sym != NULL) |
+ break; |
+ |
+ /* Now search all static file-level symbols. We have to do this for |
+ things like typedefs in the class. First search in this symtab, |
+ what we want is possibly there. */ |
+ 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 (sym != NULL) |
+ break; |
+ |
+ /* Nope. We now have to search all static blocks in all objfiles, |
+ even if block != NULL, because there's no guarantees as to which |
+ symtab the symbol we want is in. */ |
+ sym = lookup_static_symbol_aux (concatenated_name, VAR_DOMAIN); |
+ if (sym != NULL) |
+ break; |
+ |
+ /* If this class has base classes, search them next. */ |
+ CHECK_TYPEDEF (base_type); |
+ if (TYPE_N_BASECLASSES (base_type) > 0) |
+ { |
+ sym = find_symbol_in_baseclass (base_type, name, block); |
+ if (sym != NULL) |
+ break; |
+ } |
+ } |
+ |
+ do_cleanups (cleanup); |
return sym; |
} |
@@ -688,31 +820,39 @@ cp_lookup_nested_symbol (struct type *parent_type, |
just like members of namespaces; in particular, |
lookup_symbol_namespace works when looking them up. */ |
+ int size; |
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) |
return sym; |
- /* Now search all static file-level symbols. Not strictly |
- correct, but more useful than an error. We do not try to |
+ /* Now search all static file-level symbols. We have to do this |
+ for things like typedefs in the class. 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. */ |
- concatenated_name = alloca (strlen (parent_name) + 2 |
- + strlen (nested_name) + 1); |
- sprintf (concatenated_name, "%s::%s", |
+ size = strlen (parent_name) + 2 + strlen (nested_name) + 1; |
+ concatenated_name = alloca (size); |
+ xsnprintf (concatenated_name, size, "%s::%s", |
parent_name, nested_name); |
sym = lookup_static_symbol_aux (concatenated_name, VAR_DOMAIN); |
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); |
} |
+ |
+ case TYPE_CODE_FUNC: |
+ case TYPE_CODE_METHOD: |
+ return NULL; |
+ |
default: |
internal_error (__FILE__, __LINE__, |
_("cp_lookup_nested_symbol called " |