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