Sync libiberty with upstream GCC.
authorIain Buclaw <ibuclaw@gdcproject.org>
Sun, 25 Jun 2017 09:39:34 +0000 (11:39 +0200)
committerIain Buclaw <ibuclaw@gdcproject.org>
Sun, 25 Jun 2017 09:39:34 +0000 (11:39 +0200)
libiberty/ChangeLog:

* d-demangle.c (dlang_identifier): Prefix mangled init symbols
with `initializer for'.
* testsuite/demangle-expected: Update tests.

* d-demangle.c (dlang_call_convention_p): Move declaration
before dlang_type.
(dlang_type): Handle function types.
* testsuite/d-demangle-expected: Add tests.

* d-demangle.c (dlang_parse_real): Remove stack buffer, write
the demangled hexadecimal directly to string.
* testsuite/d-demangle-expected: Add tests.

* d-demangle.c (dlang_hexdigit): New function.
(ascii2hex): Remove function.
(dlang_parse_string): Update to call dlang_hexdigit.
* testsuite/d-demangle-expected: Add tests.

* d-demangle.c (strtol): Remove declaration.
Updated all callers to use dlang_number.
(dlang_number): New function.
(dlang_value): Moved check for ISDIGIT into dlang_parse_integer.
* testsuite/d-demangle-expected: Add tests.

* d-demangle.c (dlang_parse_symbol): Remove function.
(dlang_parse_qualified): New function.
(dlang_parse_mangle): New function.
(dlang_type): Update to call dlang_parse_qualified.
(dlang_identifier): Update to call either dlang_parse_qualified or
dlang_parse_mangle.
(dlang_type_modifier_p): Remove function.
(dlang_call_convention_p): Don't allow type modifiers in mangle.
(dlang_template_args): Update to call dlang_identifier.
(dlang_demangle): Update to call dlang_parse_mangle.
* testsuite/d-demangle-expected: Add tests.

* d-demangle.c (dlang_value): Add comment explaining why cases for
digits are required.
* testsuite/d-demangle-expected: Update integer value tests.

* d-demangle.c (dlang_parse_symbol): Skip over anonymous symbols.
* testsuite/d-demangle-expected: Add tests.

* d-demangle.c (dlang_identifier): Handle template constraint symbols.
(dlang_parse_template): Only advance if template symbol prefix is
followed by a digit.
* testsuite/d-demangle-expected: Add tests.

* d-demangle.c (dlang_attributes): Handle scope attributes.
* testsuite/d-demangle-expected: Add tests.

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

index 84be7272a259dff2ecab52e1f1c5fd8c7baa9d70..b3087fa0f75932fcc2d1b604756656e9e6518a76 100644 (file)
@@ -9,6 +9,77 @@
        * waitpid.c (wait) [__MINGW32__]: Define as a macro
        that calls _cwait, so that this function works on MinGW.
 
+2017-05-27  Iain Buclaw  <ibuclaw@gdcproject.org>
+
+       * d-demangle.c (dlang_identifier): Prefix mangled init symbols
+       with `initializer for'.
+       * testsuite/demangle-expected: Update tests.
+
+2017-05-27  Iain Buclaw  <ibuclaw@gdcproject.org>
+
+       * d-demangle.c (dlang_call_convention_p): Move declaration
+       before dlang_type.
+       (dlang_type): Handle function types.
+       * testsuite/d-demangle-expected: Add tests.
+
+2017-05-27  Iain Buclaw  <ibuclaw@gdcproject.org>
+
+       * d-demangle.c (dlang_parse_real): Remove stack buffer, write
+       the demangled hexadecimal directly to string.
+       * testsuite/d-demangle-expected: Add tests.
+
+2017-05-02  Iain Buclaw  <ibuclaw@gdcproject.org>
+
+       * d-demangle.c (dlang_hexdigit): New function.
+       (ascii2hex): Remove function.
+       (dlang_parse_string): Update to call dlang_hexdigit.
+       * testsuite/d-demangle-expected: Add tests.
+
+2017-05-02  Iain Buclaw  <ibuclaw@gdcproject.org>
+
+       * d-demangle.c (strtol): Remove declaration.
+       Updated all callers to use dlang_number.
+       (dlang_number): New function.
+       (dlang_value): Moved check for ISDIGIT into dlang_parse_integer.
+       * testsuite/d-demangle-expected: Add tests.
+
+2017-05-02  Iain Buclaw  <ibuclaw@gdcproject.org>
+
+       * d-demangle.c (dlang_parse_symbol): Remove function.
+       (dlang_parse_qualified): New function.
+       (dlang_parse_mangle): New function.
+       (dlang_type): Update to call dlang_parse_qualified.
+       (dlang_identifier): Update to call either dlang_parse_qualified or
+       dlang_parse_mangle.
+       (dlang_type_modifier_p): Remove function.
+       (dlang_call_convention_p): Don't allow type modifiers in mangle.
+       (dlang_template_args): Update to call dlang_identifier.
+       (dlang_demangle): Update to call dlang_parse_mangle.
+       * testsuite/d-demangle-expected: Add tests.
+
+2017-05-01  Iain Buclaw  <ibuclaw@gdcproject.org>
+
+       * d-demangle.c (dlang_value): Add comment explaining why cases for
+       digits are required.
+       * testsuite/d-demangle-expected: Update integer value tests.
+
+2017-05-01  Iain Buclaw  <ibuclaw@gdcproject.org>
+
+       * d-demangle.c (dlang_parse_symbol): Skip over anonymous symbols.
+       * testsuite/d-demangle-expected: Add tests.
+
+2017-05-01  Iain Buclaw  <ibuclaw@gdcproject.org>
+
+       * d-demangle.c (dlang_identifier): Handle template constraint symbols.
+       (dlang_parse_template): Only advance if template symbol prefix is
+       followed by a digit.
+       * testsuite/d-demangle-expected: Add tests.
+
+2017-05-01  Iain Buclaw  <ibuclaw@gdcproject.org>
+
+       * d-demangle.c (dlang_attributes): Handle scope attributes.
+       * testsuite/d-demangle-expected: Add tests.
+
 2017-04-27  Jonathan Wakely  <jwakely@redhat.com>
 
        PR demangler/80513
