OSDN Git Service

Fix handling of constructor/destructor of standard substitution:
authorian <ian@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 15 Dec 2003 14:37:25 +0000 (14:37 +0000)
committerian <ian@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 15 Dec 2003 14:37:25 +0000 (14:37 +0000)
* cp-demangle.c (struct d_standard_sub_info): Define.
(d_substitution): Add prefix argument.  Change all callers.
Rework handling of standard substitutions to print full name when
qualifying a constructor/destructor, or when DMGL_VERBOSE is set.
* testsuite/demangle-expected: Add test case.

Fix handling of negative literal constants:
* cp-demangle.c (enum d_comp_type): Add D_COMP_LITERAL_NEG.
(d_dump, d_make_comp): Handle D_COMP_LITERAL_NEG.
(d_expr_primary): Use D_COMP_LITERAL_NEG for a negative number.
(d_print_comp): Handle D_COMP_LITERAL_NEG.
* testsuite/demangle-expected: Add test case.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@74632 138bc75d-0d04-0410-961f-82ee72b054a4

libiberty/ChangeLog
libiberty/cp-demangle.c
libiberty/testsuite/demangle-expected

index ef65982..a2a430e 100644 (file)
@@ -1,3 +1,19 @@
+2003-12-15  Ian Lance Taylor  <ian@wasabisystems.com>
+
+       Fix handling of constructor/destructor of standard substitution:
+       * cp-demangle.c (struct d_standard_sub_info): Define.
+       (d_substitution): Add prefix argument.  Change all callers.
+       Rework handling of standard substitutions to print full name when
+       qualifying a constructor/destructor, or when DMGL_VERBOSE is set.
+       * testsuite/demangle-expected: Add test case.
+
+       Fix handling of negative literal constants:
+       * cp-demangle.c (enum d_comp_type): Add D_COMP_LITERAL_NEG.
+       (d_dump, d_make_comp): Handle D_COMP_LITERAL_NEG.
+       (d_expr_primary): Use D_COMP_LITERAL_NEG for a negative number.
+       (d_print_comp): Handle D_COMP_LITERAL_NEG.
+       * testsuite/demangle-expected: Add test case.
+
 2003-12-04  Ian Lance Taylor  <ian@wasabisystems.com>
 
        * cp-demangle.c (IS_UPPER, IS_LOWER): Define.
index a5835df..e675752 100644 (file)
@@ -141,6 +141,23 @@ struct d_builtin_type_info
   enum d_builtin_type_print print;
 };
 
+/* Information we keep for the standard substitutions.  */
+
+struct d_standard_sub_info
+{
+  /* The code for this substitution.  */
+  char code;
+  /* The simple string it expands to.  */
+  const char *simple_expansion;
+  /* The results of a full, verbose, expansion.  This is used when
+     qualifying a constructor/destructor, or when in verbose mode.  */
+  const char *full_expansion;
+  /* What to set the last_name field of d_info to; NULL if we should
+     not set it.  This is only relevant when qualifying a
+     constructor/destructor.  */
+  const char *set_last_name;
+};
+
 /* Component types found in mangled names.  */
 
 enum d_comp_type
@@ -239,7 +256,9 @@ enum d_comp_type
   D_COMP_TRINARY_ARG1,
   D_COMP_TRINARY_ARG2,
   /* A literal.  */
-  D_COMP_LITERAL
+  D_COMP_LITERAL,
+  /* A negative literal.  */
+  D_COMP_LITERAL_NEG
 };
 
 /* A component of the mangled name.  */
@@ -489,7 +508,7 @@ static struct d_comp *d_expr_primary PARAMS ((struct d_info *));
 static struct d_comp *d_local_name PARAMS ((struct d_info *));
 static int d_discriminator PARAMS ((struct d_info *));
 static int d_add_substitution PARAMS ((struct d_info *, struct d_comp *));
