This is the mail archive of the gdb-patches@sources.redhat.com mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[rfa] generate fully-qualified names for types


This patch tells GDB to generated fully-qualified names for types that
are nested within other types or within namespaces.  It only does this
in the DWARF-2 case; I leave the other debug formats (stabs, in
particular) up to somebody else.

As with all of this namespace work, I try to support both the case
where GCC generates DW_TAG_namespace and where GCC doesn't generate
it.  (The latter being, unfortunately, the case for all released
versions of GCC, and the last I heard it wasn't going to be fixed for
GCC 3.4 either.)  If, when compiling a given compilation unit, GDB
ever sees a DW_TAG_namespace, it uses the hierarchical structure of
DWARF combined with DW_AT_name to generate the name attributes.  If
GDB hasn't seen such a tag then, when it sees a class that isn't
nested within another class, GDB looks for a member function with a
mangled name and demangles that name to figure out if the class is
defined within a namespace.

This will make a big difference; the main effect will be that GDB will
stop constantly printing out RTTI warnings.

There are, however, some issues, even some regressions.  Some of these
I have fixed on my branch, and will submit subsequent patches to deal
with them.  (This patch, however, is big enough as is that I really
didn't want to include those fixes right here.)  Some of them I know
how to fix but haven't.  Some of them seem to be unavoidable
side-effects of the fact that GCC isn't generating good enough debug
info.  And there are doubltess some lurking gotchas that I'm not aware
of.

The issues that come to mind are:

* I haven't modified all of the symbol reading functions to properly
  use this information.  I'll need to modify linespec, the overload
  handling functions, and lookup_transparent_type.  I've done this on
  the branch; I'll move that over next.

* lookup_transparent_type poses particular problems.  That function
  deals with the situation where a class has an abstract declaration
  but not a full definition.  Unfortunately, in this situation we
  don't have any member functions around to demangle, which means that
  we generate symbols with the wrong name.  (If GCC doesn't generate
  DW_TAG_namespace, that is.)  Oops.  I have a hack on my branch that
  increases the number of cases where we get the right symbol back,
  but it really is a hack.  I'm not sure that there's anything we can
  do about this without more help from GCC.  (Hmm: why do we generate
  symbols associated to those declarations in the first place?  Maybe
  that's worth thinking about.)  You'll notice that gdb.cp/rtti.exp
  has one KFAIL=>PASS transition and one KFAIL=>FAIL transition
  (unless you use a hacked GCC); the latter is a manifestation of this
  issue.

* The dependency on the demangler is unfortunate, and it leads to
  regressions in gdb.cp/templates.exp.  There are various ways that
  the demangler could be used.  If I'm in a situation like this:

  namespace N {
    class C {
      void foo();
    };
  }

  then we need to use the demangler to deduce the existence of N at
  all.  Basically, we look at the mangled name for N::C::foo(),
  demangle it, and notice that it starts with 'N::C'.

  But there are two ways of using this information: I could grab all
  of 'N::C' from the demangler, or I could grab just 'N::' from the
  demangler, and grab 'C' from DW_AT_name.  It doesn't make a
  difference in this simple example, but if C is a templated class, it
  can make a difference.

  I chose to do the former.  The reason for this is that the demangler
  also gets used in another situation: when trying to figure out the
  RTTI information, we look at this symbol associated to the vtable,
  take its demangled name, and look at the part of it that should give
  the name of the class in question.  If that name doesn't match the
  name of the relevant symbol, we get this annoying RTTI warning.  So
  I thought it was better to use the demangler in both places.

  But it would be better still if it didn't matter; I'm planning to
  patch the demangler, though I haven't yet done that on my branch.
  The failures in templates.exp stem from these differences:

  1) The demangler introduces whitespace.  This seems perfectly
     acceptable (and will be handled just fine by our symbol lookup
     code); here, we should fix templates.exp to accept it.

  2) The demangler uses 'char const *' instead of 'const char *'.  In
     an ideal world, our symbol lookup code would handle this
     difference (PR gdb/931); that ideal world is currently nothing
     more than a hallucination, so for the time being we have to pick
     the one or the other.  The compiler uses const char *, and most
     programmers do as well, so we should see if we can fix the
     demangler to use it too.

  3) In some situations, the demangler is introducing unnecessary
     parentheses; as with case #2, we should see if we can fix the
     demangler to not do that.  (But this really is very much a corner
     case.)

