From b2a7f303a272232ff87fa82f7d1cd23377ef0b01 Mon Sep 17 00:00:00 2001 From: David Carlton Date: Mon, 30 Jun 2003 16:21:16 +0000 Subject: [PATCH] 2003-06-30 David Carlton 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 * gdb.c++/maint.exp (test_invalid_name): New. (test_first_component): Add tests for invalid names. --- gdb/ChangeLog | 11 +++++ gdb/Makefile.in | 2 +- gdb/cp-support.c | 72 +++++++++++++++++++++++++++------ gdb/testsuite/ChangeLog | 5 +++ gdb/testsuite/gdb.c++/maint.exp | 22 ++++++++++ 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 + + 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 * 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 + + * gdb.c++/maint.exp (test_invalid_name): New. + (test_first_component): Add tests for invalid names. + 2003-06-29 Michael Chastain * 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::bar" "C" gdb_test "maint cp first_component C > >::bar" "C > >" + + # 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<" } gdb_exit -- 2.30.2