+
+ /* 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);
+}
+
+/* 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. */
+
+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)
+{
+ struct objfile *objfile = cu->objfile;
+ const char *new_name = pdi->name;
+ char *full_name;
+
+ /* Calculate the full name of the namespace that we just entered. */
+
+ 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-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,
+ &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, lowpc, highpc, cu, full_name);
+
+ 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 || namespace[0] == '\0')
+ && struct_pdi->name != NULL
+ && struct_pdi->has_children)
+ {
+ /* See if we can figure out if the class lives in a namespace
+ (or is nested within another class.) We do this by looking
+ 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). */
+
+ /* FIXME: carlton/2004-01-23: If NAMESPACE equals "", we have
+ the appropriate debug information, so it would be nice to be
+ able to avoid this hack. But NAMESPACE may not be the
+ namespace where this class was defined: NAMESPACE reflects
+ where STRUCT_PDI occurs in the tree of dies, but because of
+ DW_AT_specification, that may not actually tell us where the
+ class is defined. (See the comment in read_func_scope for an
+ example of how this could occur.)
+
+ Unfortunately, our current partial symtab data structures are
+ completely unable to deal with DW_AT_specification. So, for
+ now, the best thing to do is to get nesting information from
+ places other than the tree structure of dies if there's any
+ chance that a DW_AT_specification is involved. :-( */
+
+ 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 *
+add_partial_enumeration (struct partial_die_info *enum_pdi, char *info_ptr,
+ struct dwarf2_cu *cu, const char *namespace)
+{
+ struct objfile *objfile = cu->objfile;
+ bfd *abfd = objfile->obfd;
+ struct partial_die_info pdi;
+
+ if (enum_pdi->name != NULL)
+ add_partial_symbol (enum_pdi, cu, namespace);
+
+ while (1)
+ {
+ info_ptr = read_partial_die (&pdi, abfd, info_ptr, cu);
+ if (pdi.tag == 0)
+ break;
+ if (pdi.tag != DW_TAG_enumerator || pdi.name == NULL)
+ complaint (&symfile_complaints, "malformed enumerator DIE ignored");
+ else
+ add_partial_symbol (&pdi, cu, namespace);
+ }
+
+ return info_ptr;
+}
+
+/* Locate ORIG_PDI's sibling; INFO_PTR should point to the next DIE
+ after ORIG_PDI. */
+
+static char *
+locate_pdi_sibling (struct partial_die_info *orig_pdi, char *info_ptr,
+ bfd *abfd, struct dwarf2_cu *cu)
+{
+ /* Do we know the sibling already? */
+
+ if (orig_pdi->sibling)
+ return orig_pdi->sibling;
+
+ /* Are there any children to deal with? */
+
+ if (!orig_pdi->has_children)
+ return info_ptr;
+
+ /* Okay, we don't know the sibling, but we have children that we
+ want to skip. So read children until we run into one without a
+ tag; return whatever follows it. */
+
+ while (1)
+ {
+ struct partial_die_info pdi;
+
+ info_ptr = read_partial_die (&pdi, abfd, info_ptr, cu);
+
+ if (pdi.tag == 0)
+ return info_ptr;
+ else
+ info_ptr = locate_pdi_sibling (&pdi, info_ptr, abfd, cu);
+ }