aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gdb/ChangeLog16
-rw-r--r--gdb/c-exp.y4
-rw-r--r--gdb/cp-namespace.c8
-rw-r--r--gdb/dwarf2read.c16
-rw-r--r--gdb/gdbtypes.c26
-rw-r--r--gdb/gdbtypes.h2
-rw-r--r--gdb/valops.c10
-rw-r--r--gdb/value.h2
8 files changed, 75 insertions, 9 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index b92b762..02689af 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,21 @@
2011-05-06 Jan Kratochvil <jan.kratochvil@redhat.com>
+ * c-exp.y (qualified_name): Call destructor_name_p with $1.type.
+ (classify_inner_name): Call cp_lookup_nested_type with
+ yylval.tsym.type.
+ * cp-namespace.c (cp_lookup_nested_type): New variable
+ saved_parent_type. Call CHECK_TYPEDEF for parent_type. Call
+ type_name_no_tag_or_error with saved_parent_type.
+ * dwarf2read.c (load_partial_dies): Read in any children of
+ DW_TAG_typedef with complaint in such case.
+ * gdbtypes.c (type_name_no_tag_or_error): New function.
+ * gdbtypes.h (type_name_no_tag_or_error): New prototype.
+ * valops.c (destructor_name_p): New comment for parameter type. Remove
+ type const. Make dname and cp const. Call type_name_no_tag_or_error.
+ * value.h (destructor_name_p): Remove type const.
+
+2011-05-06 Jan Kratochvil <jan.kratochvil@redhat.com>
+
* symtab.c (compare_symbol_name): New function.
(completion_list_add_name, expand_partial_symbol_name): Call it,
remove the variable ncmp.
diff --git a/gdb/c-exp.y b/gdb/c-exp.y
index 3a02e9d..94d0737 100644
--- a/gdb/c-exp.y
+++ b/gdb/c-exp.y
@@ -804,7 +804,7 @@ qualified_name: TYPENAME COLONCOLON name
tmp_token.ptr[tmp_token.length] = 0;
/* Check for valid destructor name. */
- destructor_name_p (tmp_token.ptr, type);
+ destructor_name_p (tmp_token.ptr, $1.type);
write_exp_elt_opcode (OP_SCOPE);
write_exp_elt_type (type);
write_exp_string (tmp_token);
@@ -2486,7 +2486,7 @@ classify_inner_name (struct block *block, int first_name)
return NAME;
copy = copy_name (yylval.tsym.stoken);
- new_type = cp_lookup_nested_type (type, copy, block);
+ new_type = cp_lookup_nested_type (yylval.tsym.type, copy, block);
if (new_type == NULL)
/* We know the caller won't expect us to update yylval. */
diff --git a/gdb/cp-namespace.c b/gdb/cp-namespace.c
index 030cfb9..00c68b3 100644
--- a/gdb/cp-namespace.c
+++ b/gdb/cp-namespace.c
@@ -630,6 +630,12 @@ cp_lookup_nested_type (struct type *parent_type,
const char *nested_name,
const struct block *block)
{
+ /* type_name_no_tag_required provides better error reporting using the
+ original type. */
+ struct type *saved_parent_type = parent_type;
+
+ CHECK_TYPEDEF (parent_type);
+
switch (TYPE_CODE (parent_type))
{
case TYPE_CODE_STRUCT:
@@ -643,7 +649,7 @@ cp_lookup_nested_type (struct type *parent_type,
just like members of namespaces; in particular,
lookup_symbol_namespace works when looking them up. */
- const char *parent_name = TYPE_TAG_NAME (parent_type);
+ const char *parent_name = type_name_no_tag_or_error (saved_parent_type);
struct symbol *sym
= cp_lookup_symbol_in_namespace (parent_name, nested_name,
block, VAR_DOMAIN);
diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c
index fdab83d..eb5d924 100644
--- a/gdb/dwarf2read.c
+++ b/gdb/dwarf2read.c
@@ -8946,7 +8946,7 @@ load_partial_dies (bfd *abfd, gdb_byte *buffer, gdb_byte *info_ptr,
if (parent_die == NULL
&& part_die->has_specification == 0
&& part_die->is_declaration == 0
- && (part_die->tag == DW_TAG_typedef
+ && ((part_die->tag == DW_TAG_typedef && !part_die->has_children)
|| part_die->tag == DW_TAG_base_type
|| part_die->tag == DW_TAG_subrange_type))
{
@@ -8959,6 +8959,20 @@ load_partial_dies (bfd *abfd, gdb_byte *buffer, gdb_byte *info_ptr,
continue;
}
+ /* The exception for DW_TAG_typedef with has_children above is
+ a workaround of GCC PR debug/47510. In the case of this complaint
+ type_name_no_tag_or_error will error on such types later.
+
+ GDB skipped children of DW_TAG_typedef by the shortcut above and then
+ it could not find the child DIEs referenced later, this is checked
+ above. In correct DWARF DW_TAG_typedef should have no children. */
+
+ if (part_die->tag == DW_TAG_typedef && part_die->has_children)
+ complaint (&symfile_complaints,
+ _("DW_TAG_typedef has childen - GCC PR debug/47510 bug "
+ "- DIE at 0x%x [in module %s]"),
+ part_die->offset, cu->objfile->name);
+
/* If we're at the second level, and we're an enumerator, and
our parent has no specification (meaning possibly lives in a
namespace elsewhere), then we can add the partial symbol now
diff --git a/gdb/gdbtypes.c b/gdb/gdbtypes.c
index 3b45931..2bdb4eb 100644
--- a/gdb/gdbtypes.c
+++ b/gdb/gdbtypes.c
@@ -1105,6 +1105,32 @@ type_name_no_tag (const struct type *type)
return TYPE_NAME (type);
}
+/* A wrapper of type_name_no_tag which calls error if the type is anonymous.
+ Since GCC PR debug/47510 DWARF provides associated information to detect the
+ anonymous class linkage name from its typedef.
+
+ Parameter TYPE should not yet have CHECK_TYPEDEF applied, this function will
+ apply it itself. */
+
+const char *
+type_name_no_tag_or_error (struct type *type)
+{
+ struct type *saved_type = type;
+ const char *name;
+ struct objfile *objfile;
+
+ CHECK_TYPEDEF (type);
+
+ name = type_name_no_tag (type);
+ if (name != NULL)
+ return name;
+
+ name = type_name_no_tag (saved_type);
+ objfile = TYPE_OBJFILE (saved_type);
+ error (_("Invalid anonymous type %s [in module %s], GCC PR debug/47510 bug?"),
+ name ? name : "<anonymous>", objfile ? objfile->name : "<arch>");
+}
+
/* Lookup a typedef or primitive type named NAME, visible in lexical
block BLOCK. If NOERR is nonzero, return zero if NAME is not
suitably defined. */
diff --git a/gdb/gdbtypes.h b/gdb/gdbtypes.h
index 39ca1b4..5a588a2 100644
--- a/gdb/gdbtypes.h
+++ b/gdb/gdbtypes.h
@@ -1362,6 +1362,8 @@ extern struct type *allocate_stub_method (struct type *);
extern char *type_name_no_tag (const struct type *);
+extern const char *type_name_no_tag_or_error (struct type *type);
+
extern struct type *lookup_struct_elt_type (struct type *, char *, int);
extern struct type *make_pointer_type (struct type *, struct type **);
diff --git a/gdb/valops.c b/gdb/valops.c
index 99115b7..3676103 100644
--- a/gdb/valops.c
+++ b/gdb/valops.c
@@ -3098,14 +3098,16 @@ classify_oload_match (struct badness_vector *oload_champ_bv,
/* C++: return 1 is NAME is a legitimate name for the destructor of
type TYPE. If TYPE does not have a destructor, or if NAME is
- inappropriate for TYPE, an error is signaled. */
+ inappropriate for TYPE, an error is signaled. Parameter TYPE should not yet
+ have CHECK_TYPEDEF applied, this function will apply it itself. */
+
int
-destructor_name_p (const char *name, const struct type *type)
+destructor_name_p (const char *name, struct type *type)
{
if (name[0] == '~')
{
- char *dname = type_name_no_tag (type);
- char *cp = strchr (dname, '<');
+ const char *dname = type_name_no_tag_or_error (type);
+ const char *cp = strchr (dname, '<');
unsigned int len;
/* Do not compare the template part for template classes. */
diff --git a/gdb/value.h b/gdb/value.h
index 0889cef..4c42633 100644
--- a/gdb/value.h
+++ b/gdb/value.h
@@ -736,7 +736,7 @@ extern int binop_user_defined_p (enum exp_opcode op, struct value *arg1,
extern int unop_user_defined_p (enum exp_opcode op, struct value *arg1);
-extern int destructor_name_p (const char *name, const struct type *type);
+extern int destructor_name_p (const char *name, struct type *type);
extern void value_incref (struct value *val);