OSDN Git Service

PR c++/50089
[pf3gnuchains/gcc-fork.git] / gcc / cp / mangle.c
index d4bcbac..1fcd999 100644 (file)
@@ -1,6 +1,6 @@
 /* Name mangling for the 3.0 C++ ABI.
-   Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009
-   Free Software Foundation, Inc.
+   Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009, 2010,
+   2011  Free Software Foundation, Inc.
    Written by Alex Samuel <samuel@codesourcery.com>
 
    This file is part of GCC.
@@ -52,12 +52,10 @@ along with GCC; see the file COPYING3.  If not see
 #include "tree.h"
 #include "tm_p.h"
 #include "cp-tree.h"
-#include "real.h"
 #include "obstack.h"
-#include "toplev.h"
-#include "varray.h"
 #include "flags.h"
 #include "target.h"
+#include "cgraph.h"
 
 /* Debugging support.  */
 
@@ -98,6 +96,9 @@ typedef struct GTY(()) globals {
   /* The entity that is being mangled.  */
   tree GTY ((skip)) entity;
 
+  /* How many parameter scopes we are inside.  */
+  int parm_depth;
+
   /* True if the mangling will be different in a future version of the
      ABI.  */
   bool need_abi_warning;
@@ -105,10 +106,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;
 
@@ -153,7 +150,9 @@ integer_type_codes[itk_none] =
   'l',  /* itk_long */
   'm',  /* itk_unsigned_long */
   'x',  /* itk_long_long */
-  'y'   /* itk_unsigned_long_long */
+  'y',  /* itk_unsigned_long_long */
+  'n',  /* itk_int128 */
+  'o',  /* itk_unsigned_int128  */
 };
 
 static int decl_is_template_id (const tree, tree* const);
@@ -310,7 +309,7 @@ dump_substitution_candidates (void)
   tree el;
 
   fprintf (stderr, "  ++ substitutions  ");
-  for (i = 0; VEC_iterate (tree, G.substitutions, i, el); ++i)
+  FOR_EACH_VEC_ELT (tree, G.substitutions, i, el)
     {
       const char *name = "???";
 
@@ -349,11 +348,19 @@ canonicalize_for_substitution (tree node)
   if (TYPE_P (node)
       && TYPE_CANONICAL (node) != node
       && TYPE_MAIN_VARIANT (node) != node)
+    {
       /* Here we want to strip the topmost typedef only.
          We need to do that so is_std_substitution can do proper
          name matching.  */
-    node = cp_build_qualified_type (TYPE_MAIN_VARIANT (node),
-                                    cp_type_quals (node));
+      if (TREE_CODE (node) == FUNCTION_TYPE)
+       /* Use build_qualified_type and TYPE_QUALS here to preserve
+          the old buggy mangling of attribute noreturn with abi<5.  */
+       node = build_qualified_type (TYPE_MAIN_VARIANT (node),
+                                    TYPE_QUALS (node));
+      else
+       node = cp_build_qualified_type (TYPE_MAIN_VARIANT (node),
+                                       cp_type_quals (node));
+    }
   return node;
 }
 
@@ -382,7 +389,7 @@ add_substitution (tree node)
     int i;
     tree candidate;
 
