Resync files in the binutils repository that are maintained in the gcc repository.
[deliverable/binutils-gdb.git] / libiberty / cp-demangle.c
index 7f51268e1151d262c55fb6735efeae73b60b7f32..fb1c4e5e9d5bcef89d5ad1628cbfada1d893dc06 100644 (file)
@@ -1,5 +1,5 @@
 /* Demangler for g++ V3 ABI.
-   Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
+   Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2014
    Free Software Foundation, Inc.
    Written by Ian Lance Taylor <ian@wasabisystems.com>.
 
@@ -275,6 +275,16 @@ struct d_growable_string
   int allocation_failure;
 };
 
+/* Stack of components, innermost first, used to avoid loops.  */
+
+struct d_component_stack
+{
+  /* This component.  */
+  const struct demangle_component *dc;
+  /* This component's parent.  */
+  const struct d_component_stack *parent;
+};
+
 /* A demangle component and some scope captured when it was first
    traversed.  */
 
@@ -327,10 +337,20 @@ struct d_print_info
   int pack_index;
   /* Number of d_print_flush calls so far.  */
   unsigned long int flush_count;
+  /* Stack of components, innermost first, used to avoid loops.  */
+  const struct d_component_stack *component_stack;
   /* Array of saved scopes for evaluating substitutions.  */
   struct d_saved_scope *saved_scopes;
+  /* Index of the next unused saved scope in the above array.  */
+  int next_saved_scope;
   /* Number of saved scopes in the above array.  */
   int num_saved_scopes;
+  /* Array of templates for saving into scopes.  */
+  struct d_print_template *copy_templates;
+  /* Index of the next unused copy template in the above array.  */
+  int next_copy_template;
+  /* Number of copy templates in the above array.  */
+  int num_copy_templates;
   /* The nearest enclosing template, if any.  */
   const struct demangle_component *current_template;
 };
@@ -475,7 +495,8 @@ static void
 d_growable_string_callback_adapter (const char *, size_t, void *);
 
 static void
-d_print_init (struct d_print_info *, demangle_callbackref, void *);
+d_print_init (struct d_print_info *, demangle_callbackref, void *,
+             const struct demangle_component *);
 
 static inline void d_print_error (struct d_print_info *);
 
@@ -554,6 +575,9 @@ d_dump (struct demangle_component *dc, int indent)
     case DEMANGLE_COMPONENT_TEMPLATE_PARAM:
       printf ("template parameter %ld\n", dc->u.s_number.number);
       return;
+    case DEMANGLE_COMPONENT_FUNCTION_PARAM:
+      printf ("function parameter %ld\n", dc->u.s_number.number);
+      return;
     case DEMANGLE_COMPONENT_CTOR:
       printf ("constructor %d\n", (int) dc->u.s_ctor.kind);
       d_dump (dc->u.s_ctor.name, indent + 2);
@@ -689,7 +713,9 @@ d_dump (struct demangle_component *dc, int indent)
       printf ("pointer to member type\n");
       break;
     case DEMANGLE_COMPONENT_FIXED_TYPE:
-      printf ("fixed-point type\n");
+      printf ("fixed-point type, accum? %d, sat? %d\n",
+              dc->u.s_fixed.accum, dc->u.s_fixed.sat);
+      d_dump (dc->u.s_fixed.length, indent + 2)
       break;
     case DEMANGLE_COMPONENT_ARGLIST:
       printf ("argument list\n");
@@ -739,6 +765,9 @@ d_dump (struct demangle_component *dc, int indent)
     case DEMANGLE_COMPONENT_CHARACTER:
       printf ("character '%c'\n",  dc->u.s_character.character);
       return;
+    case DEMANGLE_COMPONENT_NUMBER:
+      printf ("number %ld\n", dc->u.s_number.number);
+      return;
     case DEMANGLE_COMPONENT_DECLTYPE:
       printf ("decltype\n");
       break;
@@ -1273,7 +1302,12 @@ d_encoding (struct d_info *di, int top_level)
 static struct demangle_component *
 d_abi_tags (struct d_info *di, struct demangle_component *dc)
 {
+  struct demangle_component *hold_last_name;
   char peek;
+
+  /* Preserve the last name, so the ABI tag doesn't clobber it.  */
+  hold_last_name = di->last_name;
+
   while (peek = d_peek_char (di),
         peek == 'B')
     {
@@ -1282,6 +1316,9 @@ d_abi_tags (struct d_info *di, struct demangle_component *dc)
       tag = d_source_name (di);
       dc = d_make_comp (di, DEMANGLE_COMPONENT_TAGGED_NAME, dc, tag);
     }
+
+  di->last_name = hold_last_name;
+
   return dc;
 }
 