index 12457f003b11b66e466597f3ad55368c431d20c9..08690de9bd37d508aa7c963850d910ecfd4eb321 100644 (file)
@@ -26,9 +26,7 @@ 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.  */
+/* This file exports one function; dlang_demangle.  */
 
 #ifdef HAVE_CONFIG_H
 #include "config.h"
@@ -42,8 +40,6 @@ If not, see <http://www.gnu.org/licenses/>.  */
 
 #ifdef HAVE_STDLIB_H
 #include <stdlib.h>
-#else
-extern long strtol (const char *nptr, char **endptr, int base);
 #endif
 
 #include <demangle.h>
@@ -186,7 +182,10 @@ 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 *,
+static const char *dlang_parse_qualified (string *, const char *,
+                                         enum dlang_symbol_kinds);
+
+static const char *dlang_parse_mangle (string *, const char *,
                                       enum dlang_symbol_kinds);
 
 static const char *dlang_parse_tuple (string *, const char *);
@@ -194,6 +193,80 @@ static const char *dlang_parse_tuple (string *, const char *);
 static const char *dlang_parse_template (string *, const char *, long);
 
 
+/* Extract the number from MANGLED, and assign the result to RET.
+   Return the remaining string on success or NULL on failure.  */
+static const char *
+dlang_number (const char *mangled, long *ret)
+{
+  /* Return NULL if trying to extract something that isn't a digit.  */
+  if (mangled == NULL || !ISDIGIT (*mangled))
+    return NULL;
+
+  (*ret) = 0;
+
+  while (ISDIGIT (*mangled))
+    {
+      (*ret) *= 10;
+
+      /* If an overflow occured when multiplying by ten, the result
+        will not be a multiple of ten.  */
+      if ((*ret % 10) != 0)
+       return NULL;
+
+      (*ret) += mangled[0] - '0';
+      mangled++;
+    }
+
+  if (*mangled == '\0' || *ret < 0)
+    return NULL;
+
+  return mangled;
+}
+
+/* Extract the hex-digit from MANGLED, and assign the result to RET.
+   Return the remaining string on success or NULL on failure.  */
+static const char *
+dlang_hexdigit (const char *mangled, char *ret)
+{
+  char c;
+
+  /* Return NULL if trying to extract something that isn't a hexdigit.  */
+  if (mangled == NULL || !ISXDIGIT (mangled[0]) || !ISXDIGIT (mangled[1]))
+    return NULL;
+
+  c = mangled[0];
+  if (!ISDIGIT (c))
+    (*ret) = (c - (ISUPPER (c) ? 'A' : 'a') + 10);
+  else
+    (*ret) = (c - '0');
+
+  c = mangled[1];
+  if (!ISDIGIT (c))
+    (*ret) = (*ret << 4) | (c - (ISUPPER (c) ? 'A' : 'a') + 10);
+  else
+    (*ret) = (*ret << 4) | (c - '0');
+
+  mangled += 2;
+
+  return mangled;
+}
+
+/* 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)
+{
+  switch (*mangled)
+    {
+    case 'F': case 'U': case 'V':
+    case 'W': case 'R': case 'Y':
+      return 1;
+
+    default:
+      return 0;
+    }
+}
+
 /* Demangle the calling convention from MANGLED and append it to DECL.
    Return the remaining string on success or NULL on failure.  */
 static const char *
@@ -327,6 +400,10 @@ dlang_attributes (string *decl, const char *mangled)
          mangled++;
          string_append (decl, "return ");
          continue;
+       case 'l': /* scope */
+         mangled++;
+         string_append (decl, "scope ");
+         continue;
 
        default: /* unknown attribute */
          return NULL;
