2013-05-06 Sandra Loosemore <sandra@codesourcery.com>
[deliverable/binutils-gdb.git] / libiberty / cp-demangle.c
index 32df38c6024b1fa499d06c305b9dd5954772231b..70f54389c892957a113f627c4cfc806a79f63afb 100644 (file)
@@ -381,6 +381,9 @@ static struct demangle_component *d_ctor_dtor_name (struct d_info *);
 static struct demangle_component **
 d_cv_qualifiers (struct d_info *, struct demangle_component **, int);
 
+static struct demangle_component *
+d_ref_qualifier (struct d_info *, struct demangle_component *);
+
 static struct demangle_component *
 d_function_type (struct d_info *);
 
@@ -508,6 +511,11 @@ d_dump (struct demangle_component *dc, int indent)
     case DEMANGLE_COMPONENT_NAME:
       printf ("name '%.*s'\n", dc->u.s_name.len, dc->u.s_name.s);
       return;
+    case DEMANGLE_COMPONENT_TAGGED_NAME:
+      printf ("tagged name\n");
+      d_dump (dc->u.s_binary.left, indent + 2);
+      d_dump (dc->u.s_binary.right, indent + 2);
+      return;
     case DEMANGLE_COMPONENT_TEMPLATE_PARAM:
       printf ("template parameter %ld\n", dc->u.s_number.number);
       return;
@@ -609,6 +617,12 @@ d_dump (struct demangle_component *dc, int indent)
     case DEMANGLE_COMPONENT_CONST_THIS:
       printf ("const this\n");
       break;
+    case DEMANGLE_COMPONENT_REFERENCE_THIS:
+      printf ("reference this\n");
+      break;
+    case DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS:
+      printf ("rvalue reference this\n");
+      break;
     case DEMANGLE_COMPONENT_VENDOR_TYPE_QUAL:
       printf ("vendor type qualifier\n");
       break;
@@ -702,6 +716,14 @@ d_dump (struct demangle_component *dc, int indent)
     case DEMANGLE_COMPONENT_TLS_WRAPPER:
       printf ("tls wrapper function\n");
       break;
+    case DEMANGLE_COMPONENT_DEFAULT_ARG:
+      printf ("default argument %d\n", dc->u.s_unary_num.num);
+      d_dump (dc->u.s_unary_num.sub, indent+2);
+      return;
+    case DEMANGLE_COMPONENT_LAMBDA:
+      printf ("lambda %d\n", dc->u.s_unary_num.num);
+      d_dump (dc->u.s_unary_num.sub, indent+2);
+      return;
     }
 
   d_dump (d_left (dc), indent + 2);
@@ -809,6 +831,7 @@ d_make_comp (struct d_info *di, enum demangle_component_type type,
     case DEMANGLE_COMPONENT_QUAL_NAME:
     case DEMANGLE_COMPONENT_LOCAL_NAME:
     case DEMANGLE_COMPONENT_TYPED_NAME:
+    case DEMANGLE_COMPONENT_TAGGED_NAME:
     case DEMANGLE_COMPONENT_TEMPLATE:
     case DEMANGLE_COMPONENT_CONSTRUCTION_VTABLE:
     case DEMANGLE_COMPONENT_VENDOR_TYPE_QUAL:
@@ -879,6 +902,8 @@ 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_REFERENCE_THIS:
+    case DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS:
     case DEMANGLE_COMPONENT_ARGLIST:
     case DEMANGLE_COMPONENT_TEMPLATE_ARGLIST:
       break;
@@ -1117,6 +1142,8 @@ has_return_type (struct demangle_component *dc)
     case DEMANGLE_COMPONENT_RESTRICT_THIS:
     case DEMANGLE_COMPONENT_VOLATILE_THIS:
     case DEMANGLE_COMPONENT_CONST_THIS:
+    case DEMANGLE_COMPONENT_REFERENCE_THIS:
+    case DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS:
       return has_return_type (d_left (dc));
     }
 }
