From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 32318 invoked by alias); 12 Nov 2003 18:53:07 -0000 Mailing-List: contact gdb-patches-help@sources.redhat.com; run by ezmlm Precedence: bulk List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sources.redhat.com Received: (qmail 32299 invoked from network); 12 Nov 2003 18:53:02 -0000 Received: from unknown (HELO hawaii.kealia.com) (209.3.10.89) by sources.redhat.com with SMTP; 12 Nov 2003 18:53:02 -0000 Received: by hawaii.kealia.com (Postfix, from userid 2049) id A2303C6B2; Wed, 12 Nov 2003 10:53:01 -0800 (PST) To: gdb-patches@sources.redhat.com Cc: Daniel Jacobowitz , Elena Zannoni , Jim Blandy Subject: [rfa] generate fully-qualified names for types From: David Carlton Date: Wed, 12 Nov 2003 18:53:00 -0000 Message-ID: MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii X-SW-Source: 2003-11/txt/msg00242.txt.bz2 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 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 * 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, + "<>"); + } + 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 \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; };