-    for (i = 0; VEC_iterate (tree, G.substitutions, i, candidate); i++)
+    FOR_EACH_VEC_ELT (tree, G.substitutions, i, candidate)
       {
        gcc_assert (!(DECL_P (node) && node == candidate));
        gcc_assert (!(TYPE_P (node) && TYPE_P (candidate)
@@ -734,26 +741,17 @@ 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.  */
-
-static bool
-needs_fake_anon (const_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);
-}
-
 /* Lambdas can have a bit more context for mangling, specifically VAR_DECL
    or PARM_DECL context, which doesn't belong in DECL_CONTEXT.  */
 
 static tree
 decl_mangling_context (tree decl)
 {
+  tree tcontext = targetm.cxx.decl_mangling_context (decl);
+
+  if (tcontext != NULL_TREE)
+    return tcontext;
+
   if (TREE_CODE (decl) == TYPE_DECL
       && LAMBDA_TYPE_P (TREE_TYPE (decl)))
     {
@@ -761,6 +759,10 @@ decl_mangling_context (tree 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);
 }
 
@@ -791,18 +793,13 @@ write_name (tree decl, const int ignore_local_scope)
 
   context = decl_mangling_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;
-
   /* 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))
     {
@@ -820,9 +817,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).  */
@@ -835,10 +829,10 @@ 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
@@ -868,7 +862,7 @@ write_name (tree decl, const int ignore_local_scope)
 static void
 write_unscoped_name (const tree decl)
 {
-  tree context = CP_DECL_CONTEXT (decl);
+  tree context = decl_mangling_context (decl);
 
   MANGLE_TRACE_TREE ("unscoped-name", decl);
 
@@ -883,6 +877,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);
@@ -953,10 +948,7 @@ write_nested_name (const tree decl)
   else
     {
       /* 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_prefix (CP_DECL_CONTEXT (decl));
       write_unqualified_name (decl);
     }
   write_char ('E');
@@ -965,6 +957,7 @@ write_nested_name (const tree decl)
 /* <prefix> ::= <prefix> <unqualified-name>
            ::= <template-param>
            ::= <template-prefix> <template-args>
+           ::= <decltype>
            ::= # empty
            ::= <substitution>  */
 
@@ -981,6 +974,12 @@ write_prefix (const tree node)
 
   MANGLE_TRACE_TREE ("prefix", node);
 
+  if (TREE_CODE (node) == DECLTYPE_TYPE)
+    {
+      write_type (node);
+      return;
+    }
+
   if (find_substitution (node))
     return;
 
@@ -1141,10 +1140,55 @@ write_template_prefix (const tree node)
     <local-source-name>        ::= L <source-name> <discriminator> */
 
 static void
+write_unqualified_id (tree identifier)
+{
+  if (IDENTIFIER_TYPENAME_P (identifier))
+    write_conversion_operator_name (TREE_TYPE (identifier));
+  else if (IDENTIFIER_OPNAME_P (identifier))
+    {
+      int i;
+      const char *mangled_name = NULL;
+
+      /* Unfortunately, there is no easy way to go from the
+        name of the operator back to the corresponding tree
+        code.  */
+      for (i = 0; i < MAX_TREE_CODES; ++i)
+       if (operator_name_info[i].identifier == identifier)
+         {
+           /* The ABI says that we prefer binary operator
+              names to unary operator names.  */
+           if (operator_name_info[i].arity == 2)
+             {
+               mangled_name = operator_name_info[i].mangled_name;
+               break;
+             }
+           else if (!mangled_name)
+             mangled_name = operator_name_info[i].mangled_name;
+         }
+       else if (assignment_operator_name_info[i].identifier
+                == identifier)
+         {
+           mangled_name
+             = assignment_operator_name_info[i].mangled_name;
+           break;
+         }
+      write_string (mangled_name);
+    }
+  else
+    write_source_name (identifier);
+}
+
+static void
 write_unqualified_name (const tree decl)
 {
   MANGLE_TRACE_TREE ("unqualified-name", decl);
 
+  if (TREE_CODE (decl) == IDENTIFIER_NODE)
+    {
+      write_unqualified_id (decl);
+      return;
+    }
+
   if (DECL_NAME (decl) == NULL_TREE)
     {
       gcc_assert (DECL_ASSEMBLER_NAME_SET_P (decl));
@@ -1259,7 +1303,7 @@ nested_anon_class_index (tree type)
 {
   int index = 0;
   tree member = TYPE_FIELDS (TYPE_CONTEXT (type));
-  for (; member; member = TREE_CHAIN (member))
+  for (; member; member = DECL_CHAIN (member))
     if (DECL_IMPLICIT_TYPEDEF_P (member))
       {
        tree memtype = TREE_TYPE (member);
@@ -1605,11 +1649,11 @@ discriminator_for_local_entity (tree entity)
 {
   if (DECL_DISCRIMINATOR_P (entity))
     {
-      if (DECL_LANG_SPECIFIC (entity))
+      if (DECL_DISCRIMINATOR_SET_P (entity))
        return DECL_DISCRIMINATOR (entity);
       else
        /* The first entity with a particular name doesn't get
-          DECL_LANG_SPECIFIC/DECL_DISCRIMINATOR.  */
+          DECL_DISCRIMINATOR set up.  */
        return 0;
     }
   else if (TREE_CODE (entity) == TYPE_DECL)
@@ -1689,7 +1733,7 @@ write_local_name (tree function, const tree local_entity,
     {
       tree t;
       int i = 0;
-      for (t = DECL_ARGUMENTS (function); t; t = TREE_CHAIN (t))
+      for (t = DECL_ARGUMENTS (function); t; t = DECL_CHAIN (t))
        {
          if (t == parm)
            i = 1;
@@ -1738,6 +1782,7 @@ write_local_name (tree function, const tree local_entity,
      <type> ::= Dt <expression> # decltype of an id-expression or 
                                 # class member access
      <type> ::= DT <expression> # decltype of an expression
+     <type> ::= Dn              # decltype of nullptr
 
    TYPE is a type node.  */
 
@@ -1753,9 +1798,16 @@ write_type (tree type)
   if (type == error_mark_node)
     return;
 
+  type = canonicalize_for_substitution (type);
   if (find_substitution (type))
     return;
 
+  /* According to the C++ ABI, some library classes are passed the
+     same as the scalar type of their single member and use the same
+     mangling.  */
+  if (TREE_CODE (type) == RECORD_TYPE && TYPE_TRANSPARENT_AGGR (type))
+    type = TREE_TYPE (first_field (type));
+
   if (write_CV_qualifiers_for_type (type) > 0)
     /* If TYPE was CV-qualified, we just wrote the qualifiers; now
        mangle the unqualified type.  The recursive call is needed here
@@ -1840,16 +1892,25 @@ write_type (tree type)
              break;
 
            case POINTER_TYPE:
-             write_char ('P');
-             write_type (TREE_TYPE (type));
-             break;
-
            case REFERENCE_TYPE:
-             if (TYPE_REF_IS_RVALUE (type))
-               write_char('O');
+             if (TREE_CODE (type) == POINTER_TYPE)
+               write_char ('P');
+             else if (TYPE_REF_IS_RVALUE (type))
+               write_char ('O');
               else
                 write_char ('R');
-             write_type (TREE_TYPE (type));
+             {
+               tree target = TREE_TYPE (type);
+               /* Attribute const/noreturn are not reflected in mangling.
+                  We strip them here rather than at a lower level because
+                  a typedef or template argument can have function type
+                  with function-cv-quals (that use the same representation),
+                  but you can't have a pointer/reference to such a type.  */
+               if (abi_version_at_least (5)
+                   && TREE_CODE (target) == FUNCTION_TYPE)
+                 target = build_qualified_type (target, TYPE_UNQUALIFIED);
+               write_type (target);
+             }
              break;
 
            case TEMPLATE_TYPE_PARM:
@@ -1868,7 +1929,19 @@ write_type (tree type)
              break;
 
            case VECTOR_TYPE:
-             write_string ("U8__vector");
+             if (abi_version_at_least (4))
+               {
+                 write_string ("Dv");
+                 /* Non-constant vector size would be encoded with
+                    _ expression, but we don't support that yet.  */
+                 write_unsigned_number (TYPE_VECTOR_SUBPARTS (type));
+                 write_char ('_');
+               }
+             else
+               {
+                 G.need_abi_warning = 1;
+                 write_string ("U8__vector");
+               }
              write_type (TREE_TYPE (type));
              break;
 
@@ -1880,7 +1953,36 @@ write_type (tree type)
             case DECLTYPE_TYPE:
              /* These shouldn't make it into mangling.  */
              gcc_assert (!DECLTYPE_FOR_LAMBDA_CAPTURE (type)
-                         && !DECLTYPE_FOR_LAMBDA_RETURN (type));
+                         && !DECLTYPE_FOR_LAMBDA_PROXY (type));
+
+             /* In ABI <5, we stripped decltype of a plain decl.  */
+             if (!abi_version_at_least (5)
+                 && DECLTYPE_TYPE_ID_EXPR_OR_MEMBER_ACCESS_P (type))
+               {
+                 tree expr = DECLTYPE_TYPE_EXPR (type);
+                 tree etype = NULL_TREE;
+                 switch (TREE_CODE (expr))
+                   {
+                   case VAR_DECL:
+                   case PARM_DECL:
+                   case RESULT_DECL:
+                   case FUNCTION_DECL:
+                   case CONST_DECL:
+                   case TEMPLATE_PARM_INDEX:
+                     etype = TREE_TYPE (expr);
+                     break;
+
+                   default:
+                     break;
+                   }
+
+                 if (etype && !type_uses_auto (etype))
+                   {
+                     G.need_abi_warning = 1;
+                     write_type (etype);
+                     return;
+                   }
+               }
 
               write_char ('D');
               if (DECLTYPE_TYPE_ID_EXPR_OR_MEMBER_ACCESS_P (type))
@@ -1893,10 +1995,21 @@ write_type (tree type)
               write_char ('E');
               break;
 
+           case NULLPTR_TYPE:
+             write_string ("Dn");
+             break;
+
            case TYPEOF_TYPE:
              sorry ("mangling typeof, use decltype instead");
              break;
 
+           case UNDERLYING_TYPE:
+             sorry ("mangling __underlying_type");
+             break;
+
+           case LANG_TYPE:
+             /* fall through.  */
+
            default:
              gcc_unreachable ();
            }
@@ -1927,18 +2040,19 @@ write_CV_qualifiers_for_type (const tree type)
      Note that we do not use cp_type_quals below; given "const
      int[3]", the "const" is emitted with the "int", not with the
      array.  */
+  cp_cv_quals quals = TYPE_QUALS (type);
 
-  if (TYPE_QUALS (type) & TYPE_QUAL_RESTRICT)
+  if (quals & TYPE_QUAL_RESTRICT)
     {
       write_char ('r');
       ++num_qualifiers;
     }
-  if (TYPE_QUALS (type) & TYPE_QUAL_VOLATILE)
+  if (quals & TYPE_QUAL_VOLATILE)
     {
       write_char ('V');
       ++num_qualifiers;
     }
-  if (TYPE_QUALS (type) & TYPE_QUAL_CONST)
+  if (quals & TYPE_QUAL_CONST)
     {
       write_char ('K');
       ++num_qualifiers;
@@ -2005,7 +2119,8 @@ write_builtin_type (tree type)
             it in the array of these nodes.  */
        iagain:
          for (itk = 0; itk < itk_none; ++itk)
-           if (type == integer_types[itk])
+           if (integer_types[itk] != NULL_TREE
+               && type == integer_types[itk])
              {
                /* Print the corresponding single-letter code.  */
                write_char (integer_type_codes[itk]);
@@ -2144,7 +2259,7 @@ write_function_type (const tree type)
     {
       /* The first parameter must be a POINTER_TYPE pointing to the
         `this' parameter.  */
-      tree this_type = TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (type)));
+      tree this_type = class_of_this_parm (type);
       write_CV_qualifiers_for_type (this_type);
     }
 
@@ -2206,9 +2321,11 @@ write_bare_function_type (const tree type, const int include_return_type_p,
     write_type (TREE_TYPE (type));
 
   /* Now mangle the types of the arguments.  */
+  ++G.parm_depth;
   write_method_parms (TYPE_ARG_TYPES (type),
                      TREE_CODE (type) == METHOD_TYPE,
                      decl);
+  --G.parm_depth;
 }
 
 /* Write the mangled representation of a method parameter list of
@@ -2237,12 +2354,12 @@ write_method_parms (tree parm_types, const int method_p, const tree decl)
   if (method_p)
     {
       parm_types = TREE_CHAIN (parm_types);
-      parm_decl = parm_decl ? TREE_CHAIN (parm_decl) : NULL_TREE;
+      parm_decl = parm_decl ? DECL_CHAIN (parm_decl) : NULL_TREE;
 
       while (parm_decl && DECL_ARTIFICIAL (parm_decl))
        {
          parm_types = TREE_CHAIN (parm_types);
-         parm_decl = TREE_CHAIN (parm_decl);
+         parm_decl = DECL_CHAIN (parm_decl);
        }
     }
 
@@ -2321,14 +2438,9 @@ static void
 write_member_name (tree member)
 {
   if (TREE_CODE (member) == IDENTIFIER_NODE)
-    write_source_name (member);
+    write_unqualified_id (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);
@@ -2395,12 +2507,37 @@ write_expression (tree expr)
   else if (TREE_CODE_CLASS (code) == tcc_constant
           || (abi_version_at_least (2) && code == CONST_DECL))
     write_template_arg_literal (expr);
+  else if (code == PARM_DECL && DECL_ARTIFICIAL (expr))
+    {
+      gcc_assert (!strcmp ("this", IDENTIFIER_POINTER (DECL_NAME (expr))));
+      write_string ("fpT");
+    }
   else if (code == PARM_DECL)
     {
       /* A function parameter used in a late-specified return type.  */
       int index = DECL_PARM_INDEX (expr);
+      int level = DECL_PARM_LEVEL (expr);
+      int delta = G.parm_depth - level + 1;
       gcc_assert (index >= 1);
-      write_string ("fp");
+      write_char ('f');
+      if (delta != 0)
+       {
+         if (abi_version_at_least (5))
+           {
+             /* Let L be the number of function prototype scopes from the
+                innermost one (in which the parameter reference occurs) up
+                to (and including) the one containing the declaration of
+                the referenced parameter.  If the parameter declaration
+                clause of the innermost function prototype scope has been
+                completely seen, it is not counted (in that case -- which
+                is perhaps the most common -- L can be zero).  */
+             write_char ('L');
+             write_unsigned_number (delta - 1);
+           }
+         else
+           G.need_abi_warning = true;
+       }
+      write_char ('p');
       write_compact_number (index - 1);
     }
   else if (DECL_P (expr))
@@ -2425,71 +2562,33 @@ 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) && DECL_P (member))
+       {
+         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
        {
-         tree template_args;
-
          write_string ("sr");
          write_type (scope);
-         /* If MEMBER is a template-id, separate the template
-            from the arguments.  */
-         if (TREE_CODE (member) == TEMPLATE_ID_EXPR)
-           {
-             template_args = TREE_OPERAND (member, 1);
-             member = TREE_OPERAND (member, 0);
-           }
-         else
-           template_args = NULL_TREE;
-         /* Write out the name of the MEMBER.  */
-         if (IDENTIFIER_TYPENAME_P (member))
-           write_conversion_operator_name (TREE_TYPE (member));
-         else if (IDENTIFIER_OPNAME_P (member))
-           {
-             int i;
-             const char *mangled_name = NULL;
-
-             /* Unfortunately, there is no easy way to go from the
-                name of the operator back to the corresponding tree
-                code.  */
-             for (i = 0; i < MAX_TREE_CODES; ++i)
-               if (operator_name_info[i].identifier == member)
-                 {
-                   /* The ABI says that we prefer binary operator
-                      names to unary operator names.  */
-                   if (operator_name_info[i].arity == 2)
-                     {
-                       mangled_name = operator_name_info[i].mangled_name;
-                       break;
-                     }
-                   else if (!mangled_name)
-                     mangled_name = operator_name_info[i].mangled_name;
-                 }
-               else if (assignment_operator_name_info[i].identifier
-                        == member)
-                 {
-                   mangled_name
-                     = assignment_operator_name_info[i].mangled_name;
-                   break;
-                 }
-             write_string (mangled_name);
-           }
-         else
-           write_source_name (member);
-         /* Write out the template arguments.  */
-         if (template_args)
-           write_template_args (template_args);
+         write_member_name (member);
        }
     }
   else if (TREE_CODE (expr) == INDIRECT_REF
@@ -2498,9 +2597,37 @@ write_expression (tree expr)
     {
       write_expression (TREE_OPERAND (expr, 0));
     }
+  else if (TREE_CODE (expr) == IDENTIFIER_NODE)
+    {
+      /* An operator name appearing as a dependent name needs to be
+        specially marked to disambiguate between a use of the operator
+        name and a use of the operator in an expression.  */
+      if (IDENTIFIER_OPNAME_P (expr))
+       write_string ("on");
+      write_unqualified_id (expr);
+    }
+  else if (TREE_CODE (expr) == TEMPLATE_ID_EXPR)
+    {
+      tree fn = TREE_OPERAND (expr, 0);
+      if (is_overloaded_fn (fn))
+       fn = DECL_NAME (get_first_fn (fn));
+      if (IDENTIFIER_OPNAME_P (fn))
+       write_string ("on");
+      write_unqualified_id (fn);
+      write_template_args (TREE_OPERAND (expr, 1));
+    }
+  else if (TREE_CODE (expr) == MODOP_EXPR)
+    {
+      enum tree_code subop = TREE_CODE (TREE_OPERAND (expr, 1));
+      const char *name = (assignment_operator_name_info[(int) subop]
+                         .mangled_name);
+      write_string (name);
+      write_expression (TREE_OPERAND (expr, 0));
+      write_expression (TREE_OPERAND (expr, 2));
+    }
   else
     {
-      int i;
+      int i, len;
       const char *name;
 
       /* When we bind a variable or function to a non-type template
@@ -2564,10 +2691,7 @@ write_expression (tree expr)
                && type_dependent_expression_p_push (expr))
              fn = DECL_NAME (get_first_fn (fn));
 
-           if (TREE_CODE (fn) == IDENTIFIER_NODE)
-             write_source_name (fn);
-           else
-             write_expression (fn);
+           write_expression (fn);
          }
 
          for (i = 0; i < call_expr_nargs (expr); ++i)
@@ -2600,14 +2724,12 @@ 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).  */
+         len = cp_tree_operand_length (expr);
+
+         for (i = 0; i < len; ++i)
            {
              tree operand = TREE_OPERAND (expr, i);
              /* As a GNU extension, the middle operand of a
@@ -2640,25 +2762,34 @@ write_template_arg_literal (const tree value)
   write_char ('L');
   write_type (TREE_TYPE (value));
 
-  switch (TREE_CODE (value))
-    {
-    case CONST_DECL:
-      write_integer_cst (DECL_INITIAL (value));
-      break;
+  /* Write a null member pointer value as (type)0, regardless of its
+     real representation.  */
+  if (null_member_pointer_value_p (value))
+    write_integer_cst (integer_zero_node);
+  else
+    switch (TREE_CODE (value))
+      {
+      case CONST_DECL:
+       write_integer_cst (DECL_INITIAL (value));
+       break;
 
-    case INTEGER_CST:
-      gcc_assert (!same_type_p (TREE_TYPE (value), boolean_type_node)
-                 || integer_zerop (value) || integer_onep (value));
-      write_integer_cst (value);
-      break;
+      case INTEGER_CST:
+       gcc_assert (!same_type_p (TREE_TYPE (value), boolean_type_node)
+                   || integer_zerop (value) || integer_onep (value));
+       write_integer_cst (value);
+       break;
 
-    case REAL_CST:
-      write_real_cst (value);
-      break;
+      case REAL_CST:
+       write_real_cst (value);
+       break;
 
-    default:
-      gcc_unreachable ();
-    }
+      case STRING_CST:
+       sorry ("string literal in function template signature");
+       break;
+
+      default:
+       gcc_unreachable ();
+      }
 
   write_char ('E');
 }
@@ -2719,7 +2850,8 @@ write_template_arg (tree node)
     /* A template appearing as a template arg is a template template arg.  */
     write_template_template_arg (node);
   else if ((TREE_CODE_CLASS (code) == tcc_constant && code != PTRMEM_CST)
-          || (abi_version_at_least (2) && code == CONST_DECL))
+          || (abi_version_at_least (2) && code == CONST_DECL)
+          || null_member_pointer_value_p (node))
     write_template_arg_literal (node);
   else if (DECL_P (node))
     {
@@ -2837,8 +2969,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);
 
@@ -2848,13 +2978,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:
@@ -2987,6 +3114,25 @@ static tree
 mangle_decl_string (const tree decl)
 {
   tree result;
+  location_t saved_loc = input_location;
+  tree saved_fn = NULL_TREE;
+  bool template_p = false;
+
+  /* We shouldn't be trying to mangle an uninstantiated template.  */
+  gcc_assert (!type_dependent_expression_p (decl));
+
+  if (DECL_LANG_SPECIFIC (decl) && DECL_USE_TEMPLATE (decl))
+    {
+      struct tinst_level *tl = current_instantiation ();
+      if ((!tl || tl->decl != decl)
+         && push_tinst_level (decl))
+       {
+         template_p = true;
+         saved_fn = current_function_decl;
+         current_function_decl = NULL_TREE;
+       }
+    }
+  input_location = DECL_SOURCE_LOCATION (decl);
 
   start_mangling (decl);
 
@@ -2999,6 +3145,14 @@ mangle_decl_string (const tree decl)
   if (DEBUG_MANGLE)
     fprintf (stderr, "mangle_decl_string = '%s'\n\n",
             IDENTIFIER_POINTER (result));
+
+  if (template_p)
+    {
+      pop_tinst_level ();
+      current_function_decl = saved_fn;
+    }
+  input_location = saved_loc;
+
   return result;
 }
 
@@ -3010,20 +3164,51 @@ mangle_decl (const tree decl)
   tree id = mangle_decl_string (decl);
   id = targetm.mangle_decl_assembler_name (decl, id);
   SET_DECL_ASSEMBLER_NAME (decl, id);
+
+  if (G.need_abi_warning)
+    {
+#ifdef ASM_OUTPUT_DEF
+      /* If the mangling will change in the future, emit an alias with the
+        future mangled name for forward-compatibility.  */
+      int save_ver;
+      tree id2, alias;
+#endif
+
+      SET_IDENTIFIER_GLOBAL_VALUE (id, decl);
+      if (IDENTIFIER_GLOBAL_VALUE (id) != decl)
+       inform (DECL_SOURCE_LOCATION (decl), "-fabi-version=4 (or =0) "
+               "avoids this error with a change in vector mangling");
+
+#ifdef ASM_OUTPUT_DEF
+      save_ver = flag_abi_version;
+      flag_abi_version = 0;
+      id2 = mangle_decl_string (decl);
+      id2 = targetm.mangle_decl_assembler_name (decl, id2);
+      flag_abi_version = save_ver;
+
+      alias = make_alias_for (decl, id2);
+      DECL_IGNORED_P (alias) = 1;
+      TREE_PUBLIC (alias) = TREE_PUBLIC (decl);
+      DECL_VISIBILITY (alias) = DECL_VISIBILITY (decl);
+      if (vague_linkage_p (decl))
+       DECL_WEAK (alias) = 1;
+      if (TREE_CODE (decl) == FUNCTION_DECL)
+       cgraph_same_body_alias (cgraph_get_create_node (decl), alias, decl);
+      else
+       varpool_extra_name_alias (alias, decl);
+#endif
+    }
 }
 
-/* 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);