@@ -1172,7 +1199,9 @@ d_encoding (struct d_info *di, int top_level)
             v2 demangler without DMGL_PARAMS.  */
          while (dc->type == DEMANGLE_COMPONENT_RESTRICT_THIS
                 || dc->type == DEMANGLE_COMPONENT_VOLATILE_THIS
-                || dc->type == DEMANGLE_COMPONENT_CONST_THIS)
+                || dc->type == DEMANGLE_COMPONENT_CONST_THIS
+                || dc->type == DEMANGLE_COMPONENT_REFERENCE_THIS
+                || dc->type == DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS)
            dc = d_left (dc);
 
          /* If the top level is a DEMANGLE_COMPONENT_LOCAL_NAME, then
@@ -1186,7 +1215,9 @@ d_encoding (struct d_info *di, int top_level)
              dcr = d_right (dc);
              while (dcr->type == DEMANGLE_COMPONENT_RESTRICT_THIS
                     || dcr->type == DEMANGLE_COMPONENT_VOLATILE_THIS
-                    || dcr->type == DEMANGLE_COMPONENT_CONST_THIS)
+                    || dcr->type == DEMANGLE_COMPONENT_CONST_THIS
+                    || dcr->type == DEMANGLE_COMPONENT_REFERENCE_THIS
+                    || dcr->type == DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS)
                dcr = d_left (dcr);
              dc->u.s_binary.right = dcr;
            }
@@ -1202,6 +1233,23 @@ d_encoding (struct d_info *di, int top_level)
     }
 }
 
+/* <tagged-name> ::= <name> B <source-name> */
+
+static struct demangle_component *
+d_abi_tags (struct d_info *di, struct demangle_component *dc)
+{
+  char peek;
+  while (peek = d_peek_char (di),
+        peek == 'B')
+    {
+      struct demangle_component *tag;
+      d_advance (di, 1);
+      tag = d_source_name (di);
+      dc = d_make_comp (di, DEMANGLE_COMPONENT_TAGGED_NAME, dc, tag);
+    }
+  return dc;
+}
+
 /* <name> ::= <nested-name>
           ::= <unscoped-name>
           ::= <unscoped-template-name> <template-args>
@@ -1291,8 +1339,8 @@ d_name (struct d_info *di)
     }
 }
 
-/* <nested-name> ::= N [<CV-qualifiers>] <prefix> <unqualified-name> E
-                 ::= N [<CV-qualifiers>] <template-prefix> <template-args> E
+/* <nested-name> ::= N [<CV-qualifiers>] [<ref-qualifier>] <prefix> <unqualified-name> E
+                 ::= N [<CV-qualifiers>] [<ref-qualifier>] <template-prefix> <template-args> E
 */
 
 static struct demangle_component *
@@ -1300,6 +1348,7 @@ d_nested_name (struct d_info *di)
 {
   struct demangle_component *ret;
   struct demangle_component **pret;
+  struct demangle_component *rqual;
 
   if (! d_check_char (di, 'N'))
     return NULL;
@@ -1308,10 +1357,20 @@ d_nested_name (struct d_info *di)
   if (pret == NULL)
     return NULL;
 
+  /* Parse the ref-qualifier now and then attach it
+     once we have something to attach it to.  */
+  rqual = d_ref_qualifier (di, NULL);
+
   *pret = d_prefix (di);
   if (*pret == NULL)
     return NULL;
 
+  if (rqual)
+    {
+      d_left (rqual) = ret;
+      ret = rqual;
+    }
+
   if (! d_check_char (di, 'E'))
     return NULL;
 
@@ -1416,15 +1475,14 @@ d_prefix (struct d_info *di)
 static struct demangle_component *
 d_unqualified_name (struct d_info *di)
 {
+  struct demangle_component *ret;
   char peek;
 
   peek = d_peek_char (di);
   if (IS_DIGIT (peek))
-    return d_source_name (di);
+    ret = d_source_name (di);
   else if (IS_LOWER (peek))
     {
-      struct demangle_component *ret;
-
       ret = d_operator_name (di);
       if (ret != NULL && ret->type == DEMANGLE_COMPONENT_OPERATOR)
        {
@@ -1433,14 +1491,11 @@ d_unqualified_name (struct d_info *di)
            ret = d_make_comp (di, DEMANGLE_COMPONENT_UNARY, ret,
                               d_source_name (di));
        }
-      return ret;
     }
   else if (peek == 'C' || peek == 'D')
-    return d_ctor_dtor_name (di);
+    ret = d_ctor_dtor_name (di);
   else if (peek == 'L')
     {
-      struct demangle_component * ret;
-
       d_advance (di, 1);
 
       ret = d_source_name (di);
@@ -1448,22 +1503,27 @@ d_unqualified_name (struct d_info *di)
        return NULL;
       if (! d_discriminator (di))
        return NULL;
-      return ret;
     }
   else if (peek == 'U')
     {
       switch (d_peek_next_char (di))
        {
        case 'l':
-         return d_lambda (di);
+         ret = d_lambda (di);
+         break;
        case 't':
-         return d_unnamed_type (di);
+         ret = d_unnamed_type (di);
+         break;
        default:
          return NULL;
        }
     }
   else
     return NULL;
+
+  if (d_peek_char (di) == 'B')
+    ret = d_abi_tags (di, ret);
+  return ret;
 }
 
 /* <source-name> ::= <(positive length) number> <identifier>  */
@@ -2138,8 +2198,28 @@ cplus_demangle_type (struct d_info *di)
       pret = d_cv_qualifiers (di, &ret, 0);
       if (pret == NULL)
        return NULL;
-      *pret = cplus_demangle_type (di);
-      if (! *pret || ! d_add_substitution (di, ret))
+      if (d_peek_char (di) == 'F')
+       {
+         /* cv-qualifiers before a function type apply to 'this',
+            so avoid adding the unqualified function type to
+            the substitution list.  */
+         *pret = d_function_type (di);
+       }
+      else
+       *pret = cplus_demangle_type (di);
+      if (!*pret)
+       return NULL;
+      if ((*pret)->type == DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS
+         || (*pret)->type == DEMANGLE_COMPONENT_REFERENCE_THIS)
+       {
+         /* Move the ref-qualifier outside the cv-qualifiers so that
+            they are printed in the right order.  */
+         struct demangle_component *fn = d_left (*pret);
+         d_left (*pret) = ret;
+         ret = *pret;
+         *pret = fn;
+       }
+      if (! d_add_substitution (di, ret))
        return NULL;
       return ret;
     }
