2003-06-30 David Carlton <carlton@kealia.com>
authorDavid Carlton <carlton@bactrian.org>
Mon, 30 Jun 2003 16:21:16 +0000 (16:21 +0000)
committerDavid Carlton <carlton@bactrian.org>
Mon, 30 Jun 2003 16:21:16 +0000 (16:21 +0000)
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.

gdb/ChangeLog
gdb/Makefile.in
gdb/cp-support.c
gdb/testsuite/ChangeLog
gdb/testsuite/gdb.c++/maint.exp

index 2edf938cd21bd4a66eaeb614a306fa4be86938b2..b57a966c48e199936856e19dbde49b67a4d1b459 100644 (file)
@@ -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
index 8d056d84791bbd731485bd255e4e1a67677ea9c9..e0f80b8e13306c0df06a1cf2079510f5a572d861 100644 (file)
@@ -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) \
index 64b3f89ab53509b462486898d60be56b3d349200..d61e8e484abf78949464cdd56480e9149e408b67 100644 (file)
 #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
index fbd9483f72bbcdda69780df3632180763650bf17..f33dbdeb4ecd30a63db051793f1be71cc3d70720 100644 (file)
@@ -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
index a0f15f96bc5f65143d5aee2786e1041e1c736d76..1042c913ceb76057149f7510b99f6a950c30e18f 100644 (file)
@@ -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