]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
Update libiberty demangler.
authorMark Wielaard <mark@klomp.org>
Tue, 13 Sep 2016 19:06:23 +0000 (19:06 +0000)
committerMark Wielaard <mark@klomp.org>
Tue, 13 Sep 2016 19:06:23 +0000 (19:06 +0000)
Update the libiberty demangler using the auxprogs/update-demangler
script. There were various extensions and bug fixes since our last
import. Add new D language demangler file d-demangle.c and update
the vg_libciface.h header with some new constructs used (strtol,
xmalloc_failed, xmemdup, XDELETEVEC, XDUPVEC).

Resolves bug #359181 - Buffer Overflow during Demangling.

git-svn-id: svn://svn.valgrind.org/valgrind/trunk@15951

12 files changed:
NEWS
auxprogs/update-demangler
coregrind/Makefile.am
coregrind/m_demangle/ansidecl.h
coregrind/m_demangle/cp-demangle.c
coregrind/m_demangle/cp-demangle.h
coregrind/m_demangle/cplus-dem.c
coregrind/m_demangle/d-demangle.c [new file with mode: 0644]
coregrind/m_demangle/demangle.h
coregrind/m_demangle/dyn-string.h
coregrind/m_demangle/safe-ctype.h
coregrind/m_demangle/vg_libciface.h

diff --git a/NEWS b/NEWS
index 899050f2600669765d320dcabd8adbd5bfd5363b..09af2b9f163df21d54e77c3e482d97a72961f0bd 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -105,6 +105,7 @@ where XXXXXX is the bug number as listed below.
 358030  support direct socket calls on x86 32bit (new in linux 4.3)
 358478  drd/tests/std_thread.cpp doesn't build with GCC6
 359133  Assertion 'eltSzB <= ddpa->poolSzB' failed
+359181  Buffer Overflow during Demangling
 359201  futex syscall "skips" argument 5 if op is FUTEX_WAIT_BITSET
 359289  s390x: popcnt (B9E1) not implemented
 359472  The Power PC vsubuqm instruction doesn't always give the correct result
index 9a4a00acd2fb7218cf34d52968af94199e45a9b4..18189b3b7527626ca832cbd932e3380f084c4c76 100755 (executable)
@@ -17,8 +17,8 @@ set -e
 #---------------------------------------------------------------------
 
 # You need to modify these revision numbers for your update.
-old_gcc_revision=r181975  # the revision of the previous update
-new_gcc_revision=r212125  # the revision for this update
+old_gcc_revision=r212125  # the revision of the previous update
+new_gcc_revision=r240068  # the revision for this update
 
 # Unless the organization of demangler related files has changed, no
 # changes below this line should be necessary.
@@ -55,6 +55,7 @@ cp    ../gcc-$old_gcc_revision/libiberty/cp-demangle.c .
 cp    ../gcc-$old_gcc_revision/libiberty/cp-demangle.h .
 cp    ../gcc-$old_gcc_revision/libiberty/cplus-dem.c .
 cp    ../gcc-$old_gcc_revision/libiberty/dyn-string.c .
+cp    ../gcc-$old_gcc_revision/libiberty/d-demangle.c .
 cp    ../gcc-$old_gcc_revision/libiberty/safe-ctype.c .
 cd ..
 
@@ -81,6 +82,7 @@ cp    ../gcc-$new_gcc_revision/libiberty/cp-demangle.c .
 cp    ../gcc-$new_gcc_revision/libiberty/cp-demangle.h .
 cp    ../gcc-$new_gcc_revision/libiberty/cplus-dem.c .
 cp    ../gcc-$new_gcc_revision/libiberty/dyn-string.c .
+cp    ../gcc-$new_gcc_revision/libiberty/d-demangle.c .
 cp    ../gcc-$new_gcc_revision/libiberty/safe-ctype.c .
 cd ..
 
index d4712240533c81869c0e966777c6d4a6d532df0f..d798015d74d815521993bf0eb0593895b619e5e0 100644 (file)
@@ -357,6 +357,7 @@ COREGRIND_SOURCES_COMMON = \
        m_demangle/cplus-dem.c \
        m_demangle/demangle.c \
        m_demangle/dyn-string.c \
+       m_demangle/d-demangle.c \
        m_demangle/safe-ctype.c \
        m_dispatch/dispatch-x86-linux.S \
        m_dispatch/dispatch-amd64-linux.S \
index 0fb23bba792dbb30d852723b9ac9a5d337e3aedc..6e4bfc21f25fba689eeb896486328f45cdc537b4 100644 (file)
@@ -1,7 +1,5 @@
 /* ANSI and traditional C compatability macros
-   Copyright 1991, 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
-   2002, 2003, 2004, 2005, 2006, 2007, 2009, 2010, 2013
-   Free Software Foundation, Inc.
+   Copyright (C) 1991-2015 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
 This program is free software; you can redistribute it and/or modify
@@ -276,6 +274,15 @@ So instead we use the macro below and test it against specific values.  */
 # endif /* GNUC >= 4.3 */
 #endif /* ATTRIBUTE_HOT */
 
+/* Attribute 'no_sanitize_undefined' was valid as of gcc 4.9.  */
+#ifndef ATTRIBUTE_NO_SANITIZE_UNDEFINED
+# if (GCC_VERSION >= 4009)
+#  define ATTRIBUTE_NO_SANITIZE_UNDEFINED __attribute__ ((no_sanitize_undefined))
+# else
+#  define ATTRIBUTE_NO_SANITIZE_UNDEFINED
+# endif /* GNUC >= 4.9 */
+#endif /* ATTRIBUTE_NO_SANITIZE_UNDEFINED */
+
 /* We use __extension__ in some places to suppress -pedantic warnings
    about GCC extensions.  This feature didn't work properly before
    gcc 2.8.  */
@@ -304,6 +311,15 @@ So instead we use the macro below and test it against specific values.  */
 #define ENUM_BITFIELD(TYPE) __extension__ enum TYPE
 #else
 #define ENUM_BITFIELD(TYPE) unsigned int
+#endif
+
+    /* This is used to mark a class or virtual function as final.  */
+#if __cplusplus >= 201103L
+#define GCC_FINAL final
+#elif GCC_VERSION >= 4007
+#define GCC_FINAL __final
+#else
+#define GCC_FINAL
 #endif
 
 #ifdef __cplusplus
index 381bd4d5f708ed098e1b0b3b9e0a7f3047976fad..a3f78ab1085bf6cdc886566e77410291c48d2146 100644 (file)
    CP_DEMANGLE_DEBUG
       If defined, turns on debugging mode, which prints information on
       stdout about the mangled string.  This is not generally useful.
-*/
+
+   CHECK_DEMANGLER
+      If defined, additional sanity checks will be performed.  It will
+      cause some slowdown, but will allow to catch out-of-bound access
+      errors earlier.  This macro is intended for testing and debugging.  */
 
 #if 0 /* in valgrind */
 #if defined (_AIX) && !defined (__GNUC__)
@@ -134,6 +138,15 @@ extern char *alloca ();
 #endif /* HAVE_ALLOCA_H */
 #endif /* ! in valgrind */
 
+#if 0 /* in valgrind */
+#ifdef HAVE_LIMITS_H
+#include <limits.h>
+#endif
+#endif /* ! in valgrind */
+#ifndef INT_MAX
+# define INT_MAX       (int)(((unsigned int) ~0) >> 1)          /* 0x7FFFFFFF */ 
+#endif
+
 #if 0 /* in valgrind */
 #include "ansidecl.h"
 #include "libiberty.h"
@@ -348,7 +361,7 @@ struct d_print_info
   /* Set to 1 if we saw a demangling error.  */
   int demangle_failure;
   /* The current index into any template argument packs we are using
-     for printing.  */
+     for printing, or -1 to print the whole pack.  */
   int pack_index;
   /* Number of d_print_flush calls so far.  */
   unsigned long int flush_count;
@@ -409,7 +422,7 @@ d_make_dtor (struct d_info *, enum gnu_v3_dtor_kinds,
              struct demangle_component *);
 
 static struct demangle_component *
-d_make_template_param (struct d_info *, long);
+d_make_template_param (struct d_info *, int);
 
 static struct demangle_component *
 d_make_sub (struct d_info *, const char *, int);
@@ -432,7 +445,7 @@ static struct demangle_component *d_unqualified_name (struct d_info *);
 
 static struct demangle_component *d_source_name (struct d_info *);
 
-static long d_number (struct d_info *);
+static int d_number (struct d_info *);
 
 static struct demangle_component *d_identifier (struct d_info *, int);
 
@@ -470,6 +483,7 @@ static struct demangle_component *
 d_template_param (struct d_info *);
 
 static struct demangle_component *d_template_args (struct d_info *);
+static struct demangle_component *d_template_args_1 (struct d_info *);
 
 static struct demangle_component *
 d_template_arg (struct d_info *);
