* breakpoint.c (update_watchpoint, _initialize_breakpoint): Remove
[binutils-gdb.git] / gdb / cp-namespace.c
index d2d8f2eb88e011349f9d391c08667c70ac19c1aa..d0fdcbe44081e773a4370af98ce7b6d620a10685 100644 (file)
@@ -1,5 +1,6 @@
 /* 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);
@@ -85,7 +81,6 @@ cp_scan_for_anonymous_namespaces (const struct symbol *symbol)
       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)".  */
@@ -119,7 +114,8 @@ cp_scan_for_anonymous_namespaces (const struct symbol *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);
+             cp_add_using_directive (dest, src, NULL, NULL,
+                                     &SYMBOL_SYMTAB (symbol)->objfile->objfile_obstack);
            }
          /* The "+ 2" is for the "::".  */
          previous_component = next_component + 2;
@@ -130,26 +126,55 @@ cp_scan_for_anonymous_namespaces (const struct symbol *symbol)
     }
 }
 
-/* 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
@@ -200,73 +225,222 @@ cp_is_anonymous (const char *namespace)
          != 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
@@ -286,7 +460,6 @@ cp_lookup_symbol_nonlocal (const char *name,
 
 static struct symbol *
 lookup_namespace_scope (const char *name,
-                       const char *linkage_name,
                        const struct block *block,
                        const domain_enum domain,
                        const char *scope,
@@ -308,8 +481,7 @@ lookup_namespace_scope (const char *name,
          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;
     }
@@ -320,65 +492,7 @@ lookup_namespace_scope (const char *name,
   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
@@ -388,14 +502,13 @@ cp_lookup_symbol_namespace (const char *namespace,
 
 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;
 
@@ -408,12 +521,11 @@ lookup_symbol_file (const char *name,
       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)
@@ -452,6 +564,7 @@ cp_lookup_nested_type (struct type *parent_type,
     {
     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,
@@ -461,15 +574,28 @@ cp_lookup_nested_type (struct type *parent_type,
           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__,
@@ -533,6 +659,7 @@ cp_lookup_transparent_type_loop (const char *name, const char *scope,
     {
       struct type *retval
        = cp_lookup_transparent_type_loop (name, scope, scope_length + 2);
+
       if (retval != NULL)
        return retval;
     }
@@ -709,12 +836,11 @@ check_one_possible_namespace_symbol (const char *name, int len,
 
   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;
-      name_copy = obsavestring (name, len, &objfile->objfile_obstack);
 
       type = init_type (TYPE_CODE_NAMESPACE, 0, 0, name_copy, objfile);
 
@@ -723,7 +849,9 @@ check_one_possible_namespace_symbol (const char *name, int len,
       sym = obstack_alloc (&objfile->objfile_obstack, sizeof (struct symbol));
       memset (sym, 0, sizeof (struct symbol));
       SYMBOL_LANGUAGE (sym) = language_cplus;
-      SYMBOL_SET_NAMES (sym, name_copy, len, objfile);
+      /* Note that init_type copied the name to the objfile's
+        obstack.  */
+      SYMBOL_SET_NAMES (sym, TYPE_NAME (type), len, 0, objfile);
       SYMBOL_CLASS (sym) = LOC_TYPEDEF;
       SYMBOL_TYPE (sym) = type;
       SYMBOL_DOMAIN (sym) = VAR_DOMAIN;
@@ -749,7 +877,7 @@ lookup_possible_namespace_symbol (const char *name)
       struct symbol *sym;
 
       sym = lookup_block_symbol (get_possible_namespace_block (objfile),
-                                name, NULL, VAR_DOMAIN);
+                                name, VAR_DOMAIN);
 
       if (sym != NULL)
        return sym;
@@ -764,6 +892,7 @@ static void
 maintenance_cplus_namespace (char *args, int from_tty)
 {
   struct objfile *objfile;
+
   printf_unfiltered (_("Possible namespaces:\n"));
   ALL_OBJFILES (objfile)
     {