diff mbox series

libiberty: d: Add support for `typeof(*null)' and function literal symbols.

Message ID 20210406181851.1668959-1-ibuclaw@gdcproject.org
State New
Headers show
Series libiberty: d: Add support for `typeof(*null)' and function literal symbols. | expand

Commit Message

Iain Buclaw April 6, 2021, 6:18 p.m. UTC
Hi,

This patch adds support for demangling function literals as template
value parameters, as well as adding the new bottom type `typeof(*null)'.
Null types were incorrectly being demangled as `none', this has been
fixed to be `typeof(null)'.

Bootstrapped and regression tested on x86_64-linux-gnu.

OK for mainline?

Regards,
Iain.

---
libiberty/ChangeLog:

	* d-demangle.c (dlang_attributes): Handle typeof(*null).
	(dlang_type): Likewise.  Demangle 'n' as typeof(null).
	(dlang_identifier): Skip over fake parent manglings.
	(dlang_parse_arrayliteral): Add 'info' parameter.
	(dlang_parse_assocarray): Likewise.
	(dlang_parse_structlit): Likewise.
	(dlang_value): Likewise.  Handle function literal symbols.
	(dlang_template_args): Pass 'info' to dlang_value.
	* testsuite/d-demangle-expected: Update tests.
---
 libiberty/d-demangle.c                  | 71 +++++++++++++++++++------
 libiberty/testsuite/d-demangle-expected | 34 +++++++++++-
 2 files changed, 89 insertions(+), 16 deletions(-)
diff mbox series

Patch

diff --git a/libiberty/d-demangle.c b/libiberty/d-demangle.c
index 822c7580782..a2152cc6551 100644
--- a/libiberty/d-demangle.c
+++ b/libiberty/d-demangle.c
@@ -191,7 +191,8 @@  static const char *dlang_function_args (string *, const char *,
 
 static const char *dlang_type (string *, const char *, struct dlang_info *);
 
-static const char *dlang_value (string *, const char *, const char *, char);
+static const char *dlang_value (string *, const char *, const char *, char,
+				struct dlang_info *);
 
 static const char *dlang_parse_qualified (string *, const char *,
 					  struct dlang_info *, int);
@@ -573,9 +574,11 @@  dlang_attributes (string *decl, const char *mangled)
 	case 'g':
 	case 'h':
 	case 'k':
+	case 'n':
 	  /* inout parameter is represented as 'Ng'.
 	     vector parameter is represented as 'Nh'.
-	     return paramenter is represented as 'Nk'.
+	     return parameter is represented as 'Nk'.
+	     typeof(*null) parameter is represented as 'Nn'.
 	     If we see this, then we know we're really in the
 	     parameter list.  Rewind and break.  */
 	  mangled--;
@@ -787,6 +790,12 @@  dlang_type (string *decl, const char *mangled, struct dlang_info *info)
 	  string_append (decl, ")");
 	  return mangled;
 	}
+      else if (*mangled == 'n') /* typeof(*null) */
+	{
+	  mangled++;
+	  string_append (decl, "typeof(*null)");
+	  return mangled;
+	}
       else
 	return NULL;
     case 'A': /* dynamic array (T[]) */
@@ -884,7 +893,7 @@  dlang_type (string *decl, const char *mangled, struct dlang_info *info)
     /* Basic types */
     case 'n':
       mangled++;
-      string_append (decl, "none");
+      string_append (decl, "typeof(null)");
       return mangled;
     case 'v':
       mangled++;
@@ -1035,6 +1044,25 @@  dlang_identifier (string *decl, const char *mangled, struct dlang_info *info)
       && (mangled[2] == 'T' || mangled[2] == 'U'))
     return dlang_parse_template (decl, mangled, info, len);
 
+  /* There can be multiple different declarations in the same function that have
+     the same mangled name.  To make the mangled names unique, a fake parent in
+     the form `__Sddd' is added to the symbol.  */
+  if (len >= 4 && mangled[0] == '_' && mangled[1] == '_' && mangled[2] == 'S')
+    {
+      const char *numptr = mangled + 3;
+      while (numptr < (mangled + len) && ISDIGIT (*numptr))
+	numptr++;
+
+      if (mangled + len == numptr)
+	{
+	  /* Skip over the fake parent.  */
+	  mangled += len;
+	  return dlang_identifier (decl, mangled, info);
+	}
+
+      /* else demangle it as a plain identifier.  */
+    }
+
   return dlang_lname (decl, mangled, len);
 }
 