* DW_AT_specification leads to some charming issues: what that does is
  allows DIEs to refer to other DIEs anywhere in the hierarchy.  This
  is a major headache if, when looking at a DIE, you need information
  that's only stored in its parents.  I've dealt with this in the
  symbol case, though I'm sure I missed some spots; I've completely
  ignored this in the partial symbol case.  Basically, as far as I can
  tell, there's simply no way to deal with this in the partial symbol
  case without jumping through hoops (or making the partial symbol
  reader look an awful lot like the full symbol reader).  The real
  solution is to get GCC to generate .debug_pubtypes; until that
  happens, I'm optimistic that this isn't not going to be _too_ much
  of a problem in practice.  (In concrete terms, I got bug reports
  here at Kealia when I hadn't realized that this issue existed at
  all; those bug reports went away when I implemented a fix for full
  symbols.)

* This doesn't deal with the interactions between nested types and
  inheritance.  Given a situation like this:

  class C {
    class N;
  };

  class D : public C {
  };

  then D::N should be the same as C::N, but GDB has no idea what
  you're talking about if you refer to D::N.  (I think this is the
  issue behind PR gdb/1417.)  I haven't even begun to think about what
  to do with that; this patch doesn't make the situation any worse,
  however.

I think that's about it.  I've tested this on i686-pc-linux-gnu, with
GCC 3.2.3.  The results:

* With DWARF-2, all the new tests pass except for the four KFAILed
  ones.  One test in rtti.exp goes KFAIL=>PASS; another one goes
  KFAIL=>FAIL.  (See the second bullet point above.)  12 tests in
  templates.exp go (PASS,KFAIL)=>FAIL.  (See the third bullet point
  above.)

* With a GCC version that produces DW_TAG_namespace, all the new tests
  pass except for the four KFAILed ones.  Both the rtti tests go
  KFAIL=>PASS.  Those 12 template.exp tests FAIL.

* With stabs, all the new tests {,K}FAIL; no other changes.  A month
  or two ago, Michael Chastain noticed that a patch of mine introduced
  two regressions with GCC 3.3, stabs; my hope is that this patch will
  fix one of those regressions, but I haven't checked to see.

As I've explained above, I think that these regressions are
acceptable.

This needs both symtab and C++ approval, of course.

David Carlton
carlton@kealia.com

