* [rfa] generate fully-qualified names for types
@ 2003-11-12 18:53 David Carlton
2003-11-17 16:52 ` Daniel Jacobowitz
0 siblings, 1 reply; 6+ messages in thread
From: David Carlton @ 2003-11-12 18:53 UTC (permalink / raw)
To: gdb-patches; +Cc: Daniel Jacobowitz, Elena Zannoni, Jim Blandy
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;
};
^ permalink raw reply [flat|nested] 6+ messages in thread* Re: [rfa] generate fully-qualified names for types
2003-11-12 18:53 [rfa] generate fully-qualified names for types David Carlton
@ 2003-11-17 16:52 ` Daniel Jacobowitz
2003-11-18 17:51 ` David Carlton
0 siblings, 1 reply; 6+ messages in thread
From: Daniel Jacobowitz @ 2003-11-17 16:52 UTC (permalink / raw)
To: David Carlton; +Cc: gdb-patches, Elena Zannoni, Jim Blandy
On Wed, Nov 12, 2003 at 10:53:01AM -0800, David Carlton wrote:
> 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.
I can do stabs. It was remarkably easy the last time I tried.
However, to get any kind of usable result requires fixing GCC's stabs
emission to include a little more information and I ran into a
roadblock, so I put it down until I felt more ... whatever it is that I
need to feel to work on using stabs for C++. It can wait.
> 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
We need them. You can have this, and often do in GDB:
struct Foo;
extern void foofoo(struct Foo *);
We have to have a type associated with struct Foo in order to print the
type of this function, call it, et cetera.
> 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.)
Are the failures in templates.exp real failures caused by
internal-to-GDB differences in output, or are they caused by tolerable
changes in the output? I saw mostly the latter when working with
stabs.
I would appreciate it if you could prepare a matching patch to
templates.exp which either fixes the failures if they are output
issues, or adds KFAIL patterns otherwise. I know it's a nuisance but I
do not want to leave failures that we aren't going to fix in the short
term.
A KFAIL for the rtti.exp test would be an added bonus.
Oh, and as I said elsewhere I don't think that "fixing" the demangler
is a worthwhile exercise.
> * 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.)
OK. By the way, I don't intend for GCC to generate .debug_pubtypes,
but I do intend for it to generate something twice proposed on the
dwarf2 list: .debug_info_index. Which, as you say, looks "an awful lot
like the full symbol reader" - it uses DIEs.
> * 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.
Also OK. It would be nice to fix this, but it requires even more
drastic surgery to the symbol tables. I have some ideas but not enough
time :)
>
> 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.
Agreed with the caveat above.
> @@ -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. */
How many of these prefixes end up being identical - is it usually close
to one, or do we get one copy for each method in a class, et cetera?
We could use a bcache for this if we have duplicates.
Otherwise I have no complaints about this patch. The non-symtab parts
are OK and the rest looks good to me.
--
Daniel Jacobowitz
MontaVista Software Debian GNU/Linux Developer
^ permalink raw reply [flat|nested] 6+ messages in thread* Re: [rfa] generate fully-qualified names for types
2003-11-17 16:52 ` Daniel Jacobowitz
@ 2003-11-18 17:51 ` David Carlton
2004-01-08 20:04 ` Elena Zannoni
0 siblings, 1 reply; 6+ messages in thread
From: David Carlton @ 2003-11-18 17:51 UTC (permalink / raw)
To: gdb-patches; +Cc: Elena Zannoni, Jim Blandy
On Mon, 17 Nov 2003 11:52:09 -0500, Daniel Jacobowitz <drow@mvista.com> said:
> On Wed, Nov 12, 2003 at 10:53:01AM -0800, David Carlton wrote:
>> * 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
> We need them. You can have this, and often do in GDB:
> struct Foo;
> extern void foofoo(struct Foo *);
> We have to have a type associated with struct Foo in order to print
> the type of this function, call it, et cetera.
Yeah. And I guess there might not be a real definition anywhere in
some circumstances - e.g. the real definition could only show up in a
library without debug info.
It's an unfortunate situation. I should have been more proactive
about getting DW_TAG_namespace into GCC 3.4. Maybe it will still
happen - I hear that Devang Patel is working on it.
> Are the failures in templates.exp real failures caused by
> internal-to-GDB differences in output, or are they caused by
> tolerable changes in the output? I saw mostly the latter when
> working with stabs.
I think the changes are tolerable. Some spaces get added, some
parentheses get added, some const chars turn into char consts. Only
the latter will have any practical effect at all.
> I would appreciate it if you could prepare a matching patch to
> templates.exp which either fixes the failures if they are output
> issues, or adds KFAIL patterns otherwise. I know it's a nuisance but I
> do not want to leave failures that we aren't going to fix in the short
> term.
> A KFAIL for the rtti.exp test would be an added bonus.
Will do, for both.
> Oh, and as I said elsewhere I don't think that "fixing" the
> demangler is a worthwhile exercise.
Yeah, I know - we've argued about this enough before. :-) Like I said,
the main sticking point for me is the RTTI information. But I suppose
the proper solution would be for us to get that information some other
way. For example, we could build up a table of vptrs (mapping minimal
symbols to classes, or even addresses to classes), and have the RTTI
info use that table instead of the demangled names. Or, for that
matter, we could try to generate the demangled names of the vptrs
without using the demangler, if possible.
> OK. By the way, I don't intend for GCC to generate .debug_pubtypes,
> but I do intend for it to generate something twice proposed on the
> dwarf2 list: .debug_info_index. Which, as you say, looks "an awful lot
> like the full symbol reader" - it uses DIEs.
Interesting.
>> @@ -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. */
> How many of these prefixes end up being identical - is it usually close
> to one, or do we get one copy for each method in a class, et cetera?
> We could use a bcache for this if we have duplicates.
Lots of duplicates - all the methods in a class could share a prefix,
all of the free functions defined in a namespace could share a prefix,
etc. Having said that, I'd prefer not to use a bcache - I bet that
the memory would get lost in the noise, and our memory-management
story is already complex enough as it is.
Hmm. I guess it wouldn't be that bad. The function's caller has
access to the objfile in question, so we could just add a name_bcache
member to struct objfile. (And eventually think about the division of
labor between it and the demangled name hashtable...)
> Otherwise I have no complaints about this patch. The non-symtab parts
> are OK and the rest looks good to me.
Thanks. Then I'll prepare a testsuite patch for the failures and look
into using a bcache.
David Carlton
carlton@kealia.com
^ permalink raw reply [flat|nested] 6+ messages in thread* Re: [rfa] generate fully-qualified names for types
2003-11-18 17:51 ` David Carlton
@ 2004-01-08 20:04 ` Elena Zannoni
2004-01-09 22:41 ` Elena Zannoni
0 siblings, 1 reply; 6+ messages in thread
From: Elena Zannoni @ 2004-01-08 20:04 UTC (permalink / raw)
To: David Carlton; +Cc: gdb-patches, Elena Zannoni, Jim Blandy
As usual I'd like to split this patch in mechanical
changes/replacements and not so mechanical ones. After the mechanical
changes are in, it would be more obvious what has changed.
It looks ok to me, but I'd like to minimize the diffs and take another look.
I can see:
1. the processing_current_namespace --> processing_current_prefix rename
2. the read_namespace changes of previous namespace-->previous_prefix
3. introduction of namespace_name()
as mechanical/obvious
I can check in those changes if you are busy. I am too, but now I can
swing a day for this.
Other minor nag is about comments, I think we need more examples in
the comments about how the names get composed, etc.
elena
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [rfa] generate fully-qualified names for types
2004-01-08 20:04 ` Elena Zannoni
@ 2004-01-09 22:41 ` Elena Zannoni
2004-01-14 17:02 ` David Carlton
0 siblings, 1 reply; 6+ messages in thread
From: Elena Zannoni @ 2004-01-09 22:41 UTC (permalink / raw)
To: David Carlton; +Cc: gdb-patches
Elena Zannoni writes:
>
> As usual I'd like to split this patch in mechanical
> changes/replacements and not so mechanical ones. After the mechanical
> changes are in, it would be more obvious what has changed.
> It looks ok to me, but I'd like to minimize the diffs and take another look.
> I can see:
> 1. the processing_current_namespace --> processing_current_prefix rename
> 2. the read_namespace changes of previous namespace-->previous_prefix
> 3. introduction of namespace_name()
>
> as mechanical/obvious
>
> I can check in those changes if you are busy. I am too, but now I can
> swing a day for this.
I've done the above.
>
> Other minor nag is about comments, I think we need more examples in
> the comments about how the names get composed, etc.
I haven't done this.
Here is what is left for dwarf2read.c, cp-namespace.c and cp-support.h
(nothing). Valops.c is ok as it was.
you can check those in.
elena
--- dwarf2read.c 2004-01-09 15:36:21.000000000 -0500
+++ dwarf2read-dc.c 2004-01-09 14:44:35.000000000 -0500
@@ -666,12 +666,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,
@@ -743,6 +750,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
@@ -777,6 +786,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 *);
@@ -1368,11 +1383,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:
@@ -1430,6 +1452,17 @@ add_partial_symbol (struct partial_die_i
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_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 (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_i
/* 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_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. */
@@ -1570,9 +1633,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,
@@ -1587,6 +1651,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 *
@@ -1711,6 +1832,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);
@@ -1864,11 +1988,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_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, 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_prefix = "";
- }
+ processing_has_namespace_info = 1;
gdb_assert (die->child == NULL);
break;
default:
@@ -2777,6 +2893,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);
@@ -2784,9 +2907,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)
@@ -2846,6 +3001,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)
{
@@ -2921,6 +3111,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
@@ -2950,9 +3144,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);
@@ -3223,7 +3429,7 @@ read_namespace (struct die_info *die, st
{
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
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,
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, 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 *
--- cp-namespace.c 2004-01-09 17:15:58.000000000 -0500
+++ cp-namespace.c.dc 2003-11-13 15:38:32.000000000 -0500
@@ -32,9 +32,12 @@
#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;
@@ -222,12 +225,6 @@ 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
@@ -237,7 +234,6 @@ cp_set_block_scope (const struct 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 *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,
@@ -547,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.");
}
}
^ permalink raw reply [flat|nested] 6+ messages in thread* Re: [rfa] generate fully-qualified names for types
2004-01-09 22:41 ` Elena Zannoni
@ 2004-01-14 17:02 ` David Carlton
0 siblings, 0 replies; 6+ messages in thread
From: David Carlton @ 2004-01-14 17:02 UTC (permalink / raw)
To: gdb-patches; +Cc: Elena Zannoni
On Fri, 9 Jan 2004 17:40:33 -0500, Elena Zannoni <ezannoni@redhat.com> said:
> you can check those in.
Thanks! I've done so (patch below, just for reference; no changes
other than copyright dates). And later today I'll file PR's for the
testsuite changes and update the testsuite accordingly.
For reference, the most important changes that remain are:
* Changes to lookup_transparent_type (sigh). A hack, but probably an
important one; I'll try to generate this one quickly.
* Changes to function overloading. Probably not that important in
practice, but it shouldn't be too hard to generate this one.
* Changes to linespec to expect namespace. A bit trickier, especially
since a user found a bug in this code on Monday. Perhaps it's a bit
less important, however, though: linespec is surprisingly resilient.
At any rate, I'll certainly try to get this in to 6.1 as well.
Other changes on my branch that are less important:
* A change to dwarf2read.c involving code ranges and namespaces. I'm
not sure if this will be important for GCC 3.4 or not, but better
safe than sorry. (It's a small patch, so I'll probably try to get
it in for 6.1, too.)
* General linespec cleanup; a good idea, though not necessary for
correctness.
* Const-correctness stuff; I don't know if I'll merge this in or not.
David Carlton
carlton@kealia.com
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: 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.
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 14 Jan 2004 16:50:46 -0000
@@ -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):
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.8
diff -u -p -r1.8 cp-namespace.c
--- cp-namespace.c 9 Jan 2004 22:22:07 -0000 1.8
+++ cp-namespace.c 14 Jan 2004 16:50:46 -0000
@@ -32,9 +32,12 @@
#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
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
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 *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,
@@ -547,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: dwarf2read.c
===================================================================
RCS file: /cvs/src/src/gdb/dwarf2read.c,v
retrieving revision 1.119
diff -u -p -r1.119 dwarf2read.c
--- dwarf2read.c 9 Jan 2004 22:22:07 -0000 1.119
+++ dwarf2read.c 14 Jan 2004 16:50:49 -0000
@@ -666,12 +666,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,
@@ -743,6 +750,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
@@ -777,6 +786,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 *);
@@ -1368,11 +1383,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:
@@ -1430,6 +1452,17 @@ add_partial_symbol (struct partial_die_i
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_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 (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_i
/* 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_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. */
@@ -1570,9 +1633,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,
@@ -1587,6 +1651,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 *
@@ -1711,6 +1832,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);
@@ -1864,11 +1988,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_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, 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_prefix = "";
- }
+ processing_has_namespace_info = 1;
gdb_assert (die->child == NULL);
break;
default:
@@ -2777,6 +2893,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);
@@ -2784,9 +2907,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)
@@ -2846,6 +3001,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)
{
@@ -2921,6 +3111,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
@@ -2950,9 +3144,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);
@@ -3223,7 +3429,7 @@ read_namespace (struct die_info *die, st
{
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
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,
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, 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 14 Jan 2004 16:50:50 -0000
@@ -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_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 14 Jan 2004 16:50:57 -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.5
diff -u -p -r1.5 namespace.exp
--- testsuite/gdb.cp/namespace.exp 7 Jan 2004 08:44:32 -0000 1.5
+++ testsuite/gdb.cp/namespace.exp 14 Jan 2004 16:50:57 -0000
@@ -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,14 +249,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 14 Jan 2004 16:50:57 -0000
@@ -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
@@ -19,6 +19,11 @@
namespace C
{
+ class OtherFileClass {
+ public:
+ int z;
+ };
+
namespace {
int cXOtherFile = 29;
};
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2004-01-14 17:02 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2003-11-12 18:53 [rfa] generate fully-qualified names for types David Carlton
2003-11-17 16:52 ` Daniel Jacobowitz
2003-11-18 17:51 ` David Carlton
2004-01-08 20:04 ` Elena Zannoni
2004-01-09 22:41 ` Elena Zannoni
2004-01-14 17:02 ` David Carlton
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox