OSDN Git Service

* cp-demangle.h: Add comment explaining what to do to avoid
[pf3gnuchains/gcc-fork.git] / libiberty / cp-demangle.c
index 6c7e859..ac1dfe5 100644 (file)
@@ -1,5 +1,5 @@
 /* Demangler for g++ V3 ABI.
-   Copyright (C) 2003, 2004 Free Software Foundation, Inc.
+   Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc.
    Written by Ian Lance Taylor <ian@wasabisystems.com>.
 
    This file is part of the libiberty library, which is part of GCC.
@@ -25,7 +25,7 @@
 
    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
-   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 
+   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. 
 */
 
 /* This code implements a demangler for the g++ V3 ABI.  The ABI is
@@ -210,7 +210,7 @@ struct d_print_template
   /* Next template on the list.  */
   struct d_print_template *next;
   /* This template.  */
-  const struct demangle_component *template;
+  const struct demangle_component *template_decl;
 };
 
 /* A list of type modifiers.  This is used while printing.  */
@@ -520,6 +520,9 @@ d_dump (struct demangle_component *dc, int indent)
     case DEMANGLE_COMPONENT_REFTEMP:
       printf ("reference temporary\n");
       break;
+    case DEMANGLE_COMPONENT_HIDDEN_ALIAS:
+      printf ("hidden alias\n");
+      break;
     case DEMANGLE_COMPONENT_RESTRICT:
       printf ("restrict\n");
       break;
@@ -733,6 +736,7 @@ d_make_comp (struct d_info *di, enum demangle_component_type type,
     case DEMANGLE_COMPONENT_JAVA_CLASS:
     case DEMANGLE_COMPONENT_GUARD:
     case DEMANGLE_COMPONENT_REFTEMP:
+    case DEMANGLE_COMPONENT_HIDDEN_ALIAS:
     case DEMANGLE_COMPONENT_POINTER:
     case DEMANGLE_COMPONENT_REFERENCE:
     case DEMANGLE_COMPONENT_COMPLEX:
@@ -909,9 +913,9 @@ CP_STATIC_IF_GLIBCPP_V3
 struct demangle_component *
 cplus_demangle_mangled_name (struct d_info *di, int top_level)
 {
-  if (d_next_char (di) != '_')
+  if (! d_check_char (di, '_'))
     return NULL;
-  if (d_next_char (di) != 'Z')
+  if (! d_check_char (di, 'Z'))
     return NULL;
   return d_encoding (di, top_level);
 }
@@ -1119,7 +1123,7 @@ d_nested_name (struct d_info *di)
   struct demangle_component *ret;
   struct demangle_component **pret;
 
-  if (d_next_char (di) != 'N')
+  if (! d_check_char (di, 'N'))
     return NULL;
 
   pret = d_cv_qualifiers (di, &ret, 1);
@@ -1130,7 +1134,7 @@ d_nested_name (struct d_info *di)
   if (*pret == NULL)
     return NULL;
 
-  if (d_next_char (di) != 'E')
+  if (! d_check_char (di, 'E'))
     return NULL;
 
   return ret;
@@ -1439,16 +1443,14 @@ d_operator_name (struct d_info *di)
                   ::= TF <type>
                   ::= TJ <type>
                   ::= GR <name>
+                 ::= GA <encoding>
 */
 
 static struct demangle_component *
 d_special_name (struct d_info *di)
 {
-  char c;
-
   di->expansion += 20;
-  c = d_next_char (di);
-  if (c == 'T')
+  if (d_check_char (di, 'T'))
     {
       switch (d_next_char (di))
        {
@@ -1497,7 +1499,7 @@ d_special_name (struct d_info *di)
            offset = d_number (di);
            if (offset < 0)
              return NULL;
-           if (d_next_char (di) != '_')
+           if (! d_check_char (di, '_'))
              return NULL;
            base_type = cplus_demangle_type (di);
            /* We don't display the offset.  FIXME: We should display
@@ -1518,7 +1520,7 @@ d_special_name (struct d_info *di)
          return NULL;
        }
     }
-  else if (c == 'G')
+  else if (d_check_char (di, 'G'))
     {
       switch (d_next_char (di))
        {
@@ -1529,6 +1531,10 @@ d_special_name (struct d_info *di)
          return d_make_comp (di, DEMANGLE_COMPONENT_REFTEMP, d_name (di),
                              NULL);
 
+       case 'A':
+         return d_make_comp (di, DEMANGLE_COMPONENT_HIDDEN_ALIAS,
+                             d_encoding (di, 0), NULL);
+
        default:
          return NULL;
        }
@@ -1561,14 +1567,14 @@ d_call_offset (struct d_info *di, int c)
   else if (c == 'v')
     {
       d_number (di);
-      if (d_next_char (di) != '_')
+      if (! d_check_char (di, '_'))
        return 0;
       d_number (di);
     }
   else
     return 0;
 
-  if (d_next_char (di) != '_')
+  if (! d_check_char (di, '_'))
     return 0;
 
   return 1;
@@ -1592,13 +1598,13 @@ d_ctor_dtor_name (struct d_info *di)
       else if (di->last_name->type == DEMANGLE_COMPONENT_SUB_STD)
        di->expansion += di->last_name->u.s_string.len;
     }
-  switch (d_next_char (di))
+  switch (d_peek_char (di))
     {
     case 'C':
       {
        enum gnu_v3_ctor_kinds kind;
 
-       switch (d_next_char (di))
+       switch (d_peek_next_char (di))
          {
          case '1':
            kind = gnu_v3_complete_object_ctor;
@@ -1612,6 +1618,7 @@ d_ctor_dtor_name (struct d_info *di)
          default:
            return NULL;
          }
+       d_advance (di, 2);
        return d_make_ctor (di, kind, di->last_name);
       }
 
@@ -1619,7 +1626,7 @@ d_ctor_dtor_name (struct d_info *di)
       {
        enum gnu_v3_dtor_kinds kind;
 
-       switch (d_next_char (di))
+       switch (d_peek_next_char (di))
          {
          case '0':
            kind = gnu_v3_deleting_dtor;
@@ -1633,6 +1640,7 @@ d_ctor_dtor_name (struct d_info *di)
          default:
            return NULL;
          }
+       d_advance (di, 2);
        return d_make_dtor (di, kind, di->last_name);
       }
 
@@ -1916,7 +1924,7 @@ d_function_type (struct d_info *di)
 {
   struct demangle_component *ret;
 
-  if (d_next_char (di) != 'F')
+  if (! d_check_char (di, 'F'))
     return NULL;
   if (d_peek_char (di) == 'Y')
     {
@@ -1925,12 +1933,12 @@ d_function_type (struct d_info *di)
       d_advance (di, 1);
     }
   ret = d_bare_function_type (di, 1);
-  if (d_next_char (di) != 'E')
+  if (! d_check_char (di, 'E'))
     return NULL;
   return ret;
 }
 
-/* <bare-function-type> ::= <type>+  */
+/* <bare-function-type> ::= [J]<type>+  */
 
 static struct demangle_component *
 d_bare_function_type (struct d_info *di, int has_return_type)
@@ -1938,13 +1946,22 @@ d_bare_function_type (struct d_info *di, int has_return_type)
   struct demangle_component *return_type;
   struct demangle_component *tl;
   struct demangle_component **ptl;
+  char peek;
+
+  /* Detect special qualifier indicating that the first argument
+     is the return type.  */
+  peek = d_peek_char (di);
+  if (peek == 'J')
+    {
+      d_advance (di, 1);
+      has_return_type = 1;
+    }
 
   return_type = NULL;
   tl = NULL;
   ptl = &tl;
   while (1)
     {
-      char peek;
       struct demangle_component *type;
 
       peek = d_peek_char (di);
@@ -2003,7 +2020,7 @@ d_array_type (struct d_info *di)
   char peek;
   struct demangle_component *dim;
 
-  if (d_next_char (di) != 'A')
+  if (! d_check_char (di, 'A'))
     return NULL;
 
   peek = d_peek_char (di);
@@ -2031,7 +2048,7 @@ d_array_type (struct d_info *di)
        return NULL;
     }
 
-  if (d_next_char (di) != '_')
+  if (! d_check_char (di, '_'))
     return NULL;
 
   return d_make_comp (di, DEMANGLE_COMPONENT_ARRAY_TYPE, dim,
@@ -2047,7 +2064,7 @@ d_pointer_to_member_type (struct d_info *di)
   struct demangle_component *mem;
   struct demangle_component **pmem;
 
-  if (d_next_char (di) != 'M')
+  if (! d_check_char (di, 'M'))
     return NULL;
 
   cl = cplus_demangle_type (di);
@@ -2063,13 +2080,22 @@ d_pointer_to_member_type (struct d_info *di)
      g++ does not work that way.  g++ treats only the CV-qualified
      member function as a substitution source.  FIXME.  So to work
      with g++, we need to pull off the CV-qualifiers here, in order to
-     avoid calling add_substitution() in cplus_demangle_type().  */
+     avoid calling add_substitution() in cplus_demangle_type().  But
+     for a CV-qualified member which is not a function, g++ does
+     follow the ABI, so we need to handle that case here by calling
+     d_add_substitution ourselves.  */
 
   pmem = d_cv_qualifiers (di, &mem, 1);
   if (pmem == NULL)
     return NULL;
   *pmem = cplus_demangle_type (di);
 
+  if (pmem != &mem && (*pmem)->type != DEMANGLE_COMPONENT_FUNCTION_TYPE)
+    {
+      if (! d_add_substitution (di, mem))
+       return NULL;
+    }
+
   return d_make_comp (di, DEMANGLE_COMPONENT_PTRMEM_TYPE, cl, mem);
 }
 
@@ -2082,7 +2108,7 @@ d_template_param (struct d_info *di)
 {
   long param;
 
-  if (d_next_char (di) != 'T')
+  if (! d_check_char (di, 'T'))
     return NULL;
 
   if (d_peek_char (di) == '_')
@@ -2095,7 +2121,7 @@ d_template_param (struct d_info *di)
       param += 1;
     }
 
-  if (d_next_char (di) != '_')
+  if (! d_check_char (di, '_'))
     return NULL;
 
   ++di->did_subs;
@@ -2117,7 +2143,7 @@ d_template_args (struct d_info *di)
      constructor or destructor.  */
   hold_last_name = di->last_name;
 
-  if (d_next_char (di) != 'I')
+  if (! d_check_char (di, 'I'))
     return NULL;
 
   al = NULL;
@@ -2162,7 +2188,7 @@ d_template_arg (struct d_info *di)
     case 'X':
       d_advance (di, 1);
       ret = d_expression (di);
-      if (d_next_char (di) != 'E')
+      if (! d_check_char (di, 'E'))
        return NULL;
       return ret;
 
@@ -2289,7 +2315,7 @@ d_expr_primary (struct d_info *di)
 {
   struct demangle_component *ret;
 
-  if (d_next_char (di) != 'L')
+  if (! d_check_char (di, 'L'))
     return NULL;
   if (d_peek_char (di) == '_')
     ret = cplus_demangle_mangled_name (di, 0);
@@ -2328,10 +2354,14 @@ d_expr_primary (struct d_info *di)
        }
       s = d_str (di);
       while (d_peek_char (di) != 'E')
-       d_advance (di, 1);
+       {
+         if (d_peek_char (di) == '\0')
+           return NULL;
+         d_advance (di, 1);
+       }
       ret = d_make_comp (di, t, type, d_make_name (di, s, d_str (di) - s));
     }
-  if (d_next_char (di) != 'E')
+  if (! d_check_char (di, 'E'))
     return NULL;
   return ret;
 }
@@ -2345,12 +2375,12 @@ d_local_name (struct d_info *di)
 {
   struct demangle_component *function;
 
-  if (d_next_char (di) != 'Z')
+  if (! d_check_char (di, 'Z'))
     return NULL;
 
   function = d_encoding (di, 0);
 
-  if (d_next_char (di) != 'E')
+  if (! d_check_char (di, 'E'))
     return NULL;
 
   if (d_peek_char (di) == 's')
@@ -2455,7 +2485,7 @@ d_substitution (struct d_info *di, int prefix)
 {
   char c;
 
-  if (d_next_char (di) != 'S')
+  if (! d_check_char (di, 'S'))
     return NULL;
 
   c = d_next_char (di);
@@ -2474,6 +2504,8 @@ d_substitution (struct d_info *di, int prefix)
                id = id * 36 + c - 'A' + 10;
              else
                return NULL;
+             if (id < 0)
+               return NULL;
              c = d_next_char (di);
            }
          while (c != '_');
@@ -2551,7 +2583,7 @@ d_print_resize (struct d_print_info *dpi, size_t add)
       char *newbuf;
 
       newalc = dpi->alc * 2;
-      newbuf = realloc (dpi->buf, newalc);
+      newbuf = (char *) realloc (dpi->buf, newalc);
       if (newbuf == NULL)
        {
          free (dpi->buf);
@@ -2629,7 +2661,7 @@ cplus_demangle_print (int options, const struct demangle_component *dc,
   dpi.options = options;
 
   dpi.alc = estimate + 1;
-  dpi.buf = malloc (dpi.alc);
+  dpi.buf = (char *) malloc (dpi.alc);
   if (dpi.buf == NULL)
     {
       *palc = 1;
@@ -2730,7 +2762,7 @@ d_print_comp (struct d_print_info *dpi,
          {
            dpt.next = dpi->templates;
            dpi->templates = &dpt;
-           dpt.template = typed_name;
+           dpt.template_decl = typed_name;
          }
 
        /* If typed_name is a DEMANGLE_COMPONENT_LOCAL_NAME, then
@@ -2826,7 +2858,7 @@ d_print_comp (struct d_print_info *dpi,
            return;
          }
        i = dc->u.s_number.number;
-       for (a = d_right (dpi->templates->template);
+       for (a = d_right (dpi->templates->template_decl);
             a != NULL;
             a = d_right (a))
          {
@@ -2931,6 +2963,11 @@ d_print_comp (struct d_print_info *dpi,
       d_print_comp (dpi, d_left (dc));
       return;
 
+    case DEMANGLE_COMPONENT_HIDDEN_ALIAS:
+      d_append_string_constant (dpi, "hidden alias for ");
+      d_print_comp (dpi, d_left (dc));
+      return;
+
     case DEMANGLE_COMPONENT_SUB_STD:
       d_append_buffer (dpi, dc->u.s_string.string, dc->u.s_string.len);
       return;
@@ -3007,13 +3044,16 @@ d_print_comp (struct d_print_info *dpi,
 
     case DEMANGLE_COMPONENT_FUNCTION_TYPE:
       {
+       if ((dpi->options & DMGL_RET_POSTFIX) != 0)
+         d_print_function_type (dpi, dc, dpi->modifiers);
+
+       /* Print return type if present */
        if (d_left (dc) != NULL)
          {
            struct d_print_mod dpm;
 
            /* We must pass this type down as a modifier in order to
               print it in the right location.  */
-
            dpm.next = dpi->modifiers;
            dpi->modifiers = &dpm;
            dpm.mod = dc;
@@ -3027,10 +3067,14 @@ d_print_comp (struct d_print_info *dpi,
            if (dpm.printed)
              return;
 
-           d_append_char (dpi, ' ');
+           /* In standard prefix notation, there is a space between the
+              return type and the function signature.  */
+           if ((dpi->options & DMGL_RET_POSTFIX) == 0)
+             d_append_char (dpi, ' ');
          }
 
-       d_print_function_type (dpi, dc, dpi->modifiers);
+       if ((dpi->options & DMGL_RET_POSTFIX) == 0) 
+         d_print_function_type (dpi, dc, dpi->modifiers);
 
        return;
       }
@@ -3683,7 +3727,7 @@ d_print_cast (struct d_print_info *dpi,
 
       dpt.next = dpi->templates;
       dpi->templates = &dpt;
-      dpt.template = d_left (dc);
+      dpt.template_decl = d_left (dc);
 
       d_print_comp (dpi, d_left (d_left (dc)));
 
@@ -3764,7 +3808,7 @@ d_demangle (const char* mangled, int options, size_t *palc)
     {
       char *r;
 
-      r = malloc (40 + len - 11);
+      r = (char *) malloc (40 + len - 11);
       if (r == NULL)
        *palc = 1;
       else
@@ -3985,7 +4029,8 @@ java_demangle_v3 (const char* mangled)
   char *from;
   char *to;
 
-  demangled = d_demangle (mangled, DMGL_JAVA | DMGL_PARAMS, &alc);
+  demangled = d_demangle (mangled, DMGL_JAVA | DMGL_PARAMS | DMGL_RET_POSTFIX, 
+                         &alc);
 
   if (demangled == NULL)
     return NULL;
@@ -4144,7 +4189,7 @@ is_gnu_v3_mangled_dtor (const char *name)
 #include "getopt.h"
 #include "dyn-string.h"
 
-static void print_usage PARAMS ((FILE* fp, int exit_value));
+static void print_usage (FILE* fp, int exit_value);
 
 #define IS_ALPHA(CHAR)                                                  \
   (((CHAR) >= 'a' && (CHAR) <= 'z')                                     \