/* Helper routines for C++ support in GDB.
- Copyright (C) 2003, 2004, 2007, 2008, 2009 Free Software Foundation, Inc.
+ Copyright (C) 2003, 2004, 2007, 2008, 2009, 2010
+ Free Software Foundation, Inc.
Contributed by David Carlton and by Kealia, Inc.
#include "frame.h"
#include "buildsym.h"
-static struct using_direct *cp_copy_usings (struct using_direct *using,
- struct obstack *obstack);
-
static struct symbol *lookup_namespace_scope (const char *name,
- const char *linkage_name,
const struct block *block,
const domain_enum domain,
const char *scope,
int scope_len);
static struct symbol *lookup_symbol_file (const char *name,
- const char *linkage_name,
const struct block *block,
const domain_enum domain,
int anonymous_namespace);
const char *name = SYMBOL_DEMANGLED_NAME (symbol);
unsigned int previous_component;
unsigned int next_component;
- const char *len;
/* Start with a quick-and-dirty check for mention of "(anonymous
namespace)". */
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);
+ cp_add_using_directive (dest, src, NULL, NULL,
+ &SYMBOL_SYMTAB (symbol)->objfile->objfile_obstack);
}
/* The "+ 2" is for the "::". */
previous_component = next_component + 2;
}
}
-/* Add a using directive to using_list. If the using directive in question
- has already been added, don't add it twice. */
+
+/* Add a using directive to using_directives. If the using directive in
+ question has already been added, don't add it twice.
+ Create a new struct using_direct which imports the namespace SRC into the
+ scope DEST. ALIAS is the name of the imported namespace 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. The arguments are copied
+ into newly allocated memory so they can be temporaries. */
void
-cp_add_using_directive (const char *dest, const char *src)
+cp_add_using_directive (const char *dest,
+ const char *src,
+ const char *alias,
+ const char *declaration,
+ struct obstack *obstack)
{
struct using_direct *current;
struct using_direct *new;
-
+
/* Has it already been added? */
for (current = using_directives; current != NULL; current = current->next)
{
if (strcmp (current->import_src, src) == 0
- && strcmp (current->import_dest, dest) == 0)
+ && strcmp (current->import_dest, dest) == 0
+ && ((alias == NULL && current->alias == NULL)
+ || (alias != NULL && current->alias != NULL
+ && strcmp (alias, current->alias) == 0))
+ && ((declaration == NULL && current->declaration == NULL)
+ || (declaration != NULL && current->declaration != NULL
+ && strcmp (declaration, current->declaration) == 0)))
return;
}
- using_directives = cp_add_using (dest, src, using_directives);
+ new = OBSTACK_ZALLOC (obstack, struct using_direct);
+
+ new->import_src = obsavestring (src, strlen (src), obstack);
+ new->import_dest = obsavestring (dest, strlen (dest), obstack);
+
+ if (alias != NULL)
+ new->alias = obsavestring (alias, strlen (alias), obstack);
+
+ if (declaration != NULL)
+ new->declaration = obsavestring (declaration, strlen (declaration),
+ obstack);
+ new->next = using_directives;
+ using_directives = new;
}
/* Record the namespace that the function defined by SYMBOL was
!= NULL);
}
-/* Create a new struct using direct which imports the namespace SRC
- into the scope DEST.
- Set its next member in the linked list to NEXT; allocate all memory
- using xmalloc. It copies the strings, so NAME can be a temporary
- string. */
+/* The C++-specific version of name lookup for static and global
+ names. This makes sure that names get looked for in all namespaces
+ that are in scope. NAME is the natural name of the symbol that
+ we're looking for, BLOCK is the block that we're searching within,
+ DOMAIN says what kind of symbols we're looking for, and if SYMTAB is
+ non-NULL, we should store the symtab where we found the symbol in it. */
-struct using_direct *
-cp_add_using (const char *dest,
- const char *src,
- struct using_direct *next)
+struct symbol *
+cp_lookup_symbol_nonlocal (const char *name,
+ const struct block *block,
+ const domain_enum domain)
{
- struct using_direct *retval;
+ struct symbol *sym;
+ const char *scope = block_scope (block);
- retval = xmalloc (sizeof (struct using_direct));
- retval->import_src = savestring (src, strlen(src));
- retval->import_dest = savestring (dest, strlen(dest));
- retval->next = next;
+ sym = lookup_namespace_scope (name, block, domain, scope, 0);
+ if (sym != NULL)
+ return sym;
- return retval;
+ return cp_lookup_symbol_namespace (scope, name, block, domain);
}
-/* Make a copy of the using directives in the list pointed to by
- USING, using OBSTACK to allocate memory. Free all memory pointed
- to by USING via xfree. */
+/* Look up NAME in the C++ namespace NAMESPACE. Other arguments are as in
+ cp_lookup_symbol_nonlocal. */
-static struct using_direct *
-cp_copy_usings (struct using_direct *using,
- struct obstack *obstack)
+static struct symbol *
+cp_lookup_symbol_in_namespace (const char *namespace,
+ const char *name,
+ const struct block *block,
+ const domain_enum domain)
{
- if (using == NULL)
+ if (namespace[0] == '\0')
{
- return NULL;
+ return lookup_symbol_file (name, block, domain, 0);
}
else
{
- struct using_direct *retval
- = obstack_alloc (obstack, sizeof (struct using_direct));
- retval->import_src = obsavestring (using->import_src, strlen (using->import_src),
- obstack);
- retval->import_dest = obsavestring (using->import_dest, strlen (using->import_dest),
- obstack);
- retval->next = cp_copy_usings (using->next, obstack);
-
- xfree (using->import_src);
- xfree (using->import_dest);
- xfree (using);
-
- return retval;
+ 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, block,
+ domain, cp_is_anonymous (namespace));
}
}
-/* The C++-specific version of name lookup for static and global
- names. This makes sure that names get looked for in all namespaces
- that are in scope. NAME is the natural name of the symbol that
- we're looking for, LINKAGE_NAME (which is optional) is its linkage
- name, BLOCK is the block that we're searching within, DOMAIN says
- what kind of symbols we're looking for, and if SYMTAB is non-NULL,
- we should store the symtab where we found the symbol in it. */
+/* Used for cleanups to reset the "searched" flag incase
+ of an error. */
+
+static void
+reset_directive_searched (void *data)
+{
+ struct using_direct *direct = data;
+ direct->searched = 0;
+}
+
+/* Search for NAME by applying all import statements belonging
+ to BLOCK which are applicable in SCOPE. If DECLARATION_ONLY the search
+ is restricted to using declarations.
+ Example:
+
+ namespace A{
+ int x;
+ }
+ using A::x;
+
+ If SEARCH_PARENTS the search will include imports which are applicable in
+ parents of SCOPE.
+ Example:
+
+ namespace A{
+ using namespace X;
+ namespace B{
+ using namespace Y;
+ }
+ }
+
+ If SCOPE is "A::B" and SEARCH_PARENTS is true the imports of namespaces X
+ and Y will be considered. If SEARCH_PARENTS is false only the import of Y
+ is considered. */
struct symbol *
-cp_lookup_symbol_nonlocal (const char *name,
- const char *linkage_name,
- const struct block *block,
- const domain_enum domain)
+cp_lookup_symbol_imports (const char *scope,
+ const char *name,
+ const struct block *block,
+ const domain_enum domain,
+ const int declaration_only,
+ const int search_parents)
+{
+ struct using_direct *current;
+ struct symbol *sym = NULL;
+ int len;
+ int directive_match;
+ struct cleanup *searched_cleanup;
+
+ /* First, try to find the symbol in the given namespace. */
+ if (!declaration_only)
+ sym = cp_lookup_symbol_in_namespace (scope, name, block, domain);
+
+ if (sym != NULL)
+ return sym;
+
+ /* 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)
+ {
+ len = strlen (current->import_dest);
+ directive_match = (search_parents
+ ? (strncmp (scope, current->import_dest,
+ strlen (current->import_dest)) == 0
+ && (len == 0
+ || scope[len] == ':' || scope[len] == '\0'))
+ : strcmp (scope, current->import_dest) == 0);
+
+ /* If the import destination is the current scope or one of its ancestors then
+ it is applicable. */
+ if (directive_match && !current->searched)
+ {
+ /* Mark this import as searched so that the recursive call does not
+ search it again. */
+ current->searched = 1;
+ searched_cleanup = make_cleanup (reset_directive_searched, current);
+
+ /* If there is an import of a single declaration, compare the imported
+ declaration (after optional renaming by its alias) with the sought
+ out name. If there is a match pass current->import_src as NAMESPACE
+ to direct the search towards the imported namespace. */
+ if (current->declaration
+ && strcmp (name, current->alias ? current->alias
+ : current->declaration) == 0)
+ sym = cp_lookup_symbol_in_namespace (current->import_src,
+ current->declaration,
+ block,
+ domain);
+
+ /* If this is a DECLARATION_ONLY search or a symbol was found or
+ this import statement was an import declaration, the search
+ of this import is complete. */
+ if (declaration_only || sym != NULL || current->declaration)
+ {
+ current->searched = 0;
+ discard_cleanups (searched_cleanup);
+
+ if (sym != NULL)
+ return sym;
+
+ continue;
+ }
+
+ if (current->alias != NULL && strcmp (name, current->alias) == 0)
+ /* If the import is creating an alias and the alias matches the
+ sought name. Pass current->import_src as the NAME to direct the
+ search towards the aliased namespace. */
+ {
+ sym = cp_lookup_symbol_in_namespace (scope,
+ current->import_src,
+ block,
+ domain);
+ }
+ else if (current->alias == NULL)
+ {
+ /* If this import statement creates no alias, pass current->inner as
+ NAMESPACE to direct the search towards the imported namespace. */
+ sym = cp_lookup_symbol_imports (current->import_src,
+ name,
+ block,
+ domain,
+ 0,
+ 0);
+ }
+ current->searched = 0;
+ discard_cleanups (searched_cleanup);
+
+ if (sym != NULL)
+ return sym;
+ }
+ }
+
+ return NULL;
+}
+
+ /* Searches for NAME in the current namespace, and by applying relevant import
+ statements belonging to BLOCK and its parents. SCOPE is the namespace scope
+ of the context in which the search is being evaluated. */
+
+struct symbol*
+cp_lookup_symbol_namespace (const char *scope,
+ const char *name,
+ const struct block *block,
+ const domain_enum domain)
{
- return lookup_namespace_scope (name, linkage_name, block, domain,
- block_scope (block), 0);
+ struct symbol *sym;
+
+ /* First, try to find the symbol in the given namespace. */
+ sym = cp_lookup_symbol_in_namespace (scope, name, block, domain);
+ if (sym != NULL)
+ return sym;
+
+ /* Search for name in namespaces imported to this and parent blocks. */
+ while (block != NULL)
+ {
+ sym = cp_lookup_symbol_imports (scope, name, block, domain, 0, 1);
+
+ if (sym)
+ return sym;
+
+ block = BLOCK_SUPERBLOCK (block);
+ }
+
+ return NULL;
}
/* Lookup NAME at namespace scope (or, in C terms, in static and
static struct symbol *
lookup_namespace_scope (const char *name,
- const char *linkage_name,
const struct block *block,
const domain_enum domain,
const char *scope,
new_scope_len += 2;
}
new_scope_len += cp_find_first_component (scope + new_scope_len);
- sym = lookup_namespace_scope (name, linkage_name, block,
- domain, scope, new_scope_len);
+ sym = lookup_namespace_scope (name, block, domain, scope, new_scope_len);
if (sym != NULL)
return sym;
}
namespace = alloca (scope_len + 1);
strncpy (namespace, scope, scope_len);
namespace[scope_len] = '\0';
- return cp_lookup_symbol_namespace (namespace, name, linkage_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
- cp_lookup_symbol_nonlocal. */
-
-struct symbol *
-cp_lookup_symbol_namespace (const char *namespace,
- 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
- 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 (namespace, current->import_dest) == 0)
- {
- sym = cp_lookup_symbol_namespace (current->import_src,
- name,
- linkage_name,
- block,
- domain);
- 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 (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 cp_lookup_symbol_in_namespace (namespace, name, block, domain);
}
/* Look up NAME in BLOCK's static block and in global blocks. If
static struct symbol *
lookup_symbol_file (const char *name,
- const char *linkage_name,
const struct block *block,
const domain_enum domain,
int anonymous_namespace)
{
struct symbol *sym = NULL;
- sym = lookup_symbol_static (name, linkage_name, block, domain);
+ sym = lookup_symbol_static (name, block, domain);
if (sym != NULL)
return sym;
const struct block *global_block = block_global_block (block);
if (global_block != NULL)
- sym = lookup_symbol_aux_block (name, linkage_name, global_block,
- domain);
+ sym = lookup_symbol_aux_block (name, global_block, domain);
}
else
{
- sym = lookup_symbol_global (name, linkage_name, block, domain);
+ sym = lookup_symbol_global (name, block, domain);
}
if (sym != NULL)
{
case TYPE_CODE_STRUCT:
case TYPE_CODE_NAMESPACE:
+ case TYPE_CODE_UNION:
{
/* NOTE: carlton/2003-11-10: We don't treat C++ class members
of classes like, say, data or function members. Instead,
lookup_symbol_namespace works when looking them up. */
const char *parent_name = TYPE_TAG_NAME (parent_type);
- struct symbol *sym = cp_lookup_symbol_namespace (parent_name,
- nested_name,
- NULL,
- block,
- VAR_DOMAIN);
- if (sym == NULL || SYMBOL_CLASS (sym) != LOC_TYPEDEF)
- return NULL;
- else
+ struct symbol *sym = cp_lookup_symbol_in_namespace (parent_name,
+ nested_name,
+ block,
+ VAR_DOMAIN);
+ char *concatenated_name;
+
+ if (sym != NULL && SYMBOL_CLASS (sym) == LOC_TYPEDEF)
return SYMBOL_TYPE (sym);
+
+ /* 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 assumptions could make it too magic. */
+
+ concatenated_name = alloca (strlen (parent_name) + 2
+ + strlen (nested_name) + 1);
+ sprintf (concatenated_name, "%s::%s", parent_name, nested_name);
+ sym = lookup_static_symbol_aux (concatenated_name, VAR_DOMAIN);
+ if (sym != NULL && SYMBOL_CLASS (sym) == LOC_TYPEDEF)
+ return SYMBOL_TYPE (sym);
+
+ return NULL;
}
default:
internal_error (__FILE__, __LINE__,
{
struct type *retval
= cp_lookup_transparent_type_loop (name, scope, scope_length + 2);
+
if (retval != NULL)
return retval;
}
memcpy (name_copy, name, len);
name_copy[len] = '\0';
- sym = lookup_block_symbol (block, name_copy, NULL, VAR_DOMAIN);
+ sym = lookup_block_symbol (block, name_copy, VAR_DOMAIN);
if (sym == NULL)
{
struct symbol *sym;
sym = lookup_block_symbol (get_possible_namespace_block (objfile),
- name, NULL, VAR_DOMAIN);
+ name, VAR_DOMAIN);
if (sym != NULL)
return sym;
maintenance_cplus_namespace (char *args, int from_tty)
{
struct objfile *objfile;
+
printf_unfiltered (_("Possible namespaces:\n"));
ALL_OBJFILES (objfile)
{