@@ -1378,7 +1406,8 @@  dlang_parse_string (string *decl, const char *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)
+dlang_parse_arrayliteral (string *decl, const char *mangled,
+			  struct dlang_info *info)
 {
   unsigned long elements;
 
@@ -1389,7 +1418,7 @@  dlang_parse_arrayliteral (string *decl, const char *mangled)
   string_append (decl, "[");
   while (elements--)
     {
-      mangled = dlang_value (decl, mangled, NULL, '\0');
+      mangled = dlang_value (decl, mangled, NULL, '\0', info);
       if (mangled == NULL)
 	return NULL;
 
@@ -1404,7 +1433,8 @@  dlang_parse_arrayliteral (string *decl, const char *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)
+dlang_parse_assocarray (string *decl, const char *mangled,
+			struct dlang_info *info)
 {
   unsigned long elements;
 
@@ -1415,12 +1445,12 @@  dlang_parse_assocarray (string *decl, const char *mangled)
   string_append (decl, "[");
   while (elements--)
     {
-      mangled = dlang_value (decl, mangled, NULL, '\0');
+      mangled = dlang_value (decl, mangled, NULL, '\0', info);
       if (mangled == NULL)
 	return NULL;
 
       string_append (decl, ":");
-      mangled = dlang_value (decl, mangled, NULL, '\0');
+      mangled = dlang_value (decl, mangled, NULL, '\0', info);
       if (mangled == NULL)
 	return NULL;
 
@@ -1435,7 +1465,8 @@  dlang_parse_assocarray (string *decl, const char *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)
+dlang_parse_structlit (string *decl, const char *mangled, const char *name,
+		       struct dlang_info *info)
 {
   unsigned long args;
 
@@ -1449,7 +1480,7 @@  dlang_parse_structlit (string *decl, const char *mangled, const char *name)
   string_append (decl, "(");
   while (args--)
     {
-      mangled = dlang_value (decl, mangled, NULL, '\0');
+      mangled = dlang_value (decl, mangled, NULL, '\0', info);
       if (mangled == NULL)
 	return NULL;
 
@@ -1464,7 +1495,8 @@  dlang_parse_structlit (string *decl, const char *mangled, const char *name)
 /* 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)
+dlang_value (string *decl, const char *mangled, const char *name, char type,
+	     struct dlang_info *info)
 {
   if (mangled == NULL || *mangled == '\0')
     return NULL;
@@ -1525,15 +1557,24 @@  dlang_value (string *decl, const char *mangled, const char *name, char type)
     case 'A':
       mangled++;
       if (type == 'H')
-	mangled = dlang_parse_assocarray (decl, mangled);
+	mangled = dlang_parse_assocarray (decl, mangled, info);
       else
-	mangled = dlang_parse_arrayliteral (decl, mangled);
+	mangled = dlang_parse_arrayliteral (decl, mangled, info);
       break;
 
       /* Struct values.  */
     case 'S':
       mangled++;
-      mangled = dlang_parse_structlit (decl, mangled, name);
+      mangled = dlang_parse_structlit (decl, mangled, name, info);
+      break;
+
+      /* Function literal symbol.  */
+    case 'f':
+      mangled++;
+      if (strncmp (mangled, "_D", 2) != 0
+	  || !dlang_symbol_name_p (mangled + 2, info))
+	return NULL;
+      mangled = dlang_parse_mangle (decl, mangled, info);
       break;
 
     default:
@@ -1806,7 +1847,7 @@  dlang_template_args (string *decl, const char *mangled, struct dlang_info *info)
 	  string_need (&name, 1);
 	  *(name.p) = '\0';
 
-	  mangled = dlang_value (decl, mangled, name.b, type);
+	  mangled = dlang_value (decl, mangled, name.b, type, info);
 	  string_delete (&name);
 	  break;
 	}
diff --git a/libiberty/testsuite/d-demangle-expected b/libiberty/testsuite/d-demangle-expected
index ba0ffed5c8d..c35185c3e1e 100644
--- a/libiberty/testsuite/d-demangle-expected
+++ b/libiberty/testsuite/d-demangle-expected
@@ -83,7 +83,11 @@  demangle.test(ulong)
 #
 --format=dlang
 _D8demangle4testFnZv
-demangle.test(none)
+demangle.test(typeof(null))
+#
+--format=dlang
+_D8demangle4testFNnZv
+demangle.test(typeof(*null))
 #
 --format=dlang
 _D8demangle4testFoZv
@@ -1414,3 +1418,31 @@  std.algorithm.iteration.FilterResult!(std.typecons.Tuple!(int, "a", int, "b", in
 --format=dlang
 _D3std3uni__T6toCaseS_DQvQt12toLowerIndexFNaNbNiNewZtVii1043S_DQCjQCi10toLowerTabFNaNbNiNemZwSQDo5ascii7toLowerTAyaZQDzFNaNeQmZ14__foreachbody2MFNaNeKmKwZ14__foreachbody3MFNaNeKwZi
 std.uni.toCase!(std.uni.toLowerIndex(dchar), 1043, std.uni.toLowerTab(ulong), std.ascii.toLower, immutable(char)[]).toCase(immutable(char)[]).__foreachbody2(ref ulong, ref dchar).__foreachbody3(ref dchar)
+#
+--format=dlang
+_D8demangle4mainFZ1xi
+demangle.main().x
+#
+--format=dlang
+_D8demangle4mainFZ4__S11xi
+demangle.main().x
+#
+--format=dlang
+_D8demangle4mainFZ1fMFNaNbNiNfZv
+demangle.main().f()
+#
+--format=dlang
+_D8demangle4mainFZ4__S11fMFNaNbNiNfZv
+demangle.main().f()
+#
+--format=dlang
+_D3mod4funcFZ__T6nestedTiZQkMFNaNbNiNfZi
+mod.func().nested!(int).nested()
+#
+--format=dlang
+_D3mod4funcFZ__T6nestedTiZ4__S1QpMFNaNbNiNfZi
+mod.func().nested!(int).nested()
+#
+--format=dlang
+_D6mangle__T8fun21753VSQv6S21753S1f_DQBj10__lambda71MFNaNbNiNfZvZQCbQp
+mangle.fun21753!(mangle.S21753(mangle.__lambda71())).fun21753