OSDN Git Service

PR c++/42338
[pf3gnuchains/gcc-fork.git] / gcc / cp / mangle.c
index bb046d2..7e4cf66 100644 (file)
@@ -105,10 +105,6 @@ typedef struct GTY(()) globals {
 
 static GTY (()) globals G;
 
-/* Whether or not to pretend that a static function is in an anonymous
-   namespace.  */
-static bool fake_anon_scope;
-
 /* The obstack on which we build mangled names.  */
 static struct obstack *mangle_obstack;
 
@@ -182,10 +178,13 @@ static void write_template_prefix (const tree);
 static void write_unqualified_name (const tree);
 static void write_conversion_operator_name (const tree);
 static void write_source_name (tree);
+static void write_unnamed_type_name (const tree);
+static void write_closure_type_name (const tree);
 static int hwint_to_ascii (unsigned HOST_WIDE_INT, const unsigned int, char *,
                           const unsigned int);
 static void write_number (unsigned HOST_WIDE_INT, const int,
                          const unsigned int);
+static void write_compact_number (int num);
 static void write_integer_cst (const tree);
 static void write_real_cst (const tree);
 static void write_identifier (const char *);
@@ -211,9 +210,10 @@ static void write_substitution (const int);
 static int discriminator_for_local_entity (tree);
 static int discriminator_for_string_literal (tree, tree);
 static void write_discriminator (const int);
-static void write_local_name (const tree, const tree, const tree);
+static void write_local_name (tree, const tree, const tree);
 static void dump_substitution_candidates (void);
 static tree mangle_decl_string (const tree);
+static int local_class_index (tree);
 
 /* Control functions.  */
 
@@ -730,18 +730,24 @@ write_encoding (const tree decl)
     }
 }
 
-/* Since we now use strcmp to compare typeinfos on all targets because of
-   the RTLD_LOCAL problem, we need to munge the typeinfo name used for
-   local classes of static functions to fix g++.dg/abi/local1.C.  We do
-   that by pretending that the function is in an anonymous namespace.  */
+/* Lambdas can have a bit more context for mangling, specifically VAR_DECL
+   or PARM_DECL context, which doesn't belong in DECL_CONTEXT.  */
 
-static bool
-needs_fake_anon (const_tree decl)
+static tree
+decl_mangling_context (tree decl)
 {
-  /* Pretend there's an anonymous namespace right around a static
-     function if we're mangling for RTTI.  */
-  return (fake_anon_scope && !TREE_PUBLIC (decl)
-         && TREE_CODE (decl) == FUNCTION_DECL);
+  if (TREE_CODE (decl) == TYPE_DECL
+      && LAMBDA_TYPE_P (TREE_TYPE (decl)))
+    {
+      tree extra = LAMBDA_TYPE_EXTRA_SCOPE (TREE_TYPE (decl));
+      if (extra)
+       return extra;
+    }
+    else if (TREE_CODE (decl) == TYPE_DECL
+            && TREE_CODE (TREE_TYPE (decl)) == TEMPLATE_TYPE_PARM)
+     /* template type parms have no mangling context.  */
+      return NULL_TREE;
+  return CP_DECL_CONTEXT (decl);
 }
 
 /* <name> ::= <unscoped-name>
@@ -767,23 +773,17 @@ write_name (tree decl, const int ignore_local_scope)
       /* In case this is a typedef, fish out the corresponding
         TYPE_DECL for the main variant.  */
       decl = TYPE_NAME (TYPE_MAIN_VARIANT (TREE_TYPE (decl)));
-      context = CP_TYPE_CONTEXT (TYPE_MAIN_VARIANT (TREE_TYPE (decl)));
     }
-  else
-    context = CP_DECL_CONTEXT (decl);
-
-  gcc_assert (context != NULL_TREE);
 
-  /* If we need a fake anonymous namespace, force the nested name path.  */
-  if (needs_fake_anon (decl) && context == global_namespace)
-    context = error_mark_node;
+  context = decl_mangling_context (decl);
 
   /* A decl in :: or ::std scope is treated specially.  The former is
      mangled using <unscoped-name> or <unscoped-template-name>, the
      latter with a special substitution.  Also, a name that is
      directly in a local function scope is also mangled with
      <unscoped-name> rather than a full <nested-name>.  */