@@ -2441,6 +2478,9 @@ cplus_demangle_type (struct d_info *di)
     case 'U':
       d_advance (di, 1);
       ret = d_source_name (di);
+      if (d_peek_char (di) == 'I')
+       ret = d_make_comp (di, DEMANGLE_COMPONENT_TEMPLATE, ret,
+                          d_template_args (di));
       ret = d_make_comp (di, DEMANGLE_COMPONENT_VENDOR_TYPE_QUAL,
                         cplus_demangle_type (di), ret);
       break;
@@ -3658,6 +3698,7 @@ d_substitution (struct d_info *di, int prefix)
            {
              const char *s;
              int len;
+             struct demangle_component *c;
 
              if (p->set_last_name != NULL)
                di->last_name = d_make_sub (di, p->set_last_name,
@@ -3673,7 +3714,15 @@ d_substitution (struct d_info *di, int prefix)
                  len = p->simple_len;
                }
              di->expansion += len;
-             return d_make_sub (di, s, len);
+             c = d_make_sub (di, s, len);
+             if (d_peek_char (di) == 'B')
+               {
+                 /* If there are ABI tags on the abbreviation, it becomes
+                    a substitution candidate.  */
+                 c = d_abi_tags (di, c);
+                 d_add_substitution (di, c);
+               }
+             return c;
            }
        }
 
@@ -3777,11 +3826,145 @@ d_growable_string_callback_adapter (const char *s, size_t l, void *opaque)
   d_growable_string_append_buffer (dgs, s, l);
 }
 