-static struct d_comp *d_substitution PARAMS ((struct d_info *));
+static struct d_comp *d_substitution PARAMS ((struct d_info *, int));
 static void d_print_resize PARAMS ((struct d_print_info *, size_t));
 static void d_print_append_char PARAMS ((struct d_print_info *, int));
 static void d_print_append_buffer PARAMS ((struct d_print_info *, const char *,
@@ -683,6 +702,9 @@ d_dump (dc, indent)
     case D_COMP_LITERAL:
       printf ("literal\n");
       break;
+    case D_COMP_LITERAL_NEG:
+      printf ("negative literal\n");
+      break;
     }
 
   d_dump (d_left (dc), indent + 2);
@@ -737,6 +759,7 @@ d_make_comp (di, type, left, right)
     case D_COMP_TRINARY_ARG1:
     case D_COMP_TRINARY_ARG2:
     case D_COMP_LITERAL:
+    case D_COMP_LITERAL_NEG:
       if (left == NULL || right == NULL)
        return NULL;
       break;
@@ -1087,7 +1110,7 @@ d_name (di)
 
        if (d_peek_next_char (di) != 't')
          {
-           dc = d_substitution (di);
+           dc = d_substitution (di, 0);
            subst = 1;
          }
        else
@@ -1202,7 +1225,7 @@ d_prefix (di)
          || peek == 'D')
        dc = d_unqualified_name (di);
       else if (peek == 'S')
-       dc = d_substitution (di);
+       dc = d_substitution (di, 1);
       else if (peek == 'I')
        {
          if (ret == NULL)
@@ -1776,7 +1799,7 @@ d_type (di)
            || peek_next == '_'
            || IS_UPPER (peek_next))
          {
-           ret = d_substitution (di);
+           ret = d_substitution (di, 0);
            /* The substituted name may have been a template name and
               may be followed by tepmlate args.  */
            if (d_peek_char (di) == 'I')
@@ -2254,6 +2277,7 @@ d_expr_primary (di)
   else
     {
       struct d_comp *type;
+      enum d_comp_type t;
       const char *s;
 
       type = d_type (di);
@@ -2269,11 +2293,16 @@ d_expr_primary (di)
         constant in any readable form anyhow.  We don't attempt to
         handle these cases.  */
 
+      t = D_COMP_LITERAL;
+      if (d_peek_char (di) == 'n')
+       {
+         t = D_COMP_LITERAL_NEG;
+         d_advance (di, 1);
+       }
       s = d_str (di);
       while (d_peek_char (di) != 'E')
        d_advance (di, 1);
-      ret = d_make_comp (di, D_COMP_LITERAL, type,
-                        d_make_name (di, s, d_str (di) - s));
+      ret = d_make_comp (di, t, type, d_make_name (di, s, d_str (di) - s));
     }
   if (d_next_char (di) != 'E')
     return NULL;
@@ -2363,11 +2392,39 @@ d_add_substitution (di, dc)
                   ::= Si
                   ::= So
                   ::= Sd
+
+   If PREFIX is non-zero, then this type is being used as a prefix in
+   a qualified name.  In this case, for the standard substitutions, we
+   need to check whether we are being used as a prefix for a
+   constructor or destructor, and return a full template name.
+   Otherwise we will get something like std::iostream::~iostream()
+   which does not correspond particularly well to any function which
+   actually appears in the source.
 */
 
+static const struct d_standard_sub_info standard_subs[] =
+{
+  { 't', "std", "std", NULL },
+  { 'a', "std::allocator", "std::allocator", "allocator" },
+  { 'b', "std::basic_string", "std::basic_string", "basic_string" },
+  { 's', "std::string",
+    "std::basic_string<char, std::char_traits<char>, std::allocator<char> >",
+    "basic_string" },
+  { 'i', "std::istream",
+    "std::basic_istream<char, std::char_traits<char> >",
+    "basic_istream" },
+  { 'o', "std::ostream",
+    "std::basic_ostream<char, std::char_traits<char> >",
+    "basic_ostream" },
+  { 'd', "std::iostream",
+    "std::basic_iostream<char, std::char_traits<char> >",
+    "basic_iostream" }
+};
+
 static struct d_comp *
-d_substitution (di)
+d_substitution (di, prefix)
      struct d_info *di;
+     int prefix;
 {
   char c;
 
@@ -2404,31 +2461,36 @@ d_substitution (di)
     }
   else
     {
-      switch (c)
+      int verbose;
+      const struct d_standard_sub_info *p;
+      const struct d_standard_sub_info *pend;
+
+      verbose = (di->options & DMGL_VERBOSE) != 0;
+      if (! verbose && prefix)
        {
-       case 't':
-         return d_make_sub (di, "std");
-       case 'a':
-         di->last_name = d_make_sub (di, "allocator");
-         return d_make_sub (di, "std::allocator");
-       case 'b':
-         di->last_name = d_make_sub (di, "basic_string");
-         return d_make_sub (di, "std::basic_string");
-       case 's':
-         di->last_name = d_make_sub (di, "string");
-         return d_make_sub (di, "std::string");
-       case 'i':
-         di->last_name = d_make_sub (di, "istream");
-         return d_make_sub (di, "std::istream");
-       case 'o':
-         di->last_name = d_make_sub (di, "ostream");
-         return d_make_sub (di, "std::ostream");
-       case 'd':
-         di->last_name = d_make_sub (di, "iostream");
-         return d_make_sub (di, "std::iostream");
-       default:
-         return NULL;
+         char peek;
+
+         peek = d_peek_char (di);
+         if (peek == 'C' || peek == 'D')
+           verbose = 1;
        }
+
+      pend = (&standard_subs[0]
+             + sizeof standard_subs / sizeof standard_subs[0]);
+      for (p = &standard_subs[0]; p < pend; ++p)
+       {
+         if (c == p->code)
+           {
+             if (p->set_last_name != NULL)
+               di->last_name = d_make_sub (di, p->set_last_name);
+             if (verbose)
+               return d_make_sub (di, p->full_expansion);
+             else
+               return d_make_sub (di, p->simple_expansion);
+           }
+       }
+
+      return NULL;
     }
 }
 