@@ -539,17 +616,22 @@ dlang_type (string *decl, const char *mangled)
     }
     case 'P': /* pointer (T*) */
       mangled++;
-      /* Function pointer types don't include the trailing asterisk.  */
-      switch (*mangled)
+      if (!dlang_call_convention_p (mangled))
        {
-       case 'F': case 'U': case 'W':
-       case 'V': case 'R': case 'Y':
-         mangled = dlang_function_type (decl, mangled);
-         string_append (decl, "function");
+         mangled = dlang_type (decl, mangled);
+         string_append (decl, "*");
          return mangled;
        }
-      mangled = dlang_type (decl, mangled);
-      string_append (decl, "*");
+      /* Fall through */
+    case 'F': /* function T (D) */
+    case 'U': /* function T (C) */
+    case 'W': /* function T (Windows) */
+    case 'V': /* function T (Pascal) */
+    case 'R': /* function T (C++) */
+    case 'Y': /* function T (Objective-C) */
+      /* Function pointer types don't include the trailing asterisk.  */
+      mangled = dlang_function_type (decl, mangled);
+      string_append (decl, "function");
       return mangled;
     case 'I': /* ident T */
     case 'C': /* class T */
@@ -557,7 +639,7 @@ dlang_type (string *decl, const char *mangled)
     case 'E': /* enum T */
     case 'T': /* typedef T */
       mangled++;
