diff mbox series

demangler: Reorganize for module demangling

Message ID e84cfe63-f3b1-b5cf-99cd-d44af193bc11@acm.org
State New
Headers show
Series demangler: Reorganize for module demangling | expand

Commit Message

Nathan Sidwell May 18, 2022, 11:25 a.m. UTC
Module demangling requires some changes in how substitutions are 
handled.  This adjusts things to make that possible, these are similar 
changes to that made in the the llvm demangler.

nathan
diff mbox series

Patch

From 65851d65fb36e847a9b8ef3b0519f06d29865a14 Mon Sep 17 00:00:00 2001
From: Nathan Sidwell <nathan@acm.org>
Date: Tue, 8 Mar 2022 10:53:39 -0800
Subject: [PATCH] demangler: Reorganize for module demangling

Module demangling requires some changes in how substitutions are
handled.  This adjusts things to make that possible.

	libiberty/
	* cp-demangle.c (d_name): Add SUBSTABLE parameter,
	push substitution if requested. Adjust unscoped name handling.
	(d_prefix): Reorder main loop. Adjust all calls.
	(d_unqualified_name): Add SCOPE parameter, create qualified
	name here. Adjust all calls.
	(cplus_demangle_type): Do not handle 'S' here, leave all
	to d_class_enum_type.
	(d_class_enum_type): Add SUBSTABLE parameter.
---
 libiberty/cp-demangle.c | 224 +++++++++++++++-------------------------
 1 file changed, 84 insertions(+), 140 deletions(-)

diff --git a/libiberty/cp-demangle.c b/libiberty/cp-demangle.c
index fc618fa7383..cf451c5aff2 100644
--- a/libiberty/cp-demangle.c
+++ b/libiberty/cp-demangle.c
@@ -425,13 +425,14 @@  is_ctor_dtor_or_conversion (struct demangle_component *);
 
 static struct demangle_component *d_encoding (struct d_info *, int);
 
-static struct demangle_component *d_name (struct d_info *);
+static struct demangle_component *d_name (struct d_info *, int substable);
 
 static struct demangle_component *d_nested_name (struct d_info *);
 
 static struct demangle_component *d_prefix (struct d_info *, int);
 
-static struct demangle_component *d_unqualified_name (struct d_info *);
+static struct demangle_component *d_unqualified_name (struct d_info *,
+						      struct demangle_component *scope);
 
 static struct demangle_component *d_source_name (struct d_info *);
 
@@ -462,7 +463,7 @@  static struct demangle_component *
 d_bare_function_type (struct d_info *, int);
 
 static struct demangle_component *
-d_class_enum_type (struct d_info *);
+d_class_enum_type (struct d_info *, int);
 
 static struct demangle_component *d_array_type (struct d_info *);
 