+/* Walk the tree, counting the number of templates encountered, and
+   the number of times a scope might be saved.  These counts will be
+   used to allocate data structures for d_print_comp, so the logic
+   here must mirror the logic d_print_comp will use.  It is not
+   important that the resulting numbers are exact, so long as they
+   are larger than the actual numbers encountered.  */
+
+static void
+d_count_templates_scopes (int *num_templates, int *num_scopes,
+                         const struct demangle_component *dc)
+{
+  if (dc == NULL)
+    return;
+
+  switch (dc->type)
+    {
+    case DEMANGLE_COMPONENT_NAME:
+    case DEMANGLE_COMPONENT_TEMPLATE_PARAM:
+    case DEMANGLE_COMPONENT_FUNCTION_PARAM:
+    case DEMANGLE_COMPONENT_SUB_STD:
+    case DEMANGLE_COMPONENT_BUILTIN_TYPE:
+    case DEMANGLE_COMPONENT_OPERATOR:
+    case DEMANGLE_COMPONENT_CHARACTER:
+    case DEMANGLE_COMPONENT_NUMBER:
+    case DEMANGLE_COMPONENT_UNNAMED_TYPE:
+      break;
+
+    case DEMANGLE_COMPONENT_TEMPLATE:
+      (*num_templates)++;
+      goto recurse_left_right;
+
+    case DEMANGLE_COMPONENT_REFERENCE:
+    case DEMANGLE_COMPONENT_RVALUE_REFERENCE:
+      if (d_left (dc)->type == DEMANGLE_COMPONENT_TEMPLATE_PARAM)
+       (*num_scopes)++;
+      goto recurse_left_right;
+
+    case DEMANGLE_COMPONENT_QUAL_NAME:
+    case DEMANGLE_COMPONENT_LOCAL_NAME:
+    case DEMANGLE_COMPONENT_TYPED_NAME:
+    case DEMANGLE_COMPONENT_VTABLE:
+    case DEMANGLE_COMPONENT_VTT:
+    case DEMANGLE_COMPONENT_CONSTRUCTION_VTABLE:
+    case DEMANGLE_COMPONENT_TYPEINFO:
+    case DEMANGLE_COMPONENT_TYPEINFO_NAME:
+    case DEMANGLE_COMPONENT_TYPEINFO_FN:
+    case DEMANGLE_COMPONENT_THUNK:
+    case DEMANGLE_COMPONENT_VIRTUAL_THUNK:
+    case DEMANGLE_COMPONENT_COVARIANT_THUNK:
+    case DEMANGLE_COMPONENT_JAVA_CLASS:
+    case DEMANGLE_COMPONENT_GUARD:
+    case DEMANGLE_COMPONENT_TLS_INIT:
+    case DEMANGLE_COMPONENT_TLS_WRAPPER:
+    case DEMANGLE_COMPONENT_REFTEMP:
+    case DEMANGLE_COMPONENT_HIDDEN_ALIAS:
+    case DEMANGLE_COMPONENT_RESTRICT:
+    case DEMANGLE_COMPONENT_VOLATILE:
+    case DEMANGLE_COMPONENT_CONST:
+    case DEMANGLE_COMPONENT_RESTRICT_THIS:
+    case DEMANGLE_COMPONENT_VOLATILE_THIS:
+    case DEMANGLE_COMPONENT_CONST_THIS:
+    case DEMANGLE_COMPONENT_REFERENCE_THIS:
+    case DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS:
+    case DEMANGLE_COMPONENT_VENDOR_TYPE_QUAL:
+    case DEMANGLE_COMPONENT_POINTER:
+    case DEMANGLE_COMPONENT_COMPLEX:
+    case DEMANGLE_COMPONENT_IMAGINARY:
+    case DEMANGLE_COMPONENT_VENDOR_TYPE:
+    case DEMANGLE_COMPONENT_FUNCTION_TYPE:
+    case DEMANGLE_COMPONENT_ARRAY_TYPE:
+    case DEMANGLE_COMPONENT_PTRMEM_TYPE:
+    case DEMANGLE_COMPONENT_VECTOR_TYPE:
+    case DEMANGLE_COMPONENT_ARGLIST:
+    case DEMANGLE_COMPONENT_TEMPLATE_ARGLIST:
+    case DEMANGLE_COMPONENT_INITIALIZER_LIST:
+    case DEMANGLE_COMPONENT_CAST:
+    case DEMANGLE_COMPONENT_NULLARY:
+    case DEMANGLE_COMPONENT_UNARY:
+    case DEMANGLE_COMPONENT_BINARY:
+    case DEMANGLE_COMPONENT_BINARY_ARGS:
+    case DEMANGLE_COMPONENT_TRINARY:
+    case DEMANGLE_COMPONENT_TRINARY_ARG1:
+    case DEMANGLE_COMPONENT_TRINARY_ARG2:
+    case DEMANGLE_COMPONENT_LITERAL:
+    case DEMANGLE_COMPONENT_LITERAL_NEG:
+    case DEMANGLE_COMPONENT_JAVA_RESOURCE:
+    case DEMANGLE_COMPONENT_COMPOUND_NAME:
+    case DEMANGLE_COMPONENT_DECLTYPE:
+    case DEMANGLE_COMPONENT_TRANSACTION_CLONE:
+    case DEMANGLE_COMPONENT_NONTRANSACTION_CLONE:
+    case DEMANGLE_COMPONENT_PACK_EXPANSION:
+    case DEMANGLE_COMPONENT_TAGGED_NAME:
+    case DEMANGLE_COMPONENT_CLONE:
+    recurse_left_right:
+      d_count_templates_scopes (num_templates, num_scopes,
+                               d_left (dc));
+      d_count_templates_scopes (num_templates, num_scopes,
+                               d_right (dc));
+      break;
+
+    case DEMANGLE_COMPONENT_CTOR:
+      d_count_templates_scopes (num_templates, num_scopes,
+                               dc->u.s_ctor.name);
+      break;
+
+    case DEMANGLE_COMPONENT_DTOR:
+      d_count_templates_scopes (num_templates, num_scopes,
+                               dc->u.s_dtor.name);
+      break;
+
+    case DEMANGLE_COMPONENT_EXTENDED_OPERATOR:
+      d_count_templates_scopes (num_templates, num_scopes,
+                               dc->u.s_extended_operator.name);
+      break;
+
+    case DEMANGLE_COMPONENT_FIXED_TYPE:
+      d_count_templates_scopes (num_templates, num_scopes,
+                                dc->u.s_fixed.length);
+      break;
+
+    case DEMANGLE_COMPONENT_GLOBAL_CONSTRUCTORS:
+    case DEMANGLE_COMPONENT_GLOBAL_DESTRUCTORS:
+      d_count_templates_scopes (num_templates, num_scopes,
+                               d_left (dc));
+      break;
+
+    case DEMANGLE_COMPONENT_LAMBDA:
+    case DEMANGLE_COMPONENT_DEFAULT_ARG:
+      d_count_templates_scopes (num_templates, num_scopes,
+                               dc->u.s_unary_num.sub);
+      break;
+    }
+}
+
 /* Initialize a print information structure.  */
 
 static void
 d_print_init (struct d_print_info *dpi, demangle_callbackref callback,
-             void *opaque)
+             void *opaque, const struct demangle_component *dc)
 {
   dpi->len = 0;
   dpi->last_char = '\0';
@@ -3795,30 +3978,21 @@ d_print_init (struct d_print_info *dpi, demangle_callbackref callback,
 
   dpi->demangle_failure = 0;
 
+  dpi->component_stack = NULL;
+
   dpi->saved_scopes = NULL;
+  dpi->next_saved_scope = 0;
   dpi->num_saved_scopes = 0;
-  dpi->current_template = NULL;
-}
 
-/* Free a print information structure.  */
+  dpi->copy_templates = NULL;
+  dpi->next_copy_template = 0;
+  dpi->num_copy_templates = 0;
 
-static void
-d_print_free (struct d_print_info *dpi)
-{
-  int i;
-
-  for (i = 0; i < dpi->num_saved_scopes; i++)
-    {
-      struct d_print_template *ts, *tn;
+  d_count_templates_scopes (&dpi->num_copy_templates,
+                           &dpi->num_saved_scopes, dc);
+  dpi->num_copy_templates *= dpi->num_saved_scopes;
 
-      for (ts = dpi->saved_scopes[i].templates; ts != NULL; ts = tn)
-       {
-         tn = ts->next;
-         free (ts);
-       }
-    }
-
-  free (dpi->saved_scopes);
+  dpi->current_template = NULL;
 }
 
 /* Indicate that an error occurred during printing, and test for error.  */
@@ -3903,17 +4077,29 @@ cplus_demangle_print_callback (int options,
                                demangle_callbackref callback, void *opaque)
 {
   struct d_print_info dpi;
-  int success;
 
-  d_print_init (&dpi, callback, opaque);
+  d_print_init (&dpi, callback, opaque, dc);
+
+  {
+#ifdef CP_DYNAMIC_ARRAYS
+    __extension__ struct d_saved_scope scopes[dpi.num_saved_scopes];
+    __extension__ struct d_print_template temps[dpi.num_copy_templates];
+
+    dpi.saved_scopes = scopes;
+    dpi.copy_templates = temps;
+#else
+    dpi.saved_scopes = alloca (dpi.num_saved_scopes
+                              * sizeof (*dpi.saved_scopes));
+    dpi.copy_templates = alloca (dpi.num_copy_templates
+                                * sizeof (*dpi.copy_templates));
+#endif
 
-  d_print_comp (&dpi, options, dc);
+    d_print_comp (&dpi, options, dc);
+  }
 
   d_print_flush (&dpi);
 
-  success = ! d_print_saw_error (&dpi);
-  d_print_free (&dpi);
-  return success;
+  return ! d_print_saw_error (&dpi);
 }
 
 /* Turn components into a human readable string.  OPTIONS is the
@@ -4070,25 +4256,37 @@ d_print_subexpr (struct d_print_info *dpi, int options,
     d_append_char (dpi, ')');
 }
 
-/* Return a shallow copy of the current list of templates.
-   On error d_print_error is called and a partial list may
-   be returned.  Whatever is returned must be freed.  */
+/* Save the current scope.  */
 
-static struct d_print_template *
-d_copy_templates (struct d_print_info *dpi)
+static void
+d_save_scope (struct d_print_info *dpi,
+             const struct demangle_component *container)
 {
-  struct d_print_template *src, *result, **link = &result;
+  struct d_saved_scope *scope;
+  struct d_print_template *src, **link;
+
+  if (dpi->next_saved_scope >= dpi->num_saved_scopes)
+    {
+      d_print_error (dpi);
+      return;
+    }
+  scope = &dpi->saved_scopes[dpi->next_saved_scope];
+  dpi->next_saved_scope++;
+
+  scope->container = container;
+  link = &scope->templates;
 
   for (src = dpi->templates; src != NULL; src = src->next)
     {
-      struct d_print_template *dst =
-       (struct d_print_template *) malloc (sizeof (struct d_print_template));
+      struct d_print_template *dst;
 
-      if (dst == NULL)
+      if (dpi->next_copy_template >= dpi->num_copy_templates)
        {
          d_print_error (dpi);
-         break;
+         return;
        }
+      dst = &dpi->copy_templates[dpi->next_copy_template];
+      dpi->next_copy_template++;
 
       dst->template_decl = src->template_decl;
       *link = dst;
@@ -4096,15 +4294,29 @@ d_copy_templates (struct d_print_info *dpi)
     }
 
   *link = NULL;
+}
+
+/* Attempt to locate a previously saved scope.  Returns NULL if no
+   corresponding saved scope was found.  */
+
+static struct d_saved_scope *
+d_get_saved_scope (struct d_print_info *dpi,
+                  const struct demangle_component *container)
+{
+  int i;
 
-  return result;
+  for (i = 0; i < dpi->next_saved_scope; i++)
+    if (dpi->saved_scopes[i].container == container)
+      return &dpi->saved_scopes[i];
+
+  return NULL;
 }
 
 /* Subroutine to handle components.  */
 
 static void
-d_print_comp (struct d_print_info *dpi, int options,
-              const struct demangle_component *dc)
+d_print_comp_inner (struct d_print_info *dpi, int options,
+                 const struct demangle_component *dc)
 {
   /* Magic variable to let reference smashing skip over the next modifier
      without needing to modify *dc.  */
@@ -4492,47 +4704,45 @@ d_print_comp (struct d_print_info *dpi, int options,
        const struct demangle_component *sub = d_left (dc);
        if (sub->type == DEMANGLE_COMPONENT_TEMPLATE_PARAM)
          {
+           struct d_saved_scope *scope = d_get_saved_scope (dpi, sub);
            struct demangle_component *a;
-           struct d_saved_scope *scope = NULL, *scopes;
-           int i;
-
-           for (i = 0; i < dpi->num_saved_scopes; i++)
-             if (dpi->saved_scopes[i].container == sub)
-               scope = &dpi->saved_scopes[i];
 
            if (scope == NULL)
              {
-               size_t size;
-
                /* This is the first time SUB has been traversed.
                   We need to capture the current templates so
                   they can be restored if SUB is reentered as a
                   substitution.  */
-               ++dpi->num_saved_scopes;
-               size = sizeof (struct d_saved_scope) * dpi->num_saved_scopes;
-               scopes = (struct d_saved_scope *) realloc (dpi->saved_scopes,
-                                                          size);
-               if (scopes == NULL)
-                 {
-                   d_print_error (dpi);
-                   return;
-                 }
-
-               dpi->saved_scopes = scopes;
-               scope = dpi->saved_scopes + (dpi->num_saved_scopes - 1);
-
-               scope->container = sub;
-               scope->templates = d_copy_templates (dpi);
+               d_save_scope (dpi, sub);
                if (d_print_saw_error (dpi))
                  return;
              }
            else
              {
+               const struct d_component_stack *dcse;
+               int found_self_or_parent = 0;
+
                /* This traversal is reentering SUB as a substition.
-                  Restore the original templates temporarily.  */
-               saved_templates = dpi->templates;
-               dpi->templates = scope->templates;
-               need_template_restore = 1;
+                  If we are not beneath SUB or DC in the tree then we
+                  need to restore SUB's template stack temporarily.  */
+               for (dcse = dpi->component_stack; dcse != NULL;
+                    dcse = dcse->parent)
+                 {
+                   if (dcse->dc == sub
+                       || (dcse->dc == dc
+                           && dcse != dpi->component_stack))
+                     {
+                       found_self_or_parent = 1;
+                       break;
+                     }
+                 }
+
+               if (!found_self_or_parent)
+                 {
+                   saved_templates = dpi->templates;
+                   dpi->templates = scope->templates;
+                   need_template_restore = 1;
+                 }
              }
 
            a = d_lookup_template_argument (dpi, sub);
@@ -5171,6 +5381,21 @@ d_print_comp (struct d_print_info *dpi, int options,
     }
 }
 
+static void
+d_print_comp (struct d_print_info *dpi, int options,
+             const struct demangle_component *dc)
+{
+  struct d_component_stack self;
+
+  self.dc = dc;
+  self.parent = dpi->component_stack;
+  dpi->component_stack = &self;
+
+  d_print_comp_inner (dpi, options, dc);
+
+  dpi->component_stack = self.parent;
+}
+
 /* Print a Java dentifier.  For Java we try to handle encoded extended
    Unicode characters.  The C++ ABI doesn't mention Unicode encoding,
    so we don't it for C++.  Characters are encoded as
@@ -5679,6 +5904,8 @@ d_demangle_callback (const char *mangled, int options,
                          NULL);
        d_advance (&di, strlen (d_str (&di)));
        break;
+      default:
+       abort (); /* We have listed all the cases.  */
       }
 
     /* If DMGL_PARAMS is set, then if we didn't consume the entire
This page took 0.030432 seconds and 4 git commands to generate.