-  if (context == global_namespace
+  if (context == NULL
+      || context == global_namespace
       || DECL_NAMESPACE_STD_P (context)
       || (ignore_local_scope && TREE_CODE (context) == FUNCTION_DECL))
     {
@@ -801,9 +801,6 @@ write_name (tree decl, const int ignore_local_scope)
     }
   else
     {
-      if (context == error_mark_node)
-       context = global_namespace;
-
       /* Handle local names, unless we asked not to (that is, invoked
         under <local-name>, to handle only the part of the name under
         the local scope).  */
@@ -816,13 +813,14 @@ write_name (tree decl, const int ignore_local_scope)
             directly in that function's scope, either decl or one of
             its enclosing scopes.  */
          tree local_entity = decl;
-         while (context != global_namespace)
+         while (context != NULL && context != global_namespace)
            {
              /* Make sure we're always dealing with decls.  */
-             if (TYPE_P (context))
+             if (context != NULL && TYPE_P (context))
                context = TYPE_NAME (context);
              /* Is this a function?  */
-             if (TREE_CODE (context) == FUNCTION_DECL)
+             if (TREE_CODE (context) == FUNCTION_DECL
+                 || TREE_CODE (context) == PARM_DECL)
                {
                  /* Yes, we have local scope.  Use the <local-name>
                     production for the innermost function scope.  */
@@ -831,7 +829,7 @@ write_name (tree decl, const int ignore_local_scope)
                }
              /* Up one scope level.  */
              local_entity = context;
-             context = CP_DECL_CONTEXT (context);
+             context = decl_mangling_context (context);
            }
 
          /* No local scope found?  Fall through to <nested-name>.  */
@@ -863,6 +861,7 @@ write_unscoped_name (const tree decl)
       /* If not, it should be either in the global namespace, or directly
         in a local function scope.  */
       gcc_assert (context == global_namespace
+                 || context != NULL
                  || TREE_CODE (context) == FUNCTION_DECL);
 
       write_unqualified_name (decl);
@@ -934,9 +933,6 @@ write_nested_name (const tree decl)
     {
       /* No, just use <prefix>  */
       write_prefix (DECL_CONTEXT (decl));
-      if (needs_fake_anon (decl))
-       /* Pretend this static function is in an anonymous namespace.  */
-       write_source_name (get_anonymous_namespace_name ());
       write_unqualified_name (decl);
     }
   write_char ('E');
@@ -955,23 +951,24 @@ write_prefix (const tree node)
   /* Non-NULL if NODE represents a template-id.  */
   tree template_info = NULL;
 
-  MANGLE_TRACE_TREE ("prefix", node);
-
   if (node == NULL
       || node == global_namespace)
     return;
 
+  MANGLE_TRACE_TREE ("prefix", node);
+
   if (find_substitution (node))
     return;
 
   if (DECL_P (node))
     {
-      /* If this is a function decl, that means we've hit function
+      /* If this is a function or parm decl, that means we've hit function
         scope, so this prefix must be for a local name.  In this
         case, we're under the <local-name> production, which encodes
         the enclosing function scope elsewhere.  So don't continue
         here.  */
-      if (TREE_CODE (node) == FUNCTION_DECL)
+      if (TREE_CODE (node) == FUNCTION_DECL
+         || TREE_CODE (node) == PARM_DECL)
        return;
 
       decl = node;
@@ -1016,8 +1013,15 @@ write_prefix (const tree node)
   else
     /* Not templated.  */
     {
-      write_prefix (CP_DECL_CONTEXT (decl));
+      write_prefix (decl_mangling_context (decl));
       write_unqualified_name (decl);
+      if (TREE_CODE (decl) == VAR_DECL
+         || TREE_CODE (decl) == FIELD_DECL)
+       {
+         /* <data-member-prefix> := <member source-name> M */
+         write_char ('M');
+         return;
+       }
     }
 
   add_substitution (node);
@@ -1107,6 +1111,7 @@ write_template_prefix (const tree node)
     <unqualified-name>  ::= <operator-name>
                        ::= <special-name>
                        ::= <source-name>
+                       ::= <unnamed-type-name>
                        ::= <local-source-name> 
 
     <local-source-name>        ::= L <source-name> <discriminator> */
@@ -1172,7 +1177,18 @@ write_unqualified_name (const tree decl)
         so there's no code to output one here.  */
     }
   else
-    write_source_name (DECL_NAME (decl));
+    {
+      tree type = TREE_TYPE (decl);
+
+      if (TREE_CODE (decl) == TYPE_DECL
+          && TYPE_ANONYMOUS_P (type))
+        write_unnamed_type_name (type);
+      else if (TREE_CODE (decl) == TYPE_DECL
+               && LAMBDA_TYPE_P (type))
+        write_closure_type_name (type);
+      else
+        write_source_name (DECL_NAME (decl));
+    }
 }
 
 /* Write the unqualified-name for a conversion operator to TYPE.  */
@@ -1202,6 +1218,78 @@ write_source_name (tree identifier)
   write_identifier (IDENTIFIER_POINTER (identifier));
 }
 