@@ -1323,7 +1324,7 @@  d_encoding (struct d_info *di, int top_level)
     dc = d_special_name (di);
   else
     {
-      dc = d_name (di);
+      dc = d_name (di, 0);
 
       if (!dc)
 	/* Failed already.  */;
@@ -1417,80 +1418,64 @@  d_abi_tags (struct d_info *di, struct demangle_component *dc)
 */
 
 static struct demangle_component *
-d_name (struct d_info *di)
+d_name (struct d_info *di, int substable)
 {
   char peek = d_peek_char (di);
-  struct demangle_component *dc;
+  struct demangle_component *dc = NULL;
+  int subst = 0;
 
   switch (peek)
     {
     case 'N':
-      return d_nested_name (di);
+      dc = d_nested_name (di);
+      break;
 
     case 'Z':
-      return d_local_name (di);
+      dc = d_local_name (di);
+      break;
 
     case 'U':
-      return d_unqualified_name (di);
+      dc = d_unqualified_name (di, NULL);
+      break;
 
     case 'S':
       {
-	int subst;
-
-	if (d_peek_next_char (di) != 't')
-	  {
-	    dc = d_substitution (di, 0);
-	    subst = 1;
-	  }
-	else
+	if (d_peek_next_char (di) == 't')
 	  {
 	    d_advance (di, 2);
-	    dc = d_make_comp (di, DEMANGLE_COMPONENT_QUAL_NAME,
-			      d_make_name (di, "std", 3),
-			      d_unqualified_name (di));
+	    dc = d_make_name (di, "std", 3);
 	    di->expansion += 3;
-	    subst = 0;
-	  }
-
-	if (d_peek_char (di) != 'I')
-	  {
-	    /* The grammar does not permit this case to occur if we
-	       called d_substitution() above (i.e., subst == 1).  We
-	       don't bother to check.  */
 	  }
 	else
 	  {
-	    /* This is <template-args>, which means that we just saw
-	       <unscoped-template-name>, which is a substitution
-	       candidate if we didn't just get it from a
-	       substitution.  */
-	    if (! subst)
-	      {
-		if (! d_add_substitution (di, dc))
-		  return NULL;
-	      }
-	    dc = d_make_comp (di, DEMANGLE_COMPONENT_TEMPLATE, dc,
-			      d_template_args (di));
+	    dc = d_substitution (di, 0);
+	    if (!dc)
+	      return NULL;
+	    subst = 1;
 	  }
-
-	return dc;
       }
+      /* FALLTHROUGH */
 
     case 'L':
     default:
-      dc = d_unqualified_name (di);
+      if (!subst)
+	dc = d_unqualified_name (di, dc);
       if (d_peek_char (di) == 'I')
 	{
 	  /* This is <template-args>, which means that we just saw
 	     <unscoped-template-name>, which is a substitution
 	     candidate.  */
-	  if (! d_add_substitution (di, dc))
+	  if (!subst && !d_add_substitution (di, dc))
 	    return NULL;
 	  dc = d_make_comp (di, DEMANGLE_COMPONENT_TEMPLATE, dc,
 			    d_template_args (di));
+	  subst = 0;
 	}
-      return dc;
+      break;
     }
+  if (substable && !subst && !d_add_substitution (di, dc))
+    return NULL;
+  return dc;
 }
 
 /* <nested-name> ::= N [<CV-qualifiers>] [<ref-qualifier>] <prefix> <unqualified-name> E
@@ -1546,54 +1531,51 @@  d_nested_name (struct d_info *di)
    if not (in an unresolved-name).  */
 
 static struct demangle_component *
-d_prefix (struct d_info *di, int subst)
+d_prefix (struct d_info *di, int substable)
 {
   struct demangle_component *ret = NULL;
 
-  while (1)
+  for (;;)
     {
-      char peek;
-      enum demangle_component_type comb_type;
-      struct demangle_component *dc;
-
-      peek = d_peek_char (di);
-      if (peek == '\0')
-	return NULL;
+      char peek = d_peek_char (di);
 
       /* The older code accepts a <local-name> here, but I don't see
 	 that in the grammar.  The older code does not accept a
 	 <template-param> here.  */
 
-      comb_type = DEMANGLE_COMPONENT_QUAL_NAME;
-      if (peek == 'D')
+      if (peek == 'D'
+	  && (d_peek_next_char (di) == 'T'
+	      || d_peek_next_char (di) == 't'))
 	{
-	  char peek2 = d_peek_next_char (di);
-	  if (peek2 == 'T' || peek2 == 't')
-	    /* Decltype.  */
-	    dc = cplus_demangle_type (di);
-	  else
-	    /* Destructor name.  */
-	    dc = d_unqualified_name (di);
+	  /* Decltype.  */
+	  if (ret)
+	    return NULL;
+	  ret = cplus_demangle_type (di);
 	}
-      else if (IS_DIGIT (peek)
-	  || IS_LOWER (peek)
-	  || peek == 'C'
-	  || peek == 'U'
-	  || peek == 'L')
-	dc = d_unqualified_name (di);
       else if (peek == 'S')
-	dc = d_substitution (di, 1);
+	{
+	  if (ret)
+	    return NULL;
+	  ret = d_substitution (di, 1);
+	  if (!ret)
+	    return NULL;
+	  continue;
+	}
       else if (peek == 'I')
 	{
 	  if (ret == NULL)
 	    return NULL;
-	  comb_type = DEMANGLE_COMPONENT_TEMPLATE;
-	  dc = d_template_args (di);
+	  struct demangle_component *dc = d_template_args (di);
+	  if (!dc)
+	    return NULL;
+	  ret = d_make_comp (di, DEMANGLE_COMPONENT_TEMPLATE, ret, dc);
 	}
       else if (peek == 'T')
-	dc = d_template_param (di);
-      else if (peek == 'E')
-	return ret;
+	{
+	  if (ret)
+	    return NULL;
+	  ret = d_template_param (di);
+	}
       else if (peek == 'M')
 	{
 	  /* Initializer scope for a lambda.  We don't need to represent
@@ -1602,22 +1584,21 @@  d_prefix (struct d_info *di, int subst)
 	  if (ret == NULL)
 	    return NULL;
 	  d_advance (di, 1);
-	  continue;
 	}
       else
+	ret = d_unqualified_name (di, ret);
+
+      if (!ret)
+	break;
+
+      if (d_peek_char (di) == 'E')
+	break;
+
+      if (substable && !d_add_substitution (di, ret))
 	return NULL;
-
-      if (ret == NULL)
-	ret = dc;
-      else
-	ret = d_make_comp (di, comb_type, ret, dc);
-
-      if (peek != 'S' && d_peek_char (di) != 'E' && subst)
-	{
-	  if (! d_add_substitution (di, ret))
-	    return NULL;
-	}
     }
+
+  return ret;
 }
 
 /* <unqualified-name> ::= <operator-name> [<abi-tags>]
@@ -1629,7 +1610,7 @@  d_prefix (struct d_info *di, int subst)
 */
 
 static struct demangle_component *
-d_unqualified_name (struct d_info *di)
+d_unqualified_name (struct d_info *di, struct demangle_component *scope)
 {
   struct demangle_component *ret;
   char peek;
@@ -1709,6 +1690,9 @@  d_unqualified_name (struct d_info *di)
 
   if (d_peek_char (di) == 'B')
     ret = d_abi_tags (di, ret);
+  if (scope)
+    ret = d_make_comp (di, DEMANGLE_COMPONENT_QUAL_NAME, scope, ret);
+
   return ret;
 }
 
@@ -2149,11 +2133,11 @@  d_special_name (struct d_info *di)
 
 	case 'H':
 	  return d_make_comp (di, DEMANGLE_COMPONENT_TLS_INIT,
-			      d_name (di), NULL);
+			      d_name (di, 0), NULL);
 
 	case 'W':
 	  return d_make_comp (di, DEMANGLE_COMPONENT_TLS_WRAPPER,
-			      d_name (di), NULL);
+			      d_name (di, 0), NULL);
 
 	case 'A':
 	  return d_make_comp (di, DEMANGLE_COMPONENT_TPARM_OBJ,
@@ -2169,11 +2153,11 @@  d_special_name (struct d_info *di)
 	{
 	case 'V':
 	  return d_make_comp (di, DEMANGLE_COMPONENT_GUARD,
-			      d_name (di), NULL);
+			      d_name (di, 0), NULL);
 
 	case 'R':
 	  {
-	    struct demangle_component *name = d_name (di);
+	    struct demangle_component *name = d_name (di, 0);
 	    return d_make_comp (di, DEMANGLE_COMPONENT_REFTEMP, name,
 				d_number_component (di));
 	  }
@@ -2504,13 +2488,6 @@  cplus_demangle_type (struct d_info *di)
       ret = d_function_type (di);
       break;
 
-    case '0': case '1': case '2': case '3': case '4':
-    case '5': case '6': case '7': case '8': case '9':
-    case 'N':
-    case 'Z':
-      ret = d_class_enum_type (di);
-      break;
-
     case 'A':
       ret = d_array_type (di);
       break;
@@ -2581,39 +2558,6 @@  cplus_demangle_type (struct d_info *di)
 	}
       break;
 
-    case 'S':
-      /* If this is a special substitution, then it is the start of
-	 <class-enum-type>.  */
-      {
-	char peek_next;
-
-	peek_next = d_peek_next_char (di);
-	if (IS_DIGIT (peek_next)
-	    || peek_next == '_'
-	    || IS_UPPER (peek_next))
-	  {
-	    ret = d_substitution (di, 0);
-	    /* The substituted name may have been a template name and
-	       may be followed by tepmlate args.  */
-	    if (d_peek_char (di) == 'I')
-	      ret = d_make_comp (di, DEMANGLE_COMPONENT_TEMPLATE, ret,
-				 d_template_args (di));
-	    else
-	      can_subst = 0;
-	  }
-	else
-	  {
-	    ret = d_class_enum_type (di);
-	    /* If the substitution was a complete type, then it is not
-	       a new substitution candidate.  However, if the
-	       substitution was followed by template arguments, then
-	       the whole thing is a substitution candidate.  */
-	    if (ret != NULL && ret->type == DEMANGLE_COMPONENT_SUB_STD)
-	      can_subst = 0;
-	  }
-      }
-      break;
-
     case 'O':
       d_advance (di, 1);
       ret = d_make_comp (di, DEMANGLE_COMPONENT_RVALUE_REFERENCE,
@@ -2754,7 +2698,7 @@  cplus_demangle_type (struct d_info *di)
       break;
 
     default:
-      return NULL;
+      return d_class_enum_type (di, 1);
     }
 
   if (can_subst)
@@ -3027,9 +2971,9 @@  d_bare_function_type (struct d_info *di, int has_return_type)
 /* <class-enum-type> ::= <name>  */
 
 static struct demangle_component *
-d_class_enum_type (struct d_info *di)
+d_class_enum_type (struct d_info *di, int substable)
 {
-  return d_name (di);
+  return d_name (di, substable);
 }
 
 /* <array-type> ::= A <(positive dimension) number> _ <(element) type>
@@ -3358,11 +3302,11 @@  d_unresolved_name (struct d_info *di)
     }
   else
     type = cplus_demangle_type (di);
-  name = d_unqualified_name (di);
+  name = d_unqualified_name (di, type);
   if (d_peek_char (di) == 'I')
     name = d_make_comp (di, DEMANGLE_COMPONENT_TEMPLATE, name,
 			d_template_args (di));
-  return d_make_comp (di, DEMANGLE_COMPONENT_QUAL_NAME, type, name);
+  return name;
 }
 
 /* <expression> ::= <(unary) operator-name> <expression>
@@ -3431,7 +3375,7 @@  d_expression_1 (struct d_info *di)
 	/* operator-function-id, i.e. operator+(t).  */
 	d_advance (di, 2);
 
-      name = d_unqualified_name (di);
+      name = d_unqualified_name (di, NULL);
       if (name == NULL)
 	return NULL;
       if (d_peek_char (di) == 'I')
@@ -3539,7 +3483,7 @@  d_expression_1 (struct d_info *di)
 	      /* fold-expression.  */
 	      left = d_operator_name (di);
 	    else if (!strcmp (code, "di"))
-	      left = d_unqualified_name (di);
+	      left = d_unqualified_name (di, NULL);
 	    else
 	      left = d_expression_1 (di);
 	    if (!strcmp (code, "cl"))
@@ -3557,7 +3501,7 @@  d_expression_1 (struct d_info *di)
 		       d_unqualified_name rather than d_expression_1 here for
 		       old mangled names that didn't add 'on' before operator
 		       names.  */
-		    right = d_unqualified_name (di);
+		    right = d_unqualified_name (di, NULL);
 		    if (d_peek_char (di) == 'I')
 		      right = d_make_comp (di, DEMANGLE_COMPONENT_TEMPLATE,
 					   right, d_template_args (di));
@@ -3767,7 +3711,7 @@  d_local_name (struct d_info *di)
 	    return NULL;
 	}
 
-      name = d_name (di);
+      name = d_name (di, 0);
 
       if (name
 	  /* Lambdas and unnamed types have internal discriminators
-- 
2.30.2