/* Helper routines for C++ support in GDB.
- Copyright (C) 2003, 2004, 2007, 2008, 2009, 2010
+ Copyright (C) 2003, 2004, 2007, 2008, 2009, 2010, 2011
Free Software Foundation, Inc.
Contributed by David Carlton and by Kealia, Inc.
#include "command.h"
#include "frame.h"
#include "buildsym.h"
-
-static struct using_direct *cp_copy_usings (struct using_direct *using,
- struct obstack *obstack);
+#include "language.h"
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)",
ANONYMOUS_NAMESPACE_LEN) == 0)
{
- int dest_len = (previous_component == 0 ? 0 : previous_component - 2);
+ int dest_len = (previous_component == 0
+ ? 0 : previous_component - 2);
int src_len = next_component;
char *dest = alloca (dest_len + 1);
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;
+}
+
+/* Helper function that searches an array of symbols for one named
+ NAME. */
+
+static struct symbol *
+search_symbol_list (const char *name, int num,
+ struct symbol **syms)
{
- return lookup_namespace_scope (name, linkage_name, block, domain,
- block_scope (block), 0);
+ int i;
+
+ /* Maybe we should store a dictionary in here instead. */
+ for (i = 0; i < num; ++i)
+ {
+ if (strcmp (name, SYMBOL_NATURAL_NAME (syms[i])) == 0)
+ return syms[i];
+ }
+ return NULL;
+}
+
+/* Like cp_lookup_symbol_imports, but if BLOCK is a function, it
+ searches through the template parameters of the function and the
+ function's type. */
+
+struct symbol *
+cp_lookup_symbol_imports_or_template (const char *scope,
+ const char *name,
+ const struct block *block,
+ const domain_enum domain)
+{
+ struct symbol *function = BLOCK_FUNCTION (block);
+
+ 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))
+ {
+ struct template_symbol *templ
+ = (struct template_symbol *) function;
+ struct symbol *result;
+
+ result = search_symbol_list (name,
+ templ->n_template_arguments,
+ templ->template_arguments);
+ if (result != NULL)
+ return result;
+ }
+
+ /* Search the template parameters of the function's defining
+ context. */
+ if (SYMBOL_NATURAL_NAME (function))
+ {
+ struct type *context;
+ 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;
+ const struct block *parent = BLOCK_SUPERBLOCK (block);
+
+ while (1)
+ {
+ struct symbol *result;
+ unsigned int prefix_len = cp_entire_prefix_len (name_copy);
+
+ if (prefix_len == 0)
+ context = NULL;
+ else
+ {
+ name_copy[prefix_len] = '\0';
+ context = lookup_typename (lang, arch,
+ name_copy,
+ parent, 1);
+ }
+
+ if (context == NULL)
+ break;
+
+ result
+ = search_symbol_list (name,
+ TYPE_N_TEMPLATE_ARGUMENTS (context),
+ TYPE_TEMPLATE_ARGUMENTS (context));
+ if (result != NULL)
+ return result;
+ }
+
+ do_cleanups (cleanups);
+ }
+ }
+
+ return cp_lookup_symbol_imports (scope, name, block, domain, 1, 1);
+}
+
+ /* 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)
+{
+ 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__,
- _("cp_lookup_nested_type called on a non-aggregate type."));
+ _("cp_lookup_nested_type called "
+ "on a non-aggregate type."));
}
}
/* Lookup the the type definition associated to NAME in
namespaces/classes containing SCOPE whose name is strictly longer
- than LENGTH. LENGTH must be the index of the start of a
- component of SCOPE. */
+ than LENGTH. LENGTH must be the index of the start of a component
+ of SCOPE. */
static struct type *
-cp_lookup_transparent_type_loop (const char *name, const char *scope,
+cp_lookup_transparent_type_loop (const char *name,
+ const char *scope,
int length)
{
int scope_length = length + cp_find_first_component (scope + length);
if (scope[scope_length] == ':')
{
struct type *retval
- = cp_lookup_transparent_type_loop (name, scope, scope_length + 2);
+ = cp_lookup_transparent_type_loop (name, scope,
+ scope_length + 2);
+
if (retval != NULL)
return retval;
}
BLOCKVECTOR_NBLOCKS (bv) = FIRST_LOCAL_BLOCK + 1;
BLOCKVECTOR (namespace_symtab) = bv;
- /* Allocate empty GLOBAL_BLOCK and STATIC_BLOCK. */
+ /* Allocate empty GLOBAL_BLOCK and STATIC_BLOCK. */
bl = allocate_block (&objfile->objfile_obstack);
BLOCK_DICT (bl) = dict_create_linear (&objfile->objfile_obstack,
it shouldn't consist solely of namespaces. */
void
-cp_check_possible_namespace_symbols (const char *name, struct objfile *objfile)
+cp_check_possible_namespace_symbols (const char *name,
+ struct objfile *objfile)
{
check_possible_namespace_symbols_loop (name,
cp_find_first_component (name),
objfile);
if (!done)
- done = check_one_possible_namespace_symbol (name, len, objfile);
+ done = check_one_possible_namespace_symbol (name, len,
+ objfile);
return done;
}
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 type *type;
- type = init_type (TYPE_CODE_NAMESPACE, 0, 0, name_copy, objfile);
+ type = init_type (TYPE_CODE_NAMESPACE, 0, 0,
+ name_copy, objfile);
TYPE_TAG_NAME (type) = TYPE_NAME (type);
- sym = obstack_alloc (&objfile->objfile_obstack, sizeof (struct symbol));
+ sym = obstack_alloc (&objfile->objfile_obstack,
+ sizeof (struct symbol));
memset (sym, 0, sizeof (struct symbol));
- SYMBOL_LANGUAGE (sym) = language_cplus;
+ SYMBOL_SET_LANGUAGE (sym, language_cplus);
/* Note that init_type copied the name to the objfile's
obstack. */
SYMBOL_SET_NAMES (sym, TYPE_NAME (type), len, 0, objfile);
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)
{
struct dict_iterator iter;
struct symbol *sym;
- ALL_BLOCK_SYMBOLS (get_possible_namespace_block (objfile), iter, sym)
+ ALL_BLOCK_SYMBOLS (get_possible_namespace_block (objfile),
+ iter, sym)
{
printf_unfiltered ("%s\n", SYMBOL_PRINT_NAME (sym));
}
void
_initialize_cp_namespace (void)
{
- add_cmd ("namespace", class_maintenance, maintenance_cplus_namespace,
+ add_cmd ("namespace", class_maintenance,
+ maintenance_cplus_namespace,
_("Print the list of possible C++ namespaces."),
&maint_cplus_cmd_list);
}