summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Carlton <carlton@bactrian.org>2003-06-30 16:21:16 +0000
committerDavid Carlton <carlton@bactrian.org>2003-06-30 16:21:16 +0000
commit4902d5fb09e510b4355b5374df076d9b716d2def (patch)
tree2fc860d1b28be43518506aa0ef855333b39af51e
parent78b2b1f0724687c741d367784dbb049b59265d38 (diff)
downloadgdb-4902d5fb09e510b4355b5374df076d9b716d2def.tar.gz
2003-06-30 David Carlton <carlton@kealia.com>
Band-aid for PR c++/1245. * Makefile.in (cp-support.o): Depend on complaints_h. * cp-support.c: Include complaints.h. Add declaration for find_last_component. (cp_find_first_component): Separate code into cp_find_first_component_aux. (cp_find_first_component_aux): Call demangled_name_complaint. (demangled_name_complaint): New. 2003-06-30 David Carlton <carlton@kealia.com> * gdb.c++/maint.exp (test_invalid_name): New. (test_first_component): Add tests for invalid names.
-rw-r--r--gdb/ChangeLog11
-rw-r--r--gdb/Makefile.in2
-rw-r--r--gdb/cp-support.c72
-rw-r--r--gdb/testsuite/ChangeLog5
-rw-r--r--gdb/testsuite/gdb.c++/maint.exp22
5 files changed, 98 insertions, 14 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 2edf938cd21..b57a966c48e 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,14 @@
+2003-06-30 David Carlton <carlton@kealia.com>
+
+ Band-aid for PR c++/1245.
+ * Makefile.in (cp-support.o): Depend on complaints_h.
+ * cp-support.c: Include complaints.h. Add declaration for
+ find_last_component.
+ (cp_find_first_component): Separate code into
+ cp_find_first_component_aux.
+ (cp_find_first_component_aux): Call demangled_name_complaint.
+ (demangled_name_complaint): New.
+
2003-06-30 Andrew Cagney <cagney@redhat.com>
* remote.c (remote_write_bytes): Explicitly compute and then use
diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index 8d056d84791..e0f80b8e133 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -1647,7 +1647,7 @@ cp-namespace.o: cp-namespace.c $(defs_h) $(cp_support_h) $(gdb_obstack_h) \
$(symtab_h) $(symfile_h) $(gdb_assert_h) $(block_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) $(block_h)
+ $(objfiles_h) $(frame_h) $(block_h) $(complaints_h)
cp-valprint.o: cp-valprint.c $(defs_h) $(gdb_obstack_h) $(symtab_h) \
$(gdbtypes_h) $(expression_h) $(value_h) $(command_h) $(gdbcmd_h) \
$(demangle_h) $(annotate_h) $(gdb_string_h) $(c_lang_h) $(target_h) \
diff --git a/gdb/cp-support.c b/gdb/cp-support.c
index 64b3f89ab53..d61e8e484ab 100644
--- a/gdb/cp-support.c
+++ b/gdb/cp-support.c
@@ -32,6 +32,16 @@
#include "frame.h"
#include "symtab.h"
#include "block.h"
+#include "complaints.h"
+
+/* Functions related to demangled name parsing. */
+
+static const char *find_last_component (const char *name);
+
+static unsigned int cp_find_first_component_aux (const char *name,
+ int permissive);
+
+static void demangled_name_complaint (const char *name);
/* Functions/variables related to overload resolution. */
@@ -199,21 +209,32 @@ method_name_from_physname (const char *physname)
boundary of the first component: so, given 'A::foo' or 'A::B::foo'
it returns the 1, and given 'foo', it returns 0. */
-/* Well, that's what it should do when called externally, but to make
- the recursion easier, it also stops if it reaches an unexpected ')'
- or '>'. */
+/* The character in NAME indexed by the return value is guaranteed to
+ always be either ':' or '\0'. */
/* NOTE: carlton/2003-03-13: This function is currently only intended
for internal use: it's probably not entirely safe when called on
- user-generated input, because some of the 'index += 2' lines might
- go past the end of malformed input. */
+ user-generated input, because some of the 'index += 2' lines in
+ cp_find_first_component_aux might go past the end of malformed
+ input. */
+
+unsigned int
+cp_find_first_component (const char *name)
+{
+ return cp_find_first_component_aux (name, 0);
+}
+
+/* Helper function for cp_find_first_component. Like that function,
+ it returns the length of the first component of NAME, but to make
+ the recursion easier, it also stops if it reaches an unexpected ')'
+ or '>' if the value of PERMISSIVE is nonzero. */
/* Let's optimize away calls to strlen("operator"). */
#define LENGTH_OF_OPERATOR 8
-unsigned int
-cp_find_first_component (const char *name)
+static unsigned int
+cp_find_first_component_aux (const char *name, int permissive)
{
unsigned int index = 0;
/* Operator names can show up in unexpected places. Since these can
@@ -234,11 +255,15 @@ cp_find_first_component (const char *name)
terminating the component or a '::' between two
components. (Hence the '+ 2'.) */
index += 1;
- for (index += cp_find_first_component (name + index);
+ for (index += cp_find_first_component_aux (name + index, 1);
name[index] != '>';
- index += cp_find_first_component (name + index))
+ index += cp_find_first_component_aux (name + index, 1))
{
- gdb_assert (name[index] == ':');
+ if (name[index] != ':')
+ {
+ demangled_name_complaint (name);
+ return strlen (name);
+ }
index += 2;
}
operator_possible = 1;
@@ -246,17 +271,28 @@ cp_find_first_component (const char *name)
case '(':
/* Similar comment as to '<'. */
index += 1;
- for (index += cp_find_first_component (name + index);
+ for (index += cp_find_first_component_aux (name + index, 1);
name[index] != ')';
- index += cp_find_first_component (name + index))
+ index += cp_find_first_component_aux (name + index, 1))
{
- gdb_assert (name[index] == ':');
+ if (name[index] != ':')
+ {
+ demangled_name_complaint (name);
+ return strlen (name);
+ }
index += 2;
}
operator_possible = 1;
break;
case '>':
case ')':
+ if (permissive)
+ return index;
+ else
+ {
+ demangled_name_complaint (name);
+ return strlen (name);
+ }
case '\0':
case ':':
return index;
@@ -315,6 +351,16 @@ cp_find_first_component (const char *name)
}
}
+/* Complain about a demangled name that we don't know how to parse.
+ NAME is the demangled name in question. */
+
+static void
+demangled_name_complaint (const char *name)
+{
+ complaint (&symfile_complaints,
+ "unexpected demangled name '%s'", name);
+}
+
/* If NAME is the fully-qualified name of a C++
function/variable/method/etc., this returns the length of its
entire prefix: all of the namespaces and classes that make up its
diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog
index fbd9483f72b..f33dbdeb4ec 100644
--- a/gdb/testsuite/ChangeLog
+++ b/gdb/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2003-06-30 David Carlton <carlton@kealia.com>
+
+ * gdb.c++/maint.exp (test_invalid_name): New.
+ (test_first_component): Add tests for invalid names.
+
2003-06-29 Michael Chastain <mec@shout.net>
* gdb.c++/inherit.exp (test_print_svi_classes): Accept gdb
diff --git a/gdb/testsuite/gdb.c++/maint.exp b/gdb/testsuite/gdb.c++/maint.exp
index a0f15f96bc5..1042c913ceb 100644
--- a/gdb/testsuite/gdb.c++/maint.exp
+++ b/gdb/testsuite/gdb.c++/maint.exp
@@ -45,7 +45,19 @@ proc test_single_component {name} {
gdb_test "maint cp first_component $name" "$matchname"
}
+# This is used when NAME is invalid.
+proc test_invalid_name {name} {
+ set matchname [string_to_regexp "$name"]
+ gdb_test "maint cp first_component $name" \
+ "During symbol reading, unexpected demangled name '$matchname'.\r\n$matchname"
+}
+
proc test_first_component {} {
+ # The function in question might complain; make sure that we see
+ # all complaints.
+
+ gdb_test "set complaints -1" ""
+
test_single_component "foo"
test_single_component "operator<<"
test_single_component "operator>>"
@@ -79,6 +91,16 @@ proc test_first_component {} {
gdb_test "maint cp first_component foo::bar::baz" "foo"
gdb_test "maint cp first_component C<A>::bar" "C<A>"
gdb_test "maint cp first_component C<std::basic_streambuf<wchar_t,std::char_traits<wchar_t> > >::bar" "C<std::basic_streambuf<wchar_t,std::char_traits<wchar_t> > >"
+
+ # Make sure we behave appropriately on invalid input.
+
+ # NOTE: carlton/2003-06-25: As of today, the demangler can in fact
+ # produce examples like the third case below: there really should
+ # be a space between the two <'s. See PR gdb/1245.
+
+ test_invalid_name "foo<"
+ test_invalid_name "foo("
+ test_invalid_name "bool operator<<char>"
}
gdb_exit