2003-11-12  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: Rename processing_current_namespace to
	processing_current_prefix.  Add comments.
	(cp_set_block_scope): Delete #if 0.
	(cp_lookup_nested_type): Handle types nested within classes.
	* cp-support.h: Rename processing_current_namespace to
	processing_current_prefix.
	* dwarf2read.c: Replace uses of processing_current_namespace by
	processing_current_prefix.
	(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): Pull out name-generating code into
	namespace_name.
	(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.

2003-11-12  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.

Index: c-exp.y
===================================================================
RCS file: /cvs/src/src/gdb/c-exp.y,v
retrieving revision 1.24
diff -u -p -r1.24 c-exp.y
--- c-exp.y	6 Nov 2003 22:54:00 -0000	1.24
+++ c-exp.y	12 Nov 2003 17:45:42 -0000
@@ -939,11 +939,6 @@ typebase  /* Implements (approximately):
    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: cp-namespace.c
===================================================================
RCS file: /cvs/src/src/gdb/cp-namespace.c,v
retrieving revision 1.5
diff -u -p -r1.5 cp-namespace.c
--- cp-namespace.c	25 Sep 2003 16:39:38 -0000	1.5
+++ cp-namespace.c	12 Nov 2003 17:45:42 -0000
@@ -32,20 +32,31 @@
 #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/2003-11-10: No currently released version of GCC (the
+   latest of which is 3.3.x at the time of this writing) produces this
+   debug info.  */
 
 unsigned char processing_has_namespace_info;
 
-/* If processing_has_namespace_info is nonzero, this string should
-   contain the name of the current namespace.  The string is
-   temporary; copy it if you need it.  */
+/* This contains our best guess as to the name of the current
+   enclosing namespace(s)/class(es), if any.  For example, if we're
+   within the method foo() in the following code:
+
+    namespace N {
+      class C {
+	void foo () {
+	}
+      };
+    }
 
-/* FIXME: carlton/2003-06-12: This isn't entirely reliable: currently,
-   we get mislead by DW_AT_specification.  */
+    then processing_current_prefix should be set to "N::C".  If
+    processing_has_namespace_info is false, then this variable might
+    not be reliable.  */
 
-const char *processing_current_namespace;
+const char *processing_current_prefix;
 
 /* List of using directives that are active in the current file.  */
 
@@ -214,22 +225,15 @@ cp_set_block_scope (const struct 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
-	    (block, obsavestring (processing_current_namespace,
-				  strlen (processing_current_namespace),
+	    (block, obsavestring (processing_current_prefix,
+				  strlen (processing_current_prefix),
 				  obstack),
 	     obstack);
 	}
       else
-#endif
 	{
 	  /* Try to figure out the appropriate namespace from the
 	     demangled name.  */
@@ -512,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,
@@ -523,8 +523,16 @@ cp_lookup_nested_type (struct type *pare
 {
   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,
@@ -539,7 +547,7 @@ cp_lookup_nested_type (struct type *pare
       }
     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: cp-support.h
===================================================================
RCS file: /cvs/src/src/gdb/cp-support.h,v
retrieving revision 1.9
diff -u -p -r1.9 cp-support.h
--- cp-support.h	25 Sep 2003 16:39:38 -0000	1.9
+++ cp-support.h	12 Nov 2003 17:45:42 -0000
@@ -65,7 +65,7 @@ extern struct symbol **make_symbol_overl
 
 extern unsigned char processing_has_namespace_info;
 
-extern const char *processing_current_namespace;
+extern const char *processing_current_prefix;
 
 extern int cp_is_anonymous (const char *namespace);
 
Index: dwarf2read.c
===================================================================
RCS file: /cvs/src/src/gdb/dwarf2read.c,v
retrieving revision 1.112
diff -u -p -r1.112 dwarf2read.c
--- dwarf2read.c	12 Nov 2003 17:10:55 -0000	1.112
+++ dwarf2read.c	12 Nov 2003 17:45:43 -0000
@@ -699,12 +699,19 @@ static char *scan_partial_symbols (char 
 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,
@@ -777,6 +784,8 @@ static struct attribute *dwarf_attr (str
 
 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
@@ -811,6 +820,12 @@ static struct type *tag_type_to_type (st
 
 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 *);
@@ -843,6 +858,9 @@ static void read_common_block (struct di
 
 static void read_namespace (struct die_info *die, struct dwarf2_cu *);
 
+static const char *namespace_name (struct die_info *die,
+				   int *is_anonymous);
+
 static void read_enumeration (struct die_info *, struct dwarf2_cu *);
 
 static struct type *dwarf_base_type (int, int, struct dwarf2_cu *);
@@ -1441,11 +1459,18 @@ scan_partial_symbols (char *info_ptr, CO
 	    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:
@@ -1500,16 +1525,28 @@ add_partial_symbol (struct partial_die_i
 {
   struct objfile *objfile = cu->objfile;
   CORE_ADDR addr = 0;
+  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:
       if (pdi->is_external)
 	{
-	  /*prim_record_minimal_symbol (pdi->name, pdi->lowpc + baseaddr,
+	  /*prim_record_minimal_symbol (actual_name, pdi->lowpc + baseaddr,
 	     mst_text, objfile); */
-	  psym = add_psymbol_to_list (pdi->name, strlen (pdi->name),
+	  psym = add_psymbol_to_list (actual_name, strlen (actual_name),
 				      VAR_DOMAIN, LOC_BLOCK,
 				      &objfile->global_psymbols,
 				      0, pdi->lowpc + baseaddr,
@@ -1517,9 +1554,9 @@ add_partial_symbol (struct partial_die_i
 	}
       else
 	{
-	  /*prim_record_minimal_symbol (pdi->name, pdi->lowpc + baseaddr,
+	  /*prim_record_minimal_symbol (actual_name, pdi->lowpc + baseaddr,
 	     mst_file_text, objfile); */
-	  psym = add_psymbol_to_list (pdi->name, strlen (pdi->name),
+	  psym = add_psymbol_to_list (actual_name, strlen (actual_name),
 				      VAR_DOMAIN, LOC_BLOCK,
 				      &objfile->static_psymbols,
 				      0, pdi->lowpc + baseaddr,
@@ -1545,7 +1582,7 @@ add_partial_symbol (struct partial_die_i
 	  if (pdi->locdesc)
 	    addr = decode_locdesc (pdi->locdesc, cu);
 	  if (pdi->locdesc || pdi->has_type)
-	    psym = add_psymbol_to_list (pdi->name, strlen (pdi->name),
+	    psym = add_psymbol_to_list (actual_name, strlen (actual_name),
 					VAR_DOMAIN, LOC_STATIC,
 					&objfile->global_psymbols,
 					0, addr + baseaddr,
@@ -1557,9 +1594,9 @@ add_partial_symbol (struct partial_die_i
 	  if (pdi->locdesc == NULL)
 	    return;
 	  addr = decode_locdesc (pdi->locdesc, cu);
-	  /*prim_record_minimal_symbol (pdi->name, addr + baseaddr,
+	  /*prim_record_minimal_symbol (actual_name, addr + baseaddr,
 	     mst_file_data, objfile); */
-	  psym = add_psymbol_to_list (pdi->name, strlen (pdi->name),
+	  psym = add_psymbol_to_list (actual_name, strlen (actual_name),
 				      VAR_DOMAIN, LOC_STATIC,
 				      &objfile->static_psymbols,
 				      0, addr + baseaddr,
@@ -1568,7 +1605,7 @@ add_partial_symbol (struct partial_die_i
       break;
     case DW_TAG_typedef:
     case DW_TAG_base_type:
-      add_psymbol_to_list (pdi->name, strlen (pdi->name),
+      add_psymbol_to_list (actual_name, strlen (actual_name),
 			   VAR_DOMAIN, LOC_TYPEDEF,
 			   &objfile->static_psymbols,
 			   0, (CORE_ADDR) 0, cu_language, objfile);
@@ -1579,26 +1616,32 @@ add_partial_symbol (struct partial_die_i
     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 (pdi->name, strlen (pdi->name),
+      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)
 	{
 	  /* For C++, these implicitly act as typedefs as well. */
-	  add_psymbol_to_list (pdi->name, strlen (pdi->name),
+	  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 (pdi->name, strlen (pdi->name),
+      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:
@@ -1619,6 +1662,30 @@ add_partial_symbol (struct partial_die_i
 					 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.  */
@@ -1642,9 +1709,10 @@ add_partial_namespace (struct partial_di
     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,
@@ -1659,6 +1727,63 @@ add_partial_namespace (struct partial_di
   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 *
@@ -1783,6 +1908,9 @@ psymtab_to_symtab_1 (struct partial_symt
   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);
 
@@ -1936,11 +2064,7 @@ process_die (struct die_info *die, struc
     case DW_TAG_common_inclusion:
       break;
     case DW_TAG_namespace:
-      if (!processing_has_namespace_info)
-	{
-	  processing_has_namespace_info = 1;
-	  processing_current_namespace = "";
-	}
+      processing_has_namespace_info = 1;
       read_namespace (die, cu);
       break;
     case DW_TAG_imported_declaration:
@@ -1951,11 +2075,7 @@ process_die (struct die_info *die, struc
 	 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_namespace = "";
-	}
+      processing_has_namespace_info = 1;
       gdb_assert (die->child == NULL);
       break;
     default:
@@ -2887,6 +3007,13 @@ read_structure_scope (struct die_info *d
   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);
 
@@ -2894,9 +3021,41 @@ read_structure_scope (struct die_info *d
   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)
@@ -2956,6 +3115,41 @@ read_structure_scope (struct die_info *d
 	      /* 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)
 	    {
@@ -3029,6 +3223,10 @@ read_structure_scope (struct die_info *d
       /* 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
@@ -3058,9 +3256,21 @@ read_enumeration (struct die_info *die, 
   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);
@@ -3340,45 +3550,30 @@ static void
 read_namespace (struct die_info *die, struct dwarf2_cu *cu)
 {
   struct objfile *objfile = cu->objfile;
-  const char *previous_namespace = processing_current_namespace;
-  const char *name = NULL;
+  const char *previous_prefix = processing_current_prefix;
+  const char *name;
   int is_anonymous;
   struct die_info *current_die;
 
-  /* Loop through the extensions until we find a name.  */
-
-  for (current_die = die;
-       current_die != NULL;
-       current_die = dwarf2_extension (die))
-    {
-      name = dwarf2_name (current_die);
-      if (name != NULL)
-	break;
-    }
-
-  /* Is it an anonymous namespace?  */
-
-  is_anonymous = (name == NULL);
-  if (is_anonymous)
-    name = "(anonymous namespace)";
+  name = namespace_name (die, &is_anonymous);
 
   /* Now build the name of the current namespace.  */
 
-  if (previous_namespace[0] == '\0')
+  if (previous_prefix[0] == '\0')
     {
-      processing_current_namespace = name;
+      processing_current_prefix = name;
     }
   else
     {
-      /* We need temp_name around because processing_current_namespace
+      /* We need temp_name around because processing_current_prefix
 	 is a const char *.  */
-      char *temp_name = alloca (strlen (previous_namespace)
+      char *temp_name = alloca (strlen (previous_prefix)
 				+ 2 + strlen(name) + 1);
-      strcpy (temp_name, previous_namespace);
+      strcpy (temp_name, previous_prefix);
       strcat (temp_name, "::");
       strcat (temp_name, name);
 
-      processing_current_namespace = temp_name;
+      processing_current_prefix = temp_name;
     }
 
   /* Add a symbol associated to this if we haven't seen the namespace
@@ -3392,16 +3587,16 @@ read_namespace (struct die_info *die, st
       /* FIXME: carlton/2003-06-27: Once GDB is more const-correct,
 	 this cast will hopefully become unnecessary.  */
       type = init_type (TYPE_CODE_NAMESPACE, 0, 0,
-			(char *) processing_current_namespace,
+			(char *) processing_current_prefix,
 			objfile);
       TYPE_TAG_NAME (type) = TYPE_NAME (type);
 
       new_symbol (die, type, cu);
 
       if (is_anonymous)
-	cp_add_using_directive (processing_current_namespace,
-				strlen (previous_namespace),
-				strlen (processing_current_namespace));
+	cp_add_using_directive (processing_current_prefix,
+				strlen (previous_prefix),
+				strlen (processing_current_prefix));
     }
 
   if (die->child != NULL)
@@ -3415,7 +3610,37 @@ read_namespace (struct die_info *die, st
 	}
     }
 
-  processing_current_namespace = previous_namespace;
+  processing_current_prefix = previous_prefix;
+}
+
+/* Return the name of the namespace represented by DIE.  Set
+   *IS_ANONYMOUS to tell whether or not the namespace is an anonymous
+   namespace.  */
+
+static const char *
+namespace_name (struct die_info *die, int *is_anonymous)
+{
+  struct die_info *current_die;
+  const char *name = NULL;
+
+  /* Loop through the extensions until we find a name.  */
+
+  for (current_die = die;
+       current_die != NULL;
+       current_die = dwarf2_extension (die))
+    {
+      name = dwarf2_name (current_die);
+      if (name != NULL)
+	break;
+    }
+
+  /* Is it an anonymous namespace?  */
+
+  *is_anonymous = (name == NULL);
+  if (*is_anonymous)
+    name = "(anonymous namespace)";
+
+  return name;
 }
 
 /* Extract all information from a DW_TAG_pointer_type DIE and add to
@@ -4784,6 +5009,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.  */
@@ -5427,39 +5665,108 @@ new_symbol (struct die_info *die, struct
 	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;
@@ -5693,6 +6000,11 @@ tag_type_to_type (struct die_info *die, 
 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:
@@ -5739,6 +6051,114 @@ read_type_die (struct die_info *die, str
 		 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: valops.c
===================================================================
RCS file: /cvs/src/src/gdb/valops.c,v
retrieving revision 1.119
diff -u -p -r1.119 valops.c
--- valops.c	8 Nov 2003 00:13:03 -0000	1.119
+++ valops.c	12 Nov 2003 17:45:44 -0000
@@ -64,17 +64,21 @@ static struct value *search_struct_metho
 
 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 *curtyp
     {
     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 *curtyp
    "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 t
 					  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,32 +2400,45 @@ value_struct_elt_for_reference (struct t
 
 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.
Index: testsuite/gdb.cp/namespace.cc
===================================================================
RCS file: /cvs/src/src/gdb/testsuite/gdb.cp/namespace.cc,v
retrieving revision 1.2
diff -u -p -r1.2 namespace.cc
--- testsuite/gdb.cp/namespace.cc	25 Sep 2003 16:39:39 -0000	1.2
+++ testsuite/gdb.cp/namespace.cc	12 Nov 2003 17:45:47 -0000
@@ -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: testsuite/gdb.cp/namespace.exp
===================================================================
RCS file: /cvs/src/src/gdb/testsuite/gdb.cp/namespace.exp,v
retrieving revision 1.3
diff -u -p -r1.3 namespace.exp
--- testsuite/gdb.cp/namespace.exp	25 Sep 2003 16:39:39 -0000	1.3
+++ testsuite/gdb.cp/namespace.exp	12 Nov 2003 17:45:47 -0000
@@ -25,7 +25,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 {
@@ -82,7 +82,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,
@@ -211,6 +211,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"
@@ -236,14 +245,34 @@ gdb_test "print cc" "No symbol \"cc\" in
 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.
 
Index: testsuite/gdb.cp/namespace1.cc
===================================================================
RCS file: /cvs/src/src/gdb/testsuite/gdb.cp/namespace1.cc,v
retrieving revision 1.1
diff -u -p -r1.1 namespace1.cc
--- testsuite/gdb.cp/namespace1.cc	23 Aug 2003 03:55:59 -0000	1.1
+++ testsuite/gdb.cp/namespace1.cc	12 Nov 2003 17:45:47 -0000
@@ -19,6 +19,11 @@
 
 namespace C
 {
+  class OtherFileClass {
+  public:
+    int z;
+  };
+
   namespace {
     int cXOtherFile = 29;
   };


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]