+/* Encode 0 as _, and 1+ as n-1_.  */
+
+static void
+write_compact_number (int num)
+{
+  if (num > 0)
+    write_unsigned_number (num - 1);
+  write_char ('_');
+}
+
+/* Return how many unnamed types precede TYPE in its enclosing class.  */
+
+static int
+nested_anon_class_index (tree type)
+{
+  int index = 0;
+  tree member = TYPE_FIELDS (TYPE_CONTEXT (type));
+  for (; member; member = TREE_CHAIN (member))
+    if (DECL_IMPLICIT_TYPEDEF_P (member))
+      {
+       tree memtype = TREE_TYPE (member);
+       if (memtype == type)
+         return index;
+       else if (TYPE_ANONYMOUS_P (memtype))
+         ++index;
+      }
+
+  gcc_unreachable ();
+}
+
+/* <unnamed-type-name> ::= Ut [ <nonnegative number> ] _ */
+
+static void
+write_unnamed_type_name (const tree type __attribute__ ((__unused__)))
+{
+  int discriminator;
+  MANGLE_TRACE_TREE ("unnamed-type-name", type);
+
+  if (TYPE_FUNCTION_SCOPE_P (type))
+    discriminator = local_class_index (type);
+  else if (TYPE_CLASS_SCOPE_P (type))
+    discriminator = nested_anon_class_index (type);
+  else
+    {
+      gcc_assert (no_linkage_check (type, /*relaxed_p=*/true));
+      /* Just use the old mangling at namespace scope.  */
+      write_source_name (TYPE_IDENTIFIER (type));
+      return;
+    }
+
+  write_string ("Ut");
+  write_compact_number (discriminator);
+}
+
+/* <closure-type-name> ::= Ul <lambda-sig> E [ <nonnegative number> ] _
+   <lambda-sig> ::= <parameter type>+  # Parameter types or "v" if the lambda has no parameters */
+
+static void
+write_closure_type_name (const tree type)
+{
+  tree fn = lambda_function (type);
+  tree lambda = CLASSTYPE_LAMBDA_EXPR (type);
+  tree parms = TYPE_ARG_TYPES (TREE_TYPE (fn));
+
+  MANGLE_TRACE_TREE ("closure-type-name", type);
+
+  write_string ("Ul");
+  write_method_parms (parms, DECL_NONSTATIC_MEMBER_FUNCTION_P (fn), fn);
+  write_char ('E');
+  write_compact_number (LAMBDA_EXPR_DISCRIMINATOR (lambda));
+}
+
 /* Convert NUMBER to ascii using base BASE and generating at least
    MIN_DIGITS characters. BUFFER points to the _end_ of the buffer
    into which to store the characters. Returns the number of
@@ -1461,6 +1549,29 @@ write_special_name_destructor (const tree dtor)
     }
 }
 
+/* Scan the vector of local classes and return how many others with the
+   same name (or same no name) and context precede ENTITY.  */
+
+static int
+local_class_index (tree entity)
+{
+  int ix, discriminator = 0;
+  tree name = (TYPE_ANONYMOUS_P (entity) ? NULL_TREE
+              : TYPE_IDENTIFIER (entity));
+  tree ctx = TYPE_CONTEXT (entity);
+  for (ix = 0; ; ix++)
+    {
+      tree type = VEC_index (tree, local_classes, ix);
+      if (type == entity)
+       return discriminator;
+      if (TYPE_CONTEXT (type) == ctx
+         && (name ? TYPE_IDENTIFIER (type) == name
+             : TYPE_ANONYMOUS_P (type)))
+       ++discriminator;
+    }
+  gcc_unreachable ();
+}
+
 /* Return the discriminator for ENTITY appearing inside
    FUNCTION.  The discriminator is the lexical ordinal of VAR among
    entities with the same name in the same FUNCTION.  */