@@ -2442,7 +2522,38 @@ d_cv_qualifiers (struct d_info *di,
   return pret;
 }
 
-/* <function-type> ::= F [Y] <bare-function-type> E  */
+/* <ref-qualifier> ::= R
+                   ::= O */
+
+static struct demangle_component *
+d_ref_qualifier (struct d_info *di, struct demangle_component *sub)
+{
+  struct demangle_component *ret = sub;
+  char peek;
+
+  peek = d_peek_char (di);
+  if (peek == 'R' || peek == 'O')
+    {
+      enum demangle_component_type t;
+      if (peek == 'R')
+       {
+         t = DEMANGLE_COMPONENT_REFERENCE_THIS;
+         di->expansion += sizeof "&";
+       }
+      else
+       {
+         t = DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS;
+         di->expansion += sizeof "&&";
+       }
+      d_advance (di, 1);
+
+      ret = d_make_comp (di, t, ret, NULL);
+    }
+
+  return ret;
+}
+
+/* <function-type> ::= F [Y] <bare-function-type> [<ref-qualifier>] E  */
 
 static struct demangle_component *
 d_function_type (struct d_info *di)
@@ -2458,6 +2569,8 @@ d_function_type (struct d_info *di)
       d_advance (di, 1);
     }
   ret = d_bare_function_type (di, 1);
+  ret = d_ref_qualifier (di, ret);
+
   if (! d_check_char (di, 'E'))
     return NULL;
   return ret;
@@ -2480,6 +2593,10 @@ d_parmlist (struct d_info *di)
       char peek = d_peek_char (di);
       if (peek == '\0' || peek == 'E' || peek == '.')
        break;
+      if ((peek == 'R' || peek == 'O')
+         && d_peek_next_char (di) == 'E')
+       /* Function ref-qualifier, not a ref prefix for a parameter type.  */
+       break;
       type = cplus_demangle_type (di);
       if (type == NULL)
        return NULL;
