* gdbtypes.h: Add TYPE_CODE_NAMESPACE.
* gdbtypes.c (init_type): Handle TYPE_CODE_NAMESPACE.
(recursive_dump_type): Ditto.
* printcmd.c (print_formatted): Ditto.
* typeprint.c (print_type_scalar): Ditto.
* c-typeprint.c (c_type_print_varspec_prefix): Ditto.
(c_type_print_varspec_suffix, c_type_print_base): Ditto.
* cp-support.h: Declare cp_check_possible_namespace_symbols,
maint_cplus_cmd_list.
* cp-support.c: Make maint_cplus_cmd_list extern.
* cp-namespace.c: Include objfiles.h, gdbtypes.h, dictionary.h,
command.h.
(lookup_symbol_file): Look in possible namespace blocks when
appropriate.
(initialize_namespace_symtab): New.
(get_possible_namespace_block, free_namespace_block)
(check_possible_namespace_symbols)
(check_possible_namespace_symbols_loop)
(check_one_possible_namespace_symbol)
(lookup_possible_namespace_symbol, maintenance_cplus_namespace)
(_initialize_cp_namespace): Ditto.
* block.h: Declare allocate_block.
* block.c (allocate_block): New.
* jv-lang.c (get_java_class_symtab): Allocate blocks via
allocate_block.
* symfile.h: Update declaration of add_psymbol_to_list.
* symfile.c (add_psymbol_to_list): Return the partial symbol in
question.
* dwarf2read.c (dwarf2_build_psymtabs_hard): Add argument to
scan_partial_symbols_call.
(scan_partial_symbols): Add NAMESPACE argument; update calls to
helper functions.
(add_partial_symbol): If necessary, scan mangled names for names
of namespaces.
(add_partial_namespace): Add NAMESPACE argument; generate partial
symbols associated to namespaces.
(add_partial_enumeration): Add NAMESPACE argument.
(new_symbol): Allow namespace syms.
(read_namespace): Generate namespace syms.
* objfiles.h: Add opaque declaration of struct symtab.
(struct objfile): Add cp_namespace_symtab member.
* objfiles.c (allocate_objfile): Set
objfile->cp_namespace_symtab.
* Makefile.in (cp-namespace.o): Depend on objfiles_h, gdbtypes_h,
dictionary_h, command_h.
2003-09-11 David Carlton <carlton@kealia.com>
* gdb.c++/namespace.exp: Add tests for namespace types.
* gdb.c++/maint.exp (test_help): Test 'help maint cp namespace'.
(test_namespace): New.
+2003-09-11 David Carlton <carlton@kealia.com>
+
+ * gdbtypes.h: Add TYPE_CODE_NAMESPACE.
+ * gdbtypes.c (init_type): Handle TYPE_CODE_NAMESPACE.
+ (recursive_dump_type): Ditto.
+ * printcmd.c (print_formatted): Ditto.
+ * typeprint.c (print_type_scalar): Ditto.
+ * c-typeprint.c (c_type_print_varspec_prefix): Ditto.
+ (c_type_print_varspec_suffix, c_type_print_base): Ditto.
+ * cp-support.h: Declare cp_check_possible_namespace_symbols,
+ maint_cplus_cmd_list.
+ * cp-support.c: Make maint_cplus_cmd_list extern.
+ * cp-namespace.c: Include objfiles.h, gdbtypes.h, dictionary.h,
+ command.h.
+ (lookup_symbol_file): Look in possible namespace blocks when
+ appropriate.
+ (initialize_namespace_symtab): New.
+ (get_possible_namespace_block, free_namespace_block)
+ (check_possible_namespace_symbols)
+ (check_possible_namespace_symbols_loop)
+ (check_one_possible_namespace_symbol)
+ (lookup_possible_namespace_symbol, maintenance_cplus_namespace)
+ (_initialize_cp_namespace): Ditto.
+ * block.h: Declare allocate_block.
+ * block.c (allocate_block): New.
+ * jv-lang.c (get_java_class_symtab): Allocate blocks via
+ allocate_block.
+ * symfile.h: Update declaration of add_psymbol_to_list.
+ * symfile.c (add_psymbol_to_list): Return the partial symbol in
+ question.
+ * dwarf2read.c (dwarf2_build_psymtabs_hard): Add argument to
+ scan_partial_symbols_call.
+ (scan_partial_symbols): Add NAMESPACE argument; update calls to
+ helper functions.
+ (add_partial_symbol): If necessary, scan mangled names for names
+ of namespaces.
+ (add_partial_namespace): Add NAMESPACE argument; generate partial
+ symbols associated to namespaces.
+ (add_partial_enumeration): Add NAMESPACE argument.
+ (new_symbol): Allow namespace syms.
+ (read_namespace): Generate namespace syms.
+ * objfiles.h: Add opaque declaration of struct symtab.
+ (struct objfile): Add cp_namespace_symtab member.
+ * objfiles.c (allocate_objfile): Set
+ objfile->cp_namespace_symtab.
+ * Makefile.in (cp-namespace.o): Depend on objfiles_h, gdbtypes_h,
+ dictionary_h, command_h.
+
2003-09-11 Andrew Cagney <cagney@redhat.com>
* rs6000-tdep.c (rs6000_push_dummy_call): Use
cp-abi.o: cp-abi.c $(defs_h) $(value_h) $(cp_abi_h) $(command_h) $(gdbcmd_h) \
$(ui_out_h) $(gdb_string_h)
cp-namespace.o: cp-namespace.c $(defs_h) $(cp_support_h) $(gdb_obstack_h) \
- $(symtab_h) $(symfile_h) $(gdb_assert_h) $(block_h)
+ $(symtab_h) $(symfile_h) $(gdb_assert_h) $(block_h) $(objfiles_h) \
+ $(gdbtypes_h) $(dictionary_h) $(command_h)
cp-support.o: cp-support.c $(defs_h) $(cp_support_h) $(gdb_string_h) \
$(demangle_h) $(gdb_assert_h) $(gdbcmd_h) $(dictionary_h) \
$(objfiles_h) $(frame_h) $(symtab_h) $(block_h) $(complaints_h)
return block;
}
+
+/* Allocate a block on OBSTACK, and initialize its elements to
+ zero/NULL. This is useful for creating "dummy" blocks that don't
+ correspond to actual source files.
+
+ Warning: it sets the block's BLOCK_DICT to NULL, which isn't a
+ valid value. If you really don't want the block to have a
+ dictionary, then you should subsequently set its BLOCK_DICT to
+ dict_create_linear (obstack, NULL). */
+
+struct block *
+allocate_block (struct obstack *obstack)
+{
+ struct block *bl = obstack_alloc (obstack, sizeof (struct block));
+
+ BLOCK_START (bl) = 0;
+ BLOCK_END (bl) = 0;
+ BLOCK_FUNCTION (bl) = NULL;
+ BLOCK_SUPERBLOCK (bl) = NULL;
+ BLOCK_DICT (bl) = NULL;
+ BLOCK_NAMESPACE (bl) = NULL;
+ BLOCK_GCC_COMPILED (bl) = 0;
+
+ return bl;
+}
extern const struct block *block_global_block (const struct block *block);
+extern struct block *allocate_block (struct obstack *obstack);
+
#endif /* BLOCK_H */
case TYPE_CODE_BITSTRING:
case TYPE_CODE_COMPLEX:
case TYPE_CODE_TEMPLATE:
+ case TYPE_CODE_NAMESPACE:
/* These types need no prefix. They are listed here so that
gcc -Wall will reveal any types that haven't been handled. */
break;
case TYPE_CODE_BITSTRING:
case TYPE_CODE_COMPLEX:
case TYPE_CODE_TEMPLATE:
+ case TYPE_CODE_NAMESPACE:
/* These types do not need a suffix. They are listed so that
gcc -Wall will report types that may not have been considered. */
break;
}
break;
+ case TYPE_CODE_NAMESPACE:
+ fputs_filtered ("namespace ", stream);
+ fputs_filtered (TYPE_TAG_NAME (type), stream);
+ break;
+
default:
/* Handle types not explicitly handled by the other cases,
such as fundamental types. For these, just print whatever
#include "symfile.h"
#include "gdb_assert.h"
#include "block.h"
+#include "objfiles.h"
+#include "gdbtypes.h"
+#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
struct symtab **symtab,
int anonymous_namespace);
+static void initialize_namespace_symtab (struct objfile *objfile);
+
+static struct block *get_possible_namespace_block (struct objfile *objfile);
+
+static void free_namespace_block (struct symtab *symtab);
+
+static int check_possible_namespace_symbols_loop (const char *name,
+ int len,
+ struct objfile *objfile);
+
+static int check_one_possible_namespace_symbol (const char *name,
+ int len,
+ struct objfile *objfile);
+
+static
+struct symbol *lookup_possible_namespace_symbol (const char *name,
+ struct symtab **symtab);
+
+static void maintenance_cplus_namespace (char *args, int from_tty);
+
/* Set up support for dealing with C++ namespace info in the current
symtab. */
const struct block *global_block = block_global_block (block);
if (global_block != NULL)
- return lookup_symbol_aux_block (name, linkage_name, global_block,
- domain, symtab);
- else
- return NULL;
+ sym = lookup_symbol_aux_block (name, linkage_name, global_block,
+ domain, symtab);
}
else
{
- return lookup_symbol_global (name, linkage_name, domain, symtab);
+ sym = lookup_symbol_global (name, linkage_name, domain, symtab);
+ }
+
+ if (sym != NULL)
+ return sym;
+
+ /* Now call "lookup_possible_namespace_symbol". Symbols in here
+ claim to be associated to namespaces, but this claim might be
+ incorrect: the names in question might actually correspond to
+ classes instead of namespaces. But if they correspond to
+ classes, then we should have found a match for them above. So if
+ we find them now, they should be genuine. */
+
+ /* FIXME: carlton/2003-06-12: This is a hack and should eventually
+ be deleted: see comments below. */
+
+ if (domain == VAR_DOMAIN)
+ {
+ sym = lookup_possible_namespace_symbol (name, symtab);
+ if (sym != NULL)
+ return sym;
+ }
+
+ return NULL;
+}
+
+/* Now come functions for dealing with symbols associated to
+ namespaces. (They're used to store the namespaces themselves, not
+ objects that live in the namespaces.) These symbols come in two
+ varieties: if we run into a DW_TAG_namespace DIE, then we know that
+ we have a namespace, so dwarf2read.c creates a symbol for it just
+ like normal. But, unfortunately, versions of GCC through at least
+ 3.3 don't generate those DIE's. Our solution is to try to guess
+ their existence by looking at demangled names. This might cause us
+ to misidentify classes as namespaces, however. So we put those
+ symbols in a special block (one per objfile), and we only search
+ that block as a last resort. */
+
+/* FIXME: carlton/2003-06-12: Once versions of GCC that generate
+ DW_TAG_namespace have been out for a year or two, we should get rid
+ of all of this "possible namespace" nonsense. */
+
+/* Allocate everything necessary for the possible namespace block
+ associated to OBJFILE. */
+
+static void
+initialize_namespace_symtab (struct objfile *objfile)
+{
+ struct symtab *namespace_symtab;
+ struct blockvector *bv;
+ struct block *bl;
+
+ namespace_symtab = allocate_symtab ("<<C++-namespaces>>", objfile);
+ namespace_symtab->language = language_cplus;
+ namespace_symtab->free_code = free_nothing;
+ namespace_symtab->dirname = NULL;
+
+ bv = obstack_alloc (&objfile->symbol_obstack,
+ sizeof (struct blockvector)
+ + FIRST_LOCAL_BLOCK * sizeof (struct block *));
+ BLOCKVECTOR_NBLOCKS (bv) = FIRST_LOCAL_BLOCK + 1;
+ BLOCKVECTOR (namespace_symtab) = bv;
+
+ /* Allocate empty GLOBAL_BLOCK and STATIC_BLOCK. */
+
+ bl = allocate_block (&objfile->symbol_obstack);
+ BLOCK_DICT (bl) = dict_create_linear (&objfile->symbol_obstack,
+ NULL);
+ BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK) = bl;
+ bl = allocate_block (&objfile->symbol_obstack);
+ BLOCK_DICT (bl) = dict_create_linear (&objfile->symbol_obstack,
+ NULL);
+ BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK) = bl;
+
+ /* Allocate the possible namespace block; we put it where the first
+ local block will live, though I don't think there's any need to
+ pretend that it's actually a local block (e.g. by setting
+ BLOCK_SUPERBLOCK appropriately). We don't use the global or
+ static block because we don't want it searched during the normal
+ search of all global/static blocks in lookup_symbol: we only want
+ it used as a last resort. */
+
+ /* NOTE: carlton/2003-09-11: I considered not associating the fake
+ symbols to a block/symtab at all. But that would cause problems
+ with lookup_symbol's SYMTAB argument and with block_found, so
+ having a symtab/block for this purpose seems like the best
+ solution for now. */
+
+ bl = allocate_block (&objfile->symbol_obstack);
+ BLOCK_DICT (bl) = dict_create_hashed_expandable ();
+ BLOCKVECTOR_BLOCK (bv, FIRST_LOCAL_BLOCK) = bl;
+
+ namespace_symtab->free_func = free_namespace_block;
+
+ objfile->cp_namespace_symtab = namespace_symtab;
+}
+
+/* Locate the possible namespace block associated to OBJFILE,
+ allocating it if necessary. */
+
+static struct block *
+get_possible_namespace_block (struct objfile *objfile)
+{
+ if (objfile->cp_namespace_symtab == NULL)
+ initialize_namespace_symtab (objfile);
+
+ return BLOCKVECTOR_BLOCK (BLOCKVECTOR (objfile->cp_namespace_symtab),
+ FIRST_LOCAL_BLOCK);
+}
+
+/* Free the dictionary associated to the possible namespace block. */
+
+static void
+free_namespace_block (struct symtab *symtab)
+{
+ struct block *possible_namespace_block;
+
+ possible_namespace_block = BLOCKVECTOR_BLOCK (BLOCKVECTOR (symtab),
+ FIRST_LOCAL_BLOCK);
+ gdb_assert (possible_namespace_block != NULL);
+ dict_free (BLOCK_DICT (possible_namespace_block));
+}
+
+/* Ensure that there are symbols in the possible namespace block
+ associated to OBJFILE for all initial substrings of NAME that look
+ like namespaces or classes. NAME should end in a member variable:
+ it shouldn't consist solely of namespaces. */
+
+void
+cp_check_possible_namespace_symbols (const char *name, struct objfile *objfile)
+{
+ check_possible_namespace_symbols_loop (name,
+ cp_find_first_component (name),
+ objfile);
+}
+
+/* This is a helper loop for cp_check_possible_namespace_symbols; it
+ ensures that there are symbols in the possible namespace block
+ associated to OBJFILE for all namespaces that are initial
+ substrings of NAME of length at least LEN. It returns 1 if a
+ previous loop had already created the shortest such symbol and 0
+ otherwise.
+
+ This function assumes that if there is already a symbol associated
+ to a substring of NAME of a given length, then there are already
+ symbols associated to all substrings of NAME whose length is less
+ than that length. So if cp_check_possible_namespace_symbols has
+ been called once with argument "A::B::C::member", then that will
+ create symbols "A", "A::B", and "A::B::C". If it is then later
+ called with argument "A::B::D::member", then the new call will
+ generate a new symbol for "A::B::D", but once it sees that "A::B"
+ has already been created, it doesn't bother checking to see if "A"
+ has also been created. */
+
+static int
+check_possible_namespace_symbols_loop (const char *name, int len,
+ struct objfile *objfile)
+{
+ if (name[len] == ':')
+ {
+ int done;
+ int next_len = len + 2;
+
+ next_len += cp_find_first_component (name + next_len);
+ done = check_possible_namespace_symbols_loop (name, next_len,
+ objfile);
+
+ if (!done)
+ done = check_one_possible_namespace_symbol (name, len, objfile);
+
+ return done;
}
+ else
+ return 0;
+}
+
+/* Check to see if there's already a possible namespace symbol in
+ OBJFILE whose name is the initial substring of NAME of length LEN.
+ If not, create one and return 0; otherwise, return 1. */
+
+static int
+check_one_possible_namespace_symbol (const char *name, int len,
+ struct objfile *objfile)
+{
+ struct block *block = get_possible_namespace_block (objfile);
+ char *name_copy = obsavestring (name, len, &objfile->symbol_obstack);
+ struct symbol *sym = lookup_block_symbol (block, name_copy, NULL,
+ VAR_DOMAIN);
+
+ if (sym == NULL)
+ {
+ struct type *type = init_type (TYPE_CODE_NAMESPACE, 0, 0,
+ name_copy, objfile);
+ TYPE_TAG_NAME (type) = TYPE_NAME (type);
+
+ sym = obstack_alloc (&objfile->symbol_obstack, sizeof (struct symbol));
+ memset (sym, 0, sizeof (struct symbol));
+ SYMBOL_LANGUAGE (sym) = language_cplus;
+ SYMBOL_SET_NAMES (sym, name_copy, len, objfile);
+ SYMBOL_CLASS (sym) = LOC_TYPEDEF;
+ SYMBOL_TYPE (sym) = type;
+ SYMBOL_DOMAIN (sym) = VAR_DOMAIN;
+
+ dict_add_symbol (BLOCK_DICT (block), sym);
+
+ return 0;
+ }
+ else
+ {
+ obstack_free (&objfile->symbol_obstack, name_copy);
+
+ return 1;
+ }
+}
+
+/* Look for a symbol named NAME in all the possible namespace blocks.
+ If one is found, return it; if SYMTAB is non-NULL, set *SYMTAB to
+ equal the symtab where it was found. */
+
+static struct symbol *
+lookup_possible_namespace_symbol (const char *name, struct symtab **symtab)
+{
+ struct objfile *objfile;
+
+ ALL_OBJFILES (objfile)
+ {
+ struct symbol *sym;
+
+ sym = lookup_block_symbol (get_possible_namespace_block (objfile),
+ name, NULL, VAR_DOMAIN);
+
+ if (sym != NULL)
+ {
+ if (symtab != NULL)
+ *symtab = objfile->cp_namespace_symtab;
+
+ return sym;
+ }
+ }
+
+ return NULL;
+}
+
+/* Print out all the possible namespace symbols. */
+
+static void
+maintenance_cplus_namespace (char *args, int from_tty)
+{
+ struct objfile *objfile;
+ printf_unfiltered ("Possible namespaces:\n");
+ ALL_OBJFILES (objfile)
+ {
+ struct dict_iterator iter;
+ struct symbol *sym;
+
+ ALL_BLOCK_SYMBOLS (get_possible_namespace_block (objfile), iter, sym)
+ {
+ printf_unfiltered ("%s\n", SYMBOL_PRINT_NAME (sym));
+ }
+ }
+}
+
+void
+_initialize_cp_namespace (void)
+{
+ add_cmd ("namespace", class_maintenance, maintenance_cplus_namespace,
+ "Print the list of possible C++ namespaces.",
+ &maint_cplus_cmd_list);
}
/* The list of "maint cplus" commands. */
-static struct cmd_list_element *maint_cplus_cmd_list = NULL;
+struct cmd_list_element *maint_cplus_cmd_list = NULL;
/* The actual commands. */
const domain_enum domain,
struct symtab **symtab);
+extern void cp_check_possible_namespace_symbols (const char *name,
+ struct objfile *objfile);
+
+/* The list of "maint cplus" commands. */
+
+extern struct cmd_list_element *maint_cplus_cmd_list;
+
#endif /* CP_SUPPORT_H */
static char *scan_partial_symbols (char *, struct objfile *,
CORE_ADDR *, CORE_ADDR *,
- const struct comp_unit_head *);
+ const struct comp_unit_head *,
+ const char *namespace);
static void add_partial_symbol (struct partial_die_info *, struct objfile *,
- const struct comp_unit_head *);
+ const struct comp_unit_head *,
+ const char *namespace);
static char *add_partial_namespace (struct partial_die_info *pdi,
char *info_ptr,
struct objfile *objfile,
CORE_ADDR *lowpc, CORE_ADDR *highpc,
- const struct comp_unit_head *cu_header);
+ const struct comp_unit_head *cu_header,
+ const char *namespace);
static char *add_partial_enumeration (struct partial_die_info *enum_pdi,
char *info_ptr,
struct objfile *objfile,
- const struct comp_unit_head *cu_header);
+ const struct comp_unit_head *cu_header,
+ const char *namespace);
static char *locate_pdi_sibling (struct partial_die_info *orig_pdi,
char *info_ptr,
highpc = ((CORE_ADDR) 0);
info_ptr = scan_partial_symbols (info_ptr, objfile, &lowpc, &highpc,
- &cu_header);
+ &cu_header, NULL);
/* If we didn't find a lowpc, set it to highpc to avoid
complaints from `maint check'. */
}
/* Read in all interesting dies to the end of the compilation unit or
- to the end of the current namespace. */
+ to the end of the current namespace. NAMESPACE is NULL if we
+ haven't yet encountered any DW_TAG_namespace entries; otherwise,
+ it's the name of the current namespace. In particular, it's the
+ empty string if we're currently in the global namespace but have
+ previously encountered a DW_TAG_namespace. */
static char *
scan_partial_symbols (char *info_ptr, struct objfile *objfile,
CORE_ADDR *lowpc, CORE_ADDR *highpc,
- const struct comp_unit_head *cu_header)
+ const struct comp_unit_head *cu_header,
+ const char *namespace)
{
bfd *abfd = objfile->obfd;
struct partial_die_info pdi;
}
if (!pdi.is_declaration)
{
- add_partial_symbol (&pdi, objfile, cu_header);
+ add_partial_symbol (&pdi, objfile, cu_header, namespace);
}
}
break;
case DW_TAG_structure_type:
if (!pdi.is_declaration)
{
- add_partial_symbol (&pdi, objfile, cu_header);
+ add_partial_symbol (&pdi, objfile, cu_header, namespace);
}
break;
case DW_TAG_enumeration_type:
if (!pdi.is_declaration)
{
info_ptr = add_partial_enumeration (&pdi, info_ptr,
- objfile, cu_header);
+ objfile, cu_header,
+ namespace);
info_ptr_updated = 1;
}
break;
case DW_TAG_base_type:
/* File scope base type definitions are added to the partial
symbol table. */
- add_partial_symbol (&pdi, objfile, cu_header);
+ add_partial_symbol (&pdi, objfile, cu_header, namespace);
break;
case DW_TAG_namespace:
+ /* We've hit a DW_TAG_namespace entry, so we know this
+ file has been compiled using a compiler that
+ generates them; update NAMESPACE to reflect that. */
+ if (namespace == NULL)
+ namespace = "";
info_ptr = add_partial_namespace (&pdi, info_ptr, objfile,
- lowpc, highpc, cu_header);
+ lowpc, highpc, cu_header,
+ namespace);
info_ptr_updated = 1;
break;
default:
static void
add_partial_symbol (struct partial_die_info *pdi, struct objfile *objfile,
- const struct comp_unit_head *cu_header)
+ const struct comp_unit_head *cu_header,
+ const char *namespace)
{
CORE_ADDR addr = 0;
+ const struct partial_symbol *psym = NULL;
switch (pdi->tag)
{
{
/*prim_record_minimal_symbol (pdi->name, pdi->lowpc + baseaddr,
mst_text, objfile); */
- add_psymbol_to_list (pdi->name, strlen (pdi->name),
- VAR_DOMAIN, LOC_BLOCK,
- &objfile->global_psymbols,
- 0, pdi->lowpc + baseaddr, cu_language, objfile);
+ psym = add_psymbol_to_list (pdi->name, strlen (pdi->name),
+ VAR_DOMAIN, LOC_BLOCK,
+ &objfile->global_psymbols,
+ 0, pdi->lowpc + baseaddr,
+ cu_language, objfile);
}
else
{
/*prim_record_minimal_symbol (pdi->name, pdi->lowpc + baseaddr,
mst_file_text, objfile); */
- add_psymbol_to_list (pdi->name, strlen (pdi->name),
- VAR_DOMAIN, LOC_BLOCK,
- &objfile->static_psymbols,
- 0, pdi->lowpc + baseaddr, cu_language, objfile);
+ psym = add_psymbol_to_list (pdi->name, strlen (pdi->name),
+ VAR_DOMAIN, LOC_BLOCK,
+ &objfile->static_psymbols,
+ 0, pdi->lowpc + baseaddr,
+ cu_language, objfile);
}
break;
case DW_TAG_variable:
if (pdi->locdesc)
addr = decode_locdesc (pdi->locdesc, objfile, cu_header);
if (pdi->locdesc || pdi->has_type)
- add_psymbol_to_list (pdi->name, strlen (pdi->name),
- VAR_DOMAIN, LOC_STATIC,
- &objfile->global_psymbols,
- 0, addr + baseaddr, cu_language, objfile);
+ psym = add_psymbol_to_list (pdi->name, strlen (pdi->name),
+ VAR_DOMAIN, LOC_STATIC,
+ &objfile->global_psymbols,
+ 0, addr + baseaddr,
+ cu_language, objfile);
}
else
{
addr = decode_locdesc (pdi->locdesc, objfile, cu_header);
/*prim_record_minimal_symbol (pdi->name, addr + baseaddr,
mst_file_data, objfile); */
- add_psymbol_to_list (pdi->name, strlen (pdi->name),
- VAR_DOMAIN, LOC_STATIC,
- &objfile->static_psymbols,
- 0, addr + baseaddr, cu_language, objfile);
+ psym = add_psymbol_to_list (pdi->name, strlen (pdi->name),
+ VAR_DOMAIN, LOC_STATIC,
+ &objfile->static_psymbols,
+ 0, addr + baseaddr,
+ cu_language, objfile);
}
break;
case DW_TAG_typedef:
default:
break;
}
+
+ /* Check to see if we should scan the name for possible namespace
+ info. Only do this if this is C++, if we don't have namespace
+ debugging info in the file, if the psym is of an appropriate type
+ (otherwise we'll have psym == NULL), and if we actually had a
+ mangled name to begin with. */
+
+ if (cu_language == language_cplus
+ && namespace == NULL
+ && psym != NULL
+ && SYMBOL_CPLUS_DEMANGLED_NAME (psym) != NULL)
+ cp_check_possible_namespace_symbols (SYMBOL_CPLUS_DEMANGLED_NAME (psym),
+ objfile);
}
-/* Read a partial die corresponding to a namespace. For now, we don't
- do anything with the fact that we're in a namespace; we just read
- the symbols inside of it. */
+/* 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. */
static char *
add_partial_namespace (struct partial_die_info *pdi, char *info_ptr,
struct objfile *objfile,
CORE_ADDR *lowpc, CORE_ADDR *highpc,
- const struct comp_unit_head *cu_header)
+ const struct comp_unit_head *cu_header,
+ const char *namespace)
{
+ /* Calculate the full name of the namespace that we just entered. */
+
+ const char *new_name = pdi->name;
+ char *full_name;
+
+ if (new_name == NULL)
+ new_name = "(anonymous namespace)";
+ full_name = alloca (strlen (namespace) + 2 + strlen (new_name) + 1);
+ strcpy (full_name, namespace);
+ if (*namespace != '\0')
+ 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. */
+
+ add_psymbol_to_list (full_name, strlen (full_name),
+ VAR_DOMAIN, LOC_TYPEDEF,
+ &objfile->global_psymbols,
+ 0, 0, cu_language, objfile);
+
+ /* Now scan partial symbols in that namespace. */
+
if (pdi->has_children)
info_ptr = scan_partial_symbols (info_ptr, objfile,
lowpc, highpc,
- cu_header);
+ cu_header, full_name);
return info_ptr;
}
static char *
add_partial_enumeration (struct partial_die_info *enum_pdi, char *info_ptr,
struct objfile *objfile,
- const struct comp_unit_head *cu_header)
+ const struct comp_unit_head *cu_header,
+ const char *namespace)
{
bfd *abfd = objfile->obfd;
struct partial_die_info pdi;
if (enum_pdi->name != NULL)
- add_partial_symbol (enum_pdi, objfile, cu_header);
+ add_partial_symbol (enum_pdi, objfile, cu_header, namespace);
while (1)
{
if (pdi.tag != DW_TAG_enumerator || pdi.name == NULL)
complaint (&symfile_complaints, "malformed enumerator DIE ignored");
else
- add_partial_symbol (&pdi, objfile, cu_header);
+ add_partial_symbol (&pdi, objfile, cu_header, namespace);
}
return info_ptr;
processing_current_namespace = temp_name;
}
- /* If it's an anonymous namespace that we're seeing for the first
- time, add a using directive. */
+ /* Add a symbol associated to this if we haven't seen the namespace
+ before. Also, add a using directive if it's an anonymous
+ namespace. */
- if (is_anonymous && dwarf_attr (die, DW_AT_extension) == NULL)
- cp_add_using_directive (processing_current_namespace,
- strlen (previous_namespace),
- strlen (processing_current_namespace));
+ if (dwarf2_extension (die) == NULL)
+ {
+ struct type *type;
+
+ /* 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,
+ objfile);
+ TYPE_TAG_NAME (type) = TYPE_NAME (type);
+
+ new_symbol (die, type, objfile, cu_header);
+
+ if (is_anonymous)
+ cp_add_using_directive (processing_current_namespace,
+ strlen (previous_namespace),
+ strlen (processing_current_namespace));
+ }
if (die->has_children)
{
struct attribute *attr2 = NULL;
CORE_ADDR addr = 0;
- name = dwarf2_linkage_name (die);
+ if (die->tag != DW_TAG_namespace)
+ name = dwarf2_linkage_name (die);
+ else
+ name = TYPE_NAME (type);
+
if (name)
{
sym = (struct symbol *) obstack_alloc (&objfile->symbol_obstack,
}
add_symbol_to_list (sym, list_in_scope);
break;
+ case DW_TAG_namespace:
+ SYMBOL_CLASS (sym) = LOC_TYPEDEF;
+ add_symbol_to_list (sym, &global_symbols);
+ break;
default:
/* Not a tag we recognize. Hopefully we aren't processing
trash data, but since we must specifically ignore things
if (name && strcmp (name, "char") == 0)
TYPE_FLAGS (type) |= TYPE_FLAG_NOSIGN;
- if (code == TYPE_CODE_STRUCT || code == TYPE_CODE_UNION)
+ if (code == TYPE_CODE_STRUCT || code == TYPE_CODE_UNION
+ || code == TYPE_CODE_NAMESPACE)
{
INIT_CPLUS_SPECIFIC (type);
}
case TYPE_CODE_TEMPLATE_ARG:
printf_filtered ("(TYPE_CODE_TEMPLATE_ARG)");
break;
+ case TYPE_CODE_NAMESPACE:
+ printf_filtered ("(TYPE_CODE_NAMESPACE)");
+ break;
default:
printf_filtered ("(UNKNOWN TYPE CODE)");
break;
TYPE_CODE_TYPEDEF,
TYPE_CODE_TEMPLATE, /* C++ template */
- TYPE_CODE_TEMPLATE_ARG /* C++ template arg */
+ TYPE_CODE_TEMPLATE_ARG, /* C++ template arg */
+ TYPE_CODE_NAMESPACE, /* C++ namespace. */
};
/* For now allow source to use TYPE_CODE_CLASS for C++ classes, as an
BLOCKVECTOR (class_symtab) = bv;
/* Allocate dummy STATIC_BLOCK. */
- bl = (struct block *)
- obstack_alloc (&objfile->symbol_obstack, sizeof (struct block));
+ bl = allocate_block (&objfile->symbol_obstack);
BLOCK_DICT (bl) = dict_create_linear (&objfile->symbol_obstack,
NULL);
- BLOCK_START (bl) = 0;
- BLOCK_END (bl) = 0;
- BLOCK_FUNCTION (bl) = NULL;
- BLOCK_SUPERBLOCK (bl) = NULL;
- BLOCK_NAMESPACE (bl) = NULL;
- BLOCK_GCC_COMPILED (bl) = 0;
BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK) = bl;
- /* Allocate GLOBAL_BLOCK. This has to be relocatable. */
- bl = (struct block *)
- obstack_alloc (&objfile->symbol_obstack, sizeof (struct block));
- *bl = *BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK);
+ /* Allocate GLOBAL_BLOCK. */
+ bl = allocate_block (&objfile->symbol_obstack);
BLOCK_DICT (bl) = dict_create_hashed_expandable ();
BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK) = bl;
class_symtab->free_func = free_class_block;
/* Initialize the section indexes for this objfile, so that we can
later detect if they are used w/o being properly assigned to. */
- objfile->sect_index_text = -1;
- objfile->sect_index_data = -1;
- objfile->sect_index_bss = -1;
- objfile->sect_index_rodata = -1;
+ objfile->sect_index_text = -1;
+ objfile->sect_index_data = -1;
+ objfile->sect_index_bss = -1;
+ objfile->sect_index_rodata = -1;
+
+ /* We don't yet have a C++-specific namespace symtab. */
+
+ objfile->cp_namespace_symtab = NULL;
/* Add this file onto the tail of the linked list of other such files. */
struct bcache;
struct htab;
+struct symtab;
/* This structure maintains information on a per-objfile basis about the
"entry point" of the objfile, and the scope within which the entry point
/* Place to stash various statistics about this objfile */
OBJSTATS;
+
+ /* A symtab that the C++ code uses to stash special symbols
+ associated to namespaces. */
+
+ /* FIXME/carlton-2003-06-27: Delete this in a few years once
+ "possible namespace symbols" go away. */
+ struct symtab *cp_namespace_symtab;
};
/* Defines for the objfile flag word. */
|| TYPE_CODE (type) == TYPE_CODE_ARRAY
|| TYPE_CODE (type) == TYPE_CODE_STRING
|| TYPE_CODE (type) == TYPE_CODE_STRUCT
- || TYPE_CODE (type) == TYPE_CODE_UNION)
+ || TYPE_CODE (type) == TYPE_CODE_UNION
+ || TYPE_CODE (type) == TYPE_CODE_NAMESPACE)
/* If format is 0, use the 'natural' format for
* that type of value. If the type is non-scalar,
* we have to use language rules to print it as
}
\f
/* Add a symbol with a long value to a psymtab.
- Since one arg is a struct, we pass in a ptr and deref it (sigh). */
-
-void
+ Since one arg is a struct, we pass in a ptr and deref it (sigh).
+ Return the partial symbol that has been added. */
+
+/* NOTE: carlton/2003-09-11: The reason why we return the partial
+ symbol is so that callers can get access to the symbol's demangled
+ name, which they don't have any cheap way to determine otherwise.
+ (Currenly, dwarf2read.c is the only file who uses that information,
+ though it's possible that other readers might in the future.)
+ Elena wasn't thrilled about that, and I don't blame her, but we
+ couldn't come up with a better way to get that information. If
+ it's needed in other situations, we could consider breaking up
+ SYMBOL_SET_NAMES to provide access to the demangled name lookup
+ cache. */
+
+const struct partial_symbol *
add_psymbol_to_list (char *name, int namelength, domain_enum domain,
enum address_class class,
struct psymbol_allocation_list *list, long val, /* Value as a long */
}
*list->next++ = psym;
OBJSTAT (objfile, n_psyms++);
+
+ return psym;
}
/* Add a symbol with a long value to a psymtab. This differs from
/* #include "demangle.h" */
-extern void add_psymbol_to_list (char *, int, domain_enum, enum address_class,
- struct psymbol_allocation_list *, long,
- CORE_ADDR, enum language, struct objfile *);
+extern const
+struct partial_symbol *add_psymbol_to_list (char *, int, domain_enum,
+ enum address_class,
+ struct psymbol_allocation_list *,
+ long, CORE_ADDR,
+ enum language, struct objfile *);
extern void add_psymbol_with_dem_name_to_list (char *, int, char *, int,
domain_enum,
+2003-09-11 David Carlton <carlton@kealia.com>
+
+ * gdb.c++/namespace.exp: Add tests for namespace types.
+ * gdb.c++/maint.exp (test_help): Test 'help maint cp namespace'.
+ (test_namespace): New.
+
2003-09-11 Elena Zannoni <ezannoni@redhat.com>
* gdb.base/relocate.exp: Handle new gdb output at startup.
# Test the help messages.
proc test_help {} {
- gdb_test "help maintenance cplus" "C\\+\\+ maintenance commands.\r\n\r\nList of maintenance cplus subcommands:\r\n\r\nmaintenance cplus first_component -- Print the first class/namespace component of NAME\r\n\r\nType \"help maintenance cplus\" followed by maintenance cplus subcommand name for full documentation.\r\nCommand name abbreviations are allowed if unambiguous."
+ set first_component_help "Print the first class/namespace component of NAME"
+ set namespace_help "Print the list of possible C\\+\\+ namespaces"
- gdb_test "help maint cp" "C\\+\\+ maintenance commands.\r\n\r\nList of maintenance cplus subcommands:\r\n\r\nmaintenance cplus first_component -- Print the first class/namespace component of NAME\r\n\r\nType \"help maintenance cplus\" followed by maintenance cplus subcommand name for full documentation.\r\nCommand name abbreviations are allowed if unambiguous."
+ set multiple_help_body "List of maintenance cplus subcommands:\r\n\r\nmaintenance cplus first_component -- ${first_component_help}\r\nmaintenance cplus namespace -- ${namespace_help}\r\n\r\nType \"help maintenance cplus\" followed by maintenance cplus subcommand name for full documentation.\r\nCommand name abbreviations are allowed if unambiguous."
- gdb_test "maint cp" "\"maintenance cplus\" must be followed by the name of a command.\r\nList of maintenance cplus subcommands:\r\n\r\nmaintenance cplus first_component -- Print the first class/namespace component of NAME\r\n\r\nType \"help maintenance cplus\" followed by maintenance cplus subcommand name for full documentation.\r\nCommand name abbreviations are allowed if unambiguous."
+ set help_maint_cp "C\\+\\+ maintenance commands.\r\n\r\n${multiple_help_body}"
- gdb_test "help maint cp first_component" "Print the first class/namespace component of NAME."
+ gdb_test "help maintenance cplus" "${help_maint_cp}"
+ gdb_test "help maint cp" "${help_maint_cp}"
+ gdb_test "maint cp" "\"maintenance cplus\" must be followed by the name of a command.\r\n${multiple_help_body}"
+
+ gdb_test "help maint cp first_component" "${first_component_help}."
+ gdb_test "help maint cp namespace" "${namespace_help}."
}
# This is used when NAME should contain only a single component. Be
test_invalid_name "bool operator<<char>"
}
+proc test_namespace {} {
+ # There's not a lot we can do to test this.
+
+ gdb_test "maint cp namespace" "Possible namespaces:"
+}
+
gdb_exit
gdb_start
test_help
test_first_component
+test_namespace
gdb_exit
return 0
gdb_test "print 'E::cde'" "\\$\[0-9\].* = 5"
gdb_test "print shadow" "\\$\[0-9\].* = 13"
gdb_test "print cOtherFile" "\\$\[0-9\].* = 316"
+gdb_test "ptype C" "type = namespace C::C"
+gdb_test "ptype E" "type = namespace C::D::E"
# Some anonymous namespace tests.
case TYPE_CODE_MEMBER:
case TYPE_CODE_METHOD:
case TYPE_CODE_REF:
+ case TYPE_CODE_NAMESPACE:
error ("internal error: unhandled type in print_type_scalar");
break;