@@ -1468,29 +1579,28 @@ write_special_name_destructor (const tree dtor)
 static int
 discriminator_for_local_entity (tree entity)
 {
-  /* Assume this is the only local entity with this name.  */
-  int discriminator = 0;
-
-  if (DECL_DISCRIMINATOR_P (entity) && DECL_LANG_SPECIFIC (entity))
-    discriminator = DECL_DISCRIMINATOR (entity);
+  if (DECL_DISCRIMINATOR_P (entity))
+    {
+      if (DECL_DISCRIMINATOR_SET_P (entity))
+       return DECL_DISCRIMINATOR (entity);
+      else
+       /* The first entity with a particular name doesn't get
+          DECL_DISCRIMINATOR set up.  */
+       return 0;
+    }
   else if (TREE_CODE (entity) == TYPE_DECL)
     {
-      int ix;
-
       /* Scan the list of local classes.  */
       entity = TREE_TYPE (entity);
-      for (ix = 0; ; ix++)
-       {
-         tree type = VEC_index (tree, local_classes, ix);
-         if (type == entity)
-           break;
-         if (TYPE_IDENTIFIER (type) == TYPE_IDENTIFIER (entity)
-             && TYPE_CONTEXT (type) == TYPE_CONTEXT (entity))
-           ++discriminator;
-       }
-    }
 
-  return discriminator;
+      /* Lambdas and unnamed types have their own discriminators.  */
+      if (LAMBDA_TYPE_P (entity) || TYPE_ANONYMOUS_P (entity))
+       return 0;
+
+      return local_class_index (entity);
+    }
+  else
+    gcc_unreachable ();
 }
 
 /* Return the discriminator for STRING, a string literal used inside
@@ -1523,23 +1633,49 @@ write_discriminator (const int discriminator)
 }
 
 /* Mangle the name of a function-scope entity.  FUNCTION is the
-   FUNCTION_DECL for the enclosing function.  ENTITY is the decl for
-   the entity itself.  LOCAL_ENTITY is the entity that's directly
-   scoped in FUNCTION_DECL, either ENTITY itself or an enclosing scope
-   of ENTITY.
+   FUNCTION_DECL for the enclosing function, or a PARM_DECL for lambdas in
+   default argument scope.  ENTITY is the decl for the entity itself.
+   LOCAL_ENTITY is the entity that's directly scoped in FUNCTION_DECL,
+   either ENTITY itself or an enclosing scope of ENTITY.
 
      <local-name> := Z <function encoding> E <entity name> [<discriminator>]
-                 := Z <function encoding> E s [<discriminator>]  */
+                 := Z <function encoding> E s [<discriminator>]
+                 := Z <function encoding> Ed [ <parameter number> ] _ <entity name> */
 
 static void