@@ -2630,41 +2747,32 @@ d_pointer_to_member_type (struct d_info *di)
 {
   struct demangle_component *cl;
   struct demangle_component *mem;
-  struct demangle_component **pmem;
 
   if (! d_check_char (di, 'M'))
     return NULL;
 
   cl = cplus_demangle_type (di);
-
-  /* The ABI specifies that any type can be a substitution source, and
-     that M is followed by two types, and that when a CV-qualified
-     type is seen both the base type and the CV-qualified types are
-     substitution sources.  The ABI also specifies that for a pointer
-     to a CV-qualified member function, the qualifiers are attached to
-     the second type.  Given the grammar, a plain reading of the ABI
-     suggests that both the CV-qualified member function and the
-     non-qualified member function are substitution sources.  However,
-     g++ does not work that way.  g++ treats only the CV-qualified
-     member function as a substitution source.  FIXME.  So to work
-     with g++, we need to pull off the CV-qualifiers here, in order to
-     avoid calling add_substitution() in cplus_demangle_type().  But
-     for a CV-qualified member which is not a function, g++ does
-     follow the ABI, so we need to handle that case here by calling
-     d_add_substitution ourselves.  */
-
-  pmem = d_cv_qualifiers (di, &mem, 1);
-  if (pmem == NULL)
-    return NULL;
-  *pmem = cplus_demangle_type (di);
-  if (*pmem == NULL)
+  if (cl == NULL)
     return NULL;
 
-  if (pmem != &mem && (*pmem)->type != DEMANGLE_COMPONENT_FUNCTION_TYPE)
-    {
-      if (! d_add_substitution (di, mem))
-       return NULL;
-    }
+  /* The ABI says, "The type of a non-static member function is considered
+     to be different, for the purposes of substitution, from the type of a
+     namespace-scope or static member function whose type appears
+     similar. The types of two non-static member functions are considered
+     to be different, for the purposes of substitution, if the functions
+     are members of different classes. In other words, for the purposes of
+     substitution, the class of which the function is a member is
+     considered part of the type of function."
+
+     For a pointer to member function, this call to cplus_demangle_type
+     will end up adding a (possibly qualified) non-member function type to
+     the substitution table, which is not correct; however, the member
+     function type will never be used in a substitution, so putting the
+     wrong type in the substitution table is harmless.  */
+
+  mem = cplus_demangle_type (di);
+  if (mem == NULL)
+    return NULL;
 
   return d_make_comp (di, DEMANGLE_COMPONENT_PTRMEM_TYPE, cl, mem);
 }
@@ -3144,6 +3252,7 @@ d_expr_primary (struct d_info *di)
 
 /* <local-name> ::= Z <(function) encoding> E <(entity) name> [<discriminator>]
                 ::= Z <(function) encoding> E s [<discriminator>]
+                ::= Z <(function) encoding> E d [<parameter> number>] _ <entity name>
 */
 
 static struct demangle_component *