@@ -553,8 +567,10 @@ d_print_array_type (struct d_print_info *, int,
 static void
 d_print_expr_op (struct d_print_info *, int, const struct demangle_component *);
 
-static void
-d_print_cast (struct d_print_info *, int, const struct demangle_component *);
+static void d_print_cast (struct d_print_info *, int,
+                         const struct demangle_component *);
+static void d_print_conversion (struct d_print_info *, int,
+                               const struct demangle_component *);
 
 static int d_demangle_callback (const char *, int,
                                 demangle_callbackref, void *);
@@ -697,6 +713,9 @@ d_dump (struct demangle_component *dc, int indent)
     case DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS:
       printf ("rvalue reference this\n");
       break;
+    case DEMANGLE_COMPONENT_TRANSACTION_SAFE:
+      printf ("transaction_safe this\n");
+      break;
     case DEMANGLE_COMPONENT_VENDOR_TYPE_QUAL:
       printf ("vendor type qualifier\n");
       break;
@@ -728,7 +747,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");
@@ -742,6 +763,9 @@ d_dump (struct demangle_component *dc, int indent)
     case DEMANGLE_COMPONENT_CAST:
       printf ("cast\n");
       break;
+    case DEMANGLE_COMPONENT_CONVERSION:
+      printf ("conversion operator\n");
+      break;
     case DEMANGLE_COMPONENT_NULLARY:
       printf ("nullary operator\n");
       break;
@@ -951,6 +975,7 @@ d_make_comp (struct d_info *di, enum demangle_component_type type,
     case DEMANGLE_COMPONENT_IMAGINARY:
     case DEMANGLE_COMPONENT_VENDOR_TYPE:
     case DEMANGLE_COMPONENT_CAST:
+    case DEMANGLE_COMPONENT_CONVERSION:
     case DEMANGLE_COMPONENT_JAVA_RESOURCE:
     case DEMANGLE_COMPONENT_DECLTYPE:
     case DEMANGLE_COMPONENT_PACK_EXPANSION:
@@ -979,6 +1004,7 @@ d_make_comp (struct d_info *di, enum demangle_component_type type,
     case DEMANGLE_COMPONENT_RESTRICT_THIS:
     case DEMANGLE_COMPONENT_VOLATILE_THIS:
     case DEMANGLE_COMPONENT_CONST_THIS:
+    case DEMANGLE_COMPONENT_TRANSACTION_SAFE:
     case DEMANGLE_COMPONENT_REFERENCE_THIS:
     case DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS:
     case DEMANGLE_COMPONENT_ARGLIST:
@@ -1118,7 +1144,7 @@ d_make_dtor (struct d_info *di, enum gnu_v3_dtor_kinds kind,
 /* Add a new template parameter.  */
 
 static struct demangle_component *
-d_make_template_param (struct d_info *di, long i)
+d_make_template_param (struct d_info *di, int i)
 {
   struct demangle_component *p;
 
@@ -1134,7 +1160,7 @@ d_make_template_param (struct d_info *di, long i)
 /* Add a new function parameter.  */
 
 static struct demangle_component *
-d_make_function_param (struct d_info *di, long i)
+d_make_function_param (struct d_info *di, int i)
 {
   struct demangle_component *p;
 
@@ -1221,6 +1247,7 @@ has_return_type (struct demangle_component *dc)
     case DEMANGLE_COMPONENT_CONST_THIS:
     case DEMANGLE_COMPONENT_REFERENCE_THIS:
     case DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS:
+    case DEMANGLE_COMPONENT_TRANSACTION_SAFE:
       return has_return_type (d_left (dc));
     }
 }
@@ -1242,7 +1269,7 @@ is_ctor_dtor_or_conversion (struct demangle_component *dc)
       return is_ctor_dtor_or_conversion (d_right (dc));
     case DEMANGLE_COMPONENT_CTOR:
     case DEMANGLE_COMPONENT_DTOR:
-    case DEMANGLE_COMPONENT_CAST:
+    case DEMANGLE_COMPONENT_CONVERSION:
       return 1;
     }
 }
@@ -1277,6 +1304,7 @@ d_encoding (struct d_info *di, int top_level)
          while (dc->type == DEMANGLE_COMPONENT_RESTRICT_THIS
                 || dc->type == DEMANGLE_COMPONENT_VOLATILE_THIS
                 || dc->type == DEMANGLE_COMPONENT_CONST_THIS
+                || dc->type == DEMANGLE_COMPONENT_TRANSACTION_SAFE
                 || dc->type == DEMANGLE_COMPONENT_REFERENCE_THIS
                 || dc->type == DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS)
            dc = d_left (dc);
@@ -1293,6 +1321,7 @@ d_encoding (struct d_info *di, int top_level)
              while (dcr->type == DEMANGLE_COMPONENT_RESTRICT_THIS
                     || dcr->type == DEMANGLE_COMPONENT_VOLATILE_THIS
                     || dcr->type == DEMANGLE_COMPONENT_CONST_THIS
+                    || dcr->type == DEMANGLE_COMPONENT_TRANSACTION_SAFE
                     || dcr->type == DEMANGLE_COMPONENT_REFERENCE_THIS
                     || dcr->type == DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS)
                dcr = d_left (dcr);
@@ -1315,7 +1344,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')
     {
@@ -1324,6 +1358,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;
 }
 
@@ -1608,7 +1645,7 @@ d_unqualified_name (struct d_info *di)
 static struct demangle_component *
 d_source_name (struct d_info *di)
 {
-  long len;
+  int len;
   struct demangle_component *ret;
 
   len = d_number (di);
@@ -1621,12 +1658,12 @@ d_source_name (struct d_info *di)
 
 /* number ::= [n] <(non-negative decimal integer)>  */
 
-static long
+static int
 d_number (struct d_info *di)
 {
   int negative;
   char peek;
-  long ret;
+  int ret;
 
   negative = 0;
   peek = d_peek_char (di);
@@ -1742,6 +1779,10 @@ const struct demangle_operator_info cplus_demangle_operators[] =
   { "eO", NL ("^="),        2 },
   { "eo", NL ("^"),         2 },
   { "eq", NL ("=="),        2 },
+  { "fL", NL ("..."),       3 },
+  { "fR", NL ("..."),       3 },
+  { "fl", NL ("..."),       2 },
+  { "fr", NL ("..."),       2 },
   { "ge", NL (">="),        2 },
   { "gs", NL ("::"),       1 },
   { "gt", NL (">"),         2 },
@@ -1776,6 +1817,8 @@ const struct demangle_operator_info cplus_demangle_operators[] =
   { "rc", NL ("reinterpret_cast"), 2 },
   { "rm", NL ("%"),         2 },
   { "rs", NL (">>"),        2 },
+  { "sP", NL ("sizeof..."), 1 },
+  { "sZ", NL ("sizeof..."), 1 },
   { "sc", NL ("static_cast"), 2 },
   { "st", NL ("sizeof "),   1 },
   { "sz", NL ("sizeof "),   1 },
@@ -1798,11 +1841,16 @@ d_operator_name (struct d_info *di)
     {
       struct demangle_component *type;
       int was_conversion = di->is_conversion;
+      struct demangle_component *res;
 
       di->is_conversion = ! di->is_expression;
       type = cplus_demangle_type (di);
+      if (di->is_conversion)
+       res = d_make_comp (di, DEMANGLE_COMPONENT_CONVERSION, type, NULL);
+      else
+       res = d_make_comp (di, DEMANGLE_COMPONENT_CAST, type, NULL);
       di->is_conversion = was_conversion;
-      return d_make_comp (di, DEMANGLE_COMPONENT_CAST, type, NULL);
+      return res;
     }
   else
     {
@@ -1853,7 +1901,7 @@ d_java_resource (struct d_info *di)
 {
   struct demangle_component *p = NULL;
   struct demangle_component *next = NULL;
-  long len, i;
+  int len, i;
   char c;
   const char *str;
 
@@ -1995,7 +2043,7 @@ d_special_name (struct d_info *di)
        case 'C':
          {
            struct demangle_component *derived_type;
-           long offset;
+           int offset;
            struct demangle_component *base_type;
 
            derived_type = cplus_demangle_type (di);
@@ -2282,7 +2330,8 @@ cplus_demangle_type (struct d_info *di)
      names.  */
 
   peek = d_peek_char (di);
-  if (peek == 'r' || peek == 'V' || peek == 'K')
+  if (peek == 'r' || peek == 'V' || peek == 'K'
+      || (peek == 'D' && d_peek_next_char (di) == 'x'))
     {
       struct demangle_component **pret;
 
@@ -2483,6 +2532,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;
@@ -2590,7 +2642,7 @@ cplus_demangle_type (struct d_info *di)
   return ret;
 }
 
-/* <CV-qualifiers> ::= [r] [V] [K]  */
+/* <CV-qualifiers> ::= [r] [V] [K] [Dx] */
 
 static struct demangle_component **
 d_cv_qualifiers (struct d_info *di,
@@ -2601,7 +2653,8 @@ d_cv_qualifiers (struct d_info *di,
 
   pstart = pret;
   peek = d_peek_char (di);
-  while (peek == 'r' || peek == 'V' || peek == 'K')
+  while (peek == 'r' || peek == 'V' || peek == 'K'
+        || (peek == 'D' && d_peek_next_char (di) == 'x'))
     {
       enum demangle_component_type t;
 
@@ -2620,13 +2673,19 @@ d_cv_qualifiers (struct d_info *di,
               : DEMANGLE_COMPONENT_VOLATILE);
          di->expansion += sizeof "volatile";
        }
-      else
+      else if (peek == 'K')
        {
          t = (member_fn
               ? DEMANGLE_COMPONENT_CONST_THIS
               : DEMANGLE_COMPONENT_CONST);
          di->expansion += sizeof "const";
        }
+      else
+       {
+         t = DEMANGLE_COMPONENT_TRANSACTION_SAFE;
+         di->expansion += sizeof "transaction_safe";
+         d_advance (di, 1);
+       }
 
       *pret = d_make_comp (di, t, NULL, NULL);
       if (*pret == NULL)
@@ -2692,7 +2751,7 @@ d_ref_qualifier (struct d_info *di, struct demangle_component *sub)
   return ret;
 }
 
-/* <function-type> ::= F [Y] <bare-function-type> [<ref-qualifier>] E  */
+/* <function-type> ::= F [Y] <bare-function-type> [<ref-qualifier>] [T] E  */
 
 static struct demangle_component *
 d_function_type (struct d_info *di)
@@ -2918,10 +2977,10 @@ d_pointer_to_member_type (struct d_info *di)
 
 /* <non-negative number> _ */
 
-static long
+static int
 d_compact_number (struct d_info *di)
 {
-  long num;
+  int num;
   if (d_peek_char (di) == '_')
     num = 0;
   else if (d_peek_char (di) == 'n')
@@ -2929,7 +2988,7 @@ d_compact_number (struct d_info *di)
   else
     num = d_number (di) + 1;
 
-  if (! d_check_char (di, '_'))
+  if (num < 0 || ! d_check_char (di, '_'))
     return -1;
   return num;
 }
@@ -2941,7 +3000,7 @@ d_compact_number (struct d_info *di)
 static struct demangle_component *
 d_template_param (struct d_info *di)
 {
-  long param;
+  int param;
 
   if (! d_check_char (di, 'T'))
     return NULL;
@@ -2959,6 +3018,19 @@ d_template_param (struct d_info *di)
 
 static struct demangle_component *
 d_template_args (struct d_info *di)
+{
+  if (d_peek_char (di) != 'I'
+      && d_peek_char (di) != 'J')
+    return NULL;
+  d_advance (di, 1);
+
+  return d_template_args_1 (di);
+}
+
+/* <template-arg>* E  */
+
+static struct demangle_component *
+d_template_args_1 (struct d_info *di)
 {
   struct demangle_component *hold_last_name;
   struct demangle_component *al;
@@ -2969,11 +3041,6 @@ d_template_args (struct d_info *di)
      constructor or destructor.  */
   hold_last_name = di->last_name;
 
-  if (d_peek_char (di) != 'I'
-      && d_peek_char (di) != 'J')
-    return NULL;
-  d_advance (di, 1);
-
   if (d_peek_char (di) == 'E')
     {
       /* An argument pack can be empty.  */
@@ -3143,9 +3210,10 @@ d_expression_1 (struct d_info *di)
        }
       else
        {
-         index = d_compact_number (di) + 1;
-         if (index == 0)
+         index = d_compact_number (di);
+         if (index == INT_MAX || index == -1)
            return NULL;
+         index++;
        }
       return d_make_function_param (di, index);
     }
@@ -3176,6 +3244,8 @@ d_expression_1 (struct d_info *di)
       struct demangle_component *type = NULL;
       if (peek == 't')
        type = cplus_demangle_type (di);
+      if (!d_peek_next_char (di))
+       return NULL;
       d_advance (di, 2);
       return d_make_comp (di, DEMANGLE_COMPONENT_INITIALIZER_LIST,
                          type, d_exprlist (di, 'E'));
@@ -3232,6 +3302,8 @@ d_expression_1 (struct d_info *di)
            if (op->type == DEMANGLE_COMPONENT_CAST
                && d_check_char (di, '_'))
              operand = d_exprlist (di, 'E');
+           else if (code && !strcmp (code, "sP"))
+             operand = d_template_args_1 (di);
            else
              operand = d_expression_1 (di);
 
@@ -3250,8 +3322,13 @@ d_expression_1 (struct d_info *di)
            struct demangle_component *left;
            struct demangle_component *right;
 
+           if (code == NULL)
+             return NULL;
            if (op_is_new_cast (op))
              left = cplus_demangle_type (di);
+           else if (code[0] == 'f')
+             /* fold-expression.  */
+             left = d_operator_name (di);
            else
              left = d_expression_1 (di);
            if (!strcmp (code, "cl"))
@@ -3277,13 +3354,22 @@ d_expression_1 (struct d_info *di)
            struct demangle_component *second;
            struct demangle_component *third;
 
-           if (!strcmp (code, "qu"))
+           if (code == NULL)
+             return NULL;
+           else if (!strcmp (code, "qu"))
              {
                /* ?: expression.  */
                first = d_expression_1 (di);
                second = d_expression_1 (di);
                third = d_expression_1 (di);
              }
+           else if (code[0] == 'f')
+             {
+               /* fold-expression.  */
+               first = d_operator_name (di);
+               second = d_expression_1 (di);
+               third = d_expression_1 (di);
+             }
            else if (code[0] == 'n')
              {
                /* new-expression.  */
@@ -3468,7 +3554,7 @@ d_local_name (struct d_info *di)
 static int
 d_discriminator (struct d_info *di)
 {
-  long discrim;
+  int discrim;
 
   if (d_peek_char (di) != '_')
     return 1;
@@ -3524,7 +3610,7 @@ static struct demangle_component *
 d_unnamed_type (struct d_info *di)
 {
   struct demangle_component *ret;
-  long num;
+  int num;
 
   if (! d_check_char (di, 'U'))
     return NULL;
@@ -3700,6 +3786,7 @@ d_substitution (struct d_info *di, int prefix)
            {
              const char *s;
              int len;
+             struct demangle_component *dc;
 
              if (p->set_last_name != NULL)
                di->last_name = d_make_sub (di, p->set_last_name,
@@ -3715,7 +3802,15 @@ d_substitution (struct d_info *di, int prefix)
                  len = p->simple_len;
                }
              di->expansion += len;
-             return d_make_sub (di, s, len);
+             dc = 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.  */
+                 dc = d_abi_tags (di, dc);
+                 d_add_substitution (di, dc);
+               }
+             return dc;
            }
        }
 
@@ -3882,6 +3977,7 @@ d_count_templates_scopes (int *num_templates, int *num_scopes,
     case DEMANGLE_COMPONENT_CONST_THIS:
     case DEMANGLE_COMPONENT_REFERENCE_THIS:
     case DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS:
+    case DEMANGLE_COMPONENT_TRANSACTION_SAFE:
     case DEMANGLE_COMPONENT_VENDOR_TYPE_QUAL:
     case DEMANGLE_COMPONENT_POINTER:
     case DEMANGLE_COMPONENT_COMPLEX:
@@ -3890,12 +3986,12 @@ d_count_templates_scopes (int *num_templates, int *num_scopes,
     case DEMANGLE_COMPONENT_FUNCTION_TYPE:
     case DEMANGLE_COMPONENT_ARRAY_TYPE:
     case DEMANGLE_COMPONENT_PTRMEM_TYPE:
-    case DEMANGLE_COMPONENT_FIXED_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_CONVERSION:
     case DEMANGLE_COMPONENT_NULLARY:
     case DEMANGLE_COMPONENT_UNARY:
     case DEMANGLE_COMPONENT_BINARY:
@@ -3935,6 +4031,11 @@ d_count_templates_scopes (int *num_templates, int *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,
@@ -4037,10 +4138,10 @@ d_append_string (struct d_print_info *dpi, const char *s)
 }
 
 static inline void
-d_append_num (struct d_print_info *dpi, long l)
+d_append_num (struct d_print_info *dpi, int l)
 {
   char buf[25];
-  sprintf (buf,"%ld", l);
+  sprintf (buf,"%d", l);
   d_append_string (dpi, buf);
 }
 
@@ -4072,8 +4173,12 @@ cplus_demangle_print_callback (int options,
   {
 #if 0 /* in valgrind */
 #ifdef CP_DYNAMIC_ARRAYS
-    __extension__ struct d_saved_scope scopes[dpi.num_saved_scopes ?: 1];
-    __extension__ struct d_print_template temps[dpi.num_copy_templates ?: 1];
+    /* Avoid zero-length VLAs, which are prohibited by the C99 standard
+       and flagged as errors by Address Sanitizer.  */
+    __extension__ struct d_saved_scope scopes[(dpi.num_saved_scopes > 0)
+                                              ? dpi.num_saved_scopes : 1];
+    __extension__ struct d_print_template temps[(dpi.num_copy_templates > 0)
+                                                ? dpi.num_copy_templates : 1];
 
     dpi.saved_scopes = scopes;
     dpi.copy_templates = temps;
@@ -4138,13 +4243,17 @@ cplus_demangle_print (int options, const struct demangle_component *dc,
 }
 
 /* Returns the I'th element of the template arglist ARGS, or NULL on
-   failure.  */
+   failure.  If I is negative, return the entire arglist.  */
 
 static struct demangle_component *
 d_index_template_argument (struct demangle_component *args, int i)
 {
   struct demangle_component *a;
 
+  if (i < 0)
+    /* Print the whole argument pack.  */
+    return args;
+
   for (a = args;
        a != NULL;
        a = d_right (a))
@@ -4209,6 +4318,9 @@ d_find_pack (struct d_print_info *dpi,
     case DEMANGLE_COMPONENT_CHARACTER:
     case DEMANGLE_COMPONENT_FUNCTION_PARAM:
     case DEMANGLE_COMPONENT_UNNAMED_TYPE:
+    case DEMANGLE_COMPONENT_FIXED_TYPE:
+    case DEMANGLE_COMPONENT_DEFAULT_ARG:
+    case DEMANGLE_COMPONENT_NUMBER:
       return NULL;
 
     case DEMANGLE_COMPONENT_EXTENDED_OPERATOR:
@@ -4241,6 +4353,30 @@ d_pack_length (const struct demangle_component *dc)
   return count;
 }
 
+/* Returns the number of template args in DC, expanding any pack expansions
+   found there.  */
+
+static int
+d_args_length (struct d_print_info *dpi, const struct demangle_component *dc)
+{
+  int count = 0;
+  for (; dc && dc->type == DEMANGLE_COMPONENT_TEMPLATE_ARGLIST;
+       dc = d_right (dc))
+    {
+      struct demangle_component *elt = d_left (dc);
+      if (elt == NULL)
+       break;
+      if (elt->type == DEMANGLE_COMPONENT_PACK_EXPANSION)
+       {
+         struct demangle_component *a = d_find_pack (dpi, d_left (elt));
+         count += d_pack_length (a);
+       }
+      else
+       ++count;
+    }
+  return count;
+}
+
 /* DC is a component of a mangled expression.  Print it, wrapped in parens
    if needed.  */
 
@@ -4317,6 +4453,70 @@ d_get_saved_scope (struct d_print_info *dpi,
   return NULL;
 }
 
+/* If DC is a C++17 fold-expression, print it and return true; otherwise
+   return false.  */
+
+static int
+d_maybe_print_fold_expression (struct d_print_info *dpi, int options,
+                              const struct demangle_component *dc)
+{
+  const struct demangle_component *ops, *operator_, *op1, *op2;
+  int save_idx;
+
+  const char *fold_code = d_left (dc)->u.s_operator.op->code;
+  if (fold_code[0] != 'f')
+    return 0;
+
+  ops = d_right (dc);
+  operator_ = d_left (ops);
+  op1 = d_right (ops);
+  op2 = 0;
+  if (op1->type == DEMANGLE_COMPONENT_TRINARY_ARG2)
+    {
+      op2 = d_right (op1);
+      op1 = d_left (op1);
+    }
+
+  /* Print the whole pack.  */
+  save_idx = dpi->pack_index;
+  dpi->pack_index = -1;
+
+  switch (fold_code[1])
+    {
+      /* Unary left fold, (... + X).  */
+    case 'l':
+      d_append_string (dpi, "(...");
+      d_print_expr_op (dpi, options, operator_);
+      d_print_subexpr (dpi, options, op1);
+      d_append_char (dpi, ')');
+      break;
+
+      /* Unary right fold, (X + ...).  */
+    case 'r':
+      d_append_char (dpi, '(');
+      d_print_subexpr (dpi, options, op1);
+      d_print_expr_op (dpi, options, operator_);
+      d_append_string (dpi, "...)");
+      break;
+
+      /* Binary left fold, (42 + ... + X).  */
+    case 'L':
+      /* Binary right fold, (X + ... + 42).  */
+    case 'R':
+      d_append_char (dpi, '(');
+      d_print_subexpr (dpi, options, op1);
+      d_print_expr_op (dpi, options, operator_);
+      d_append_string (dpi, "...");
+      d_print_expr_op (dpi, options, operator_);
+      d_print_subexpr (dpi, options, op2);
+      d_append_char (dpi, ')');
+      break;
+    }
+
+  dpi->pack_index = save_idx;
+  return 1;
+}
+
 /* Subroutine to handle components.  */
 
 static void
@@ -4412,6 +4612,7 @@ d_print_comp_inner (struct d_print_info *dpi, int options,
                && typed_name->type != DEMANGLE_COMPONENT_VOLATILE_THIS
                && typed_name->type != DEMANGLE_COMPONENT_CONST_THIS
                && typed_name->type != DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS
+               && typed_name->type != DEMANGLE_COMPONENT_TRANSACTION_SAFE
                && typed_name->type != DEMANGLE_COMPONENT_REFERENCE_THIS)
              break;
 
@@ -4444,10 +4645,16 @@ d_print_comp_inner (struct d_print_info *dpi, int options,
            local_name = d_right (typed_name);
            if (local_name->type == DEMANGLE_COMPONENT_DEFAULT_ARG)
              local_name = local_name->u.s_unary_num.sub;
+           if (local_name == NULL)
+             {
+               d_print_error (dpi);
+               return;
+             }
            while (local_name->type == DEMANGLE_COMPONENT_RESTRICT_THIS
                   || local_name->type == DEMANGLE_COMPONENT_VOLATILE_THIS
                   || local_name->type == DEMANGLE_COMPONENT_CONST_THIS
                   || local_name->type == DEMANGLE_COMPONENT_REFERENCE_THIS
+                  || local_name->type == DEMANGLE_COMPONENT_TRANSACTION_SAFE
                   || (local_name->type
                       == DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS))
              {
@@ -4783,6 +4990,7 @@ d_print_comp_inner (struct d_print_info *dpi, int options,
     case DEMANGLE_COMPONENT_POINTER:
     case DEMANGLE_COMPONENT_COMPLEX:
     case DEMANGLE_COMPONENT_IMAGINARY:
+    case DEMANGLE_COMPONENT_TRANSACTION_SAFE:
     modifier:
       {
        /* We keep a list of modifiers on the stack.  */
@@ -5032,9 +5240,9 @@ d_print_comp_inner (struct d_print_info *dpi, int options,
       d_print_comp (dpi, options, dc->u.s_extended_operator.name);
       return;
 
-    case DEMANGLE_COMPONENT_CAST:
+    case DEMANGLE_COMPONENT_CONVERSION:
       d_append_string (dpi, "operator ");
-      d_print_cast (dpi, options, dc);
+      d_print_conversion (dpi, options, dc);
       return;
 
     case DEMANGLE_COMPONENT_NULLARY:
@@ -5069,6 +5277,21 @@ d_print_comp_inner (struct d_print_info *dpi, int options,
              }
          }
 
+       /* For sizeof..., just print the pack length.  */
+       if (code && !strcmp (code, "sZ"))
+         {
+           struct demangle_component *a = d_find_pack (dpi, operand);
+           int len = d_pack_length (a);
+           d_append_num (dpi, len);
+           return;
+         }
+       else if (code && !strcmp (code, "sP"))
+         {
+           int len = d_args_length (dpi, operand);
+           d_append_num (dpi, len);
+           return;
+         }
+
        if (op->type != DEMANGLE_COMPONENT_CAST)
          d_print_expr_op (dpi, options, op);
        else
@@ -5110,6 +5333,9 @@ d_print_comp_inner (struct d_print_info *dpi, int options,
          return;
        }
 
+      if (d_maybe_print_fold_expression (dpi, options, dc))
+       return;
+
       /* We wrap an expression which uses the greater-than operator in
         an extra layer of parens so that it does not get confused
         with the '>' which ends the template parameters.  */
@@ -5165,6 +5391,8 @@ d_print_comp_inner (struct d_print_info *dpi, int options,
          d_print_error (dpi);
          return;
        }
+      if (d_maybe_print_fold_expression (dpi, options, dc))
+       return;
       {
        struct demangle_component *op = d_left (dc);
        struct demangle_component *first = d_left (d_right (dc));
@@ -5471,6 +5699,7 @@ d_print_mod_list (struct d_print_info *dpi, int options,
              || mods->mod->type == DEMANGLE_COMPONENT_VOLATILE_THIS
              || mods->mod->type == DEMANGLE_COMPONENT_CONST_THIS
              || mods->mod->type == DEMANGLE_COMPONENT_REFERENCE_THIS
+             || mods->mod->type == DEMANGLE_COMPONENT_TRANSACTION_SAFE
              || (mods->mod->type
                  == DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS))))
     {
@@ -5529,6 +5758,7 @@ d_print_mod_list (struct d_print_info *dpi, int options,
             || dc->type == DEMANGLE_COMPONENT_VOLATILE_THIS
             || dc->type == DEMANGLE_COMPONENT_CONST_THIS
             || dc->type == DEMANGLE_COMPONENT_REFERENCE_THIS
+            || dc->type == DEMANGLE_COMPONENT_TRANSACTION_SAFE
             || dc->type == DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS)
        dc = d_left (dc);
 
@@ -5565,6 +5795,9 @@ d_print_mod (struct d_print_info *dpi, int options,
     case DEMANGLE_COMPONENT_CONST_THIS:
       d_append_string (dpi, " const");
       return;
+    case DEMANGLE_COMPONENT_TRANSACTION_SAFE:
+      d_append_string (dpi, " transaction_safe");
+      return;
     case DEMANGLE_COMPONENT_VENDOR_TYPE_QUAL:
       d_append_char (dpi, ' ');
       d_print_comp (dpi, options, d_right (mod));
@@ -5577,11 +5810,13 @@ d_print_mod (struct d_print_info *dpi, int options,
     case DEMANGLE_COMPONENT_REFERENCE_THIS:
       /* For the ref-qualifier, put a space before the &.  */
       d_append_char (dpi, ' ');
+      /* FALLTHRU */
     case DEMANGLE_COMPONENT_REFERENCE:
       d_append_char (dpi, '&');
       return;
     case DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS:
       d_append_char (dpi, ' ');
+      /* FALLTHRU */
     case DEMANGLE_COMPONENT_RVALUE_REFERENCE:
       d_append_string (dpi, "&&");
       return;
@@ -5655,6 +5890,7 @@ d_print_function_type (struct d_print_info *dpi, int options,
        case DEMANGLE_COMPONENT_CONST_THIS:
        case DEMANGLE_COMPONENT_REFERENCE_THIS:
        case DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS:
+       case DEMANGLE_COMPONENT_TRANSACTION_SAFE:
          break;
        default:
          break;
@@ -5767,11 +6003,20 @@ d_print_expr_op (struct d_print_info *dpi, int options,
 
 static void
 d_print_cast (struct d_print_info *dpi, int options,
-              const struct demangle_component *dc)
+                   const struct demangle_component *dc)
+{
+  d_print_comp (dpi, options, d_left (dc));
+}
+
+/* Print a conversion operator.  */
+
+static void
+d_print_conversion (struct d_print_info *dpi, int options,
+                   const struct demangle_component *dc)
 {
   struct d_print_template dpt;
 
-  /* For a cast operator, we need the template parameters from
+  /* For a conversion operator, we need the template parameters from
      the enclosing template in scope for processing the type.  */
   if (dpi->current_template != NULL)
     {
@@ -6206,6 +6451,7 @@ is_ctor_or_dtor (const char *mangled,
          case DEMANGLE_COMPONENT_CONST_THIS:
          case DEMANGLE_COMPONENT_REFERENCE_THIS:
          case DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS:
+         case DEMANGLE_COMPONENT_TRANSACTION_SAFE:
          default:
            dc = NULL;
            break;
index 6fce0252dc4d0665c6812047e9ad8fa73b0c9978..197883e25602f4d8d506de50c6b5d6f800babc97 100644 (file)
@@ -135,12 +135,37 @@ struct d_info
    - call d_check_char(di, '\0')
    Everything else is safe.  */
 #define d_peek_char(di) (*((di)->n))
-#define d_peek_next_char(di) ((di)->n[1])
-#define d_advance(di, i) ((di)->n += (i))
+#ifndef CHECK_DEMANGLER
+#  define d_peek_next_char(di) ((di)->n[1])
+#  define d_advance(di, i) ((di)->n += (i))
+#endif
 #define d_check_char(di, c) (d_peek_char(di) == c ? ((di)->n++, 1) : 0)
 #define d_next_char(di) (d_peek_char(di) == '\0' ? '\0' : *((di)->n++))
 #define d_str(di) ((di)->n)
 
+#ifdef CHECK_DEMANGLER
+static inline char
+d_peek_next_char (const struct d_info *di)
+{
+  if (!di->n[0])
+    abort ();
+  return di->n[1];
+}
+
+static inline void
+d_advance (struct d_info *di, int i)
+{
+  if (i < 0)
+    abort ();
+  while (i--)
+    {
+      if (!di->n[0])
+       abort ();
+      di->n++;
+    }
+}
+#endif
+
 /* Functions and arrays in cp-demangle.c which are referenced by
    functions in cp-demint.c.  */
 #ifdef IN_GLIBCPP_V3
index 46cc3b5363b29eeca14c33506b3d335c14ea6598..d00f79fa5427188c0c614edf84f096101174581c 100644 (file)
@@ -64,6 +64,15 @@ void * realloc ();
 #endif
 #endif /* ! in valgrind */
 
+#if 0 /* in valgrind */
+#ifdef HAVE_LIMITS_H
+#include <limits.h>
+#endif
+#endif /* ! in valgrind */
+#ifndef INT_MAX
+# define INT_MAX       (int)(((unsigned int) ~0) >> 1)          /* 0x7FFFFFFF */ 
+#endif
+
 #if 0 /* in valgrind */
 #include <demangle.h>
 #undef CURRENT_DEMANGLING_STYLE
@@ -155,6 +164,9 @@ struct work_stuff
   string* previous_argument; /* The last function argument demangled.  */
   int nrepeats;         /* The number of times to repeat the previous
                           argument.  */
+  int *proctypevec;     /* Indices of currently processed remembered typevecs.  */
+  int proctypevec_size;
+  int nproctypes;
 };
 
 #define PRINT_ANSI_QUALIFIERS (work -> options & DMGL_ANSI)
@@ -255,6 +267,7 @@ typedef enum type_kind_t
   tk_none,
   tk_pointer,
   tk_reference,
+  tk_rvalue_reference,
   tk_integral,
   tk_bool,
   tk_char,
@@ -323,6 +336,12 @@ const struct demangler_engine libiberty_demanglers[] =
     "GNAT style demangling"
   }
   ,
+  {
+    DLANG_DEMANGLING_STYLE_STRING,
+    dlang_demangling,
+    "DLANG style demangling"
+  }
+  ,
   {
     NULL, unknown_demangling, NULL
   }
@@ -439,6 +458,10 @@ iterate_demangle_function (struct work_stuff *,
 
 static void remember_type (struct work_stuff *, const char *, int);
 
+static void push_processed_type (struct work_stuff *, int);
+
+static void pop_processed_type (struct work_stuff *);
+
 static void remember_Btype (struct work_stuff *, const char *, int, int);
 
 static int register_Btype (struct work_stuff *);
@@ -887,6 +910,13 @@ ML_(cplus_demangle) (const char *mangled, int options)
   if (GNAT_DEMANGLING)
     return ada_demangle (mangled, options);
 
+  if (DLANG_DEMANGLING)
+    {
+      ret = dlang_demangle (mangled, options);
+      if (ret)
+       return ret;
+    }
+
   ret = internal_cplus_demangle (work, mangled);
   squangle_mop_up (work);
   return (ret);
@@ -1241,11 +1271,13 @@ squangle_mop_up (struct work_stuff *work)
     {
       free ((char *) work -> btypevec);
       work->btypevec = NULL;
+      work->bsize = 0;
     }
   if (work -> ktypevec != NULL)
     {
       free ((char *) work -> ktypevec);
       work->ktypevec = NULL;
+      work->ksize = 0;
     }
 }
 
@@ -1296,6 +1328,10 @@ work_stuff_copy_to_from (struct work_stuff *to, struct work_stuff *from)
       memcpy (to->btypevec[i], from->btypevec[i], len);
     }
 
+  if (from->proctypevec)
+    to->proctypevec =
+      XDUPVEC (int, from->proctypevec, from->proctypevec_size);
+
   if (from->ntmpl_args)
     to->tmpl_argvec = XNEWVEC (char *, from->ntmpl_args);
 
@@ -1324,11 +1360,17 @@ delete_non_B_K_work_stuff (struct work_stuff *work)
   /* Discard the remembered types, if any.  */
 
   forget_types (work);
-  if (work -> typevec != NULL)
+  if (work->typevec != NULL)
     {
-      free ((char *) work -> typevec);
-      work -> typevec = NULL;
-      work -> typevec_size = 0;
+      free ((char *) work->typevec);
+      work->typevec = NULL;
+      work->typevec_size = 0;
+    }
+  if (work->proctypevec != NULL)
+    {
+      free (work->proctypevec);
+      work->proctypevec = NULL;
+      work->proctypevec_size = 0;
     }
   if (work->tmpl_argvec)
     {
@@ -2037,7 +2079,8 @@ demangle_template_value_parm (struct work_stuff *work, const char **mangled,
     }
   else if (tk == tk_real)
     success = demangle_real_value (work, mangled, s);
-  else if (tk == tk_pointer || tk == tk_reference)
+  else if (tk == tk_pointer || tk == tk_reference
+          || tk == tk_rvalue_reference)
     {
       if (**mangled == 'Q')
        success = demangle_qualified (work, mangled, s,
@@ -2046,7 +2089,8 @@ demangle_template_value_parm (struct work_stuff *work, const char **mangled,
       else
        {
          int symbol_len  = consume_count (mangled);
-         if (symbol_len == -1)
+         if (symbol_len == -1
+             || symbol_len > (long) strlen (*mangled))
            return -1;
          if (symbol_len == 0)
            string_appendn (s, "0", 1);
@@ -3003,6 +3047,11 @@ gnu_special (struct work_stuff *work, const char **mangled, string *declp)
                      success = 1;
                      break;
                    }
+                 else if (n == -1)
+                   {
+                     success = 0;
+                     break;
+                   }
                }
              else
                {
@@ -3542,6 +3591,8 @@ static int
 do_type (struct work_stuff *work, const char **mangled, string *result)
 {
   int n;
+  int i;
+  int is_proctypevec;
   int done;
   int success;
   string decl;
@@ -3554,6 +3605,7 @@ do_type (struct work_stuff *work, const char **mangled, string *result)
 
   done = 0;
   success = 1;
+  is_proctypevec = 0;
   while (success && !done)
     {
       int member;
@@ -3578,6 +3630,14 @@ do_type (struct work_stuff *work, const char **mangled, string *result)
            tk = tk_reference;
          break;
 
+         /* An rvalue reference type */
+       case 'O':
+         (*mangled)++;
+         string_prepend (&decl, "&&");
+         if (tk == tk_none)
+           tk = tk_rvalue_reference;
+         break;
+
          /* An array */
        case 'A':
          {
@@ -3601,13 +3661,20 @@ do_type (struct work_stuff *work, const char **mangled, string *result)
        /* A back reference to a previously seen type */
        case 'T':
          (*mangled)++;
-         if (!get_count (mangled, &n) || n >= work -> ntypes)
+         if (!get_count (mangled, &n) || n < 0 || n >= work -> ntypes)
            {
              success = 0;
            }
          else
-           {
-             remembered_type = work -> typevec[n];
+           for (i = 0; i < work->nproctypes; i++)
+             if (work -> proctypevec [i] == n)
+               success = 0;
+
+         if (success)
+           {    
+             is_proctypevec = 1;
+             push_processed_type (work, n);
+             remembered_type = work->typevec[n];
              mangled = &remembered_type;
            }
          break;
@@ -3635,7 +3702,6 @@ do_type (struct work_stuff *work, const char **mangled, string *result)
          break;
 
        case 'M':
-       case 'O':
          {
            type_quals = TYPE_UNQUALIFIED;
 
@@ -3779,7 +3845,7 @@ do_type (struct work_stuff *work, const char **mangled, string *result)
     /* A back reference to a previously seen squangled type */
     case 'B':
       (*mangled)++;
-      if (!get_count (mangled, &n) || n >= work -> numb)
+      if (!get_count (mangled, &n) || n < 0 || n >= work -> numb)
        success = 0;
       else
        string_append (result, work->btypevec[n]);
@@ -3830,6 +3896,9 @@ do_type (struct work_stuff *work, const char **mangled, string *result)
     string_delete (result);
   string_delete (&decl);
 
+  if (is_proctypevec)
+    pop_processed_type (work); 
+
   if (success)
     /* Assume an integral type, if we're not sure.  */
     return (int) ((tk == tk_none) ? tk_integral : tk);
@@ -4127,7 +4196,8 @@ do_hpacc_template_literal (struct work_stuff *work, const char **mangled,
 
   literal_len = consume_count (mangled);
 
-  if (literal_len <= 0)
+  if (literal_len <= 0
+      || literal_len > (long) strlen (*mangled))
     return 0;
 
   /* Literal parameters are names of arrays, functions, etc.  and the
@@ -4248,6 +4318,41 @@ do_arg (struct work_stuff *work, const char **mangled, string *result)
   return 1;
 }
 
+static void
+push_processed_type (struct work_stuff *work, int typevec_index)
+{
+  if (work->nproctypes >= work->proctypevec_size)
+    {
+      if (!work->proctypevec_size)
+       {
+         work->proctypevec_size = 4;
+         work->proctypevec = XNEWVEC (int, work->proctypevec_size);
+       }
+      else 
+       {
+         if (work->proctypevec_size < 16)
+           /* Double when small.  */
+           work->proctypevec_size *= 2;
+         else
+           {
+             /* Grow slower when large.  */
+             if (work->proctypevec_size > (INT_MAX / 3) * 2)
+                xmalloc_failed (INT_MAX);
+              work->proctypevec_size = (work->proctypevec_size * 3 / 2);
+           }   
+          work->proctypevec
+            = XRESIZEVEC (int, work->proctypevec, work->proctypevec_size);
+       }
+    }
+    work->proctypevec [work->nproctypes++] = typevec_index;
+}
+
+static void
+pop_processed_type (struct work_stuff *work)
+{
+  work->nproctypes--;
+}
+
 static void
 remember_type (struct work_stuff *work, const char *start, int len)
 {
@@ -4265,6 +4370,8 @@ remember_type (struct work_stuff *work, const char *start, int len)
        }
       else
        {
+          if (work -> typevec_size > INT_MAX / 2)
+           xmalloc_failed (INT_MAX);
          work -> typevec_size *= 2;
          work -> typevec
            = XRESIZEVEC (char *, work->typevec, work->typevec_size);
@@ -4292,6 +4399,8 @@ remember_Ktype (struct work_stuff *work, const char *start, int len)
        }
       else
        {
+          if (work -> ksize > INT_MAX / 2)
+           xmalloc_failed (INT_MAX);
          work -> ksize *= 2;
          work -> ktypevec
            = XRESIZEVEC (char *, work->ktypevec, work->ksize);
@@ -4321,6 +4430,8 @@ register_Btype (struct work_stuff *work)
        }
       else
        {
+          if (work -> bsize > INT_MAX / 2)
+           xmalloc_failed (INT_MAX);
          work -> bsize *= 2;
          work -> btypevec
            = XRESIZEVEC (char *, work->btypevec, work->bsize);
@@ -4506,10 +4617,13 @@ demangle_args (struct work_stuff *work, const char **mangled,
                {
                  string_append (declp, ", ");
                }
+             push_processed_type (work, t);  
              if (!do_arg (work, &tem, &arg))
                {
+                 pop_processed_type (work);
                  return (0);
                }
+             pop_processed_type (work);
              if (PRINT_ARG_TYPES)
                {
                  string_appends (declp, &arg);
@@ -4791,6 +4905,8 @@ string_need (string *s, int n)
   else if (s->e - s->p < n)
     {
       tem = s->p - s->b;
+      if (n > INT_MAX / 2 - tem)
+        xmalloc_failed (INT_MAX); 
       n += tem;
       n *= 2;
       s->b = XRESIZEVEC (char, s->b, n);
diff --git a/coregrind/m_demangle/d-demangle.c b/coregrind/m_demangle/d-demangle.c
new file mode 100644 (file)
index 0000000..129999c
--- /dev/null
@@ -0,0 +1,1618 @@
+/* Demangler for the D programming language
+   Copyright 2014, 2015, 2016 Free Software Foundation, Inc.
+   Written by Iain Buclaw (ibuclaw@gdcproject.org)
+
+This file is part of the libiberty library.
+Libiberty is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public
+License as published by the Free Software Foundation; either
+version 2 of the License, or (at your option) any later version.
+
+In addition to the permissions in the GNU Library General Public
+License, the Free Software Foundation gives you unlimited permission
+to link the compiled version of this file into combinations with other
+programs, and to distribute those combinations without any restriction
+coming from the use of this file.  (The Library Public License
+restrictions do apply in other respects; for example, they cover
+modification of the file, and distribution when not linked into a
+combined executable.)
+
+Libiberty is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with libiberty; see the file COPYING.LIB.
+If not, see <http://www.gnu.org/licenses/>.  */
+
+/* This file exports one function; dlang_demangle.
+
+   This file imports strtol for decoding mangled literals.  */
+
+#if 0 /* in valgrind */
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+#endif /* ! in valgrind */
+
+#if 0 /* in valgrind */
+#include "safe-ctype.h"
+#endif /* ! in valgrind */
+
+#if 0 /* in valgrind */
+#include <sys/types.h>
+#include <string.h>
+#include <stdio.h>
+#endif /* ! in valgrind */
+
+#if 0 /* in valgrind */
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#else
+extern long strtol (const char *nptr, char **endptr, int base);
+#endif
+#endif /* ! in valgrind */
+
+#if 0 /* in valgrind */
+#include <demangle.h>
+#include "libiberty.h"
+#endif /* ! in valgrind */
+
+#include "vg_libciface.h"
+
+#include "ansidecl.h"
+#include "demangle.h"
+#include "safe-ctype.h"
+
+/* A mini string-handling package */
+
+typedef struct string          /* Beware: these aren't required to be */
+{                              /*  '\0' terminated.  */
+  char *b;                     /* pointer to start of string */
+  char *p;                     /* pointer after last character */
+  char *e;                     /* pointer after end of allocated space */
+} string;
+
+static void
+string_need (string *s, int n)
+{
+  int tem;
+
+  if (s->b == NULL)
+    {
+      if (n < 32)
+       {
+         n = 32;
+       }
+      s->p = s->b = XNEWVEC (char, n);
+      s->e = s->b + n;
+    }
+  else if (s->e - s->p < n)
+    {
+      tem = s->p - s->b;
+      n += tem;
+      n *= 2;
+      s->b = XRESIZEVEC (char, s->b, n);
+      s->p = s->b + tem;
+      s->e = s->b + n;
+    }
+}
+
+static void
+string_delete (string *s)
+{
+  if (s->b != NULL)
+    {
+      XDELETEVEC (s->b);
+      s->b = s->e = s->p = NULL;
+    }
+}
+
+static void
+string_init (string *s)
+{
+  s->b = s->p = s->e = NULL;
+}
+
+static int
+string_length (string *s)
+{
+  if (s->p == s->b)
+    {
+      return 0;
+    }
+  return s->p - s->b;
+}
+
+static void
+string_setlength (string *s, int n)
+{
+  if (n - string_length (s) < 0)
+    {
+      s->p = s->b + n;
+    }
+}
+
+static void
+string_append (string *p, const char *s)
+{
+  int n = strlen (s);
+  string_need (p, n);
+  memcpy (p->p, s, n);
+  p->p += n;
+}
+
+static void
+string_appendn (string *p, const char *s, int n)
+{
+  if (n != 0)
+    {
+      string_need (p, n);
+      memcpy (p->p, s, n);
+      p->p += n;
+    }
+}
+
+static void
+string_prependn (string *p, const char *s, int n)
+{
+  char *q;
+
+  if (n != 0)
+    {
+      string_need (p, n);
+      for (q = p->p - 1; q >= p->b; q--)
+       {
+         q[n] = q[0];
+       }
+      memcpy (p->b, s, n);
+      p->p += n;
+    }
+}
+
+static void
+string_prepend (string *p, const char *s)
+{
+  if (s != NULL && *s != '\0')
+    {
+      string_prependn (p, s, strlen (s));
+    }
+}
+
+/* What kinds of symbol we could be parsing.  */
+enum dlang_symbol_kinds
+{
+  /* Top-level symbol, needs it's type checked.  */
+  dlang_top_level,
+  /* Function symbol, needs it's type checked.   */
+  dlang_function,
+  /* Strongly typed name, such as for classes, structs and enums.  */
+  dlang_type_name,
+  /* Template identifier.  */
+  dlang_template_ident,
+  /* Template symbol parameter.  */
+  dlang_template_param
+};
+
+/* Prototypes for forward referenced functions */
+static const char *dlang_function_args (string *, const char *);
+
+static const char *dlang_type (string *, const char *);
+
+static const char *dlang_value (string *, const char *, const char *, char);
+
+static const char *dlang_parse_symbol (string *, const char *,
+                                      enum dlang_symbol_kinds);
+
+static const char *dlang_parse_tuple (string *, const char *);
+
+static const char *dlang_parse_template (string *, const char *, long);
+
+
+/* Demangle the calling convention from MANGLED and append it to DECL.
+   Return the remaining string on success or NULL on failure.  */
+static const char *
+dlang_call_convention (string *decl, const char *mangled)
+{
+  if (mangled == NULL || *mangled == '\0')
+    return NULL;
+
+  switch (*mangled)
+    {
+    case 'F': /* (D) */
+      mangled++;
+      break;
+    case 'U': /* (C) */
+      mangled++;
+      string_append (decl, "extern(C) ");
+      break;
+    case 'W': /* (Windows) */
+      mangled++;
+      string_append (decl, "extern(Windows) ");
+      break;
+    case 'V': /* (Pascal) */
+      mangled++;
+      string_append (decl, "extern(Pascal) ");
+      break;
+    case 'R': /* (C++) */
+      mangled++;
+      string_append (decl, "extern(C++) ");
+      break;
+    case 'Y': /* (Objective-C) */
+      mangled++;
+      string_append (decl, "extern(Objective-C) ");
+      break;
+    default:
+      return NULL;
+    }
+
+  return mangled;
+}
+
+/* Extract the type modifiers from MANGLED and append them to DECL.
+   Returns the remaining signature on success or NULL on failure.  */
+static const char *
+dlang_type_modifiers (string *decl, const char *mangled)
+{
+  if (mangled == NULL || *mangled == '\0')
+    return NULL;
+
+  switch (*mangled)
+    {
+    case 'x': /* const */
+      mangled++;
+      string_append (decl, " const");
+      return mangled;
+    case 'y': /* immutable */
+      mangled++;
+      string_append (decl, " immutable");
+      return mangled;
+    case 'O': /* shared */
+      mangled++;
+      string_append (decl, " shared");
+      return dlang_type_modifiers (decl, mangled);
+    case 'N':
+      mangled++;
+      if (*mangled == 'g') /* wild */
+       {
+         mangled++;
+         string_append (decl, " inout");
+         return dlang_type_modifiers (decl, mangled);
+       }
+      else
+       return NULL;
+
+    default:
+      return mangled;
+    }
+}
+
+/* Demangle the D function attributes from MANGLED and append it to DECL.
+   Return the remaining string on success or NULL on failure.  */
+static const char *
+dlang_attributes (string *decl, const char *mangled)
+{
+  if (mangled == NULL || *mangled == '\0')
+    return NULL;
+
+  while (*mangled == 'N')
+    {
+      mangled++;
+      switch (*mangled)
+       {
+       case 'a': /* pure */
+         mangled++;
+         string_append (decl, "pure ");
+         continue;
+       case 'b': /* nothrow */
+         mangled++;
+         string_append (decl, "nothrow ");
+         continue;
+       case 'c': /* ref */
+         mangled++;
+         string_append (decl, "ref ");
+         continue;
+       case 'd': /* @property */
+         mangled++;
+         string_append (decl, "@property ");
+         continue;
+       case 'e': /* @trusted */
+         mangled++;
+         string_append (decl, "@trusted ");
+         continue;
+       case 'f': /* @safe */
+         mangled++;
+         string_append (decl, "@safe ");
+         continue;
+       case 'g':
+       case 'h':
+       case 'k':
+         /* inout parameter is represented as 'Ng'.
+            vector parameter is represented as 'Nh'.
+            return paramenter is represented as 'Nk'.
+            If we see this, then we know we're really in the
+            parameter list.  Rewind and break.  */
+         mangled--;
+         break;
+       case 'i': /* @nogc */
+         mangled++;
+         string_append (decl, "@nogc ");
+         continue;
+       case 'j': /* return */
+         mangled++;
+         string_append (decl, "return ");
+         continue;
+
+       default: /* unknown attribute */
+         return NULL;
+       }
+      break;
+    }
+
+  return mangled;
+}
+
+/* Demangle the function type from MANGLED and append it to DECL.
+   Return the remaining string on success or NULL on failure.  */
+static const char *
+dlang_function_type (string *decl, const char *mangled)
+{
+  string attr, args, type;
+  size_t szattr, szargs, sztype;
+
+  if (mangled == NULL || *mangled == '\0')
+    return NULL;
+
+  /* The order of the mangled string is:
+       CallConvention FuncAttrs Arguments ArgClose Type
+
+     The demangled string is re-ordered as:
+       CallConvention Type Arguments FuncAttrs
+   */
+  string_init (&attr);
+  string_init (&args);
+  string_init (&type);
+
+  /* Function call convention.  */
+  mangled = dlang_call_convention (decl, mangled);
+
+  /* Function attributes.  */
+  mangled = dlang_attributes (&attr, mangled);
+  szattr = string_length (&attr);
+
+  /* Function arguments.  */
+  mangled = dlang_function_args (&args, mangled);
+  szargs = string_length (&args);
+
+  /* Function return type.  */
+  mangled = dlang_type (&type, mangled);
+  sztype = string_length (&type);
+
+  /* Append to decl in order. */
+  string_appendn (decl, type.b, sztype);
+  string_append (decl, "(");
+  string_appendn (decl, args.b, szargs);
+  string_append (decl, ") ");
+  string_appendn (decl, attr.b, szattr);
+
+  string_delete (&attr);
+  string_delete (&args);
+  string_delete (&type);
+  return mangled;
+}
+
+/* Demangle the argument list from MANGLED and append it to DECL.
+   Return the remaining string on success or NULL on failure.  */
+static const char *
+dlang_function_args (string *decl, const char *mangled)
+{
+  size_t n = 0;
+
+  while (mangled && *mangled != '\0')
+    {
+      switch (*mangled)
+       {
+       case 'X': /* (variadic T t...) style.  */
+         mangled++;
+         string_append (decl, "...");
+         return mangled;
+       case 'Y': /* (variadic T t, ...) style.  */
+         mangled++;
+         if (n != 0)
+           string_append (decl, ", ");
+         string_append (decl, "...");
+         return mangled;
+       case 'Z': /* Normal function.  */
+         mangled++;
+         return mangled;
+       }
+
+      if (n++)
+       string_append (decl, ", ");
+
+      if (*mangled == 'M') /* scope(T) */
+       {
+         mangled++;
+         string_append (decl, "scope ");
+       }
+
+      if (mangled[0] == 'N' && mangled[1] == 'k') /* return(T) */
+       {
+         mangled += 2;
+         string_append (decl, "return ");
+       }
+
+      switch (*mangled)
+       {
+       case 'J': /* out(T) */
+         mangled++;
+         string_append (decl, "out ");
+         break;
+       case 'K': /* ref(T) */
+         mangled++;
+         string_append (decl, "ref ");
+         break;
+       case 'L': /* lazy(T) */
+         mangled++;
+         string_append (decl, "lazy ");
+         break;
+       }
+      mangled = dlang_type (decl, mangled);
+    }
+
+  return mangled;
+}
+
+/* Demangle the type from MANGLED and append it to DECL.
+   Return the remaining string on success or NULL on failure.  */
+static const char *
+dlang_type (string *decl, const char *mangled)
+{
+  if (mangled == NULL || *mangled == '\0')
+    return NULL;
+
+  switch (*mangled)
+    {
+    case 'O': /* shared(T) */
+      mangled++;
+      string_append (decl, "shared(");
+      mangled = dlang_type (decl, mangled);
+      string_append (decl, ")");
+      return mangled;
+    case 'x': /* const(T) */
+      mangled++;
+      string_append (decl, "const(");
+      mangled = dlang_type (decl, mangled);
+      string_append (decl, ")");
+      return mangled;
+    case 'y': /* immutable(T) */
+      mangled++;
+      string_append (decl, "immutable(");
+      mangled = dlang_type (decl, mangled);
+      string_append (decl, ")");
+      return mangled;
+    case 'N':
+      mangled++;
+      if (*mangled == 'g') /* wild(T) */
+       {
+         mangled++;
+         string_append (decl, "inout(");
+         mangled = dlang_type (decl, mangled);
+         string_append (decl, ")");
+         return mangled;
+       }
+      else if (*mangled == 'h') /* vector(T) */
+       {
+         mangled++;
+         string_append (decl, "__vector(");
+         mangled = dlang_type (decl, mangled);
+         string_append (decl, ")");
+         return mangled;
+       }
+      else
+       return NULL;
+    case 'A': /* dynamic array (T[]) */
+      mangled++;
+      mangled = dlang_type (decl, mangled);
+      string_append (decl, "[]");
+      return mangled;
+    case 'G': /* static array (T[N]) */
+    {
+      const char *numptr;
+      size_t num = 0;
+      mangled++;
+
+      numptr = mangled;
+      while (ISDIGIT (*mangled))
+       {
+         num++;
+         mangled++;
+       }
+      mangled = dlang_type (decl, mangled);
+      string_append (decl, "[");
+      string_appendn (decl, numptr, num);
+      string_append (decl, "]");
+      return mangled;
+    }
+    case 'H': /* associative array (T[T]) */
+    {
+      string type;
+      size_t sztype;
+      mangled++;
+
+      string_init (&type);
+      mangled = dlang_type (&type, mangled);
+      sztype = string_length (&type);
+
+      mangled = dlang_type (decl, mangled);
+      string_append (decl, "[");
+      string_appendn (decl, type.b, sztype);
+      string_append (decl, "]");
+
+      string_delete (&type);
+      return mangled;
+    }
+    case 'P': /* pointer (T*) */
+      mangled++;
+      /* Function pointer types don't include the trailing asterisk.  */
+      switch (*mangled)
+       {
+       case 'F': case 'U': case 'W':
+       case 'V': case 'R': case 'Y':
+         mangled = dlang_function_type (decl, mangled);
+         string_append (decl, "function");
+         return mangled;
+       }
+      mangled = dlang_type (decl, mangled);
+      string_append (decl, "*");
+      return mangled;
+    case 'I': /* ident T */
+    case 'C': /* class T */
+    case 'S': /* struct T */
+    case 'E': /* enum T */
+    case 'T': /* typedef T */
+      mangled++;
+      return dlang_parse_symbol (decl, mangled, dlang_type_name);
+    case 'D': /* delegate T */
+    {
+      string mods;
+      size_t szmods;
+      mangled++;
+
+      string_init (&mods);
+      mangled = dlang_type_modifiers (&mods, mangled);
+      szmods = string_length (&mods);
+
+      mangled = dlang_function_type (decl, mangled);
+      string_append (decl, "delegate");
+      string_appendn (decl, mods.b, szmods);
+
+      string_delete (&mods);
+      return mangled;
+    }
+    case 'B': /* tuple T */
+      mangled++;
+      return dlang_parse_tuple (decl, mangled);
+
+    /* Basic types */
+    case 'n':
+      mangled++;
+      string_append (decl, "none");
+      return mangled;
+    case 'v':
+      mangled++;
+      string_append (decl, "void");
+      return mangled;
+    case 'g':
+      mangled++;
+      string_append (decl, "byte");
+      return mangled;
+    case 'h':
+      mangled++;
+      string_append (decl, "ubyte");
+      return mangled;
+    case 's':
+      mangled++;
+      string_append (decl, "short");
+      return mangled;
+    case 't':
+      mangled++;
+      string_append (decl, "ushort");
+      return mangled;
+    case 'i':
+      mangled++;
+      string_append (decl, "int");
+      return mangled;
+    case 'k':
+      mangled++;
+      string_append (decl, "uint");
+      return mangled;
+    case 'l':
+      mangled++;
+      string_append (decl, "long");
+      return mangled;
+    case 'm':
+      mangled++;
+      string_append (decl, "ulong");
+      return mangled;
+    case 'f':
+      mangled++;
+      string_append (decl, "float");
+      return mangled;
+    case 'd':
+      mangled++;
+      string_append (decl, "double");
+      return mangled;
+    case 'e':
+      mangled++;
+      string_append (decl, "real");
+      return mangled;
+
+    /* Imaginary and Complex types */
+    case 'o':
+      mangled++;
+      string_append (decl, "ifloat");
+      return mangled;
+    case 'p':
+      mangled++;
+      string_append (decl, "idouble");
+      return mangled;
+    case 'j':
+      mangled++;
+      string_append (decl, "ireal");
+      return mangled;
+    case 'q':
+      mangled++;
+      string_append (decl, "cfloat");
+      return mangled;
+    case 'r':
+      mangled++;
+      string_append (decl, "cdouble");
+      return mangled;
+    case 'c':
+      mangled++;
+      string_append (decl, "creal");
+      return mangled;
+
+    /* Other types */
+    case 'b':
+      mangled++;
+      string_append (decl, "bool");
+      return mangled;
+    case 'a':
+      mangled++;
+      string_append (decl, "char");
+      return mangled;
+    case 'u':
+      mangled++;
+      string_append (decl, "wchar");
+      return mangled;
+    case 'w':
+      mangled++;
+      string_append (decl, "dchar");
+      return mangled;
+    case 'z':
+      mangled++;
+      switch (*mangled)
+       {
+       case 'i':
+         mangled++;
+         string_append (decl, "cent");
+         return mangled;
+       case 'k':
+         mangled++;
+         string_append (decl, "ucent");
+         return mangled;
+       }
+      return NULL;
+
+    default: /* unhandled */
+      return NULL;
+    }
+}
+
+/* Extract the identifier from MANGLED and append it to DECL.
+   Return the remaining string on success or NULL on failure.  */
+static const char *
+dlang_identifier (string *decl, const char *mangled,
+                 enum dlang_symbol_kinds kind)
+{
+  char *endptr;
+  long len;
+
+  if (mangled == NULL || *mangled == '\0')
+    return NULL;
+
+  len = strtol (mangled, &endptr, 10);
+
+  if (endptr == NULL || len <= 0)
+    return NULL;
+
+  /* In template parameter symbols, the first character of the mangled
+     name can be a digit.  This causes ambiguity issues because the
+     digits of the two numbers are adjacent.  */
+  if (kind == dlang_template_param)
+    {
+      long psize = len;
+      char *pend;
+      int saved = string_length (decl);
+
+      /* Work backwards until a match is found.  */
+      for (pend = endptr; endptr != NULL; pend--)
+       {
+         mangled = pend;
+
+         /* Reached the beginning of the pointer to the name length,
+            try parsing the entire symbol.  */
+         if (psize == 0)
+           {
+             psize = len;
+             pend = endptr;
+             endptr = NULL;
+           }
+
+         /* Check whether template parameter is a function with a valid
+            return type or an untyped identifier.  */
+         if (ISDIGIT (*mangled))
+           mangled = dlang_parse_symbol (decl, mangled, dlang_template_ident);
+         else if (strncmp (mangled, "_D", 2) == 0)
+           {
+             mangled += 2;
+             mangled = dlang_parse_symbol (decl, mangled, dlang_function);
+           }
+
+         /* Check for name length mismatch.  */
+         if (mangled && (mangled - pend) == psize)
+           return mangled;
+
+         psize /= 10;
+         string_setlength (decl, saved);
+       }
+
+      /* No match on any combinations.  */
+      return NULL;
+    }
+  else
+    {
+      if (strlen (endptr) < (size_t) len)
+       return NULL;
+
+      mangled = endptr;
+
+      /* May be a template instance.  */
+      if (len >= 5 && strncmp (mangled, "__T", 3) == 0)
+       {
+         /* Template symbol.  */
+         if (ISDIGIT (mangled[3]) && mangled[3] != '0')
+           return dlang_parse_template (decl, mangled, len);
+
+         return NULL;
+       }
+
+      switch (len)
+       {
+       case 6:
+         if (strncmp (mangled, "__ctor", len) == 0)
+           {
+             /* Constructor symbol for a class/struct.  */
+             string_append (decl, "this");
+             mangled += len;
+             return mangled;
+           }
+         else if (strncmp (mangled, "__dtor", len) == 0)
+           {
+             /* Destructor symbol for a class/struct.  */
+             string_append (decl, "~this");
+             mangled += len;
+             return mangled;
+           }
+         else if (strncmp (mangled, "__initZ", len+1) == 0)
+           {
+             /* The static initialiser for a given symbol.  */
+             string_append (decl, "init$");
+             mangled += len;
+             return mangled;
+           }
+         else if (strncmp (mangled, "__vtblZ", len+1) == 0)
+           {
+             /* The vtable symbol for a given class.  */
+             string_prepend (decl, "vtable for ");
+             string_setlength (decl, string_length (decl) - 1);
+             mangled += len;
+             return mangled;
+           }
+         break;
+
+       case 7:
+         if (strncmp (mangled, "__ClassZ", len+1) == 0)
+           {
+             /* The classinfo symbol for a given class.  */
+             string_prepend (decl, "ClassInfo for ");
+             string_setlength (decl, string_length (decl) - 1);
+             mangled += len;
+             return mangled;
+           }
+         break;
+
+       case 10:
+         if (strncmp (mangled, "__postblitMFZ", len+3) == 0)
+           {
+             /* Postblit symbol for a struct.  */
+             string_append (decl, "this(this)");
+             mangled += len + 3;
+             return mangled;
+           }
+         break;
+
+       case 11:
+         if (strncmp (mangled, "__InterfaceZ", len+1) == 0)
+           {
+             /* The interface symbol for a given class.  */
+             string_prepend (decl, "Interface for ");
+             string_setlength (decl, string_length (decl) - 1);
+             mangled += len;
+             return mangled;
+           }
+         break;
+
+       case 12:
+         if (strncmp (mangled, "__ModuleInfoZ", len+1) == 0)
+           {
+             /* The ModuleInfo symbol for a given module.  */
+             string_prepend (decl, "ModuleInfo for ");
+             string_setlength (decl, string_length (decl) - 1);
+             mangled += len;
+             return mangled;
+           }
+         break;
+       }
+
+      string_appendn (decl, mangled, len);
+      mangled += len;
+    }
+
+  return mangled;
+}
+
+/* Extract the integer value from MANGLED and append it to DECL,
+   where TYPE is the type it should be represented as.
+   Return the remaining string on success or NULL on failure.  */
+static const char *
+dlang_parse_integer (string *decl, const char *mangled, char type)
+{
+  if (type == 'a' || type == 'u' || type == 'w')
+    {
+      /* Parse character value.  */
+      char value[10];
+      int pos = 10;
+      int width = 0;
+      char *endptr;
+      long val = strtol (mangled, &endptr, 10);
+
+      if (endptr == NULL || val < 0)
+       return NULL;
+
+      string_append (decl, "'");
+
+      if (type == 'a' && val >= 0x20 && val < 0x7F)
+       {
+         /* Represent as a character literal.  */
+         char c = (char) val;
+         string_appendn (decl, &c, 1);
+       }
+      else
+       {
+         /* Represent as a hexadecimal value.  */
+         switch (type)
+           {
+           case 'a': /* char */
+             string_append (decl, "\\x");
+             width = 2;
+             break;
+           case 'u': /* wchar */
+             string_append (decl, "\\u");
+             width = 4;
+             break;
+           case 'w': /* dchar */
+             string_append (decl, "\\U");
+             width = 8;
+             break;
+           }
+
+         while (val > 0)
+           {
+             int digit = val % 16;
+
+             if (digit < 10)
+               value[--pos] = (char)(digit + '0');
+             else
+               value[--pos] = (char)((digit - 10) + 'a');
+
+             val /= 16;
+             width--;
+           }
+
+         for (; width > 0; width--)
+           value[--pos] = '0';
+
+         string_appendn (decl, &(value[pos]), 10 - pos);
+       }
+      string_append (decl, "'");
+      mangled = endptr;
+    }
+  else if (type == 'b')
+    {
+      /* Parse boolean value.  */
+      char *endptr;
+      long val = strtol (mangled, &endptr, 10);
+
+      if (endptr == NULL || val < 0)
+       return NULL;
+
+      string_append (decl, val ? "true" : "false");
+      mangled = endptr;
+    }
+  else
+    {
+      /* Parse integer value.  */
+      const char *numptr = mangled;
+      size_t num = 0;
+
+      while (ISDIGIT (*mangled))
+       {
+         num++;
+         mangled++;
+       }
+      string_appendn (decl, numptr, num);
+
+      /* Append suffix.  */
+      switch (type)
+       {
+       case 'h': /* ubyte */
+       case 't': /* ushort */
+       case 'k': /* uint */
+         string_append (decl, "u");
+         break;
+       case 'l': /* long */
+         string_append (decl, "L");
+         break;
+       case 'm': /* ulong */
+         string_append (decl, "uL");
+         break;
+       }
+    }
+
+  return mangled;
+}
+
+/* Extract the floating-point value from MANGLED and append it to DECL.
+   Return the remaining string on success or NULL on failure.  */
+static const char *
+dlang_parse_real (string *decl, const char *mangled)
+{
+  char buffer[64];
+  int len = 0;
+
+  /* Handle NAN and +-INF.  */
+  if (strncmp (mangled, "NAN", 3) == 0)
+    {
+      string_append (decl, "NaN");
+      mangled += 3;
+      return mangled;
+    }
+  else if (strncmp (mangled, "INF", 3) == 0)
+    {
+      string_append (decl, "Inf");
+      mangled += 3;
+      return mangled;
+    }
+  else if (strncmp (mangled, "NINF", 4) == 0)
+    {
+      string_append (decl, "-Inf");
+      mangled += 4;
+      return mangled;
+    }
+
+  /* Hexadecimal prefix and leading bit.  */
+  if (*mangled == 'N')
+    {
+      buffer[len++] = '-';
+      mangled++;
+    }
+
+  if (!ISXDIGIT (*mangled))
+    return NULL;
+
+  buffer[len++] = '0';
+  buffer[len++] = 'x';
+  buffer[len++] = *mangled;
+  buffer[len++] = '.';
+  mangled++;
+
+  /* Significand.  */
+  while (ISXDIGIT (*mangled))
+    {
+      buffer[len++] = *mangled;
+      mangled++;
+    }
+
+  /* Exponent.  */
+  if (*mangled != 'P')
+    return NULL;
+
+  buffer[len++] = 'p';
+  mangled++;
+
+  if (*mangled == 'N')
+    {
+      buffer[len++] = '-';
+      mangled++;
+    }
+
+  while (ISDIGIT (*mangled))
+    {
+      buffer[len++] = *mangled;
+      mangled++;
+    }
+
+  /* Write out the demangled hexadecimal, rather than trying to
+     convert the buffer into a floating-point value.  */
+  buffer[len] = '\0';
+  len = strlen (buffer);
+  string_appendn (decl, buffer, len);
+  return mangled;
+}
+
+/* Convert VAL from an ascii hexdigit to value.  */
+static char
+ascii2hex (char val)
+{
+  if (val >= 'a' && val <= 'f')
+    return (val - 'a' + 10);
+
+  if (val >= 'A' && val <= 'F')
+    return (val - 'A' + 10);
+
+  if (val >= '0' && val <= '9')
+    return (val - '0');
+
+  return 0;
+}
+
+/* Extract the string value from MANGLED and append it to DECL.
+   Return the remaining string on success or NULL on failure.  */
+static const char *
+dlang_parse_string (string *decl, const char *mangled)
+{
+  char type = *mangled;
+  char *endptr;
+  long len;
+
+  mangled++;
+  len = strtol (mangled, &endptr, 10);
+
+  if (endptr == NULL || len < 0)
+    return NULL;
+
+  mangled = endptr;
+  if (*mangled != '_')
+    return NULL;
+
+  mangled++;
+  string_append (decl, "\"");
+  while (len--)
+    {
+      if (ISXDIGIT (mangled[0]) && ISXDIGIT (mangled[1]))
+       {
+         char a = ascii2hex (mangled[0]);
+         char b = ascii2hex (mangled[1]);
+         char val = (a << 4) | b;
+
+         /* Sanitize white and non-printable characters.  */
+         switch (val)
+           {
+           case ' ':
+             string_append (decl, " ");
+             break;
+           case '\t':
+             string_append (decl, "\\t");
+             break;
+           case '\n':
+             string_append (decl, "\\n");
+             break;
+           case '\r':
+             string_append (decl, "\\r");
+             break;
+           case '\f':
+             string_append (decl, "\\f");
+             break;
+           case '\v':
+             string_append (decl, "\\v");
+             break;
+
+           default:
+             if (ISPRINT (val))
+               string_appendn (decl, &val, 1);
+             else
+               {
+                 string_append (decl, "\\x");
+                 string_appendn (decl, mangled, 2);
+               }
+           }
+       }
+      else
+       return NULL;
+
+      mangled += 2;
+    }
+  string_append (decl, "\"");
+
+  if (type != 'a')
+    string_appendn (decl, &type, 1);
+
+  return mangled;
+}
+
+/* Extract the static array value from MANGLED and append it to DECL.
+   Return the remaining string on success or NULL on failure.  */
+static const char *
+dlang_parse_arrayliteral (string *decl, const char *mangled)
+{
+  char *endptr;
+  long elements = strtol (mangled, &endptr, 10);
+
+  if (endptr == NULL || elements < 0)
+    return NULL;
+
+  mangled = endptr;
+  string_append (decl, "[");
+  while (elements--)
+    {
+      mangled = dlang_value (decl, mangled, NULL, '\0');
+      if (elements != 0)
+       string_append (decl, ", ");
+    }
+
+  string_append (decl, "]");
+  return mangled;
+}
+
+/* Extract the associative array value from MANGLED and append it to DECL.
+   Return the remaining string on success or NULL on failure.  */
+static const char *
+dlang_parse_assocarray (string *decl, const char *mangled)
+{
+  char *endptr;
+  long elements = strtol (mangled, &endptr, 10);
+
+  if (endptr == NULL || elements < 0)
+    return NULL;
+
+  mangled = endptr;
+  string_append (decl, "[");
+  while (elements--)
+    {
+      mangled = dlang_value (decl, mangled, NULL, '\0');
+      string_append (decl, ":");
+      mangled = dlang_value (decl, mangled, NULL, '\0');
+
+      if (elements != 0)
+       string_append (decl, ", ");
+    }
+
+  string_append (decl, "]");
+  return mangled;
+}
+
+/* Extract the struct literal value for NAME from MANGLED and append it to DECL.
+   Return the remaining string on success or NULL on failure.  */
+static const char *
+dlang_parse_structlit (string *decl, const char *mangled, const char *name)
+{
+  char *endptr;
+  long args = strtol (mangled, &endptr, 10);
+
+  if (endptr == NULL || args < 0)
+    return NULL;
+
+  mangled = endptr;
+  if (name != NULL)
+    string_append (decl, name);
+
+  string_append (decl, "(");
+  while (args--)
+    {
+      mangled = dlang_value (decl, mangled, NULL, '\0');
+      if (args != 0)
+       string_append (decl, ", ");
+    }
+
+  string_append (decl, ")");
+  return mangled;
+}
+
+/* Extract the value from MANGLED and append it to DECL.
+   Return the remaining string on success or NULL on failure.  */
+static const char *
+dlang_value (string *decl, const char *mangled, const char *name, char type)
+{
+  if (mangled == NULL || *mangled == '\0')
+    return NULL;
+
+  switch (*mangled)
+    {
+      /* Null value.  */
+    case 'n':
+      mangled++;
+      string_append (decl, "null");
+      break;
+
+      /* Integral values.  */
+    case 'N':
+      mangled++;
+      string_append (decl, "-");
+      mangled = dlang_parse_integer (decl, mangled, type);
+      break;
+
+    case 'i':
+      mangled++;
+      if (*mangled < '0' || *mangled > '9')
+       return NULL;
+      /* Fall through */
+    case '0': case '1': case '2': case '3': case '4':
+    case '5': case '6': case '7': case '8': case '9':
+      mangled = dlang_parse_integer (decl, mangled, type);
+      break;
+
+      /* Real value.  */
+    case 'e':
+      mangled++;
+      mangled = dlang_parse_real (decl, mangled);
+      break;
+
+      /* Complex value.  */
+    case 'c':
+      mangled++;
+      mangled = dlang_parse_real (decl, mangled);
+      string_append (decl, "+");
+      if (mangled == NULL || *mangled != 'c')
+       return NULL;
+      mangled++;
+      mangled = dlang_parse_real (decl, mangled);
+      string_append (decl, "i");
+      break;
+
+      /* String values.  */
+    case 'a': /* UTF8 */
+    case 'w': /* UTF16 */
+    case 'd': /* UTF32 */
+      mangled = dlang_parse_string (decl, mangled);
+      break;
+
+      /* Array values.  */
+    case 'A':
+      mangled++;
+      if (type == 'H')
+       mangled = dlang_parse_assocarray (decl, mangled);
+      else
+       mangled = dlang_parse_arrayliteral (decl, mangled);
+      break;
+
+      /* Struct values.  */
+    case 'S':
+      mangled++;
+      mangled = dlang_parse_structlit (decl, mangled, name);
+      break;
+
+    default:
+      return NULL;
+    }
+
+  return mangled;
+}
+
+/* Extract the type modifiers from MANGLED and return the string
+   length that it consumes in MANGLED on success or 0 on failure.  */
+static int
+dlang_type_modifier_p (const char *mangled)
+{
+  int i;
+
+  switch (*mangled)
+    {
+    case 'x': case 'y':
+      return 1;
+
+    case 'O':
+      mangled++;
+      i = dlang_type_modifier_p (mangled);
+      return i + 1;
+
+    case 'N':
+      mangled++;
+      if (*mangled == 'g')
+       {
+         mangled++;
+         i = dlang_type_modifier_p (mangled);
+         return i + 2;
+       }
+    }
+
+  return 0;
+}
+
+/* Extract the function calling convention from MANGLED and
+   return 1 on success or 0 on failure.  */
+static int
+dlang_call_convention_p (const char *mangled)
+{
+  /* Prefix for functions needing 'this' */
+  if (*mangled == 'M')
+    {
+      mangled++;
+      /* Also skip over any type modifiers.  */
+      mangled += dlang_type_modifier_p (mangled);
+    }
+
+  switch (*mangled)
+    {
+    case 'F': case 'U': case 'V':
+    case 'W': case 'R': case 'Y':
+      return 1;
+
+    default:
+      return 0;
+    }
+}
+
+/* Extract and demangle the symbol in MANGLED and append it to DECL.
+   Returns the remaining signature on success or NULL on failure.  */
+static const char *
+dlang_parse_symbol (string *decl, const char *mangled,
+                   enum dlang_symbol_kinds kind)
+{
+  int saved;
+  size_t n = 0;
+  do
+    {
+      if (n++)
+       string_append (decl, ".");
+
+      mangled = dlang_identifier (decl, mangled, kind);
+
+      if (mangled && dlang_call_convention_p (mangled))
+       {
+         string mods;
+         const char *start = NULL;
+         int checkpoint = 0;
+
+         /* Skip over 'this' parameter.  */
+         if (*mangled == 'M')
+           mangled++;
+
+         /* We have reached here because we expect an extern(Pascal) function.
+            However this is so rare, that it is more likely a template value
+            parameter.  Since this can't be assumed, first attempt parsing
+            the symbol as a function, and then back out on failure.  */
+         if (*mangled == 'V')
+           {
+             start = mangled;
+             checkpoint = string_length (decl);
+           }
+
+         /* Save the type modifiers for appending at the end.  */
+         string_init (&mods);
+         mangled = dlang_type_modifiers (&mods, mangled);
+
+         /* Skip over calling convention and attributes in qualified name.  */
+         saved = string_length (decl);
+         mangled = dlang_call_convention (decl, mangled);
+         mangled = dlang_attributes (decl, mangled);
+         string_setlength (decl, saved);
+
+         string_append (decl, "(");
+         mangled = dlang_function_args (decl, mangled);
+         string_append (decl, ")");
+
+         /* Add any const/immutable/shared modifier. */
+         string_appendn (decl, mods.b, string_length (&mods));
+         string_delete (&mods);
+
+         if (mangled == NULL && checkpoint != 0)
+           {
+             mangled = start;
+             string_setlength (decl, checkpoint);
+           }
+       }
+    }
+  while (mangled && ISDIGIT (*mangled));
+
+  /* Only top-level symbols or function template parameters have
+     a type that needs checking.  */
+  if (kind == dlang_top_level || kind == dlang_function)
+    {
+      /* Artificial symbols end with 'Z' and have no type.  */
+      if (mangled && *mangled == 'Z')
+       mangled++;
+      else
+       {
+         saved = string_length (decl);
+         mangled = dlang_type (decl, mangled);
+         string_setlength (decl, saved);
+       }
+
+      /* Check that the entire symbol was successfully demangled.  */
+      if (kind == dlang_top_level)
+       {
+         if (mangled == NULL || *mangled != '\0')
+           return NULL;
+       }
+    }
+
+  return mangled;
+}
+
+/* Demangle the tuple from MANGLED and append it to DECL.
+   Return the remaining string on success or NULL on failure.  */
+static const char *
+dlang_parse_tuple (string *decl, const char *mangled)
+{
+  char *endptr;
+  long elements = strtol (mangled, &endptr, 10);
+
+  if (endptr == NULL || elements < 0)
+    return NULL;
+
+  mangled = endptr;
+  string_append (decl, "Tuple!(");
+
+  while (elements--)
+    {
+      mangled = dlang_type (decl, mangled);
+      if (elements != 0)
+       string_append (decl, ", ");
+    }
+
+  string_append (decl, ")");
+  return mangled;
+}
+
+/* Demangle the argument list from MANGLED and append it to DECL.
+   Return the remaining string on success or NULL on failure.  */
+static const char *
+dlang_template_args (string *decl, const char *mangled)
+{
+  size_t n = 0;
+
+  while (mangled && *mangled != '\0')
+    {
+      switch (*mangled)
+       {
+       case 'Z': /* End of parameter list.  */
+         mangled++;
+         return mangled;
+       }
+
+      if (n++)
+       string_append (decl, ", ");
+
+      /* Skip over specialised template prefix.  */
+      if (*mangled == 'H')
+       mangled++;
+
+      switch (*mangled)
+       {
+       case 'S': /* Symbol parameter.  */
+         mangled++;
+         mangled = dlang_parse_symbol (decl, mangled, dlang_template_param);
+         break;
+       case 'T': /* Type parameter.  */
+         mangled++;
+         mangled = dlang_type (decl, mangled);
+         break;
+       case 'V': /* Value parameter.  */
+       {
+         string name;
+         char type;
+
+         /* Peek at the type.  */
+         mangled++;
+         type = *mangled;
+
+         /* In the few instances where the type is actually desired in
+            the output, it should precede the value from dlang_value.  */
+         string_init (&name);
+         mangled = dlang_type (&name, mangled);
+         string_need (&name, 1);
+         *(name.p) = '\0';
+
+         mangled = dlang_value (decl, mangled, name.b, type);
+         string_delete (&name);
+         break;
+       }
+
+       default:
+         return NULL;
+       }
+    }
+
+  return mangled;
+}
+
+/* Extract and demangle the template symbol in MANGLED, expected to
+   be made up of LEN characters, and append it to DECL.
+   Returns the remaining signature on success or NULL on failure.  */
+static const char *
+dlang_parse_template (string *decl, const char *mangled, long len)
+{
+  const char *start = mangled;
+
+  /* Template instance names have the types and values of its parameters
+     encoded into it.
+
+       TemplateInstanceName:
+           Number __T LName TemplateArgs Z
+                  ^
+     The start pointer should be at the above location, and LEN should be
+     the value of the decoded number.
+   */
+  if (strncmp (mangled, "__T", 3) != 0)
+    return NULL;
+
+  mangled += 3;
+
+  /* Template identifier.  */
+  mangled = dlang_identifier (decl, mangled, dlang_template_ident);
+
+  /* Template arguments.  */
+  string_append (decl, "!(");
+  mangled = dlang_template_args (decl, mangled);
+  string_append (decl, ")");
+
+  /* Check for template name length mismatch.  */
+  if (mangled && (mangled - start) != len)
+    return NULL;
+
+  return mangled;
+}
+
+/* Extract and demangle the symbol in MANGLED.  Returns the demangled
+   signature on success or NULL on failure.  */
+
+char *
+dlang_demangle (const char *mangled, int option ATTRIBUTE_UNUSED)
+{
+  string decl;
+  char *demangled = NULL;
+
+  if (mangled == NULL || *mangled == '\0')
+    return NULL;
+
+  if (strncmp (mangled, "_D", 2) != 0)
+    return NULL;
+
+  string_init (&decl);
+
+  if (strcmp (mangled, "_Dmain") == 0)
+    {
+      string_append (&decl, "D main");
+    }
+  else
+    {
+      mangled += 2;
+
+      if (dlang_parse_symbol (&decl, mangled, dlang_top_level) == NULL)
+       string_delete (&decl);
+    }
+
+  if (string_length (&decl) > 0)
+    {
+      string_need (&decl, 1);
+      *(decl.p) = '\0';
+      demangled = decl.b;
+    }
+
+  return demangled;
+}
+
index 129d856495dd2facbeab078fd7b8831bdde586ea..b3439d957700e9e79e860093f825805e029886f8 100644 (file)
@@ -1,7 +1,6 @@
 /* Defs for interface to demanglers.
-   Copyright 1992, 1993, 1994, 1995, 1996, 1997, 1998, 2000, 2001, 2002,
-   2003, 2004, 2005, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
-   
+   Copyright (C) 1992-2015 Free Software Foundation, Inc.
+
    This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU Library General Public License
    as published by the Free Software Foundation; either version 2, or
@@ -65,9 +64,10 @@ extern "C" {
 #define DMGL_EDG        (1 << 13)
 #define DMGL_GNU_V3     (1 << 14)
 #define DMGL_GNAT       (1 << 15)
+#define DMGL_DLANG      (1 << 16)
 
 /* If none of these are set, use 'current_demangling_style' as the default. */
-#define DMGL_STYLE_MASK (DMGL_AUTO|DMGL_GNU|DMGL_LUCID|DMGL_ARM|DMGL_HP|DMGL_EDG|DMGL_GNU_V3|DMGL_JAVA|DMGL_GNAT)
+#define DMGL_STYLE_MASK (DMGL_AUTO|DMGL_GNU|DMGL_LUCID|DMGL_ARM|DMGL_HP|DMGL_EDG|DMGL_GNU_V3|DMGL_JAVA|DMGL_GNAT|DMGL_DLANG)
 
 /* Enumeration of possible demangling styles.
 
@@ -89,7 +89,8 @@ extern enum demangling_styles
   edg_demangling = DMGL_EDG,
   gnu_v3_demangling = DMGL_GNU_V3,
   java_demangling = DMGL_JAVA,
-  gnat_demangling = DMGL_GNAT
+  gnat_demangling = DMGL_GNAT,
+  dlang_demangling = DMGL_DLANG
 } current_demangling_style;
 
 /* Define string names for the various demangling styles. */
@@ -104,6 +105,7 @@ extern enum demangling_styles
 #define GNU_V3_DEMANGLING_STYLE_STRING        "gnu-v3"
 #define JAVA_DEMANGLING_STYLE_STRING          "java"
 #define GNAT_DEMANGLING_STYLE_STRING          "gnat"
+#define DLANG_DEMANGLING_STYLE_STRING         "dlang"
 
 /* Some macros to test what demangling style is active. */
 
@@ -117,6 +119,7 @@ extern enum demangling_styles
 #define GNU_V3_DEMANGLING (((int) CURRENT_DEMANGLING_STYLE) & DMGL_GNU_V3)
 #define JAVA_DEMANGLING (((int) CURRENT_DEMANGLING_STYLE) & DMGL_JAVA)
 #define GNAT_DEMANGLING (((int) CURRENT_DEMANGLING_STYLE) & DMGL_GNAT)
+#define DLANG_DEMANGLING (((int) CURRENT_DEMANGLING_STYLE) & DMGL_DLANG)
 
 /* Provide information about the available demangle styles. This code is
    pulled from gdb into libiberty because it is useful to binutils also.  */
@@ -142,10 +145,10 @@ cplus_mangle_opname (const char *opname, int options);
 extern void
 set_cplus_marker_for_demangling (int ch);
 
-extern enum demangling_styles 
+extern enum demangling_styles
 cplus_demangle_set_style (enum demangling_styles style);
 
-extern enum demangling_styles 
+extern enum demangling_styles
 cplus_demangle_name_to_style (const char *name);
 
 /* Callback typedef for allocation-less demangler interfaces. */
@@ -171,6 +174,9 @@ java_demangle_v3 (const char *mangled);
 char *
 ada_demangle (const char *mangled, int options);
 
+extern char *
+dlang_demangle (const char *mangled, int options);
+
 enum gnu_v3_ctor_kinds {
   gnu_v3_complete_object_ctor = 1,
   gnu_v3_base_object_ctor,
@@ -375,6 +381,10 @@ enum demangle_component_type
   /* A typecast, represented as a unary operator.  The one subtree is
      the type to which the argument should be cast.  */
   DEMANGLE_COMPONENT_CAST,
+  /* A conversion operator, represented as a unary operator.  The one
+     subtree is the type to which the argument should be converted
+     to.  */
+  DEMANGLE_COMPONENT_CONVERSION,
   /* A nullary expression.  The left subtree is the operator.  */
   DEMANGLE_COMPONENT_NULLARY,
   /* A unary expression.  The left subtree is the operator, and the
@@ -438,6 +448,8 @@ enum demangle_component_type
   DEMANGLE_COMPONENT_PACK_EXPANSION,
   /* A name with an ABI tag.  */
   DEMANGLE_COMPONENT_TAGGED_NAME,
+  /* A transaction-safe function type.  */
+  DEMANGLE_COMPONENT_TRANSACTION_SAFE,
   /* A cloned function.  */
   DEMANGLE_COMPONENT_CLONE
 };
index 2b147271e5f85b52ac2bc07f6696dbb08fb0e80b..7c3684b7cf8a3ec89fb1ba29463ddf7c3da2fc63 100644 (file)
@@ -1,6 +1,5 @@
 /* An abstract string datatype.
-   Copyright (C) 1998, 1999, 2000, 2002, 2004, 2005, 2009
-   Free Software Foundation, Inc.
+   Copyright (C) 1998-2015 Free Software Foundation, Inc.
    Contributed by Mark Mitchell (mark@markmitchell.com).
 
 This file is part of GCC.
index 3b16827e04ed7a8f840fc652889d664cc3e5afb7..1f4465bf5a4c896ef508d75c5c42f3ac92f6bc23 100644 (file)
@@ -1,6 +1,6 @@
 /* <ctype.h> replacement macros.
 
-   Copyright (C) 2000, 2001 Free Software Foundation, Inc.
+   Copyright (C) 2000-2015 Free Software Foundation, Inc.
    Contributed by Zack Weinberg <zackw@stanford.edu>.
 
 This file is part of the libiberty library.
index 883250000db5ba05c56cd59090e742456ecdccf3..dd57fcadb296a326f23ad0e0ae4121c66cd4ea3e 100644 (file)
 #define strpbrk(_ss,_aa)     VG_(strpbrk)((_ss),(_aa))
 #define strspn(_ss,_aa)      VG_(strspn)((_ss),(_aa))
 #define strstr(_hh,_nn)      VG_(strstr)((_hh),(_nn))
+/* strtol supports base 16 or else assumes it is base 10 */
+#define strtol(s,r,b)         ((b) == 16 ? \
+                               VG_(strtoll16) ((s),(r)) \
+                               : VG_(strtoll10) ((s),(r)))
+
 
 #define size_t SizeT
 
 #define xmalloc(_nn)      \
    VG_(arena_malloc)(VG_AR_DEMANGLE, "m_demangle.xmalloc", (_nn))
+#define xmalloc_failed(_sz) abort()
 #define xrealloc(_pt,_sz) \
    VG_(arena_realloc)(VG_AR_DEMANGLE,"m_demangle.xrealloc",(_pt),(_sz))
 #define xstrdup(_str) \
    VG_(arena_strdup)(VG_AR_DEMANGLE,"m_demangle.xstrdup",(_str))
 
+static inline void *xmemdup(const void *in, size_t c_size, size_t a_size) {
+   void *dst;
+   dst = VG_(arena_malloc)(VG_AR_DEMANGLE, "m_demangle.xmemdup", a_size);
+   if (a_size > c_size)
+      memset ((char *) dst + c_size, 0, a_size - c_size);
+   return memcpy (dst, in, c_size);
+}
+
 /* Required by safe-ctype.h */
 
 #undef EOF
 #define XNEW(_Ty) \
         ((_Ty *) xmalloc(sizeof (_Ty)))
 
+#define XDELETEVEC(P) \
+       free ((void*) (P))
+
+#define XDUPVEC(T, P, N) \
+       ((T *) xmemdup ((P), sizeof (T) * (N), sizeof (T) * (N)))
 
 /*--------------------------------------------------------------------*/
 /*--- end                                           vg_libciface.h ---*/