-write_local_name (const tree function, const tree local_entity,
+write_local_name (tree function, const tree local_entity,
                  const tree entity)
 {
+  tree parm = NULL_TREE;
+
   MANGLE_TRACE_TREE ("local-name", entity);
 
+  if (TREE_CODE (function) == PARM_DECL)
+    {
+      parm = function;
+      function = DECL_CONTEXT (parm);
+    }
+
   write_char ('Z');
   write_encoding (function);
   write_char ('E');
+
+  /* For this purpose, parameters are numbered from right-to-left.  */
+  if (parm)
+    {
+      tree t;
+      int i = 0;
+      for (t = DECL_ARGUMENTS (function); t; t = TREE_CHAIN (t))
+       {
+         if (t == parm)
+           i = 1;
+         else if (i)
+           ++i;
+       }
+      write_char ('d');
+      write_compact_number (i - 1);
+    }
+
   if (TREE_CODE (entity) == STRING_CST)
     {
       write_char ('s');
@@ -1718,6 +1854,10 @@ write_type (tree type)
               break;
 
             case DECLTYPE_TYPE:
+             /* These shouldn't make it into mangling.  */
+             gcc_assert (!DECLTYPE_FOR_LAMBDA_CAPTURE (type)
+                         && !DECLTYPE_FOR_LAMBDA_RETURN (type));
+
               write_char ('D');
               if (DECLTYPE_TYPE_ID_EXPR_OR_MEMBER_ACCESS_P (type))
                 write_char ('t');
@@ -1894,6 +2034,12 @@ write_builtin_type (tree type)
        write_char ('d');
       else if (type == long_double_type_node)
        write_char ('e');
+      else if (type == dfloat32_type_node)
+       write_string ("Df");
+      else if (type == dfloat64_type_node)
+       write_string ("Dd");
+      else if (type == dfloat128_type_node)
+       write_string ("De");
       else
        gcc_unreachable ();
       break;
@@ -2114,21 +2260,22 @@ write_class_enum_type (const tree type)
 /* Non-terminal <template-args>.  ARGS is a TREE_VEC of template
    arguments.
 
-     <template-args> ::= I <template-arg>+ E  */
+     <template-args> ::= I <template-arg>* E  */
 
 static void
 write_template_args (tree args)
 {
   int i;
-  int length = TREE_VEC_LENGTH (args);
+  int length = 0;
 
   MANGLE_TRACE_TREE ("template-args", args);
 
   write_char ('I');
 
-  gcc_assert (length > 0);
+  if (args)
+    length = TREE_VEC_LENGTH (args);
 
-  if (TREE_CODE (TREE_VEC_ELT (args, 0)) == TREE_VEC)
+  if (args && TREE_CODE (TREE_VEC_ELT (args, 0)) == TREE_VEC)
     {
       /* We have nested template args.  We want the innermost template
         argument list.  */
@@ -2152,12 +2299,7 @@ write_member_name (tree member)
   if (TREE_CODE (member) == IDENTIFIER_NODE)
     write_source_name (member);
   else if (DECL_P (member))
-    {
-      /* G++ 3.2 incorrectly put out both the "sr" code and
-        the nested name of the qualified name.  */
-      G.need_abi_warning = 1;
-      write_unqualified_name (member);
-    }
+    write_unqualified_name (member);
   else if (TREE_CODE (member) == TEMPLATE_ID_EXPR)
     {
       tree name = TREE_OPERAND (member, 0);
@@ -2230,9 +2372,7 @@ write_expression (tree expr)
       int index = DECL_PARM_INDEX (expr);
       gcc_assert (index >= 1);
       write_string ("fp");
-      if (index > 1)
-       write_unsigned_number (index - 2);
-      write_char ('_');
+      write_compact_number (index - 1);
     }
   else if (DECL_P (expr))
     {
@@ -2256,17 +2396,27 @@ write_expression (tree expr)
       write_string ("at");
       write_type (TREE_OPERAND (expr, 0));
     }
-  else if (abi_version_at_least (2) && TREE_CODE (expr) == SCOPE_REF)
+  else if (TREE_CODE (expr) == SCOPE_REF)
     {
       tree scope = TREE_OPERAND (expr, 0);
       tree member = TREE_OPERAND (expr, 1);
 
+      if (!abi_version_at_least (2))
+       {
+         write_string ("sr");
+         write_type (scope);
+         /* G++ 3.2 incorrectly put out both the "sr" code and
+            the nested name of the qualified name.  */
+         G.need_abi_warning = 1;
+         write_encoding (member);
+       }
+
       /* If the MEMBER is a real declaration, then the qualifying
         scope was not dependent.  Ideally, we would not have a
         SCOPE_REF in those cases, but sometimes we do.  If the second
         argument is a DECL, then the name must not have been
         dependent.  */
-      if (DECL_P (member))
+      else if (DECL_P (member))
        write_expression (member);
       else
        {
@@ -2331,7 +2481,7 @@ write_expression (tree expr)
     }
   else
     {
-      int i;
+      int i, len;
       const char *name;
 
       /* When we bind a variable or function to a non-type template
@@ -2431,14 +2581,28 @@ write_expression (tree expr)
          sorry ("mangling new-expression");
          break;
 
-       /* Handle pointers-to-members specially.  */
-       case SCOPE_REF:
-         write_type (TREE_OPERAND (expr, 0));
-         write_member_name (TREE_OPERAND (expr, 1));
-         break;
-
        default:
-         for (i = 0; i < TREE_OPERAND_LENGTH (expr); ++i)
+         /* In the middle-end, some expressions have more operands than
+            they do in templates (and mangling).  */
+         switch (code)
+           {
+           case PREINCREMENT_EXPR:
+           case PREDECREMENT_EXPR:
+           case POSTINCREMENT_EXPR:
+           case POSTDECREMENT_EXPR:
+             len = 1;
+             break;
+
+           case ARRAY_REF:
+             len = 2;
+             break;
+
+           default:
+             len = TREE_OPERAND_LENGTH (expr);
+             break;
+           }
+
+         for (i = 0; i < len; ++i)
            {
              tree operand = TREE_OPERAND (expr, i);
              /* As a GNU extension, the middle operand of a
@@ -2668,8 +2832,6 @@ static void
 write_template_param (const tree parm)
 {
   int parm_index;
-  int parm_level;
-  tree parm_type = NULL_TREE;
 
   MANGLE_TRACE_TREE ("template-parm", parm);
 
@@ -2679,13 +2841,10 @@ write_template_param (const tree parm)
     case TEMPLATE_TEMPLATE_PARM:
     case BOUND_TEMPLATE_TEMPLATE_PARM:
       parm_index = TEMPLATE_TYPE_IDX (parm);
-      parm_level = TEMPLATE_TYPE_LEVEL (parm);
       break;
 
     case TEMPLATE_PARM_INDEX:
       parm_index = TEMPLATE_PARM_IDX (parm);
-      parm_level = TEMPLATE_PARM_LEVEL (parm);
-      parm_type = TREE_TYPE (TEMPLATE_PARM_DECL (parm));
       break;
 
     default:
@@ -2695,9 +2854,7 @@ write_template_param (const tree parm)
   write_char ('T');
   /* NUMBER as it appears in the mangling is (-1)-indexed, with the
      earliest template param denoted by `_'.  */
-  if (parm_index > 0)
-    write_unsigned_number (parm_index - 1);
-  write_char ('_');
+  write_compact_number (parm_index);
 }
 
 /*  <template-template-param>
@@ -2792,7 +2949,7 @@ finish_mangling_get_identifier (const bool warn)
   finish_mangling_internal (warn);
   /* Don't obstack_finish here, and the next start_mangling will
      remove the identifier.  */
-  return get_identifier ((const char *) name_base);
+  return get_identifier ((const char *) obstack_base (mangle_obstack));
 }
 
 /* Initialize data structures for mangling.  */
@@ -2845,18 +3002,15 @@ mangle_decl (const tree decl)
   SET_DECL_ASSEMBLER_NAME (decl, id);
 }
 
-/* Generate the mangled representation of TYPE for the typeinfo name.  */
+/* Generate the mangled representation of TYPE.  */
 
 const char *
-mangle_type_string_for_rtti (const tree type)
+mangle_type_string (const tree type)
 {
   const char *result;
 
   start_mangling (type);
-  /* Mangle in a fake anonymous namespace if necessary.  */
-  fake_anon_scope = true;
   write_type (type);
-  fake_anon_scope = false;
   result = finish_mangling (/*warn=*/false);
   if (DEBUG_MANGLE)
     fprintf (stderr, "mangle_type_string = '%s'\n\n", result);