@@ -3031,6 +3093,7 @@ d_print_comp (dpi, dc)
       return;
 
     case D_COMP_LITERAL:
+    case D_COMP_LITERAL_NEG:
       /* For some builtin types, produce simpler output.  */
       if (d_left (dc)->type == D_COMP_BUILTIN_TYPE)
        {
@@ -3039,6 +3102,8 @@ d_print_comp (dpi, dc)
            case D_PRINT_INT:
              if (d_right (dc)->type == D_COMP_NAME)
                {
+                 if (dc->type == D_COMP_LITERAL_NEG)
+                   d_append_char (dpi, '-');
                  d_print_comp (dpi, d_right (dc));
                  return;
                }
@@ -3047,6 +3112,8 @@ d_print_comp (dpi, dc)
            case D_PRINT_LONG:
              if (d_right (dc)->type == D_COMP_NAME)
                {
+                 if (dc->type == D_COMP_LITERAL_NEG)
+                   d_append_char (dpi, '-');
                  d_print_comp (dpi, d_right (dc));
                  d_append_char (dpi, 'l');
                  return;
@@ -3055,7 +3122,8 @@ d_print_comp (dpi, dc)
 
            case D_PRINT_BOOL:
              if (d_right (dc)->type == D_COMP_NAME
-                 && d_right (dc)->u.s_name.len == 1)
+                 && d_right (dc)->u.s_name.len == 1
+                 && dc->type == D_COMP_LITERAL)
                {
                  switch (d_right (dc)->u.s_name.s[0])
                    {
@@ -3079,6 +3147,8 @@ d_print_comp (dpi, dc)
       d_append_char (dpi, '(');
       d_print_comp (dpi, d_left (dc));
       d_append_char (dpi, ')');
+      if (dc->type == D_COMP_LITERAL_NEG)
+       d_append_char (dpi, '-');
       d_print_comp (dpi, d_right (dc));
       return;
 
index c47c6ae..b39e2f4 100644 (file)
@@ -2905,7 +2905,17 @@ bool std::operator< <file_path, std::string>(std::pair<file_path, std::string> c
 --format=gnu-v3
 _Z9hairyfuncM1YKFPVPFrPA2_PM1XKFKPA3_ilEPcEiE
 hairyfunc(int (* const (X::** (* restrict (* volatile*(Y::*)(int) const)(char*)) [2])(long) const) [3])
-# 
+#
+# Check that negative numbers are handled correctly.
+--format=gnu-v3
+_Z1fILin1EEvv
+void f<-1>()
+#
+# Check a destructor of a standard substitution.
+--format=gnu-v3
+_ZNSdD0Ev
+std::basic_iostream<char, std::char_traits<char> >::~basic_iostream()
+#
 # This caused an infinite loop.
 #
 # This is generated by an EDG compiler (kcc 4.0).  To demangle it