2004-01-14 David Carlton <carlton@kealia.com>
authorDavid Carlton <carlton@bactrian.org>
Wed, 14 Jan 2004 16:54:43 +0000 (16:54 +0000)
committerDavid Carlton <carlton@bactrian.org>
Wed, 14 Jan 2004 16:54:43 +0000 (16:54 +0000)
Change symbols for C++ nested types to contain the fully qualified
name, if possible.  (At least in the DWARF-2 case.)  Partial fix
for PR's c++/57, c++/488, c++/539, c++/573, c++/609, c++/832,
c++/895.
* c-exp.y: Update copyright:
(qualified_type): Handle types nested within classes.
* cp-namespace.c: Update comments.
(cp_set_block_scope): Delete #if 0.
(cp_lookup_nested_type): Handle types nested within classes.
* dwarf2read.c: (scan_partial_symbols): Call add_partial_structure
when appropriate.
(add_partial_symbol): Add the name of the enclosing namespace to
types.
(pdi_needs_namespace): New.
(add_partial_namespace): Tweak comment.
(add_partial_structure): New.
(psymtab_to_symtab_1): Initialize processing_current_prefix
here...
(process_die): instead of here.
(read_structure_scope): Try to figure out the name of the class or
namespace that the structure might be defined within.
(read_enumeration): Generate fully-qualified names, if possible.
(read_namespace): Don't set name to NULL.
(die_specification): New.
(new_symbol): Generate fully-qualified names for types.
(read_type_die): Determine appropriate prefix.
(determine_prefix): New.
(typename_concat): New.
(class_name): New.
* valops.c: Update copyright.
(value_aggregate_elt): Pass NOSIDE to
value_struct_elt_for_reference.
(value_struct_elt_for_reference): Make static, add NOSIDE
parameter, call value_maybe_namespace_elt as a last resort.
(value_namespace_elt): Break out code into
value_maybe_namespace_elt.
(value_maybe_namespace_elt): New.

2004-01-14  David Carlton  <carlton@kealia.com>

* gdb.cp/namespace.exp: Add tests involving classes defined within
namespaces.
* gdb.cp/namespace.cc (C::CClass): New.
* gdb.cp/namespace1.cc: Update copyright.
(C::OtherFileClass): New.

gdb/ChangeLog
gdb/c-exp.y
gdb/cp-namespace.c
gdb/dwarf2read.c
gdb/testsuite/ChangeLog
gdb/testsuite/gdb.cp/namespace.cc
gdb/testsuite/gdb.cp/namespace.exp
gdb/testsuite/gdb.cp/namespace1.cc
gdb/valops.c

index b9364b276d9f26d1921e781a6cb886aa9538f22a..d6e088dc85b66ce3290b335936844d5bae057b47 100644 (file)
@@ -1,3 +1,41 @@
+2004-01-14  David Carlton  <carlton@kealia.com>
+
+       Change symbols for C++ nested types to contain the fully qualified
+       name, if possible.  (At least in the DWARF-2 case.)  Partial fix
+       for PR's c++/57, c++/488, c++/539, c++/573, c++/609, c++/832,
+       c++/895.
+       * c-exp.y (qualified_type): Handle types nested within classes.
+       * cp-namespace.c: Update comments.
+       (cp_set_block_scope): Delete #if 0.
+       (cp_lookup_nested_type): Handle types nested within classes.
+       * dwarf2read.c: (scan_partial_symbols): Call add_partial_structure
+       when appropriate.
+       (add_partial_symbol): Add the name of the enclosing namespace to
+       types.
+       (pdi_needs_namespace): New.
+       (add_partial_namespace): Tweak comment.
+       (add_partial_structure): New.
+       (psymtab_to_symtab_1): Initialize processing_current_prefix
+       here...
+       (process_die): instead of here.
+       (read_structure_scope): Try to figure out the name of the class or
+       namespace that the structure might be defined within.
+       (read_enumeration): Generate fully-qualified names, if possible.
+       (read_namespace): Don't set name to NULL.
+       (die_specification): New.
+       (new_symbol): Generate fully-qualified names for types.
+       (read_type_die): Determine appropriate prefix.
+       (determine_prefix): New.
+       (typename_concat): New.
+       (class_name): New.
+       * valops.c (value_aggregate_elt): Pass NOSIDE to
+       value_struct_elt_for_reference.
+       (value_struct_elt_for_reference): Make static, add NOSIDE
+       parameter, call value_maybe_namespace_elt as a last resort.
+       (value_namespace_elt): Break out code into
+       value_maybe_namespace_elt.
+       (value_maybe_namespace_elt): New.
+
 2004-01-12  Andrew Cagney  <cagney@redhat.com>
 
        * mips-tdep.c (mips_convert_register_p): Handle both raw and
index 1f3e68381035054f88c4c75ef4d5a124d6029556..f11b93e3a2b434e2a0043ff097438d85aa3728e3 100644 (file)
@@ -1,6 +1,6 @@
 /* YACC parser for C expressions, for GDB.
    Copyright 1986, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997,
-   1998, 1999, 2000, 2003
+   1998, 1999, 2000, 2003, 2004
    Free Software Foundation, Inc.
 
 This file is part of GDB.
@@ -939,11 +939,6 @@ typebase  /* Implements (approximately): (type-qualifier)* type-specifier */
    decode_line_1), but I'm not holding my breath waiting for somebody
    to get around to cleaning this up...  */
 