-      return dlang_parse_symbol (decl, mangled, dlang_type_name);
+      return dlang_parse_qualified (decl, mangled, dlang_type_name);
     case 'D': /* delegate T */
     {
       string mods;
@@ -702,15 +784,10 @@ static const char *
 dlang_identifier (string *decl, const char *mangled,
                  enum dlang_symbol_kinds kind)
 {
-  char *endptr;
   long len;
+  const char *endptr = dlang_number (mangled, &len);
 
-  if (mangled == NULL || *mangled == '\0')
-    return NULL;
-
-  len = strtol (mangled, &endptr, 10);
-
-  if (endptr == NULL || len <= 0)
+  if (endptr == NULL || len == 0)
     return NULL;
 
   /* In template parameter symbols, the first character of the mangled
@@ -719,7 +796,7 @@ dlang_identifier (string *decl, const char *mangled,
   if (kind == dlang_template_param)
     {
       long psize = len;
-      char *pend;
+      const char *pend;
       int saved = string_length (decl);
 
       /* Work backwards until a match is found.  */
@@ -739,12 +816,10 @@ dlang_identifier (string *decl, const char *mangled,
          /* 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);
+           mangled = dlang_parse_qualified (decl, mangled,
+                                            dlang_template_ident);
          else if (strncmp (mangled, "_D", 2) == 0)
-           {
-             mangled += 2;
-             mangled = dlang_parse_symbol (decl, mangled, dlang_function);
-           }
+           mangled = dlang_parse_mangle (decl, mangled, dlang_function);
 
          /* Check for name length mismatch.  */
          if (mangled && (mangled - pend) == psize)
@@ -765,14 +840,9 @@ dlang_identifier (string *decl, const char *mangled,
       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;
-       }
+      if (len >= 5 && mangled[0] == '_' && mangled[1] == '_'
+         && (mangled[2] == 'T' || mangled[2] == 'U'))
+       return dlang_parse_template (decl, mangled, len);
 
       switch (len)
        {
@@ -794,7 +864,8 @@ dlang_identifier (string *decl, const char *mangled,
          else if (strncmp (mangled, "__initZ", len+1) == 0)
            {
              /* The static initialiser for a given symbol.  */
-             string_append (decl, "init$");
+             string_prepend (decl, "initializer for ");
+             string_setlength (decl, string_length (decl) - 1);
              mangled += len;
              return mangled;
            }
@@ -871,10 +942,10 @@ dlang_parse_integer (string *decl, const char *mangled, char type)
       char value[10];
       int pos = 10;
       int width = 0;
-      char *endptr;
-      long val = strtol (mangled, &endptr, 10);
+      long val;
 
-      if (endptr == NULL || val < 0)
+      mangled = dlang_number (mangled, &val);
+      if (mangled == NULL)
        return NULL;
 
       string_append (decl, "'");
@@ -923,19 +994,17 @@ dlang_parse_integer (string *decl, const char *mangled, char type)
          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);
+      long val;
 
-      if (endptr == NULL || val < 0)
+      mangled = dlang_number (mangled, &val);
+      if (mangled == NULL)
        return NULL;
 
       string_append (decl, val ? "true" : "false");
-      mangled = endptr;
     }
   else
     {
@@ -943,6 +1012,9 @@ dlang_parse_integer (string *decl, const char *mangled, char type)
       const char *numptr = mangled;
       size_t num = 0;
 
+      if (! ISDIGIT (*mangled))
+       return NULL;
+
       while (ISDIGIT (*mangled))
        {
          num++;
@@ -975,9 +1047,6 @@ dlang_parse_integer (string *decl, const char *mangled, char type)
 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)
     {
@@ -1001,23 +1070,22 @@ dlang_parse_real (string *decl, const char *mangled)
   /* Hexadecimal prefix and leading bit.  */
   if (*mangled == 'N')
     {
-      buffer[len++] = '-';
+      string_append (decl, "-");
       mangled++;
     }
 
   if (!ISXDIGIT (*mangled))
     return NULL;
 
-  buffer[len++] = '0';
-  buffer[len++] = 'x';
-  buffer[len++] = *mangled;
-  buffer[len++] = '.';
+  string_append (decl, "0x");
+  string_appendn (decl, mangled, 1);
+  string_append (decl, ".");
   mangled++;
 
   /* Significand.  */
   while (ISXDIGIT (*mangled))
     {
-      buffer[len++] = *mangled;
+      string_appendn (decl, mangled, 1);
       mangled++;
     }
 
@@ -1025,110 +1093,80 @@ dlang_parse_real (string *decl, const char *mangled)
   if (*mangled != 'P')
     return NULL;
 
-  buffer[len++] = 'p';
+  string_append (decl, "p");
   mangled++;
 
   if (*mangled == 'N')
     {
-      buffer[len++] = '-';
+      string_append (decl, "-");
       mangled++;
     }
 
   while (ISDIGIT (*mangled))
     {
-      buffer[len++] = *mangled;
+      string_appendn (decl, mangled, 1);
       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 != '_')
+  mangled = dlang_number (mangled, &len);
+  if (mangled == NULL || *mangled != '_')
     return NULL;
 
   mangled++;
   string_append (decl, "\"");
   while (len--)
     {
-      if (ISXDIGIT (mangled[0]) && ISXDIGIT (mangled[1]))
+      char val;
+      const char *endptr = dlang_hexdigit (mangled, &val);
+
+      if (endptr == NULL)
+       return NULL;
+
+      /* Sanitize white and non-printable characters.  */
+      switch (val)
        {
-         char a = ascii2hex (mangled[0]);
-         char b = ascii2hex (mangled[1]);
-         char val = (a << 4) | b;
+       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;
 
-         /* Sanitize white and non-printable characters.  */
-         switch (val)
+       default:
+         if (ISPRINT (val))
+           string_appendn (decl, &val, 1);
+         else
            {
-           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);
-               }
+             string_append (decl, "\\x");
+             string_appendn (decl, mangled, 2);
            }
        }
-      else
-       return NULL;
 
-      mangled += 2;
+      mangled = endptr;
     }
   string_append (decl, "\"");
 
@@ -1143,13 +1181,12 @@ dlang_parse_string (string *decl, const char *mangled)
 static const char *
 dlang_parse_arrayliteral (string *decl, const char *mangled)
 {
-  char *endptr;
-  long elements = strtol (mangled, &endptr, 10);
+  long elements;
 
-  if (endptr == NULL || elements < 0)
+  mangled = dlang_number (mangled, &elements);
+  if (mangled == NULL)
     return NULL;
 
-  mangled = endptr;
   string_append (decl, "[");
   while (elements--)
     {
@@ -1167,13 +1204,12 @@ dlang_parse_arrayliteral (string *decl, const char *mangled)
 static const char *
 dlang_parse_assocarray (string *decl, const char *mangled)
 {
-  char *endptr;
-  long elements = strtol (mangled, &endptr, 10);
+  long elements;
 
-  if (endptr == NULL || elements < 0)
+  mangled = dlang_number (mangled, &elements);
+  if (mangled == NULL)
     return NULL;
 
-  mangled = endptr;
   string_append (decl, "[");
   while (elements--)
     {
@@ -1194,13 +1230,12 @@ dlang_parse_assocarray (string *decl, const char *mangled)
 static const char *
 dlang_parse_structlit (string *decl, const char *mangled, const char *name)
 {
-  char *endptr;
-  long args = strtol (mangled, &endptr, 10);
+  long args;
 
-  if (endptr == NULL || args < 0)
+  mangled = dlang_number (mangled, &args);
+  if (mangled == NULL)
     return NULL;
 
-  mangled = endptr;
   if (name != NULL)
     string_append (decl, name);
 
@@ -1241,9 +1276,11 @@ dlang_value (string *decl, const char *mangled, const char *name, char type)
 
     case 'i':
       mangled++;
-      if (*mangled < '0' || *mangled > '9')
-       return NULL;
       /* Fall through */
+
+      /* There really should always be an `i' before encoded numbers, but there
+        wasn't in early versions of D2, so this case range must remain for
+        backwards compatibility.  */
     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);
@@ -1296,101 +1333,133 @@ dlang_value (string *decl, const char *mangled, const char *name, char type)
   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)
+/* 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_mangle (string *decl, const char *mangled,
+                   enum dlang_symbol_kinds kind)
 {
-  int i;
+  /* A D mangled symbol is comprised of both scope and type information.
+
+       MangleName:
+           _D QualifiedName Type
+           _D QualifiedName M Type
+           _D QualifiedName Z
+           ^
+     The caller should have guaranteed that the start pointer is at the
+     above location.
+   */
+  mangled += 2;
 
-  switch (*mangled)
+  mangled = dlang_parse_qualified (decl, mangled, dlang_top_level);
+
+  if (mangled != NULL)
     {
-    case 'x': case 'y':
-      return 1;
+      /* Artificial symbols end with 'Z' and have no type.  */
+      if (*mangled == 'Z')
+       mangled++;
+      else
+       {
+         string mods;
+         int saved;
 
-    case 'O':
-      mangled++;
-      i = dlang_type_modifier_p (mangled);
-      return i + 1;
+         /* Skip over 'this' parameter.  */
+         if (*mangled == 'M')
+           mangled++;
 
-    case 'N':
-      mangled++;
-      if (*mangled == 'g')
-       {
-         mangled++;
-         i = dlang_type_modifier_p (mangled);
-         return i + 2;
-       }
-    }
+         /* Save the type modifiers for appending at the end if needed.  */
+         string_init (&mods);
+         mangled = dlang_type_modifiers (&mods, mangled);
 
-  return 0;
-}
+         if (mangled && dlang_call_convention_p (mangled))
+           {
+             /* Skip over calling convention and attributes.  */
+             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));
+           }
 
-/* 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);
+         /* Consume the decl type of symbol.  */
+         saved = string_length (decl);
+         mangled = dlang_type (decl, mangled);
+         string_setlength (decl, saved);
+
+         string_delete (&mods);
+       }
     }
 
-  switch (*mangled)
+  /* Check that the entire symbol was successfully demangled.  */
+  if (kind == dlang_top_level)
     {
-    case 'F': case 'U': case 'V':
-    case 'W': case 'R': case 'Y':
-      return 1;
-
-    default:
-      return 0;
+      if (mangled == NULL || *mangled != '\0')
+       return NULL;
     }
+
+  return mangled;
 }
 
-/* Extract and demangle the symbol in MANGLED and append it to DECL.
+/* Extract and demangle the qualified 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)
+dlang_parse_qualified (string *decl, const char *mangled,
+                      enum dlang_symbol_kinds kind)
 {
-  int saved;
+  /* Qualified names are identifiers separated by their encoded length.
+     Nested functions also encode their argument types without specifying
+     what they return.
+
+       QualifiedName:
+           SymbolName
+           SymbolName QualifiedName
+           SymbolName TypeFunctionNoReturn QualifiedName
+           SymbolName M TypeModifiers TypeFunctionNoReturn QualifiedName
+           ^
+     The start pointer should be at the above location.
+   */
   size_t n = 0;
   do
     {
       if (n++)
        string_append (decl, ".");
 
+      /* Skip over anonymous symbols.  */
+      while (*mangled == '0')
+       mangled++;
+
       mangled = dlang_identifier (decl, mangled, kind);
 
-      if (mangled && dlang_call_convention_p (mangled))
+      /* Consume the encoded arguments.  However if this is not followed by the
+        next encoded length, then this is not a continuation of a qualified
+        name, in which case we backtrack and return the current unconsumed
+        position of the mangled decl.  */
+      if (mangled && (*mangled == 'M' || dlang_call_convention_p (mangled)))
        {
-         string mods;
-         const char *start = NULL;
-         int checkpoint = 0;
+         const char *start = mangled;
+         int saved = string_length (decl);
 
-         /* Skip over 'this' parameter.  */
+         /* Skip over 'this' parameter and type modifiers.  */
          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);
+             mangled++;
+             mangled = dlang_type_modifiers (decl, mangled);
+             string_setlength (decl, saved);
            }
 
-         /* Save the type modifiers for appending at the end.  */
-         string_init (&mods);
-         mangled = dlang_type_modifiers (&mods, mangled);
+         /* The rule we expect to match in the mangled string is:
 
-         /* Skip over calling convention and attributes in qualified name.  */
-         saved = string_length (decl);
+               TypeFunctionNoReturn:
+                   CallConvention FuncAttrs Arguments ArgClose
+
+            The calling convention and function attributes are not included
+            in the demangled string.  */
          mangled = dlang_call_convention (decl, mangled);
          mangled = dlang_attributes (decl, mangled);
          string_setlength (decl, saved);
@@ -1399,41 +1468,16 @@ dlang_parse_symbol (string *decl, const char *mangled,
          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)
+         if (mangled == NULL || !ISDIGIT (*mangled))
            {
+             /* Did not match the rule we were looking for.  */
              mangled = start;
-             string_setlength (decl, checkpoint);
+             string_setlength (decl, saved);
            }
        }
     }
   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;
 }
 