@@ -3745,6 +3854,7 @@ d_find_pack (struct d_print_info *dpi,
       
     case DEMANGLE_COMPONENT_LAMBDA:
     case DEMANGLE_COMPONENT_NAME:
+    case DEMANGLE_COMPONENT_TAGGED_NAME:
     case DEMANGLE_COMPONENT_OPERATOR:
     case DEMANGLE_COMPONENT_BUILTIN_TYPE:
     case DEMANGLE_COMPONENT_SUB_STD:
@@ -3830,6 +3940,13 @@ d_print_comp (struct d_print_info *dpi, int options,
        d_print_java_identifier (dpi, dc->u.s_name.s, dc->u.s_name.len);
       return;
 
+    case DEMANGLE_COMPONENT_TAGGED_NAME:
+      d_print_comp (dpi, options, d_left (dc));
+      d_append_string (dpi, "[abi:");
+      d_print_comp (dpi, options, d_right (dc));
+      d_append_char (dpi, ']');
+      return;
+
     case DEMANGLE_COMPONENT_QUAL_NAME:
     case DEMANGLE_COMPONENT_LOCAL_NAME:
       d_print_comp (dpi, options, d_left (dc));
@@ -3837,7 +3954,17 @@ d_print_comp (struct d_print_info *dpi, int options,
        d_append_string (dpi, "::");
       else
        d_append_char (dpi, '.');
-      d_print_comp (dpi, options, d_right (dc));
+      {
+       struct demangle_component *local_name = d_right (dc);
+       if (local_name->type == DEMANGLE_COMPONENT_DEFAULT_ARG)
+         {
+           d_append_string (dpi, "{default arg#");
+           d_append_num (dpi, local_name->u.s_unary_num.num + 1);
+           d_append_string (dpi, "}::");
+           local_name = local_name->u.s_unary_num.sub;
+         }
+       d_print_comp (dpi, options, local_name);
+      }
       return;
 
     case DEMANGLE_COMPONENT_TYPED_NAME:
@@ -3872,7 +3999,9 @@ d_print_comp (struct d_print_info *dpi, int options,
 
            if (typed_name->type != DEMANGLE_COMPONENT_RESTRICT_THIS
                && typed_name->type != DEMANGLE_COMPONENT_VOLATILE_THIS
-               && typed_name->type != DEMANGLE_COMPONENT_CONST_THIS)
+               && typed_name->type != DEMANGLE_COMPONENT_CONST_THIS
+               && typed_name->type != DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS
+               && typed_name->type != DEMANGLE_COMPONENT_REFERENCE_THIS)
              break;
 
            typed_name = d_left (typed_name);
@@ -3906,7 +4035,10 @@ d_print_comp (struct d_print_info *dpi, int options,
              local_name = local_name->u.s_unary_num.sub;
            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_CONST_THIS
+                  || local_name->type == DEMANGLE_COMPONENT_REFERENCE_THIS
+                  || (local_name->type
+                      == DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS))
              {
                if (i >= sizeof adpm / sizeof adpm[0])
                  {
@@ -4183,6 +4315,8 @@ d_print_comp (struct d_print_info *dpi, int options,
     case DEMANGLE_COMPONENT_RESTRICT_THIS:
     case DEMANGLE_COMPONENT_VOLATILE_THIS:
     case DEMANGLE_COMPONENT_CONST_THIS:
+    case DEMANGLE_COMPONENT_REFERENCE_THIS:
+    case DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS:
     case DEMANGLE_COMPONENT_VENDOR_TYPE_QUAL:
     case DEMANGLE_COMPONENT_POINTER:
     case DEMANGLE_COMPONENT_COMPLEX:
@@ -4855,7 +4989,10 @@ d_print_mod_list (struct d_print_info *dpi, int options,
       || (! suffix
          && (mods->mod->type == DEMANGLE_COMPONENT_RESTRICT_THIS
              || mods->mod->type == DEMANGLE_COMPONENT_VOLATILE_THIS
-             || mods->mod->type == DEMANGLE_COMPONENT_CONST_THIS)))
+             || mods->mod->type == DEMANGLE_COMPONENT_CONST_THIS
+             || mods->mod->type == DEMANGLE_COMPONENT_REFERENCE_THIS
+             || (mods->mod->type
+                 == DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS))))
     {
       d_print_mod_list (dpi, options, mods->next, suffix);
       return;
@@ -4910,7 +5047,9 @@ d_print_mod_list (struct d_print_info *dpi, int options,
 
       while (dc->type == DEMANGLE_COMPONENT_RESTRICT_THIS
             || dc->type == DEMANGLE_COMPONENT_VOLATILE_THIS
-            || dc->type == DEMANGLE_COMPONENT_CONST_THIS)
+            || dc->type == DEMANGLE_COMPONENT_CONST_THIS
+            || dc->type == DEMANGLE_COMPONENT_REFERENCE_THIS
+            || dc->type == DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS)
        dc = d_left (dc);
 
       d_print_comp (dpi, options, dc);
@@ -4955,9 +5094,14 @@ d_print_mod (struct d_print_info *dpi, int options,
       if ((options & DMGL_JAVA) == 0)
        d_append_char (dpi, '*');
       return;
+    case DEMANGLE_COMPONENT_REFERENCE_THIS:
+      /* For the ref-qualifier, put a space before the &.  */
+      d_append_char (dpi, ' ');
     case DEMANGLE_COMPONENT_REFERENCE:
       d_append_char (dpi, '&');
       return;
+    case DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS:
+      d_append_char (dpi, ' ');
     case DEMANGLE_COMPONENT_RVALUE_REFERENCE:
       d_append_string (dpi, "&&");
       return;
@@ -5029,6 +5173,8 @@ d_print_function_type (struct d_print_info *dpi, int options,
        case DEMANGLE_COMPONENT_RESTRICT_THIS:
        case DEMANGLE_COMPONENT_VOLATILE_THIS:
        case DEMANGLE_COMPONENT_CONST_THIS:
+       case DEMANGLE_COMPONENT_REFERENCE_THIS:
+       case DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS:
          break;
        default:
          break;
@@ -5549,14 +5695,17 @@ is_ctor_or_dtor (const char *mangled,
       {
        switch (dc->type)
          {
+           /* These cannot appear on a constructor or destructor.  */
+         case DEMANGLE_COMPONENT_RESTRICT_THIS:
+         case DEMANGLE_COMPONENT_VOLATILE_THIS:
+         case DEMANGLE_COMPONENT_CONST_THIS:
+         case DEMANGLE_COMPONENT_REFERENCE_THIS:
+         case DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS:
          default:
            dc = NULL;
            break;
          case DEMANGLE_COMPONENT_TYPED_NAME:
          case DEMANGLE_COMPONENT_TEMPLATE:
-         case DEMANGLE_COMPONENT_RESTRICT_THIS:
-         case DEMANGLE_COMPONENT_VOLATILE_THIS:
-         case DEMANGLE_COMPONENT_CONST_THIS:
            dc = d_left (dc);
            break;
          case DEMANGLE_COMPONENT_QUAL_NAME:
This page took 0.030094 seconds and 4 git commands to generate.