-/* FIXME: carlton/2003-09-25: Currently, the only qualified type
-   symbols that we generate are nested namespaces.  Next on my TODO
-   list is to generate all nested type names properly (or at least as
-   well as possible, assuming that we're using DWARF-2).  */
-
 qualified_type: typebase COLONCOLON name
                {
                  struct type *type = $1;
@@ -953,14 +948,16 @@ qualified_type: typebase COLONCOLON name
                  memcpy (ncopy, $3.ptr, $3.length);
                  ncopy[$3.length] = '\0';
 
-                 if (TYPE_CODE (type) != TYPE_CODE_NAMESPACE)
-                   error ("`%s' is not defined as a namespace.",
+                 if (TYPE_CODE (type) != TYPE_CODE_STRUCT
+                     && TYPE_CODE (type) != TYPE_CODE_UNION
+                     && TYPE_CODE (type) != TYPE_CODE_NAMESPACE)
+                   error ("`%s' is not defined as an aggregate type.",
                           TYPE_NAME (type));
 
                  new_type = cp_lookup_nested_type (type, ncopy,
                                                    expression_context_block);
                  if (new_type == NULL)
-                   error ("No type \"%s\" in namespace \"%s\".",
+                   error ("No type \"%s\" within class or namespace \"%s\".",
                           ncopy, TYPE_NAME (type));
                  
                  $$ = new_type;
index a766acb470a970f1f1b59f987dd31a0efdb4b60f..fed440ebc5001271efb7f2ec6e550005dd053824 100644 (file)
 #include "dictionary.h"
 #include "command.h"
 
-/* When set, the file that we're processing seems to have debugging
-   info for C++ namespaces, so cp-namespace.c shouldn't try to guess
-   namespace info itself.  */
+/* When set, the file that we're processing is known to have debugging
+   info for C++ namespaces.  */
+
+/* NOTE: carlton/2004-01-13: No currently released version of GCC (the
+   latest of which is 3.3.x at the time of this writing) produces this
+   debug info.  GCC 3.4 should, however.  */
 
 unsigned char processing_has_namespace_info;
 
@@ -222,12 +225,6 @@ cp_set_block_scope (const struct symbol *symbol,
 
   if (SYMBOL_CPLUS_DEMANGLED_NAME (symbol) != NULL)
     {
-#if 0
-      /* FIXME: carlton/2003-06-12: As mentioned above,
-        'processing_has_namespace_info' currently isn't entirely
-        reliable, so let's always use demangled names to get this
-        information for now.  */
-
       if (processing_has_namespace_info)
        {
          block_set_scope
@@ -237,7 +234,6 @@ cp_set_block_scope (const struct symbol *symbol,
             obstack);
        }
       else
-#endif
        {
          /* Try to figure out the appropriate namespace from the
             demangled name.  */
@@ -520,10 +516,6 @@ lookup_symbol_file (const char *name,
    class or namespace given by PARENT_TYPE, from within the context
    given by BLOCK.  Return NULL if there is no such nested type.  */
 
-/* FIXME: carlton/2003-09-24: For now, this only works for nested
-   namespaces; the patch to make this work on other sorts of nested
-   types is next on my TODO list.  */
-
 struct type *
 cp_lookup_nested_type (struct type *parent_type,
                       const char *nested_name,
@@ -531,8 +523,16 @@ cp_lookup_nested_type (struct type *parent_type,
 {
   switch (TYPE_CODE (parent_type))
     {
+    case TYPE_CODE_STRUCT:
     case TYPE_CODE_NAMESPACE:
       {
+       /* NOTE: carlton/2003-11-10: We don't treat C++ class members
+          of classes like, say, data or function members.  Instead,
+          they're just represented by symbols whose names are
+          qualified by the name of the surrounding class.  This is
+          just like members of namespaces; in particular,
+          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,
@@ -547,7 +547,7 @@ cp_lookup_nested_type (struct type *parent_type,
       }
     default:
       internal_error (__FILE__, __LINE__,
-                     "cp_lookup_nested_type called on a non-namespace.");
+                     "cp_lookup_nested_type called on a non-aggregate type.");
     }
 }
 
index 765ac7d845dc4bd4891905543a3371933c5d32aa..b2c34a5d9abf4ebcec57440b43379cdd7897c44c 100644 (file)
@@ -666,12 +666,19 @@ static char *scan_partial_symbols (char *, CORE_ADDR *, CORE_ADDR *,
 static void add_partial_symbol (struct partial_die_info *, struct dwarf2_cu *,
                                const char *namespace);
 
+static int pdi_needs_namespace (enum dwarf_tag tag, const char *namespace);
+
 static char *add_partial_namespace (struct partial_die_info *pdi,
                                    char *info_ptr,
                                    CORE_ADDR *lowpc, CORE_ADDR *highpc,
                                    struct dwarf2_cu *cu,
                                    const char *namespace);
 
+static char *add_partial_structure (struct partial_die_info *struct_pdi,
+                                   char *info_ptr,
+                                   struct dwarf2_cu *cu,
+                                   const char *namespace);
+
 static char *add_partial_enumeration (struct partial_die_info *enum_pdi,
                                      char *info_ptr,
                                      struct dwarf2_cu *cu,
@@ -743,6 +750,8 @@ static struct attribute *dwarf_attr (struct die_info *, unsigned int);
 
 static int die_is_declaration (struct die_info *);
 
+static struct die_info *die_specification (struct die_info *die);
+
 static void free_line_header (struct line_header *lh);
 
 static struct line_header *(dwarf_decode_line_header
@@ -777,6 +786,12 @@ static struct type *tag_type_to_type (struct die_info *, struct dwarf2_cu *);
 
 static void read_type_die (struct die_info *, struct dwarf2_cu *);
 
+static char *determine_prefix (struct die_info *die);
+
+static char *typename_concat (const char *prefix, const char *suffix);
+
+static char *class_name (struct die_info *die);
+
 static void read_typedef (struct die_info *, struct dwarf2_cu *);
 
 static void read_base_type (struct die_info *, struct dwarf2_cu *);
@@ -1368,11 +1383,18 @@ scan_partial_symbols (char *info_ptr, CORE_ADDR *lowpc,
            case DW_TAG_variable:
            case DW_TAG_typedef:
            case DW_TAG_union_type:
+             if (!pdi.is_declaration)
+               {
+                 add_partial_symbol (&pdi, cu, namespace);
+               }
+             break;
            case DW_TAG_class_type:
            case DW_TAG_structure_type:
              if (!pdi.is_declaration)
                {
-                 add_partial_symbol (&pdi, cu, namespace);
+                 info_ptr = add_partial_structure (&pdi, info_ptr, cu,
+                                                   namespace);
+                 info_ptr_updated = 1;
                }
              break;
            case DW_TAG_enumeration_type:
@@ -1430,6 +1452,17 @@ add_partial_symbol (struct partial_die_info *pdi,
   char *actual_name = pdi->name;
   const struct partial_symbol *psym = NULL;
 
+  /* If we're not in the global namespace and if the namespace name
+     isn't encoded in a mangled actual_name, add it.  */
+  
+  if (pdi_needs_namespace (pdi->tag, namespace))
+    {
+      actual_name = alloca (strlen (pdi->name) + 2 + strlen (namespace) + 1);
+      strcpy (actual_name, namespace);
+      strcat (actual_name, "::");
+      strcat (actual_name, pdi->name);
+    }
+
   switch (pdi->tag)
     {
     case DW_TAG_subprogram:
@@ -1507,11 +1540,15 @@ add_partial_symbol (struct partial_die_info *pdi,
     case DW_TAG_enumeration_type:
       /* Skip aggregate types without children, these are external
          references.  */
+      /* NOTE: carlton/2003-10-07: See comment in new_symbol about
+        static vs. global.  */
       if (pdi->has_children == 0)
        return;
       add_psymbol_to_list (actual_name, strlen (actual_name),
                           STRUCT_DOMAIN, LOC_TYPEDEF,
-                          &objfile->static_psymbols,
+                          cu_language == language_cplus
+                          ? &objfile->global_psymbols
+                          : &objfile->static_psymbols,
                           0, (CORE_ADDR) 0, cu_language, objfile);
 
       if (cu_language == language_cplus)
@@ -1519,14 +1556,16 @@ add_partial_symbol (struct partial_die_info *pdi,
          /* For C++, these implicitly act as typedefs as well. */
          add_psymbol_to_list (actual_name, strlen (actual_name),
                               VAR_DOMAIN, LOC_TYPEDEF,
-                              &objfile->static_psymbols,
+                              &objfile->global_psymbols,
                               0, (CORE_ADDR) 0, cu_language, objfile);
        }
       break;
     case DW_TAG_enumerator:
       add_psymbol_to_list (actual_name, strlen (actual_name),
                           VAR_DOMAIN, LOC_CONST,
-                          &objfile->static_psymbols,
+                          cu_language == language_cplus
+                          ? &objfile->static_psymbols
+                          : &objfile->global_psymbols,
                           0, (CORE_ADDR) 0, cu_language, objfile);
       break;
     default:
@@ -1547,6 +1586,30 @@ add_partial_symbol (struct partial_die_info *pdi,
                                         objfile);
 }
 
+/* Determine whether a die of type TAG living in the C++ namespace
+   NAMESPACE needs to have the name of the namespace prepended to the
+   name listed in the die.  */
+
+static int
+pdi_needs_namespace (enum dwarf_tag tag, const char *namespace)
+{
+  if (namespace == NULL || namespace[0] == '\0')
+    return 0;
+
+  switch (tag)
+    {
+    case DW_TAG_typedef:
+    case DW_TAG_class_type:
+    case DW_TAG_structure_type:
+    case DW_TAG_union_type:
+    case DW_TAG_enumeration_type:
+    case DW_TAG_enumerator:
+      return 1;
+    default:
+      return 0;
+    }
+}
+
 /* Read a partial die corresponding to a namespace; also, add a symbol
    corresponding to that namespace to the symbol table.  NAMESPACE is
    the name of the enclosing namespace.  */
@@ -1570,9 +1633,10 @@ add_partial_namespace (struct partial_die_info *pdi, char *info_ptr,
     strcat (full_name, "::");
   strcat (full_name, new_name);
 
-  /* FIXME: carlton/2003-06-27: Once we build qualified names for more
-     symbols than just namespaces, we should replace this by a call to
-     add_partial_symbol.  */
+  /* FIXME: carlton/2003-10-07: We can't just replace this by a call
+     to add_partial_symbol, because we don't have a way to pass in the
+     full name to that function; that might be a flaw in
+     add_partial_symbol's interface.  */
 
   add_psymbol_to_list (full_name, strlen (full_name),
                       VAR_DOMAIN, LOC_TYPEDEF,
@@ -1587,6 +1651,63 @@ add_partial_namespace (struct partial_die_info *pdi, char *info_ptr,
   return info_ptr;
 }
 
+/* Read a partial die corresponding to a class or structure.  */
+
+static char *
+add_partial_structure (struct partial_die_info *struct_pdi, char *info_ptr,
+                      struct dwarf2_cu *cu,
+                      const char *namespace)
+{
+  bfd *abfd = cu->objfile->obfd;
+  char *actual_class_name = NULL;
+
+  if (cu_language == language_cplus
+      && namespace == NULL
+      && struct_pdi->name != NULL
+      && struct_pdi->has_children)
+    {
+      /* We don't have namespace debugging information, so see if we
+        can figure out if this structure lives in a namespace.  Look
+        for a member function; its demangled name will contain
+        namespace info, if there is any.  */
+
+      /* NOTE: carlton/2003-10-07: Getting the info this way changes
+        what template types look like, because the demangler
+        frequently doesn't give the same name as the debug info.  We
+        could fix this by only using the demangled name to get the
+        prefix (but see comment in read_structure_scope).  */
+
+      char *next_child = info_ptr;
+
+      while (1)
+       {
+         struct partial_die_info child_pdi;
+
+         next_child = read_partial_die (&child_pdi, abfd, next_child,
+                                        cu);
+         if (!child_pdi.tag)
+           break;
+         if (child_pdi.tag == DW_TAG_subprogram)
+           {
+             actual_class_name = class_name_from_physname (child_pdi.name);
+             if (actual_class_name != NULL)
+               struct_pdi->name = actual_class_name;
+             break;
+           }
+         else
+           {
+             next_child = locate_pdi_sibling (&child_pdi, next_child,
+                                              abfd, cu);
+           }
+       }
+    }
+
+  add_partial_symbol (struct_pdi, cu, namespace);
+  xfree(actual_class_name);
+
+  return locate_pdi_sibling (struct_pdi, info_ptr, abfd, cu);
+}
+
 /* Read a partial die corresponding to an enumeration type.  */
 
 static char *
@@ -1711,6 +1832,9 @@ psymtab_to_symtab_1 (struct partial_symtab *pst)
   cu_header_offset = offset;
   info_ptr = dwarf_info_buffer + offset;
 
+  /* We're in the global namespace.  */
+  processing_current_prefix = "";
+
   obstack_init (&dwarf2_tmp_obstack);
   back_to = make_cleanup (dwarf2_free_tmp_obstack, NULL);
 
@@ -1864,11 +1988,7 @@ process_die (struct die_info *die, struct dwarf2_cu *cu)
     case DW_TAG_common_inclusion:
       break;
     case DW_TAG_namespace:
-      if (!processing_has_namespace_info)
-       {
-         processing_has_namespace_info = 1;
-         processing_current_prefix = "";
-       }
+      processing_has_namespace_info = 1;
       read_namespace (die, cu);
       break;
     case DW_TAG_imported_declaration:
@@ -1879,11 +1999,7 @@ process_die (struct die_info *die, struct dwarf2_cu *cu)
         shouldn't in the C++ case, but conceivably could in the
         Fortran case, so we'll have to replace this gdb_assert if
         Fortran compilers start generating that info.  */
-      if (!processing_has_namespace_info)
-       {
-         processing_has_namespace_info = 1;
-         processing_current_prefix = "";
-       }
+      processing_has_namespace_info = 1;
       gdb_assert (die->child == NULL);
       break;
     default:
@@ -2777,6 +2893,13 @@ read_structure_scope (struct die_info *die, struct dwarf2_cu *cu)
   struct objfile *objfile = cu->objfile;
   struct type *type;
   struct attribute *attr;
+  const char *name = NULL;
+  const char *previous_prefix = processing_current_prefix;
+  struct cleanup *back_to = NULL;
+  /* This says whether or not we want to try to update the structure's
+     name to include enclosing namespace/class information, if
+     any.  */
+  int need_to_update_name = 0;
 
   type = alloc_type (objfile);
 
@@ -2784,9 +2907,41 @@ read_structure_scope (struct die_info *die, struct dwarf2_cu *cu)
   attr = dwarf_attr (die, DW_AT_name);
   if (attr && DW_STRING (attr))
     {
-      TYPE_TAG_NAME (type) = obsavestring (DW_STRING (attr),
-                                          strlen (DW_STRING (attr)),
-                                          &objfile->type_obstack);
+      name = DW_STRING (attr);
+
+      if (cu_language == language_cplus)
+       {
+         struct die_info *spec_die = die_specification (die);
+
+         if (spec_die != NULL)
+           {
+             char *specification_prefix = determine_prefix (spec_die);
+             processing_current_prefix = specification_prefix;
+             back_to = make_cleanup (xfree, specification_prefix);
+           }
+       }
+
+      if (processing_has_namespace_info)
+       {
+         /* FIXME: carlton/2003-11-10: This variable exists only for
+            const-correctness reasons.  When I tried to change
+            TYPE_TAG_NAME to be a const char *, I ran into a cascade
+            of changes which would have forced decode_line_1 to take
+            a const char **.  */
+         char *new_prefix = obconcat (&objfile->type_obstack,
+                                      processing_current_prefix,
+                                      processing_current_prefix[0] == '\0'
+                                      ? "" : "::",
+                                      name);
+         TYPE_TAG_NAME (type) = new_prefix;
+         processing_current_prefix = new_prefix;
+       }
+      else
+       {
+         TYPE_TAG_NAME (type) = obsavestring (name, strlen (name),
+                                              &objfile->type_obstack);
+         need_to_update_name = (cu_language == language_cplus);
+       }
     }
 
   if (die->tag == DW_TAG_structure_type)
@@ -2846,6 +3001,41 @@ read_structure_scope (struct die_info *die, struct dwarf2_cu *cu)
              /* C++ member function. */
              process_die (child_die, cu);
              dwarf2_add_member_fn (&fi, child_die, type, cu);
+             if (need_to_update_name)
+               {
+                 /* The demangled names of member functions contain
+                    information about enclosing namespaces/classes,
+                    if any.  */
+
+                 /* FIXME: carlton/2003-11-10: The excessive
+                    demangling here is a bit wasteful, as is the
+                    memory usage for names.  */
+
+                 /* NOTE: carlton/2003-11-10: As commented in
+                    add_partial_structure, the demangler sometimes
+                    prints the type info in a different form from the
+                    debug info.  We could solve this by using the
+                    demangled name to get the prefix; if doing so,
+                    however, we'd need to be careful when reading a
+                    class that's nested inside a template class.
+                    That would also cause problems when trying to
+                    determine RTTI information, since we use the
+                    demangler to determine the appropriate class
+                    name.  */
+                 char *actual_class_name
+                   = class_name_from_physname (dwarf2_linkage_name
+                                               (child_die));
+                 if (actual_class_name != NULL
+                     && strcmp (actual_class_name, name) != 0)
+                   {
+                     TYPE_TAG_NAME (type)
+                       = obsavestring (actual_class_name,
+                                       strlen (actual_class_name),
+                                       &objfile->type_obstack);
+                   }
+                 xfree (actual_class_name);
+                 need_to_update_name = 0;
+               }
            }
          else if (child_die->tag == DW_TAG_inheritance)
            {
@@ -2921,6 +3111,10 @@ read_structure_scope (struct die_info *die, struct dwarf2_cu *cu)
       /* No children, must be stub. */
       TYPE_FLAGS (type) |= TYPE_FLAG_STUB;
     }
+
+  processing_current_prefix = previous_prefix;
+  if (back_to != NULL)
+    do_cleanups (back_to);
 }
 
 /* Given a pointer to a die which begins an enumeration, process all
@@ -2950,9 +3144,21 @@ read_enumeration (struct die_info *die, struct dwarf2_cu *cu)
   attr = dwarf_attr (die, DW_AT_name);
   if (attr && DW_STRING (attr))
     {
-      TYPE_TAG_NAME (type) = obsavestring (DW_STRING (attr),
-                                          strlen (DW_STRING (attr)),
-                                          &objfile->type_obstack);
+      const char *name = DW_STRING (attr);
+
+      if (processing_has_namespace_info)
+       {
+         TYPE_TAG_NAME (type) = obconcat (&objfile->type_obstack,
+                                          processing_current_prefix,
+                                          processing_current_prefix[0] == '\0'
+                                          ? "" : "::",
+                                          name);
+       }
+      else
+       {
+         TYPE_TAG_NAME (type) = obsavestring (name, strlen (name),
+                                              &objfile->type_obstack);
+       }
     }
 
   attr = dwarf_attr (die, DW_AT_byte_size);
@@ -3223,7 +3429,7 @@ read_namespace (struct die_info *die, struct dwarf2_cu *cu)
 {
   struct objfile *objfile = cu->objfile;
   const char *previous_prefix = processing_current_prefix;
-  const char *name = NULL;
+  const char *name;
   int is_anonymous;
   struct die_info *current_die;
 
@@ -4679,6 +4885,19 @@ die_is_declaration (struct die_info *die)
          && ! dwarf_attr (die, DW_AT_specification));
 }
 
+/* Return the die giving the specification for DIE, if there is
+   one.  */
+
+static struct die_info *
+die_specification (struct die_info *die)
+{
+  struct attribute *spec_attr = dwarf_attr (die, DW_AT_specification);
+
+  if (spec_attr == NULL)
+    return NULL;
+  else
+    return follow_die_ref (dwarf2_get_ref_die_offset (spec_attr));
+}
 
 /* Free the line_header structure *LH, and any arrays and strings it
    refers to.  */
@@ -5322,39 +5541,108 @@ new_symbol (struct die_info *die, struct type *type, struct dwarf2_cu *cu)
        case DW_TAG_enumeration_type:
          SYMBOL_CLASS (sym) = LOC_TYPEDEF;
          SYMBOL_DOMAIN (sym) = STRUCT_DOMAIN;
-         add_symbol_to_list (sym, list_in_scope);
 
-         /* The semantics of C++ state that "struct foo { ... }" also
-            defines a typedef for "foo". Synthesize a typedef symbol so
-            that "ptype foo" works as expected.  */
+         /* Make sure that the symbol includes appropriate enclosing
+            classes/namespaces in its name.  These are calculated in
+            read_structure_scope, and the correct name is saved in
+            the type.  */
+
          if (cu_language == language_cplus)
            {
-             struct symbol *typedef_sym = (struct symbol *)
-             obstack_alloc (&objfile->symbol_obstack,
-                            sizeof (struct symbol));
-             *typedef_sym = *sym;
-             SYMBOL_DOMAIN (typedef_sym) = VAR_DOMAIN;
-             if (TYPE_NAME (SYMBOL_TYPE (sym)) == 0)
-               TYPE_NAME (SYMBOL_TYPE (sym)) =
-                 obsavestring (DEPRECATED_SYMBOL_NAME (sym),
-                               strlen (DEPRECATED_SYMBOL_NAME (sym)),
-                               &objfile->type_obstack);
-             add_symbol_to_list (typedef_sym, list_in_scope);
+             struct type *type = SYMBOL_TYPE (sym);
+             
+             if (TYPE_TAG_NAME (type) != NULL)
+               {
+                 /* FIXME: carlton/2003-11-10: Should this use
+                    SYMBOL_SET_NAMES instead?  (The same problem also
+                    arises a further down in the function.)  */
+                 SYMBOL_LINKAGE_NAME (sym)
+                   = obsavestring (TYPE_TAG_NAME (type),
+                                   strlen (TYPE_TAG_NAME (type)),
+                                   &objfile->symbol_obstack);
+               }
            }
+
+         {
+           /* NOTE: carlton/2003-11-10: C++ class symbols shouldn't
+              really ever be static objects: otherwise, if you try
+              to, say, break of a class's method and you're in a file
+              which doesn't mention that class, it won't work unless
+              the check for all static symbols in lookup_symbol_aux
+              saves you.  See the OtherFileClass tests in
+              gdb.c++/namespace.exp.  */
+
+           struct pending **list_to_add;
+
+           list_to_add = (list_in_scope == &file_symbols
+                          && cu_language == language_cplus
+                          ? &global_symbols : list_in_scope);
+         
+           add_symbol_to_list (sym, list_to_add);
+
+           /* The semantics of C++ state that "struct foo { ... }" also
+              defines a typedef for "foo". Synthesize a typedef symbol so
+              that "ptype foo" works as expected.  */
+           if (cu_language == language_cplus)
+             {
+               struct symbol *typedef_sym = (struct symbol *)
+                 obstack_alloc (&objfile->symbol_obstack,
+                                sizeof (struct symbol));
+               *typedef_sym = *sym;
+               SYMBOL_DOMAIN (typedef_sym) = VAR_DOMAIN;
+               if (TYPE_NAME (SYMBOL_TYPE (sym)) == 0)
+                 TYPE_NAME (SYMBOL_TYPE (sym)) =
+                   obsavestring (SYMBOL_NATURAL_NAME (sym),
+                                 strlen (SYMBOL_NATURAL_NAME (sym)),
+                                 &objfile->type_obstack);
+               add_symbol_to_list (typedef_sym, list_to_add);
+             }
+         }
          break;
        case DW_TAG_typedef:
+         if (processing_has_namespace_info
+             && processing_current_prefix[0] != '\0')
+           {
+             SYMBOL_LINKAGE_NAME (sym) = obconcat (&objfile->symbol_obstack,
+                                                   processing_current_prefix,
+                                                   "::",
+                                                   name);
+           }
+         SYMBOL_CLASS (sym) = LOC_TYPEDEF;
+         SYMBOL_DOMAIN (sym) = VAR_DOMAIN;
+         add_symbol_to_list (sym, list_in_scope);
+         break;
        case DW_TAG_base_type:
          SYMBOL_CLASS (sym) = LOC_TYPEDEF;
          SYMBOL_DOMAIN (sym) = VAR_DOMAIN;
          add_symbol_to_list (sym, list_in_scope);
          break;
        case DW_TAG_enumerator:
+         if (processing_has_namespace_info
+             && processing_current_prefix[0] != '\0')
+           {
+             SYMBOL_LINKAGE_NAME (sym) = obconcat (&objfile->symbol_obstack,
+                                                   processing_current_prefix,
+                                                   "::",
+                                                   name);
+           }
          attr = dwarf_attr (die, DW_AT_const_value);
          if (attr)
            {
              dwarf2_const_value (attr, sym, cu);
            }
-         add_symbol_to_list (sym, list_in_scope);
+         {
+           /* NOTE: carlton/2003-11-10: See comment above in the
+              DW_TAG_class_type, etc. block.  */
+
+           struct pending **list_to_add;
+
+           list_to_add = (list_in_scope == &file_symbols
+                          && cu_language == language_cplus
+                          ? &global_symbols : list_in_scope);
+         
+           add_symbol_to_list (sym, list_to_add);
+         }
          break;
        case DW_TAG_namespace:
          SYMBOL_CLASS (sym) = LOC_TYPEDEF;
@@ -5588,6 +5876,11 @@ tag_type_to_type (struct die_info *die, struct dwarf2_cu *cu)
 static void
 read_type_die (struct die_info *die, struct dwarf2_cu *cu)
 {
+  char *prefix = determine_prefix (die);
+  const char *old_prefix = processing_current_prefix;
+  struct cleanup *back_to = make_cleanup (xfree, prefix);
+  processing_current_prefix = prefix;
+  
   switch (die->tag)
     {
     case DW_TAG_class_type:
@@ -5634,6 +5927,114 @@ read_type_die (struct die_info *die, struct dwarf2_cu *cu)
                 dwarf_tag_name (die->tag));
       break;
     }
+
+  processing_current_prefix = old_prefix;
+  do_cleanups (back_to);
+}
+
+/* Return the name of the namespace/class that DIE is defined
+   within, or NULL if we can't tell.  The caller should xfree the
+   result.  */
+
+static char *
+determine_prefix (struct die_info *die)
+{
+  struct die_info *parent;
+
+  if (cu_language != language_cplus)
+    return NULL;
+
+  parent = die->parent;
+
+  if (parent == NULL)
+    {
+      return (processing_has_namespace_info ? xstrdup ("") : NULL);
+    }
+  else
+    {
+      char *parent_prefix = determine_prefix (parent);
+      char *retval;
+
+      switch (parent->tag) {
+      case DW_TAG_namespace:
+       {
+         int dummy;
+
+         retval = typename_concat (parent_prefix,
+                                   namespace_name (parent, &dummy));
+       }
+       break;
+      case DW_TAG_class_type:
+      case DW_TAG_structure_type:
+       {
+         if (parent_prefix != NULL)
+           {
+             const char *parent_name = dwarf2_name (parent);
+
+             if (parent_name != NULL)
+               retval = typename_concat (parent_prefix, dwarf2_name (parent));
+             else
+               /* FIXME: carlton/2003-11-10: I'm not sure what the
+                  best thing to do here is.  */
+               retval = typename_concat (parent_prefix,
+                                         "<<anonymous class>>");
+           }
+         else
+           retval = class_name (parent);
+       }
+       break;
+      default:
+       retval = parent_prefix;
+       break;
+      }
+
+      if (retval != parent_prefix)
+       xfree (parent_prefix);
+      return retval;
+    }
+}
+
+/* Return a newly-allocated string formed by concatenating PREFIX,
+   "::", and SUFFIX, except that if PREFIX is NULL or the empty
+   string, just return a copy of SUFFIX.  */
+
+static char *
+typename_concat (const char *prefix, const char *suffix)
+{
+  if (prefix == NULL || prefix[0] == '\0')
+    return xstrdup (suffix);
+  else
+    {
+      char *retval = xmalloc (strlen (prefix) + 2 + strlen (suffix) + 1);
+
+      strcpy (retval, prefix);
+      strcat (retval, "::");
+      strcat (retval, suffix);
+
+      return retval;
+    }
+}
+
+/* Return a newly-allocated string giving the name of the class given
+   by DIE.  */
+
+static char *
+class_name (struct die_info *die)
+{
+  struct die_info *child;
+  const char *name;
+
+  for (child = die->child; child != NULL; child = sibling_die (child))
+    {
+      if (child->tag == DW_TAG_subprogram)
+       return class_name_from_physname (dwarf2_linkage_name (child));
+    }
+
+  name = dwarf2_name (die);
+  if (name != NULL)
+    return xstrdup (name);
+  else
+    return xstrdup ("");
 }
 
 static struct type *
index 22af38b1f97b26b3db287b148d55d9028b06605f..59737777b7845d0efe542a73d912592a62ada9df 100644 (file)
@@ -1,3 +1,10 @@
+2004-01-14  David Carlton  <carlton@kealia.com>
+
+       * gdb.cp/namespace.exp: Add tests involving classes defined within
+       namespaces.
+       * gdb.cp/namespace.cc (C::CClass): New.
+       * gdb.cp/namespace1.cc (C::OtherFileClass): New.
+
 2004-01-14  Elena Zannoni  <ezannoni@redhat.com>
 
        * gdb.base/sepdebug.exp: Bail out of the test if we don't know
index a0814ee707c66360523fe55acfbeb2d4d7d9bdbb..6a6837392061626ed2da4b7d4cfec7533e10fb50 100644 (file)
@@ -88,6 +88,15 @@ namespace C
   int c = 1;
   int shadow = 12;
 
+  class CClass {
+  public:
+    int x;
+    class NestedClass {
+    public:
+      int y;
+    };
+  };
+
   namespace
   {
     int cX = 6;
index fda393e5869e45a05cffb4a5b7b09d3980750974..eb03a3edbd75337498181fa544322164960cc33e 100644 (file)
@@ -26,7 +26,7 @@
 # Note: The original tests were geared to the HP aCC compiler,
 # which has an idiosyncratic way of emitting debug info
 # for namespaces.
-# Note: As of 2000-06-03, these pass under g++ - djb
+# Note: As of 2000-06-03, they passed under g++ - djb
 
 
 if $tracelevel then {
@@ -83,7 +83,7 @@ if ![runto 'marker1'] then {
 gdb_test "up" ".*main.*" "up from marker1"
 
 # Access a data item inside a namespace using colons and
-# single quotes :-(
+# single quotes. :-(
 
 # NOTE: carlton/2003-09-24: the quotes are becoming less necessary (or
 # even desirable.)  For tests where it should still work with quotes,
@@ -215,6 +215,15 @@ gdb_expect {
    timeout { fail "(timeout) print 'BBB::Class::xyzq'" }
 }
 
+send_gdb "print BBB::Class::xyzq\n"
+gdb_expect {
+   -re "\\$\[0-9\]* = \{char \\((BBB::|)Class \\*( const|), (char|int)\\)\} $hex <BBB::Class::xyzq\\(char\\)>\r\n$gdb_prompt $" {
+       pass "print BBB::Class::xyzq"
+   }
+   -re ".*$gdb_prompt $" { fail "print BBB::Class::xyzq" }
+   timeout { fail "(timeout) print BBB::Class::xyzq" }
+}
+
 # Break on a function in a class in a namespace
 
 send_gdb "break BBB::Class::xyzq\n"
@@ -240,15 +249,35 @@ gdb_test "print cc" "No symbol \"cc\" in current context."
 gdb_test "print 'C::cc'" "\\$\[0-9\].* = 2"
 gdb_test "print C::cc" "\\$\[0-9\].* = 2"
 gdb_test "print cd" "\\$\[0-9\].* = 3"
-gdb_test "print C::D::cd" "No type \"D\" in namespace \"C::C\"."
+gdb_test "print C::D::cd" "No type \"D\" within class or namespace \"C::C\"."
 gdb_test "print 'E::cde'" "\\$\[0-9\].* = 5"
 gdb_test "print E::cde" "\\$\[0-9\].* = 5"
 gdb_test "print shadow" "\\$\[0-9\].* = 13"
 gdb_test "print E::ce" "No symbol \"ce\" in namespace \"C::D::E\"."
-gdb_test "print cOtherFile" "\\$\[0-9\].* = 316"
 gdb_test "ptype C" "type = namespace C::C"
 gdb_test "ptype E" "type = namespace C::D::E"
 
+gdb_test "ptype CClass" "type = class C::CClass \{\r\n  public:\r\n    int x;\r\n\}"
+gdb_test "ptype CClass::NestedClass" "type = class C::CClass::NestedClass \{\r\n  public:\r\n    int y;\r\n\}"
+gdb_test "ptype NestedClass" "No symbol \"NestedClass\" in current context."
+setup_kfail "gdb/1448" "*-*-*"
+gdb_test "ptype ::C::CClass" "type = class C::CClass \{\r\n  public:\r\n    int x;\r\n\}"
+setup_kfail "gdb/1448" "*-*-*"
+gdb_test "ptype ::C::CClass::NestedClass" "type = class C::CClass::NestedClass \{\r\n  public:\r\n    int y;\r\n\}"
+setup_kfail "gdb/1448" "*-*-*"
+gdb_test "ptype ::C::NestedClass" "No symbol \"NestedClass\" in namespace \"C\"."
+gdb_test "ptype C::CClass" "No symbol \"CClass\" in namespace \"C::C\"."
+gdb_test "ptype C::CClass::NestedClass" "No type \"CClass\" within class or namespace \"C::C\"."
+gdb_test "ptype C::NestedClass" "No symbol \"NestedClass\" in namespace \"C::C\"."
+
+# Tests involving multiple files
+
+gdb_test "print cOtherFile" "\\$\[0-9\].* = 316"
+gdb_test "ptype OtherFileClass" "type = class C::OtherFileClass \{\r\n  public:\r\n    int z;\r\n\}"
+setup_kfail "gdb/1448" "*-*-*"
+gdb_test "ptype ::C::OtherFileClass" "type = class C::OtherFileClass \{\r\n  public:\r\n    int z;\r\n\}"
+gdb_test "ptype C::OtherFileClass" "No symbol \"OtherFileClass\" in namespace \"C::C\"."
+
 # Some anonymous namespace tests.
 
 gdb_test "print cX" "\\$\[0-9\].* = 6"
index 4a5900a8b3deaef568c43cc60ee13bfbf7b0d048..5d668106511181383669aeae4e9222c8dc4b64ea 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright 2003 Free Software Foundation, Inc.
+/* Copyright 2003, 2004 Free Software Foundation, Inc.
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
 
 namespace C
 {
+  class OtherFileClass {
+  public:
+    int z;
+  };
+
   namespace {
     int cXOtherFile = 29;
   };
index 5f302ca57ffd21ca9b89f4783e6be636b44d8ad8..14fefd90174279be4605feebb39b59e4eb392ede 100644 (file)
@@ -1,6 +1,6 @@
 /* Perform non-arithmetic operations on values, for GDB.
    Copyright 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994,
-   1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
+   1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004
    Free Software Foundation, Inc.
 
    This file is part of GDB.
@@ -64,17 +64,21 @@ static struct value *search_struct_method (char *, struct value **,
 
 static int check_field_in (struct type *, const char *);
 
-
 static struct value *value_struct_elt_for_reference (struct type *domain,
                                                     int offset,
                                                     struct type *curtype,
                                                     char *name,
-                                                    struct type *intype);
+                                                    struct type *intype,
+                                                    enum noside noside);
 
 static struct value *value_namespace_elt (const struct type *curtype,
-                                         const char *name,
+                                         char *name,
                                          enum noside noside);
 
+static struct value *value_maybe_namespace_elt (const struct type *curtype,
+                                               char *name,
+                                               enum noside noside);
+
 static CORE_ADDR allocate_space_in_inferior (int);
 
 static struct value *cast_into_complex (struct type *, struct value *);
@@ -2234,7 +2238,8 @@ value_aggregate_elt (struct type *curtype,
     {
     case TYPE_CODE_STRUCT:
     case TYPE_CODE_UNION:
-      return value_struct_elt_for_reference (curtype, 0, curtype, name, NULL);
+      return value_struct_elt_for_reference (curtype, 0, curtype, name, NULL,
+                                            noside);
     case TYPE_CODE_NAMESPACE:
       return value_namespace_elt (curtype, name, noside);
     default:
@@ -2250,10 +2255,11 @@ value_aggregate_elt (struct type *curtype,
    "pointers to member functions".  This function is used
    to resolve user expressions of the form "DOMAIN::NAME".  */
 
-struct value *
+static struct value *
 value_struct_elt_for_reference (struct type *domain, int offset,
                                struct type *curtype, char *name,
-                               struct type *intype)
+                               struct type *intype,
+                               enum noside noside)
 {
   struct type *t = curtype;
   int i;
@@ -2376,11 +2382,17 @@ value_struct_elt_for_reference (struct type *domain, int offset,
                                          offset + base_offset,
                                          TYPE_BASECLASS (t, i),
                                          name,
-                                         intype);
+                                         intype,
+                                         noside);
       if (v)
        return v;
     }
-  return 0;
+
+  /* As a last chance, pretend that CURTYPE is a namespace, and look
+     it up that way; this (frequently) works for types nested inside
+     classes.  */
+
+  return value_maybe_namespace_elt (curtype, name, noside);
 }
 
 /* C++: Return the member NAME of the namespace given by the type
@@ -2388,33 +2400,46 @@ value_struct_elt_for_reference (struct type *domain, int offset,
 
 static struct value *
 value_namespace_elt (const struct type *curtype,
-                    const char *name,
+                    char *name,
                     enum noside noside)
+{
+  struct value *retval = value_maybe_namespace_elt (curtype, name,
+                                                   noside);
+
+  if (retval == NULL)
+    error ("No symbol \"%s\" in namespace \"%s\".", name,
+          TYPE_TAG_NAME (curtype));
+
+  return retval;
+}
+
+/* A helper function used by value_namespace_elt and
+   value_struct_elt_for_reference.  It looks up NAME inside the
+   context CURTYPE; this works if CURTYPE is a namespace or if CURTYPE
+   is a class and NAME refers to a type in CURTYPE itself (as opposed
+   to, say, some base class of CURTYPE).  */
+
+static struct value *
+value_maybe_namespace_elt (const struct type *curtype,
+                          char *name,
+                          enum noside noside)
 {
   const char *namespace_name = TYPE_TAG_NAME (curtype);
   struct symbol *sym;
-  struct value *retval;
 
   sym = cp_lookup_symbol_namespace (namespace_name, name, NULL,
                                    get_selected_block (0), VAR_DOMAIN,
                                    NULL);
 
   if (sym == NULL)
-    retval = NULL;
+    return NULL;
   else if ((noside == EVAL_AVOID_SIDE_EFFECTS)
           && (SYMBOL_CLASS (sym) == LOC_TYPEDEF))
-    retval = allocate_value (SYMBOL_TYPE (sym));
+    return allocate_value (SYMBOL_TYPE (sym));
   else
-    retval = value_of_variable (sym, get_selected_block (0));
-
-  if (retval == NULL)
-    error ("No symbol \"%s\" in namespace \"%s\".", name,
-          TYPE_TAG_NAME (curtype));
-
-  return retval;
+    return value_of_variable (sym, get_selected_block (0));
 }
 
-
 /* Given a pointer value V, find the real (RTTI) type
    of the object it points to.
    Other parameters FULL, TOP, USING_ENC as with value_rtti_type()