@@ -1442,13 +1486,12 @@ dlang_parse_symbol (string *decl, const char *mangled,
 static const char *
 dlang_parse_tuple (string *decl, const char *mangled)
 {
-  char *endptr;
-  long elements = strtol (mangled, &endptr, 10);
+  long elements;
 
-  if (endptr == NULL || elements < 0)
+  mangled = dlang_number (mangled, &elements);
+  if (mangled == NULL)
     return NULL;
 
-  mangled = endptr;
   string_append (decl, "Tuple!(");
 
   while (elements--)
@@ -1489,7 +1532,7 @@ dlang_template_args (string *decl, const char *mangled)
        {
        case 'S': /* Symbol parameter.  */
          mangled++;
-         mangled = dlang_parse_symbol (decl, mangled, dlang_template_param);
+         mangled = dlang_identifier (decl, mangled, dlang_template_param);
          break;
        case 'T': /* Type parameter.  */
          mangled++;
@@ -1537,11 +1580,14 @@ dlang_parse_template (string *decl, const char *mangled, long len)
 
        TemplateInstanceName:
            Number __T LName TemplateArgs Z
+           Number __U 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)
+
+  /* Template symbol.  */
+  if (!ISDIGIT (mangled[3]) || mangled[3] == '0')
     return NULL;
 
   mangled += 3;
@@ -1584,9 +1630,7 @@ dlang_demangle (const char *mangled, int option ATTRIBUTE_UNUSED)
     }
   else
     {
-      mangled += 2;
-
-      if (dlang_parse_symbol (&decl, mangled, dlang_top_level) == NULL)
+      if (dlang_parse_mangle (&decl, mangled, dlang_top_level) == NULL)
        string_delete (&decl);
     }
 
index 04d39f41015e93c7c20f02afdde3af7de65282fe..547a2ddec397b44b118226275fbe46b2167eb3b1 100644 (file)
@@ -22,6 +22,14 @@ _D8demangle4testPFLAiYi
 demangle.test
 #
 --format=dlang
+_D8demangle4testFZv
+demangle.test()
+#
+--format=dlang
+_D8demangle4testMFZ2fnMFZv
+demangle.test().fn()
+#
+--format=dlang
 _D8demangle4testFaZv
 demangle.test(char)
 #
@@ -330,6 +338,10 @@ _D8demangle4testFNkaZv
 demangle.test(return char)
 #
 --format=dlang
+_D8demangle4testFNlaZv
+demangle.test(char)
+#
+--format=dlang
 _D8demangle4testFaXv
 demangle.test(char...)
 #
@@ -478,6 +490,26 @@ _D8demangle4testFNjNkDFNjZaZv
 demangle.test(return char() return delegate)
 #
 --format=dlang
+_D8demangle4testFNlDFZaZv
+demangle.test(char() delegate)
+#
+--format=dlang
+_D8demangle4testFMDFZaZv
+demangle.test(scope char() delegate)
+#
+--format=dlang
+_D8demangle4testFDFNlZaZv
+demangle.test(char() scope delegate)
+#
+--format=dlang
+_D8demangle4testFMDFNlZaZv
+demangle.test(scope char() scope delegate)
+#
+--format=dlang
+_D8demangle4testFNlMDFNlZaZv
+demangle.test(scope char() scope delegate)
+#
+--format=dlang
 _D8demangle4testFPFNaZaZv
 demangle.test(char() pure function)
 #
@@ -534,8 +566,28 @@ _D8demangle4testFNjNkPFNjZaZv
 demangle.test(return char() return function)
 #
 --format=dlang
+_D8demangle4testFNlPFZaZv
+demangle.test(char() function)
+#
+--format=dlang
+_D8demangle4testFMPFZaZv
+demangle.test(scope char() function)
+#
+--format=dlang
+_D8demangle4testFPFNlZaZv
+demangle.test(char() scope function)
+#
+--format=dlang
+_D8demangle4testFMPFNlZaZv
+demangle.test(scope char() scope function)
+#
+--format=dlang
+_D8demangle4testFNlMPFNlZaZv
+demangle.test(scope char() scope function)
+#
+--format=dlang
 _D8demangle4test6__initZ
-demangle.test.init$
+initializer for demangle.test
 #
 --format=dlang
 _D8demangle4test6__vtblZ
@@ -606,6 +658,10 @@ _D8demangle9__T4testZv
 demangle.test!()
 #
 --format=dlang
+_D8demangle9__U4testZv
+demangle.test!()
+#
+--format=dlang
 _D8demangle11__T4testTaZv
 demangle.test!(char)
 #
@@ -650,35 +706,35 @@ _D8demangle13__T4testVPinZv
 demangle.test!(null)
 #
 --format=dlang
-_D8demangle14__T4testVg123Zv
+_D8demangle15__T4testVgi123Zv
 demangle.test!(123)
 #
 --format=dlang
-_D8demangle14__T4testVi123Zv
+_D8demangle15__T4testVii123Zv
 demangle.test!(123)
 #
 --format=dlang
-_D8demangle14__T4testVs123Zv
+_D8demangle15__T4testVsi123Zv
 demangle.test!(123)
 #
 --format=dlang
-_D8demangle14__T4testVh123Zv
+_D8demangle15__T4testVhi123Zv
 demangle.test!(123u)
 #
 --format=dlang
-_D8demangle14__T4testVk123Zv
+_D8demangle15__T4testVki123Zv
 demangle.test!(123u)
 #
 --format=dlang
-_D8demangle14__T4testVt123Zv
+_D8demangle15__T4testVti123Zv
 demangle.test!(123u)
 #
 --format=dlang
-_D8demangle14__T4testVl123Zv
+_D8demangle15__T4testVli123Zv
 demangle.test!(123L)
 #
 --format=dlang
-_D8demangle14__T4testVm123Zv
+_D8demangle15__T4testVmi123Zv
 demangle.test!(123uL)
 #
 --format=dlang
@@ -698,35 +754,35 @@ _D8demangle15__T4testVmN123Zv
 demangle.test!(-123uL)
 #
 --format=dlang
-_D8demangle12__T4testVb1Zv
+_D8demangle13__T4testVbi1Zv
 demangle.test!(true)
 #
 --format=dlang
-_D8demangle12__T4testVb0Zv
+_D8demangle13__T4testVbi0Zv
 demangle.test!(false)
 #
 --format=dlang
-_D8demangle13__T4testVa10Zv
+_D8demangle14__T4testVai10Zv
 demangle.test!('\x0a')
 #
 --format=dlang
-_D8demangle13__T4testVa32Zv
+_D8demangle14__T4testVai32Zv
 demangle.test!(' ')
 #
 --format=dlang
-_D8demangle13__T4testVa65Zv
+_D8demangle14__T4testVai65Zv
 demangle.test!('A')
 #
 --format=dlang
-_D8demangle14__T4testVa126Zv
+_D8demangle15__T4testVai126Zv
 demangle.test!('~')
 #
 --format=dlang
-_D8demangle15__T4testVu1000Zv
+_D8demangle16__T4testVui1000Zv
 demangle.test!('\u03e8')
 #
 --format=dlang
-_D8demangle17__T4testVw100000Zv
+_D8demangle18__T4testVwi100000Zv
 demangle.test!('\U000186a0')
 #
 --format=dlang
@@ -782,6 +838,10 @@ _D8demangle52__T4testVrcN0C4CCCCCCCCCCCCCDP4c0B666666666666666P6Zv
 demangle.test!(-0x0.C4CCCCCCCCCCCCCDp4+0x0.B666666666666666p6i)
 #
 --format=dlang
+_D8demangle91__T4testVde000111222333444555666777888999AAABBBCCCDDDEEEFFFP000111222333444555666777888999Zv
+demangle.test!(0x0.00111222333444555666777888999AAABBBCCCDDDEEEFFFp000111222333444555666777888999)
+#
+--format=dlang
 _D8demangle22__T4testVG3ua3_616263Zv
 demangle.test!("abc")
 #
@@ -794,6 +854,14 @@ _D8demangle22__T4testVG3uw3_616263Zv
 demangle.test!("abc"w)
 #
 --format=dlang
+_D8demangle16__T4testVAyaa0_Zv
+demangle.test!("")
+#
+--format=dlang
+_D8demangle32__T4testVAyaa8_20090a0d0c0b00ffZv
+demangle.test!(" \t\n\r\f\v\x00\xff")
+#
+--format=dlang
 _D8demangle22__T4testVAiA4i1i2i3i4Zv
 demangle.test!([1, 2, 3, 4])
 #
@@ -818,6 +886,10 @@ _D8demangle35__T4testVS8demangle1SS2i1a3_616263Zv
 demangle.test!(demangle.S(1, "abc"))
 #
 --format=dlang
+_D8demangle13__T4testTFZaZ6mangleFZv
+demangle.test!(char() function).mangle()
+#
+--format=dlang
 _D8demangle4testMxFZv
 demangle.test() const
 #
@@ -881,6 +953,14 @@ demangle.test(char() delegate shared inout)
 _D8demangle4testFDONgxFZaZv
 demangle.test(char() delegate shared inout const)
 #
+--format=dlang
+_D8demangle004testFaZv
+demangle.test(char)
+#
+--format=dlang
+_D8demangle000000004testFaZv
+demangle.test(char)
+#
 # Unittests
 #
 --format=dlang
@@ -900,6 +980,126 @@ _D5__T1aZv
 _D5__T1aZv
 #
 --format=dlang
+_D00
+_D00
+#
+--format=dlang
+_D9223372036854775817
+_D9223372036854775817
+#
+--format=dlang
+_D1az
+_D1az
+#
+--format=dlang
+_D1aN
+_D1aN
+#
+--format=dlang
+_D1aF
+_D1aF
+#
+--format=dlang
+_D1aM
+_D1aM
+#
+--format=dlang
+_D1aFZNz
+_D1aFZNz
+#
+--format=dlang
+_D1aFNzZv
+_D1aFNzZv
+#
+--format=dlang
+_D4testFDX
+_D4testFDX
+#
+--format=dlang
+_D5__T0aZv
+_D5__T0aZv
+#
+--format=dlang
+_D10__T4testYZv
+_D10__T4testYZv
+#
+--format=dlang
+_D4testFBaZv
+_D4testFBaZv
+#
+--format=dlang
+_D8__T4test
+_D8__T4test
+#
+--format=dlang
+_D10__T4testVi
+_D10__T4testVi
+#
+--format=dlang
+_D10__T4testVai
+_D10__T4testVai
+#
+--format=dlang
+_D10__T4testVbi
+_D10__T4testVbi
+#
+--format=dlang
+_D11__T4testS1a
+_D11__T4testS1a
+#
+--format=dlang
+_D12__T4testViiZv
+_D12__T4testViiZv
+#
+--format=dlang
+_D12__T4testViYZv
+_D12__T4testViYZv
+#
+--format=dlang
+_D12__T4testVrcZv
+_D12__T4testVrcZv
+#
+--format=dlang
+_D13__T4testVdeYZv
+_D13__T4testVdeYZv
+#
+--format=dlang
+_D13__T4testViSiZv
+_D13__T4testViSiZv
+#
+--format=dlang
+_D14__T4testVAiAiZv
+_D14__T4testVAiAiZv
+#
+--format=dlang
+_D14__T4testS123aZv
+_D14__T4testS123aZv
+#
+--format=dlang
+_D15__T4testVHiiAiZv
+_D15__T4testVHiiAiZv
+#
+--format=dlang
+_D15__T4testVfe0p1Zv
+_D15__T4testVfe0p1Zv
+#
+--format=dlang
+_D15__T4testVAyaa1_
+_D15__T4testVAyaa1_
+#
+--format=dlang
+_D16__T4testVAyaa0aZv
+_D16__T4testVAyaa0aZv
+#
+--format=dlang
+_D18__T4testVAyaa1_0GZv
+_D18__T4testVAyaa1_0GZv
+#
+--format=dlang
+_D18__T4testVAyaa1_YYZv
+_D18__T4testVAyaa1_YYZv
+#
+--format=dlang
 _D4test3fooAa
 test.foo
 #
@@ -1020,7 +1220,7 @@ _D8demangle20__T2fnVAiA4i1i2i3i4Z2fnFZv
 demangle.fn!([1, 2, 3, 4]).fn()
 #
 --format=dlang
-_D8demangle10__T2fnVi1Z2fnFZv
+_D8demangle11__T2fnVii1Z2fnFZv
 demangle.fn!(1).fn()
 #
 --format=dlang
@@ -1052,6 +1252,18 @@ _D8demangle29__T2fnVa97Va9Va0Vu257Vw65537Z2fnFZv
 demangle.fn!('a', '\x09', '\x00', '\u0101', '\U00010001').fn()
 #
 --format=dlang
+_D8demangle32__T2fnTS3symVS3valS1a4_6e756c6cZ3fun13__T8positionZ13__T8confusesZ8demangleFDFxaZvZv
+demangle.fn!(sym, val("null")).fun.position!().confuses!().demangle(void(const(char)) delegate)
+#
+--format=dlang
+_D8demangle39__T2fnVAyaa12_d0bfd180d0b8d0bcd0b5d180Z2fnFZv
+demangle.fn!("\xd0\xbf\xd1\x80\xd0\xb8\xd0\xbc\xd0\xb5\xd1\x80").fn()
+#
+--format=dlang
+_D8demangle26__T2fnVAyaa6_e4b896e7958cZ2fnFZv
+demangle.fn!("\xe4\xb8\x96\xe7\x95\x8c").fn()
+#
+--format=dlang
 _D2gc11gctemplates56__T8mkBitmapTS3std5range13__T4iotaTiTiZ4iotaFiiZ6ResultZ8mkBitmapFNbNiNfPmmZv
 gc.gctemplates.mkBitmap!(std.range.iota!(int, int).iota(int, int).Result).mkBitmap(ulong*, ulong)
 #
@@ -1090,3 +1302,7 @@ std.traits.fqnSym!(std).adjustIdent(immutable(char)[])
 --format=dlang
 _D2rt8lifetime36__T14_d_newarrayOpTS13_d_newarrayiTZ14_d_newarrayOpTFNaNbxC8TypeInfomPmZAv
 rt.lifetime._d_newarrayOpT!(_d_newarrayiT)._d_newarrayOpT(const(TypeInfo), ulong, ulong*)
+#
+--format=dlang
+_D4core8demangle16__T6mangleTFZPvZ6mangleFNaNbNfAxaAaZ11DotSplitter5emptyMxFNaNbNdNiNfZb
+core.demangle.mangle!(void*() function).mangle(const(char)[], char[]).DotSplitter.empty() const