]> git.ipfire.org Git - thirdparty/gcc.git/blobdiff - gcc/cp/mangle.c
Update copyright years.
[thirdparty/gcc.git] / gcc / cp / mangle.c
index a8b9f37dd7ab7f5d7b950ee39800d7179a835704..11eb8962d2848765e482fe5054e1f0e7c97bd243 100644 (file)
@@ -1,5 +1,5 @@
-/* Name mangling for the 3.0 C++ ABI.
-   Copyright (C) 2000-2016 Free Software Foundation, Inc.
+/* Name mangling for the 3.0 -*- C++ -*- ABI.
+   Copyright (C) 2000-2021 Free Software Foundation, Inc.
    Written by Alex Samuel <samuel@codesourcery.com>
 
    This file is part of GCC.
@@ -81,16 +81,24 @@ along with GCC; see the file COPYING3.  If not see
    instantiated outside of the template, and A is the type used
    without parameters inside the template.  */
 #define CLASSTYPE_TEMPLATE_ID_P(NODE)                                  \
-  (TYPE_LANG_SPECIFIC (NODE) != NULL                                   \
-   && (TREE_CODE (NODE) == BOUND_TEMPLATE_TEMPLATE_PARM                        \
-       || (CLASSTYPE_TEMPLATE_INFO (NODE) != NULL                      \
-          && (PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (NODE))))))
+  (TREE_CODE (NODE) == BOUND_TEMPLATE_TEMPLATE_PARM                    \
+   || (CLASS_TYPE_P (NODE)                                             \
+       && CLASSTYPE_TEMPLATE_INFO (NODE) != NULL                       \
+       && PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (NODE))))
 
 /* For deciding whether to set G.need_abi_warning, we need to consider both
    warn_abi_version and flag_abi_compat_version.  */
 #define abi_warn_or_compat_version_crosses(N) \
   (abi_version_crosses (N) || abi_compat_version_crosses (N))
 
+/* And sometimes we can simplify the code path if we don't need to worry about
+   previous ABIs.  */
+#define abi_flag_at_least(flag,N) (flag == 0 || flag >= N)
+#define any_abi_below(N) \
+  (!abi_version_at_least (N) \
+   || !abi_flag_at_least (warn_abi_version, (N)) \
+   || !abi_flag_at_least (flag_abi_compat_version, (N)))
+
 /* Things we only need one of.  This module is not reentrant.  */
 struct GTY(()) globals {
   /* An array of the current substitution candidates, in the order
@@ -106,6 +114,12 @@ struct GTY(()) globals {
   /* True if the mangling will be different in a future version of the
      ABI.  */
   bool need_abi_warning;
+
+  /* True if the mangling will be different in C++17 mode.  */
+  bool need_cxx17_warning;
+
+  /* True if we mangled a module name.  */
+  bool mod;
 };
 
 static GTY (()) globals G;
@@ -159,7 +173,7 @@ integer_type_codes[itk_none] =
   '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0'
 };
 
-static int decl_is_template_id (const tree, tree* const);
+static tree maybe_template_info (const tree);
 
 /* Functions for handling substitutions.  */
 
@@ -222,17 +236,14 @@ static void write_discriminator (const int);
 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);
+static void maybe_check_abi_tags (tree, tree = NULL_TREE, int = 10);
+static bool equal_abi_tags (tree, tree);
 
 /* Control functions.  */
 
 static inline void start_mangling (const tree);
 static tree mangle_special_for_type (const tree, const char *);
 
-/* Foreign language functions.  */
-
-static void write_java_integer_type_codes (const tree);
-
 /* Append a single character to the end of the mangled
    representation.  */
 #define write_char(CHAR)                                               \
@@ -263,12 +274,11 @@ static void write_java_integer_type_codes (const tree);
 #define write_unsigned_number(NUMBER)                                  \
   write_number ((NUMBER), /*unsigned_p=*/1, 10)
 
-/* If DECL is a template instance, return nonzero and, if
-   TEMPLATE_INFO is non-NULL, set *TEMPLATE_INFO to its template info.
-   Otherwise return zero.  */
+/* If DECL is a template instance (including the uninstantiated template
+   itself), return its TEMPLATE_INFO.  Otherwise return NULL.  */
 
-static int
-decl_is_template_id (const tree decl, tree* const template_info)
+static tree
+maybe_template_info (const tree decl)
 {
   if (TREE_CODE (decl) == TYPE_DECL)
     {
@@ -277,32 +287,20 @@ decl_is_template_id (const tree decl, tree* const template_info)
       const tree type = TREE_TYPE (decl);
 
       if (CLASS_TYPE_P (type) && CLASSTYPE_TEMPLATE_ID_P (type))
-       {
-         if (template_info != NULL)
-           /* For a templated TYPE_DECL, the template info is hanging
-              off the type.  */
-           *template_info = TYPE_TEMPLATE_INFO (type);
-         return 1;
-       }
+       return TYPE_TEMPLATE_INFO (type);
     }
   else
     {
-      /* Check if this is a primary template.  */
+      /* Check if the template is a primary template.  */
       if (DECL_LANG_SPECIFIC (decl) != NULL
-         && DECL_USE_TEMPLATE (decl)
-         && PRIMARY_TEMPLATE_P (DECL_TI_TEMPLATE (decl))
-         && TREE_CODE (decl) != TEMPLATE_DECL)
-       {
-         if (template_info != NULL)
-           /* For most templated decls, the template info is hanging
-              off the decl.  */
-           *template_info = DECL_TEMPLATE_INFO (decl);
-         return 1;
-       }
+         && VAR_OR_FUNCTION_DECL_P (decl)
+         && DECL_TEMPLATE_INFO (decl)
+         && PRIMARY_TEMPLATE_P (DECL_TI_TEMPLATE (decl)))
+       return DECL_TEMPLATE_INFO (decl);
     }
 
   /* It's not a template id.  */
-  return 0;
+  return NULL_TREE;
 }
 
 /* Produce debugging output of current substitution candidates.  */
@@ -337,6 +335,45 @@ dump_substitution_candidates (void)
     }
 }
 
+/* <exception-spec> ::=
+      Do  -- non-throwing exception specification
+      DO <expression> E  -- computed (instantiation-dependent) noexcept
+      Dw <type>* E  -- throw (types)  */
+
+static void
+write_exception_spec (tree spec)
+{
+
+  if (!spec || spec == noexcept_false_spec)
+    /* Nothing.  */
+    return;
+
+  if (!flag_noexcept_type)
+    {
+      G.need_cxx17_warning = true;
+      return;
+    }
+
+  if (spec == noexcept_true_spec || spec == empty_except_spec)
+    write_string ("Do");
+  else if (tree expr = TREE_PURPOSE (spec))
+    {
+      /* noexcept (expr)  */
+      gcc_assert (uses_template_parms (expr));
+      write_string ("DO");
+      write_expression (expr);
+      write_char ('E');
+    }
+  else
+    {
+      /* throw (type-list) */
+      write_string ("Dw");
+      for (tree t = spec; t; t = TREE_CHAIN (t))
+       write_type (TREE_VALUE (t));
+      write_char ('E');
+    }
+}
+
 /* Both decls and types can be substitution candidates, but sometimes
    they refer to the same thing.  For instance, a TYPE_DECL and
    RECORD_TYPE for the same class refer to the same thing, and should
@@ -366,9 +403,16 @@ canonicalize_for_substitution (tree node)
       else
        node = cp_build_qualified_type (TYPE_MAIN_VARIANT (node),
                                        cp_type_quals (node));
-      if (TREE_CODE (node) == FUNCTION_TYPE
-         || TREE_CODE (node) == METHOD_TYPE)
-       node = build_ref_qualified_type (node, type_memfn_rqual (orig));
+      if (FUNC_OR_METHOD_TYPE_P (node))
+       {
+         node = build_ref_qualified_type (node, type_memfn_rqual (orig));
+         tree r = canonical_eh_spec (TYPE_RAISES_EXCEPTIONS (orig));
+         if (flag_noexcept_type)
+           node = build_exception_variant (node, r);
+         else
+           /* Set the warning flag if appropriate.  */
+           write_exception_spec (r);
+       }
     }
   return node;
 }
@@ -445,6 +489,30 @@ is_std_substitution (const tree node,
              == subst_identifiers[index]));
 }
 
+/* Return the ABI tags (the TREE_VALUE of the "abi_tag" attribute entry) for T,
+   which can be a decl or type.  */
+
+static tree
+get_abi_tags (tree t)
+{
+  if (!t || TREE_CODE (t) == NAMESPACE_DECL)
+    return NULL_TREE;
+
+  if (DECL_P (t) && DECL_DECLARES_TYPE_P (t))
+    t = TREE_TYPE (t);
+
+  tree attrs;
+  if (TYPE_P (t))
+    attrs = TYPE_ATTRIBUTES (t);
+  else
+    attrs = DECL_ATTRIBUTES (t);
+
+  tree tags = lookup_attribute ("abi_tag", attrs);
+  if (tags)
+    tags = TREE_VALUE (tags);
+  return tags;
+}
+
 /* Helper function for find_substitution.  Returns nonzero if NODE,
    which may be a decl or a CLASS_TYPE, is the template-id
    ::std::identifier<char>, where identifier is
@@ -549,7 +617,7 @@ find_substitution (tree node)
            {
              tree args = CLASSTYPE_TI_ARGS (type);
              if (TREE_VEC_LENGTH (args) == 3
-                 && same_type_p (TREE_VEC_ELT (args, 0), char_type_node)
+                 && template_args_equal (TREE_VEC_ELT (args, 0), char_type_node)
                  && is_std_substitution_char (TREE_VEC_ELT (args, 1),
                                               SUBID_CHAR_TRAITS)
                  && is_std_substitution_char (TREE_VEC_ELT (args, 2),
@@ -573,8 +641,7 @@ find_substitution (tree node)
         args <char, std::char_traits<char> > .  */
       tree args = CLASSTYPE_TI_ARGS (type);
       if (TREE_VEC_LENGTH (args) == 2
-         && TYPE_P (TREE_VEC_ELT (args, 0))
-         && same_type_p (TREE_VEC_ELT (args, 0), char_type_node)
+         && template_args_equal (TREE_VEC_ELT (args, 0), char_type_node)
          && is_std_substitution_char (TREE_VEC_ELT (args, 1),
                                       SUBID_CHAR_TRAITS))
        {
@@ -599,7 +666,7 @@ find_substitution (tree node)
 
   tree tags = NULL_TREE;
   if (OVERLOAD_TYPE_P (node) || DECL_CLASS_TEMPLATE_P (node))
-    tags = lookup_attribute ("abi_tag", TYPE_ATTRIBUTES (type));
+    tags = get_abi_tags (type);
   /* Now check the list of available substitutions for this mangling
      operation.  */
   if (!abbr || tags) for (i = 0; i < size; ++i)
@@ -665,7 +732,7 @@ unmangled_name_p (const tree decl)
        return false;
 
       /* Declarations with ABI tags are mangled.  */
-      if (lookup_attribute ("abi_tag", DECL_ATTRIBUTES (decl)))
+      if (get_abi_tags (decl))
        return false;
 
       /* The names of non-static global variables aren't mangled.  */
@@ -719,7 +786,7 @@ mangle_return_type_p (tree decl)
   return (!DECL_CONSTRUCTOR_P (decl)
          && !DECL_DESTRUCTOR_P (decl)
          && !DECL_CONV_FN_P (decl)
-         && decl_is_template_id (decl, NULL));
+         && maybe_template_info (decl));
 }
 
 /*   <encoding>                ::= <function name> <bare-function-type>
@@ -747,7 +814,7 @@ write_encoding (const tree decl)
       tree fn_type;
       tree d;
 
-      if (decl_is_template_id (decl, NULL))
+      if (maybe_template_info (decl))
        {
          fn_type = get_mostly_instantiated_function_type (decl);
          /* FN_TYPE will not have parameter types for in-charge or
@@ -768,6 +835,62 @@ write_encoding (const tree decl)
     }
 }
 
+/* Interface to substitution and identifer mangling, used by the
+   module name mangler.  */
+
+void
+mangle_module_substitution (int v)
+{
+  if (v < 10)
+    {
+      write_char ('_');
+      write_char ('0' + v);
+    }
+  else
+    {
+      write_char ('W');
+      write_unsigned_number (v - 10);
+      write_char ('_');
+    }
+}
+
+void
+mangle_identifier (char c, tree id)
+{
+  if (c)
+    write_char (c);
+  write_source_name (id);
+}
+
+/* If the outermost non-namespace context (including DECL itself) is
+   a module-linkage decl, mangle the module information.  For module
+   global initializers we need to include the partition part.
+
+   <module-name> ::= W <module-id>+ E
+   <module-id> :: <unqualified-name>
+               || _ <digit>  ;; short backref
+              || W <number> _  ;; long backref
+               || P <module-id> ;; partition introducer
+*/
+
+static void
+write_module (int m, bool include_partition)
+{
+  G.mod = true;
+
+  write_char ('W');
+  mangle_module (m, include_partition);
+  write_char ('E');
+}
+
+static void
+maybe_write_module (tree decl)
+{
+  int m = get_originating_module (decl, true);
+  if (m >= 0)
+    write_module (m, false);
+}
+
 /* Lambdas can have a bit more context for mangling, specifically VAR_DECL
    or PARM_DECL context, which doesn't belong in DECL_CONTEXT.  */
 
@@ -793,7 +916,16 @@ decl_mangling_context (tree decl)
   else if (template_type_parameter_p (decl))
      /* template type parms have no mangling context.  */
       return NULL_TREE;
-  return CP_DECL_CONTEXT (decl);
+
+  tcontext = CP_DECL_CONTEXT (decl);
+
+  /* Ignore the artificial declare reduction functions.  */
+  if (tcontext
+      && TREE_CODE (tcontext) == FUNCTION_DECL
+      && DECL_OMP_DECLARE_REDUCTION_P (tcontext))
+    return decl_mangling_context (tcontext);
+
+  return tcontext;
 }
 
 /* <name> ::= <unscoped-name>
@@ -821,6 +953,9 @@ write_name (tree decl, const int ignore_local_scope)
       decl = TYPE_NAME (TYPE_MAIN_VARIANT (TREE_TYPE (decl)));
     }
 
+  if (modules_p ())
+    maybe_write_module (decl);
+
   context = decl_mangling_context (decl);
 
   gcc_assert (context != NULL_TREE);
@@ -842,13 +977,12 @@ write_name (tree decl, const int ignore_local_scope)
              || (abi_version_at_least (7)
                  && TREE_CODE (context) == PARM_DECL))))
     {
-      tree template_info;
       /* Is this a template instance?  */
-      if (decl_is_template_id (decl, &template_info))
+      if (tree info = maybe_template_info (decl))
        {
          /* Yes: use <unscoped-template-name>.  */
-         write_unscoped_template_name (TI_TEMPLATE (template_info));
-         write_template_args (TI_ARGS (template_info));
+         write_unscoped_template_name (TI_TEMPLATE (info));
+         write_template_args (TI_ARGS (info));
        }
       else
        /* Everything else gets an <unqualified-name>.  */
@@ -950,8 +1084,6 @@ write_unscoped_template_name (const tree decl)
 static void
 write_nested_name (const tree decl)
 {
-  tree template_info;
-
   MANGLE_TRACE_TREE ("nested-name", decl);
 
   write_char ('N');
@@ -974,11 +1106,11 @@ write_nested_name (const tree decl)
     }
 
   /* Is this a template instance?  */
-  if (decl_is_template_id (decl, &template_info))
+  if (tree info = maybe_template_info (decl))
     {
       /* Yes, use <template-prefix>.  */
       write_template_prefix (decl);
-      write_template_args (TI_ARGS (template_info));
+      write_template_args (TI_ARGS (info));
     }
   else if ((!abi_version_at_least (10) || TREE_CODE (decl) == TYPE_DECL)
           && TREE_CODE (TREE_TYPE (decl)) == TYPENAME_TYPE)
@@ -1015,8 +1147,6 @@ static void
 write_prefix (const tree node)
 {
   tree decl;
-  /* Non-NULL if NODE represents a template-id.  */
-  tree template_info = NULL;
 
   if (node == NULL
       || node == global_namespace)
@@ -1033,6 +1163,7 @@ write_prefix (const tree node)
   if (find_substitution (node))
     return;
 
+  tree template_info = NULL_TREE;
   if (DECL_P (node))
     {
       /* If this is a function or parm decl, that means we've hit function
@@ -1045,19 +1176,20 @@ write_prefix (const tree node)
        return;
 
       decl = node;
-      decl_is_template_id (decl, &template_info);
+      template_info = maybe_template_info (decl);
     }
   else
     {
       /* Node is a type.  */
       decl = TYPE_NAME (node);
+      /* The DECL might not point at the node.  */
       if (CLASSTYPE_TEMPLATE_ID_P (node))
        template_info = TYPE_TEMPLATE_INFO (node);
     }
 
   if (TREE_CODE (node) == TEMPLATE_TYPE_PARM)
     write_template_param (node);
-  else if (template_info != NULL)
+  else if (template_info)
     /* Templated.  */
     {
       write_template_prefix (decl);
@@ -1104,15 +1236,14 @@ write_template_prefix (const tree node)
   tree decl = DECL_P (node) ? node : TYPE_NAME (node);
   tree type = DECL_P (node) ? TREE_TYPE (node) : node;
   tree context = decl_mangling_context (decl);
-  tree template_info;
   tree templ;
   tree substitution;
 
   MANGLE_TRACE_TREE ("template-prefix", node);
 
   /* Find the template decl.  */
-  if (decl_is_template_id (decl, &template_info))
-    templ = TI_TEMPLATE (template_info);
+  if (tree info = maybe_template_info (decl))
+    templ = TI_TEMPLATE (info);
   else if (TREE_CODE (type) == TYPENAME_TYPE)
     /* For a typename type, all we have is the name.  */
     templ = DECL_NAME (decl);
@@ -1165,6 +1296,51 @@ write_template_prefix (const tree node)
   add_substitution (substitution);
 }
 
+/* As the list of identifiers for the structured binding declaration
+   DECL is likely gone, try to recover the DC <source-name>+ E portion
+   from its mangled name.  Return pointer to the DC and set len to
+   the length up to and including the terminating E.  On failure
+   return NULL.  */
+
+static const char *
+find_decomp_unqualified_name (tree decl, size_t *len)
+{
+  const char *p = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
+  const char *end = p + IDENTIFIER_LENGTH (DECL_ASSEMBLER_NAME (decl));
+  bool nested = false;
+  if (strncmp (p, "_Z", 2))
+    return NULL;
+  p += 2;
+  if (!strncmp (p, "St", 2))
+    p += 2;
+  else if (*p == 'N')
+    {
+      nested = true;
+      ++p;
+      while (ISDIGIT (p[0]))
+       {
+         char *e;
+         long num = strtol (p, &e, 10);
+         if (num >= 1 && num < end - e)
+           p = e + num;
+         else
+           break;
+       }
+    }
+  if (strncmp (p, "DC", 2))
+    return NULL;
+  if (nested)
+    {
+      if (end[-1] != 'E')
+       return NULL;
+      --end;
+    }
+  if (end[-1] != 'E')
+    return NULL;
+  *len = end - p;
+  return p;
+}
+
 /* We don't need to handle thunks, vtables, or VTTs here.  Those are
    mangled through special entry points.
 
@@ -1179,37 +1355,12 @@ write_template_prefix (const tree node)
 static void
 write_unqualified_id (tree identifier)
 {
-  if (IDENTIFIER_TYPENAME_P (identifier))
+  if (IDENTIFIER_CONV_OP_P (identifier))
     write_conversion_operator_name (TREE_TYPE (identifier));
-  else if (IDENTIFIER_OPNAME_P (identifier))
+  else if (IDENTIFIER_OVL_OP_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);
+      const ovl_op_info_t *ovl_op = IDENTIFIER_OVL_OP_INFO (identifier);
+      write_string (ovl_op->mangled_name);
     }
   else if (UDLIT_OPER_P (identifier))
     write_literal_operator_name (identifier);
@@ -1234,7 +1385,17 @@ write_unqualified_name (tree decl)
     {
       found = true;
       gcc_assert (DECL_ASSEMBLER_NAME_SET_P (decl));
-      write_source_name (DECL_ASSEMBLER_NAME (decl));
+      const char *decomp_str = NULL;
+      size_t decomp_len = 0;
+      if (VAR_P (decl)
+         && DECL_DECOMPOSITION_P (decl)
+         && DECL_NAME (decl) == NULL_TREE
+         && DECL_NAMESPACE_SCOPE_P (decl))
+       decomp_str = find_decomp_unqualified_name (decl, &decomp_len);
+      if (decomp_str)
+       write_chars (decomp_str, decomp_len);
+      else
+       write_source_name (DECL_ASSEMBLER_NAME (decl));
     }
   else if (DECL_DECLARES_FUNCTION_P (decl))
     {
@@ -1248,28 +1409,24 @@ write_unqualified_name (tree decl)
          /* Conversion operator. Handle it right here.
             <operator> ::= cv <type>  */
          tree type;
-         if (decl_is_template_id (decl, NULL))
+         if (maybe_template_info (decl))
            {
              tree fn_type;
              fn_type = get_mostly_instantiated_function_type (decl);
              type = TREE_TYPE (fn_type);
            }
          else if (FNDECL_USED_AUTO (decl))
-           type = (DECL_STRUCT_FUNCTION (decl)->language
-                   ->x_auto_return_pattern);
+           type = DECL_SAVED_AUTO_RETURN_TYPE (decl);
          else
            type = DECL_CONV_FN_TYPE (decl);
          write_conversion_operator_name (type);
        }
       else if (DECL_OVERLOADED_OPERATOR_P (decl))
        {
-         operator_name_info_t *oni;
-         if (DECL_ASSIGNMENT_OPERATOR_P (decl))
-           oni = assignment_operator_name_info;
-         else
-           oni = operator_name_info;
-
-         write_string (oni[DECL_OVERLOADED_OPERATOR_P (decl)].mangled_name);
+         const char *mangled_name
+           = (ovl_op_info[DECL_ASSIGNMENT_OPERATOR_P (decl)]
+              [DECL_OVERLOADED_OPERATOR_CODE_RAW (decl)].mangled_name);
+         write_string (mangled_name);
        }
       else if (UDLIT_OPER_P (DECL_NAME (decl)))
        write_literal_operator_name (DECL_NAME (decl));
@@ -1294,30 +1451,69 @@ write_unqualified_name (tree decl)
       tree type = TREE_TYPE (decl);
 
       if (TREE_CODE (decl) == TYPE_DECL
-          && TYPE_ANONYMOUS_P (type))
+          && TYPE_UNNAMED_P (type))
         write_unnamed_type_name (type);
-      else if (TREE_CODE (decl) == TYPE_DECL
-               && LAMBDA_TYPE_P (type))
+      else if (TREE_CODE (decl) == TYPE_DECL && LAMBDA_TYPE_P (type))
         write_closure_type_name (type);
       else
         write_source_name (DECL_NAME (decl));
     }
 
-  /* We use the ABI tags from the primary template, ignoring tags on any
+  /* We use the ABI tags from the primary class template, ignoring tags on any
      specializations.  This is necessary because C++ doesn't require a
-     specialization to be declared before it is used unless the use
-     requires a complete type, but we need to get the tags right on
-     incomplete types as well.  */
+     specialization to be declared before it is used unless the use requires a
+     complete type, but we need to get the tags right on incomplete types as
+     well.  */
   if (tree tmpl = most_general_template (decl))
-    decl = DECL_TEMPLATE_RESULT (tmpl);
-  /* Don't crash on an unbound class template.  */
-  if (decl && TREE_CODE (decl) != NAMESPACE_DECL)
     {
-      tree attrs = (TREE_CODE (decl) == TYPE_DECL
-                   ? TYPE_ATTRIBUTES (TREE_TYPE (decl))
-                   : DECL_ATTRIBUTES (decl));
-      write_abi_tags (lookup_attribute ("abi_tag", attrs));
+      tree res = DECL_TEMPLATE_RESULT (tmpl);
+      if (res == NULL_TREE)
+       /* UNBOUND_CLASS_TEMPLATE.  */;
+      else if (DECL_DECLARES_TYPE_P (decl))
+       decl = res;
+      else if (any_abi_below (11))
+       {
+         /* ABI v10 implicit tags on the template.  */
+         tree mtags = missing_abi_tags (res);
+         /* Explicit tags on the template.  */
+         tree ttags = get_abi_tags (res);
+         /* Tags on the instantiation.  */
+         tree dtags = get_abi_tags (decl);
+
+         if (mtags && abi_warn_or_compat_version_crosses (10))
+           G.need_abi_warning = 1;
+
+         /* Add the v10 tags to the explicit tags now.  */
+         mtags = chainon (mtags, ttags);
+
+         if (!G.need_abi_warning
+             && abi_warn_or_compat_version_crosses (11)
+             && !equal_abi_tags (dtags, mtags))
+           G.need_abi_warning = 1;
+
+         if (!abi_version_at_least (10))
+           /* In abi <10, we only got the explicit tags.  */
+           decl = res;
+         else if (flag_abi_version == 10)
+           {
+             /* In ABI 10, we want explict and implicit tags.  */
+             write_abi_tags (mtags);
+             return;
+           }
+       }
     }
+
+  tree tags = get_abi_tags (decl);
+  if (TREE_CODE (decl) == FUNCTION_DECL && DECL_CONV_FN_P (decl)
+      && any_abi_below (11))
+    if (tree mtags = missing_abi_tags (decl))
+      {
+       if (abi_warn_or_compat_version_crosses (11))
+         G.need_abi_warning = true;
+       if (!abi_version_at_least (11))
+         tags = chainon (mtags, tags);
+      }
+  write_abi_tags (tags);
 }
 
 /* Write the unqualified-name for a conversion operator to TYPE.  */
@@ -1338,11 +1534,6 @@ write_source_name (tree identifier)
 {
   MANGLE_TRACE_TREE ("source-name", identifier);
 
-  /* Never write the whole template-id name including the template
-     arguments; we only want the template name.  */
-  if (IDENTIFIER_TEMPLATE (identifier))
-    identifier = IDENTIFIER_TEMPLATE (identifier);
-
   write_unsigned_number (IDENTIFIER_LENGTH (identifier));
   write_identifier (IDENTIFIER_POINTER (identifier));
 }
@@ -1360,17 +1551,11 @@ tree_string_cmp (const void *p1, const void *p2)
                 TREE_STRING_POINTER (s2));
 }
 
-/* ID is the name of a function or type with abi_tags attribute TAGS.
-   Write out the name, suitably decorated.  */
+/* Return the TREE_LIST of TAGS as a sorted VEC.  */
 
-static void
-write_abi_tags (tree tags)
+static vec<tree, va_gc> *
+sorted_abi_tags (tree tags)
 {
-  if (tags == NULL_TREE)
-    return;
-
-  tags = TREE_VALUE (tags);
-
   vec<tree, va_gc> * vec = make_tree_vector();
 
   for (tree t = tags; t; t = TREE_CHAIN (t))
@@ -1383,6 +1568,20 @@ write_abi_tags (tree tags)
 
   vec->qsort (tree_string_cmp);
 
+  return vec;
+}
+
+/* ID is the name of a function or type with abi_tags attribute TAGS.
+   Write out the name, suitably decorated.  */
+
+static void
+write_abi_tags (tree tags)
+{
+  if (tags == NULL_TREE)
+    return;
+
+  vec<tree, va_gc> * vec = sorted_abi_tags (tags);
+
   unsigned i; tree str;
   FOR_EACH_VEC_ELT (*vec, i, str)
     {
@@ -1394,6 +1593,23 @@ write_abi_tags (tree tags)
   release_tree_vector (vec);
 }
 
+/* True iff the TREE_LISTS T1 and T2 of ABI tags are equivalent.  */
+
+static bool
+equal_abi_tags (tree t1, tree t2)
+{
+  releasing_vec v1 = sorted_abi_tags (t1);
+  releasing_vec v2 = sorted_abi_tags (t2);
+
+  unsigned len1 = v1->length();
+  if (len1 != v2->length())
+    return false;
+  for (unsigned i = 0; i < len1; ++i)
+    if (tree_string_cmp (v1[i], v2[i]) != 0)
+      return false;
+  return true;
+}
+
 /* Write a user-defined literal operator.
           ::= li <source-name>    # "" <source-name>
    IDENTIFIER is an LITERAL_IDENTIFIER_NODE.  */
@@ -1430,10 +1646,13 @@ nested_anon_class_index (tree type)
        tree memtype = TREE_TYPE (member);
        if (memtype == type)
          return index;
-       else if (TYPE_ANONYMOUS_P (memtype))
+       else if (TYPE_UNNAMED_P (memtype))
          ++index;
       }
 
+  if (seen_error ())
+    return -1;
+
   gcc_unreachable ();
 }
 
@@ -1446,7 +1665,7 @@ write_unnamed_type_name (const tree type)
   MANGLE_TRACE_TREE ("unnamed-type-name", type);
 
   if (TYPE_FUNCTION_SCOPE_P (type))
-    discriminator = local_class_index (type);
+    discriminator = discriminator_for_local_entity (TYPE_NAME (type));
   else if (TYPE_CLASS_SCOPE_P (type))
     discriminator = nested_anon_class_index (type);
   else
@@ -1563,7 +1782,7 @@ write_integer_cst (const tree cst)
 
       type = c_common_signed_or_unsigned_type (1, TREE_TYPE (cst));
       base = build_int_cstu (type, chunk);
-      n = wide_int_to_tree (type, cst);
+      n = wide_int_to_tree (type, wi::to_wide (cst));
 
       if (sign < 0)
        {
@@ -1620,11 +1839,13 @@ static void
 write_real_cst (const tree value)
 {
   long target_real[4];  /* largest supported float */
-  char buffer[9];       /* eight hex digits in a 32-bit number */
+  /* Buffer for eight hex digits in a 32-bit number but big enough
+     even for 64-bit long to avoid warnings.  */
+  char buffer[17];
   int i, limit, dir;
 
   tree type = TREE_TYPE (value);
-  int words = GET_MODE_BITSIZE (TYPE_MODE (type)) / 32;
+  int words = GET_MODE_BITSIZE (SCALAR_FLOAT_TYPE_MODE (type)) / 32;
 
   real_to_target (target_real, &TREE_REAL_CST (value),
                  TYPE_MODE (type));
@@ -1668,18 +1889,25 @@ write_identifier (const char *identifier)
 static void
 write_special_name_constructor (const tree ctor)
 {
+  write_char ('C');
+  bool new_inh = (flag_new_inheriting_ctors
+                 && DECL_INHERITED_CTOR (ctor));
+  if (new_inh)
+    write_char ('I');
   if (DECL_BASE_CONSTRUCTOR_P (ctor))
-    write_string ("C2");
+    write_char ('2');
   /* This is the old-style "[unified]" constructor.
      In some cases, we may emit this function and call
      it from the clones in order to share code and save space.  */
   else if (DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (ctor))
-    write_string ("C4");
+    write_char ('4');
   else
     {
       gcc_assert (DECL_COMPLETE_CONSTRUCTOR_P (ctor));
-      write_string ("C1");
+      write_char ('1');
     }
+  if (new_inh)
+    write_type (DECL_INHERITED_CTOR_BASE (ctor));
 }
 
 /* Handle destructor productions of non-terminal <special-name>.
@@ -1708,58 +1936,25 @@ 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 = (*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.  */
+   FUNCTION.  The discriminator is the lexical ordinal of VAR or TYPE among
+   entities with the same name and kind in the same FUNCTION.  */
 
 static int
 discriminator_for_local_entity (tree 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)
+  if (!DECL_LANG_SPECIFIC (entity))
     {
-      /* Scan the list of local classes.  */
-      entity = TREE_TYPE (entity);
-
-      /* Lambdas and unnamed types have their own discriminators.  */
-      if (LAMBDA_TYPE_P (entity) || TYPE_ANONYMOUS_P (entity))
-       return 0;
-
-      return local_class_index (entity);
+      /* Some decls, like __FUNCTION__, don't need a discriminator.  */
+      gcc_checking_assert (DECL_ARTIFICIAL (entity));
+      return 0;
     }
+  else if (tree disc = DECL_DISCRIMINATOR (entity))
+    return TREE_INT_CST_LOW (disc);
   else
-    gcc_unreachable ();
+    /* The first entity with a particular name doesn't get
+       DECL_DISCRIMINATOR set up.  */
+    return 0;
 }
 
 /* Return the discriminator for STRING, a string literal used inside
@@ -1774,7 +1969,8 @@ discriminator_for_string_literal (tree /*function*/,
   return 0;
 }
 
-/*   <discriminator> := _ <number>
+/*   <discriminator> := _ <number>    # when number < 10
+                     := __ <number> _ # when number >= 10
 
    The discriminator is used only for the second and later occurrences
    of the same name within a single function. In this case <number> is
@@ -1787,7 +1983,16 @@ write_discriminator (const int discriminator)
   if (discriminator > 0)
     {
       write_char ('_');
+      if (discriminator - 1 >= 10)
+       {
+         if (abi_warn_or_compat_version_crosses (11))
+           G.need_abi_warning = 1;
+         if (abi_version_at_least (11))
+           write_char ('_');
+       }
       write_unsigned_number (discriminator - 1);
+      if (abi_version_at_least (11) && discriminator - 1 >= 10)
+       write_char ('_');
     }
 }
 
@@ -1847,7 +2052,10 @@ write_local_name (tree function, const tree local_entity,
         from <local-name>, so it doesn't try to process the enclosing
         function scope again.  */
       write_name (entity, /*ignore_local_scope=*/1);
-      write_discriminator (discriminator_for_local_entity (local_entity));
+      if (DECL_DISCRIMINATOR_P (local_entity)
+         && !(TREE_CODE (local_entity) == TYPE_DECL
+              && TYPE_ANON_P (TREE_TYPE (local_entity))))
+       write_discriminator (discriminator_for_local_entity (local_entity));
     }
 }
 
@@ -1910,10 +2118,14 @@ write_type (tree type)
          t = cp_build_type_attribute_variant (t, attrs);
        }
       gcc_assert (t != type);
-      if (TREE_CODE (t) == FUNCTION_TYPE
-         || TREE_CODE (t) == METHOD_TYPE)
+      if (FUNC_OR_METHOD_TYPE_P (t))
        {
          t = build_ref_qualified_type (t, type_memfn_rqual (type));
+         if (flag_noexcept_type)
+           {
+             tree r = TYPE_RAISES_EXCEPTIONS (type);
+             t = build_exception_variant (t, r);
+           }
          if (abi_version_at_least (8)
              || type == TYPE_MAIN_VARIANT (type))
            /* Avoid adding the unqualified function type as a substitution.  */
@@ -1937,9 +2149,8 @@ write_type (tree type)
 
       /* See through any typedefs.  */
       type = TYPE_MAIN_VARIANT (type);
-      if (TREE_CODE (type) == FUNCTION_TYPE
-         || TREE_CODE (type) == METHOD_TYPE)
-       type = build_ref_qualified_type (type, type_memfn_rqual (type_orig));
+      if (FUNC_OR_METHOD_TYPE_P (type))
+       type = cxx_copy_lang_qualifiers (type, type_orig);
 
       /* According to the C++ ABI, some library classes are passed the
         same as the scalar type of their single member and use the same
@@ -2049,7 +2260,7 @@ write_type (tree type)
                  ++is_builtin_type;
                  break;
                }
-             /* else fall through.  */
+             /* fall through.  */
            case TEMPLATE_PARM_INDEX:
              write_template_param (type);
              break;
@@ -2070,7 +2281,8 @@ write_type (tree type)
                  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_unsigned_number (TYPE_VECTOR_SUBPARTS (type)
+                                        .to_constant ());
                  write_char ('_');
                }
              else
@@ -2142,11 +2354,11 @@ write_type (tree type)
              break;
 
            case TYPEOF_TYPE:
-             sorry ("mangling typeof, use decltype instead");
+             sorry ("mangling %<typeof%>, use %<decltype%> instead");
              break;
 
            case UNDERLYING_TYPE:
-             sorry ("mangling __underlying_type");
+             sorry ("mangling %<__underlying_type%>");
              break;
 
            case LANG_TYPE:
@@ -2177,6 +2389,34 @@ attr_strcmp (const void *p1, const void *p2)
   return strcmp (as1->name, as2->name);
 }
 
+/* Return true if we should mangle a type attribute with name NAME.  */
+
+static bool
+mangle_type_attribute_p (tree name)
+{
+  const attribute_spec *as = lookup_attribute_spec (name);
+  if (!as || !as->affects_type_identity)
+    return false;
+
+  /* Skip internal-only attributes, which are distinguished from others
+     by having a space.  At present, all internal-only attributes that
+     affect type identity are target-specific and are handled by
+     targetm.mangle_type instead.
+
+     Another reason to do this is that a space isn't a valid identifier
+     character for most file formats.  */
+  if (strchr (IDENTIFIER_POINTER (name), ' '))
+    return false;
+
+  /* The following attributes are mangled specially.  */
+  if (is_attribute_p ("transaction_safe", name))
+    return false;
+  if (is_attribute_p ("abi_tag", name))
+    return false;
+
+  return true;
+}
+
 /* Non-terminal <CV-qualifiers> for type nodes.  Returns the number of
    CV-qualifiers written for TYPE.
 
@@ -2202,14 +2442,8 @@ write_CV_qualifiers_for_type (const tree type)
     {
       auto_vec<tree> vec;
       for (tree a = TYPE_ATTRIBUTES (type); a; a = TREE_CHAIN (a))
-       {
-         tree name = get_attribute_name (a);
-         const attribute_spec *as = lookup_attribute_spec (name);
-         if (as && as->affects_type_identity
-             && !is_attribute_p ("transaction_safe", name)
-             && !is_attribute_p ("abi_tag", name))
-           vec.safe_push (a);
-       }
+       if (mangle_type_attribute_p (get_attribute_name (a)))
+         vec.safe_push (a);
       if (abi_warn_or_compat_version_crosses (10) && !vec.is_empty ())
        G.need_abi_warning = true;
       if (abi_version_at_least (10))
@@ -2306,16 +2540,16 @@ write_builtin_type (tree type)
       break;
 
     case INTEGER_TYPE:
-      /* TYPE may still be wchar_t, char16_t, or char32_t, since that
+      /* TYPE may still be wchar_t, char8_t, char16_t, or char32_t, since that
         isn't in integer_type_nodes.  */
       if (type == wchar_type_node)
        write_char ('w');
+      else if (type == char8_type_node)
+       write_string ("Du");
       else if (type == char16_type_node)
        write_string ("Ds");
       else if (type == char32_type_node)
        write_string ("Di");
-      else if (TYPE_FOR_JAVA (type))
-       write_java_integer_type_codes (type);
       else
        {
          size_t itk;
@@ -2370,19 +2604,17 @@ write_builtin_type (tree type)
       break;
 
     case REAL_TYPE:
-      if (type == float_type_node
-         || type == java_float_type_node)
+      if (type == float_type_node)
        write_char ('f');
-      else if (type == double_type_node
-              || type == java_double_type_node)
+      else if (type == double_type_node)
        write_char ('d');
       else if (type == long_double_type_node)
        write_char ('e');
-      else if (type == dfloat32_type_node)
+      else if (type == dfloat32_type_node || type == fallback_dfloat32_type)
        write_string ("Df");
-      else if (type == dfloat64_type_node)
+      else if (type == dfloat64_type_node || type == fallback_dfloat64_type)
        write_string ("Dd");
-      else if (type == dfloat128_type_node)
+      else if (type == dfloat128_type_node || type == fallback_dfloat128_type)
        write_string ("De");
       else
        gcc_unreachable ();
@@ -2468,6 +2700,8 @@ write_function_type (const tree type)
       write_CV_qualifiers_for_type (this_type);
     }
 
+  write_exception_spec (TYPE_RAISES_EXCEPTIONS (type));
+
   if (tx_safe_fn_type_p (type))
     write_string ("Dx");
 
@@ -2499,40 +2733,16 @@ write_function_type (const tree type)
 /* Non-terminal <bare-function-type>.  TYPE is a FUNCTION_TYPE or
    METHOD_TYPE.  If INCLUDE_RETURN_TYPE is nonzero, the return value
    is mangled before the parameter types.  If non-NULL, DECL is
-   FUNCTION_DECL for the function whose type is being emitted.
-
-   If DECL is a member of a Java type, then a literal 'J'
-   is output and the return type is mangled as if INCLUDE_RETURN_TYPE
-   were nonzero.
-
-     <bare-function-type> ::= [J]</signature/ type>+  */
+   FUNCTION_DECL for the function whose type is being emitted.  */
 
 static void
 write_bare_function_type (const tree type, const int include_return_type_p,
                          const tree decl)
 {
-  int java_method_p;
-
   MANGLE_TRACE_TREE ("bare-function-type", type);
 
-  /* Detect Java methods and emit special encoding.  */
-  if (decl != NULL
-      && DECL_FUNCTION_MEMBER_P (decl)
-      && TYPE_FOR_JAVA (DECL_CONTEXT (decl))
-      && !DECL_CONSTRUCTOR_P (decl)
-      && !DECL_DESTRUCTOR_P (decl)
-      && !DECL_CONV_FN_P (decl))
-    {
-      java_method_p = 1;
-      write_char ('J');
-    }
-  else
-    {
-      java_method_p = 0;
-    }
-
   /* Mangle the return type, if requested.  */
-  if (include_return_type_p || java_method_p)
+  if (include_return_type_p)
     write_type (TREE_TYPE (type));
 
   /* Now mangle the types of the arguments.  */
@@ -2576,6 +2786,10 @@ write_method_parms (tree parm_types, const int method_p, const tree decl)
          parm_types = TREE_CHAIN (parm_types);
          parm_decl = DECL_CHAIN (parm_decl);
        }
+
+      if (decl && ctor_omit_inherited_parms (decl))
+       /* Bring back parameters omitted from an inherited ctor.  */
+       parm_types = FUNCTION_FIRST_USER_PARMTYPE (DECL_ORIGIN (decl));
     }
 
   for (first_parm_type = parm_types;
@@ -2653,14 +2867,24 @@ static void
 write_member_name (tree member)
 {
   if (identifier_p (member))
-    write_unqualified_id (member);
+    {
+      if (abi_version_at_least (11) && IDENTIFIER_ANY_OP_P (member))
+       {
+         write_string ("on");
+         if (abi_warn_or_compat_version_crosses (11))
+           G.need_abi_warning = 1;
+       }
+      write_unqualified_id (member);
+    }
   else if (DECL_P (member))
-    write_unqualified_name (member);
+    {
+      gcc_assert (!DECL_OVERLOADED_OPERATOR_P (member));
+      write_unqualified_name (member);
+    }
   else if (TREE_CODE (member) == TEMPLATE_ID_EXPR)
     {
       tree name = TREE_OPERAND (member, 0);
-      if (TREE_CODE (name) == OVERLOAD)
-       name = OVL_FUNCTION (name);
+      name = OVL_FIRST (name);
       write_member_name (name);
       write_template_args (TREE_OPERAND (member, 1));
     }
@@ -2668,6 +2892,60 @@ write_member_name (tree member)
     write_expression (member);
 }
 
+/* EXPR is a base COMPONENT_REF; write the minimized base conversion path for
+   converting to BASE, or just the conversion of EXPR if BASE is null.
+
+   "Given a fully explicit base path P := C_n -> ... -> C_0, the minimized base
+   path Min(P) is defined as follows: let C_i be the last element for which the
+   conversion to C_0 is unambiguous; if that element is C_n, the minimized path
+   is C_n -> C_0; otherwise, the minimized path is Min(C_n -> ... -> C_i) ->
+   C_0."
+
+   We mangle the conversion to C_i if it's different from C_n.  */
+
+static bool
+write_base_ref (tree expr, tree base = NULL_TREE)
+{
+  if (TREE_CODE (expr) != COMPONENT_REF)
+    return false;
+
+  tree field = TREE_OPERAND (expr, 1);
+
+  if (TREE_CODE (field) != FIELD_DECL || !DECL_FIELD_IS_BASE (field))
+    return false;
+
+  tree object = TREE_OPERAND (expr, 0);
+
+  tree binfo = NULL_TREE;
+  if (base)
+    {
+      tree cur = TREE_TYPE (object);
+      binfo = lookup_base (cur, base, ba_unique, NULL, tf_none);
+    }
+  else
+    /* We're at the end of the base conversion chain, so it can't be
+       ambiguous.  */
+    base = TREE_TYPE (field);
+
+  if (binfo == error_mark_node)
+    {
+      /* cur->base is ambiguous, so make the conversion to
+        last explicit, expressed as a cast (last&)object.  */
+      tree last = TREE_TYPE (expr);
+      write_string (OVL_OP_INFO (false, CAST_EXPR)->mangled_name);
+      write_type (build_reference_type (last));
+      write_expression (object);
+    }
+  else if (write_base_ref (object, base))
+    /* cur->base is unambiguous, but we had another base conversion
+       underneath and wrote it out.  */;
+  else
+    /* No more base conversions, just write out the object.  */
+    write_expression (object);
+
+  return true;
+}
+
 /* <expression> ::= <unary operator-name> <expression>
                ::= <binary operator-name> <expression> <expression>
                ::= <expr-primary>
@@ -2684,13 +2962,22 @@ write_expression (tree expr)
 {
   enum tree_code code = TREE_CODE (expr);
 
-  /* Skip NOP_EXPRs.  They can occur when (say) a pointer argument
-     is converted (via qualification conversions) to another
-     type.  */
-  while (TREE_CODE (expr) == NOP_EXPR
+  if (TREE_CODE (expr) == TARGET_EXPR)
+    {
+      expr = TARGET_EXPR_INITIAL (expr);
+      code = TREE_CODE (expr);
+    }
+
+  /* Skip NOP_EXPR and CONVERT_EXPR.  They can occur when (say) a pointer
+     argument is converted (via qualification conversions) to another type.  */
+  while (CONVERT_EXPR_CODE_P (code)
+        || code == IMPLICIT_CONV_EXPR
+        || location_wrapper_p (expr)
         /* Parentheses aren't mangled.  */
         || code == PAREN_EXPR
-        || TREE_CODE (expr) == NON_LVALUE_EXPR)
+        || code == NON_LVALUE_EXPR
+        || (code == VIEW_CONVERT_EXPR
+            && TREE_CODE (TREE_OPERAND (expr, 0)) == TEMPLATE_PARM_INDEX))
     {
       expr = TREE_OPERAND (expr, 0);
       code = TREE_CODE (expr);
@@ -2728,7 +3015,7 @@ write_expression (tree expr)
     write_template_arg_literal (expr);
   else if (code == PARM_DECL && DECL_ARTIFICIAL (expr))
     {
-      gcc_assert (!strcmp ("this", IDENTIFIER_POINTER (DECL_NAME (expr))));
+      gcc_assert (id_equal (DECL_NAME (expr), "this"));
       write_string ("fpT");
     }
   else if (code == PARM_DECL)
@@ -2765,23 +3052,92 @@ write_expression (tree expr)
       write_mangled_name (expr, false);
       write_char ('E');
     }
-  else if (TREE_CODE (expr) == SIZEOF_EXPR
-          && SIZEOF_EXPR_TYPE_P (expr))
-    {
-      write_string ("st");
-      write_type (TREE_TYPE (TREE_OPERAND (expr, 0)));
-    }
-  else if (TREE_CODE (expr) == SIZEOF_EXPR
-          && TYPE_P (TREE_OPERAND (expr, 0)))
+  else if (TREE_CODE (expr) == SIZEOF_EXPR)
     {
-      write_string ("st");
-      write_type (TREE_OPERAND (expr, 0));
+      tree op = TREE_OPERAND (expr, 0);
+
+      if (PACK_EXPANSION_P (op))
+       {
+         if (abi_warn_or_compat_version_crosses (11))
+           G.need_abi_warning = true;
+         if (abi_version_at_least (11))
+           {
+             /* sZ rather than szDp.  */
+             write_string ("sZ");
+             write_expression (PACK_EXPANSION_PATTERN (op));
+             return;
+           }
+       }
+
+      if (SIZEOF_EXPR_TYPE_P (expr))
+       {
+         write_string ("st");
+         write_type (TREE_TYPE (op));
+       }
+      else if (ARGUMENT_PACK_P (op))
+       {
+         tree args = ARGUMENT_PACK_ARGS (op);
+         int length = TREE_VEC_LENGTH (args);
+         if (abi_warn_or_compat_version_crosses (10))
+           G.need_abi_warning = true;
+         if (abi_version_at_least (10))
+           {
+             /* sP <template-arg>* E # sizeof...(T), size of a captured
+                template parameter pack from an alias template */
+             write_string ("sP");
+             for (int i = 0; i < length; ++i)
+               write_template_arg (TREE_VEC_ELT (args, i));
+             write_char ('E');
+           }
+         else
+           {
+             /* In GCC 5 we represented this sizeof wrong, with the effect
+                that we mangled it as the last element of the pack.  */
+             tree arg = TREE_VEC_ELT (args, length-1);
+             if (TYPE_P (op))
+               {
+                 write_string ("st");
+                 write_type (arg);
+               }
+             else
+               {
+                 write_string ("sz");
+                 write_expression (arg);
+               }
+           }
+       }
+      else if (TYPE_P (TREE_OPERAND (expr, 0)))
+       {
+         write_string ("st");
+         write_type (TREE_OPERAND (expr, 0));
+       }
+      else
+       goto normal_expr;
     }
-  else if (TREE_CODE (expr) == ALIGNOF_EXPR
-          && TYPE_P (TREE_OPERAND (expr, 0)))
+  else if (TREE_CODE (expr) == ALIGNOF_EXPR)
     {
-      write_string ("at");
-      write_type (TREE_OPERAND (expr, 0));
+      if (!ALIGNOF_EXPR_STD_P (expr))
+       {
+         if (abi_warn_or_compat_version_crosses (15))
+           G.need_abi_warning = true;
+         if (abi_version_at_least (15))
+           {
+             /* We used to mangle __alignof__ like alignof.  */
+             write_string ("v111__alignof__");
+             if (TYPE_P (TREE_OPERAND (expr, 0)))
+               write_type (TREE_OPERAND (expr, 0));
+             else
+               write_expression (TREE_OPERAND (expr, 0));
+             return;
+           }
+       }
+      if (TYPE_P (TREE_OPERAND (expr, 0)))
+       {
+         write_string ("at");
+         write_type (TREE_OPERAND (expr, 0));
+       }
+      else
+       goto normal_expr;
     }
   else if (code == SCOPE_REF
           || code == BASELINK)
@@ -2791,6 +3147,8 @@ write_expression (tree expr)
        {
          scope = TREE_OPERAND (expr, 0);
          member = TREE_OPERAND (expr, 1);
+         if (BASELINK_P (member))
+           member = BASELINK_FUNCTIONS (member);
        }
       else
        {
@@ -2807,6 +3165,7 @@ write_expression (tree expr)
        write_expression (member);
       else
        {
+         gcc_assert (code != BASELINK || BASELINK_QUALIFIED_P (expr));
          write_string ("sr");
          write_type (scope);
          write_member_name (member);
@@ -2814,7 +3173,7 @@ write_expression (tree expr)
     }
   else if (INDIRECT_REF_P (expr)
           && TREE_TYPE (TREE_OPERAND (expr, 0))
-          && TREE_CODE (TREE_TYPE (TREE_OPERAND (expr, 0))) == REFERENCE_TYPE)
+          && TYPE_REF_P (TREE_TYPE (TREE_OPERAND (expr, 0))))
     {
       write_expression (TREE_OPERAND (expr, 0));
     }
@@ -2823,18 +3182,15 @@ write_expression (tree expr)
       /* 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))
+      if (IDENTIFIER_ANY_OP_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 = get_first_fn (fn);
-      if (DECL_P (fn))
-       fn = DECL_NAME (fn);
-      if (IDENTIFIER_OPNAME_P (fn))
+      fn = OVL_NAME (fn);
+      if (IDENTIFIER_ANY_OP_P (fn))
        write_string ("on");
       write_unqualified_id (fn);
       write_template_args (TREE_OPERAND (expr, 1));
@@ -2842,8 +3198,8 @@ write_expression (tree expr)
   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);
+      const char *name = OVL_OP_INFO (true, subop)->mangled_name;
+
       write_string (name);
       write_expression (TREE_OPERAND (expr, 0));
       write_expression (TREE_OPERAND (expr, 2));
@@ -2868,7 +3224,7 @@ write_expression (tree expr)
       if (NEW_EXPR_USE_GLOBAL (expr))
        write_string ("gs");
 
-      write_string (operator_name_info[(int) code].mangled_name);
+      write_string (OVL_OP_INFO (false, code)->mangled_name);
 
       for (t = placement; t; t = TREE_CHAIN (t))
        write_expression (TREE_VALUE (t));
@@ -2908,7 +3264,7 @@ write_expression (tree expr)
       if (DELETE_EXPR_USE_GLOBAL (expr))
        write_string ("gs");
 
-      write_string (operator_name_info[(int) code].mangled_name);
+      write_string (OVL_OP_INFO (false, code)->mangled_name);
 
       write_expression (TREE_OPERAND (expr, 0));
     }
@@ -2925,26 +3281,80 @@ write_expression (tree expr)
     }
   else if (code == CONSTRUCTOR)
     {
-      vec<constructor_elt, va_gc> *elts = CONSTRUCTOR_ELTS (expr);
-      unsigned i; tree val;
+      bool braced_init = BRACE_ENCLOSED_INITIALIZER_P (expr);
+      tree etype = TREE_TYPE (expr);
 
-      if (BRACE_ENCLOSED_INITIALIZER_P (expr))
+      if (braced_init)
        write_string ("il");
       else
        {
          write_string ("tl");
-         write_type (TREE_TYPE (expr));
+         write_type (etype);
+       }
+
+      bool nontriv = !trivial_type_p (etype);
+      if (nontriv || !zero_init_expr_p (expr))
+       {
+         /* Convert braced initializer lists to STRING_CSTs so that
+            A<"Foo"> mangles the same as A<{'F', 'o', 'o', 0}> while
+            still using the latter mangling for strings that
+            originated as braced initializer lists.  */
+         expr = braced_lists_to_strings (etype, expr);
+
+         if (TREE_CODE (expr) == CONSTRUCTOR)
+           {
+             vec<constructor_elt, va_gc> *elts = CONSTRUCTOR_ELTS (expr);
+             unsigned last_nonzero = UINT_MAX, i;
+             constructor_elt *ce;
+             tree val;
+
+             if (!nontriv)
+               FOR_EACH_CONSTRUCTOR_VALUE (elts, i, val)
+                 if (!zero_init_expr_p (val))
+                   last_nonzero = i;
+
+             if (nontriv || last_nonzero != UINT_MAX)
+               for (HOST_WIDE_INT i = 0; vec_safe_iterate (elts, i, &ce); ++i)
+                 {
+                   if (i > last_nonzero)
+                     break;
+                   /* FIXME handle RANGE_EXPR */
+                   if (TREE_CODE (etype) == UNION_TYPE)
+                     {
+                       /* Express the active member as a designator.  */
+                       write_string ("di");
+                       write_unqualified_name (ce->index);
+                     }
+                   write_expression (ce->value);
+                 }
+           }
+         else
+           {
+             gcc_assert (TREE_CODE (expr) == STRING_CST);
+             write_expression (expr);
+           }
        }
-      FOR_EACH_CONSTRUCTOR_VALUE (elts, i, val)
-       write_expression (val);
+      write_char ('E');
+    }
+  else if (code == LAMBDA_EXPR)
+    {
+      /* [temp.over.link] Two lambda-expressions are never considered
+        equivalent.
+
+        So just use the closure type mangling.  */
+      write_string ("tl");
+      write_type (LAMBDA_EXPR_CLOSURE (expr));
       write_char ('E');
     }
   else if (dependent_name (expr))
     {
-      write_unqualified_id (dependent_name (expr));
+      tree name = dependent_name (expr);
+      gcc_assert (!IDENTIFIER_ANY_OP_P (name));
+      write_unqualified_id (name);
     }
   else
     {
+    normal_expr:
       int i, len;
       const char *name;
 
@@ -2954,7 +3364,7 @@ write_expression (tree expr)
         don't actually want to output a mangling code for the `&'.  */
       if (TREE_CODE (expr) == ADDR_EXPR
          && TREE_TYPE (expr)
-         && TREE_CODE (TREE_TYPE (expr)) == REFERENCE_TYPE)
+         && TYPE_REF_P (TREE_TYPE (expr)))
        {
          expr = TREE_OPERAND (expr, 0);
          if (DECL_P (expr))
@@ -2972,10 +3382,12 @@ write_expression (tree expr)
 
          if (TREE_CODE (ob) == ARROW_EXPR)
            {
-             write_string (operator_name_info[(int)code].mangled_name);
+             write_string (OVL_OP_INFO (false, code)->mangled_name);
              ob = TREE_OPERAND (ob, 0);
              write_expression (ob);
            }
+         else if (write_base_ref (expr))
+           return;
          else if (!is_dummy_object (ob))
            {
              write_string ("dt");
@@ -2989,7 +3401,7 @@ write_expression (tree expr)
        }
 
       /* If it wasn't any of those, recursively expand the expression.  */
-      name = operator_name_info[(int) code].mangled_name;
+      name = OVL_OP_INFO (false, code)->mangled_name;
 
       /* We used to mangle const_cast and static_cast like a C cast.  */
       if (code == CONST_CAST_EXPR
@@ -2998,7 +3410,7 @@ write_expression (tree expr)
          if (abi_warn_or_compat_version_crosses (6))
            G.need_abi_warning = 1;
          if (!abi_version_at_least (6))
-           name = operator_name_info[CAST_EXPR].mangled_name;
+           name = OVL_OP_INFO (false, CAST_EXPR)->mangled_name;
        }
 
       if (name == NULL)
@@ -3030,10 +3442,9 @@ write_expression (tree expr)
 
            /* Mangle a dependent name as the name, not whatever happens to
               be the first function in the overload set.  */
-           if ((TREE_CODE (fn) == FUNCTION_DECL
-                || TREE_CODE (fn) == OVERLOAD)
+           if (OVL_P (fn)
                && type_dependent_expression_p_push (expr))
-             fn = DECL_NAME (get_first_fn (fn));
+             fn = OVL_NAME (fn);
 
            write_expression (fn);
          }
@@ -3092,6 +3503,29 @@ write_expression (tree expr)
                         "cannot be mangled");
                  continue;
                }
+             else if (FOLD_EXPR_P (expr))
+               {
+                 /* The first 'operand' of a fold-expression is the operator
+                    that it folds over.  */
+                 if (i == 0)
+                   {
+                     int fcode = TREE_INT_CST_LOW (operand);
+                     write_string (OVL_OP_INFO (false, fcode)->mangled_name);
+                     continue;
+                   }
+                 else if (code == BINARY_LEFT_FOLD_EXPR)
+                   {
+                     /* The order of operands of the binary left and right
+                        folds is the same, but we want to mangle them in
+                        lexical order, i.e. non-pack first.  */
+                     if (i == 1)
+                       operand = FOLD_EXPR_INIT (expr);
+                     else
+                       operand = FOLD_EXPR_PACK (expr);
+                   }
+                 if (PACK_EXPANSION_P (operand))
+                   operand = PACK_EXPANSION_PATTERN (operand);
+               }
              write_expression (operand);
            }
        }
@@ -3108,8 +3542,14 @@ write_expression (tree expr)
 static void
 write_template_arg_literal (const tree value)
 {
-  write_char ('L');
-  write_type (TREE_TYPE (value));
+  if (TREE_CODE (value) == STRING_CST)
+    /* Temporarily mangle strings as braced initializer lists.  */
+    write_string ("tl");
+  else
+    write_char ('L');
+
+  tree valtype = TREE_TYPE (value);
+  write_type (valtype);
 
   /* Write a null member pointer value as (type)0, regardless of its
      real representation.  */
@@ -3125,7 +3565,9 @@ write_template_arg_literal (const tree value)
       case INTEGER_CST:
        gcc_assert (!same_type_p (TREE_TYPE (value), boolean_type_node)
                    || integer_zerop (value) || integer_onep (value));
-       write_integer_cst (value);
+       if (!(abi_version_at_least (14)
+             && NULLPTR_TYPE_P (TREE_TYPE (value))))
+         write_integer_cst (value);
        break;
 
       case REAL_CST:
@@ -3152,8 +3594,31 @@ write_template_arg_literal (const tree value)
        break;
 
       case STRING_CST:
-       sorry ("string literal in function template signature");
-       break;
+       {
+         /* Mangle strings the same as braced initializer lists.  */
+         unsigned n = TREE_STRING_LENGTH (value);
+         const char *str = TREE_STRING_POINTER (value);
+
+         /* Count the number of trailing nuls and subtract them from
+            STRSIZE because they don't need to be mangled.  */
+         for (const char *p = str + n - 1; ; --p)
+           {
+             if (*p || p == str)
+               {
+                 n -= str + n - !!*p - p;
+                 break;
+               }
+           }
+         tree eltype = TREE_TYPE (valtype);
+         for (const char *p = str; n--; ++p)
+           {
+             write_char ('L');
+             write_type (eltype);
+             write_unsigned_number (*(const unsigned char*)p);
+             write_string ("E");
+           }
+         break;
+       }
 
       default:
        gcc_unreachable ();
@@ -3189,10 +3654,17 @@ write_template_arg (tree node)
        }
     }
 
+  if (template_parm_object_p (node))
+    /* We want to mangle the argument, not the var we stored it in.  */
+    node = tparm_object_argument (node);
+
+  /* Strip a conversion added by convert_nontype_argument.  */
+  if (TREE_CODE (node) == IMPLICIT_CONV_EXPR)
+    node = TREE_OPERAND (node, 0);
   if (REFERENCE_REF_P (node))
     node = TREE_OPERAND (node, 0);
   if (TREE_CODE (node) == NOP_EXPR
-      && TREE_CODE (TREE_TYPE (node)) == REFERENCE_TYPE)
+      && TYPE_REF_P (TREE_TYPE (node)))
     {
       /* Template parameters can be of reference type. To maintain
         internal consistency, such arguments use a conversion from
@@ -3280,8 +3752,10 @@ write_template_template_arg (const tree decl)
                  ::= A <expression> _ </element/ type>
 
      "Array types encode the dimension (number of elements) and the
-     element type. For variable length arrays, the dimension (but not
-     the '_' separator) is omitted."  */
+     element type.  For variable length arrays, the dimension (but not
+     the '_' separator) is omitted."
+     Note that for flexible array members, like for other arrays of
+     unspecified size, the dimension is also omitted.  */
 
 static void
 write_array_type (const tree type)
@@ -3290,29 +3764,31 @@ write_array_type (const tree type)
   if (TYPE_DOMAIN (type))
     {
       tree index_type;
-      tree max;
 
       index_type = TYPE_DOMAIN (type);
-      /* The INDEX_TYPE gives the upper and lower bounds of the
-        array.  */
-      max = TYPE_MAX_VALUE (index_type);
-      if (TREE_CODE (max) == INTEGER_CST)
-       {
-         /* The ABI specifies that we should mangle the number of
-            elements in the array, not the largest allowed index.  */
-         offset_int wmax = wi::to_offset (max) + 1;
-         /* Truncate the result - this will mangle [0, SIZE_INT_MAX]
-            number of elements as zero.  */
-         wmax = wi::zext (wmax, TYPE_PRECISION (TREE_TYPE (max)));
-         gcc_assert (wi::fits_uhwi_p (wmax));
-         write_unsigned_number (wmax.to_uhwi ());
-       }
-      else
+      /* The INDEX_TYPE gives the upper and lower bounds of the array.
+        It's null for flexible array members which have no upper bound
+        (this is a change from GCC 5 and prior where such members were
+        incorrectly mangled as zero-length arrays).  */
+      if (tree max = TYPE_MAX_VALUE (index_type))
        {
-         max = TREE_OPERAND (max, 0);
-         write_expression (max);
+         if (TREE_CODE (max) == INTEGER_CST)
+           {
+             /* The ABI specifies that we should mangle the number of
+                elements in the array, not the largest allowed index.  */
+             offset_int wmax = wi::to_offset (max) + 1;
+             /* Truncate the result - this will mangle [0, SIZE_INT_MAX]
+                number of elements as zero.  */
+             wmax = wi::zext (wmax, TYPE_PRECISION (TREE_TYPE (max)));
+             gcc_assert (wi::fits_uhwi_p (wmax));
+             write_unsigned_number (wmax.to_uhwi ());
+           }
+         else
+           {
+             max = TREE_OPERAND (max, 0);
+             write_expression (max);
+           }
        }
-
     }
   write_char ('_');
   write_type (TREE_TYPE (type));
@@ -3416,14 +3892,14 @@ start_mangling (const tree entity)
 {
   G.entity = entity;
   G.need_abi_warning = false;
+  G.need_cxx17_warning = false;
+  G.mod = false;
   obstack_free (&name_obstack, name_base);
   mangle_obstack = &name_obstack;
   name_base = obstack_alloc (&name_obstack, 0);
 }
 
-/* Done with mangling. If WARN is true, and the name of G.entity will
-   be mangled differently in a future version of the ABI, issue a
-   warning.  */
+/* Done with mangling.  Release the data.  */
 
 static void
 finish_mangling_internal (void)
@@ -3431,6 +3907,9 @@ finish_mangling_internal (void)
   /* Clear all the substitutions.  */
   vec_safe_truncate (G.substitutions, 0);
 
+  if (G.mod)
+    mangle_module_fini ();
+
   /* Null-terminate the string.  */
   write_char ('\0');
 }
@@ -3475,13 +3954,26 @@ init_mangle (void)
   subst_identifiers[SUBID_BASIC_IOSTREAM] = get_identifier ("basic_iostream");
 }
 
+/* Generate a mangling for MODULE's global initializer fn.  */
+
+tree
+mangle_module_global_init (int module)
+{
+  start_mangling (NULL_TREE);
+
+  write_string ("_ZGI");
+  write_module (module, true);
+  write_char ('v');
+
+  return finish_mangling_get_identifier ();
+}
+
 /* Generate the mangled name of DECL.  */
 
 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;
 
@@ -3491,7 +3983,7 @@ mangle_decl_string (const tree decl)
   if (DECL_LANG_SPECIFIC (decl) && DECL_USE_TEMPLATE (decl))
     {
       struct tinst_level *tl = current_instantiation ();
-      if ((!tl || tl->decl != decl)
+      if ((!tl || tl->maybe_get_node () != decl)
          && push_tinst_level (decl))
        {
          template_p = true;
@@ -3499,7 +3991,7 @@ mangle_decl_string (const tree decl)
          current_function_decl = NULL_TREE;
        }
     }
-  input_location = DECL_SOURCE_LOCATION (decl);
+  iloc_sentinel ils (DECL_SOURCE_LOCATION (decl));
 
   start_mangling (decl);
 
@@ -3518,7 +4010,6 @@ mangle_decl_string (const tree decl)
       pop_tinst_level ();
       current_function_decl = saved_fn;
     }
-  input_location = saved_loc;
 
   return result;
 }
@@ -3532,38 +4023,6 @@ get_mangled_id (tree decl)
   return targetm.mangle_decl_assembler_name (decl, id);
 }
 
-/* If DECL is an implicit mangling alias, return its symtab node; otherwise
-   return NULL.  */
-
-static symtab_node *
-decl_implicit_alias_p (tree decl)
-{
-  if (DECL_P (decl) && DECL_ARTIFICIAL (decl)
-      && DECL_IGNORED_P (decl)
-      && (TREE_CODE (decl) == FUNCTION_DECL
-         || (VAR_P (decl) && TREE_STATIC (decl))))
-    {
-      symtab_node *n = symtab_node::get (decl);
-      if (n && n->cpp_implicit_alias)
-       return n;
-    }
-  return NULL;
-}
-
-/* If DECL is a mangling alias, remove it from the symbol table and return
-   true; otherwise return false.  */
-
-bool
-maybe_remove_implicit_alias (tree decl)
-{
-  if (symtab_node *n = decl_implicit_alias_p (decl))
-    {
-      n->remove();
-      return true;
-    }
-  return false;
-}
-
 /* Create an identifier for the external mangled name of DECL.  */
 
 void
@@ -3595,60 +4054,56 @@ mangle_decl (const tree decl)
     {
       gcc_assert (TREE_CODE (decl) != TYPE_DECL
                  || !no_linkage_check (TREE_TYPE (decl), true));
+      if (abi_version_at_least (10))
+       if (tree fn = decl_function_context (decl))
+         maybe_check_abi_tags (fn, decl);
       id = get_mangled_id (decl);
     }
   SET_DECL_ASSEMBLER_NAME (decl, id);
 
+  if (G.need_cxx17_warning
+      && (TREE_PUBLIC (decl) || DECL_REALLY_EXTERN (decl)))
+    warning_at (DECL_SOURCE_LOCATION (decl), OPT_Wnoexcept_type,
+               "mangled name for %qD will change in C++17 because the "
+               "exception specification is part of a function type",
+               decl);
+
   if (id != DECL_NAME (decl)
-      && !DECL_REALLY_EXTERN (decl)
       /* Don't do this for a fake symbol we aren't going to emit anyway.  */
       && TREE_CODE (decl) != TYPE_DECL
-      && !DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (decl)
-      && !DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P (decl))
+      && !DECL_MAYBE_IN_CHARGE_CDTOR_P (decl))
     {
-      bool set = false;
+      int save_ver = flag_abi_version;
+      tree id2 = NULL_TREE;
 
-      /* Check IDENTIFIER_GLOBAL_VALUE before setting to avoid redundant
-        errors from multiple definitions.  */
-      tree d = IDENTIFIER_GLOBAL_VALUE (id);
-      if (!d || decl_implicit_alias_p (d))
+      if (!DECL_REALLY_EXTERN (decl))
        {
-         set = true;
-         SET_IDENTIFIER_GLOBAL_VALUE (id, decl);
-       }
+         record_mangling (decl, G.need_abi_warning);
 
-      if (!G.need_abi_warning)
-       return;
+         if (!G.need_abi_warning)
+           return;
 
-      /* If the mangling will change in the future, emit an alias with the
-        future mangled name for forward-compatibility.  */
-      int save_ver;
-      tree id2;
+         flag_abi_version = flag_abi_compat_version;
+         id2 = mangle_decl_string (decl);
+         id2 = targetm.mangle_decl_assembler_name (decl, id2);
+         flag_abi_version = save_ver;
 
-      if (!set)
-       {
-         SET_IDENTIFIER_GLOBAL_VALUE (id, decl);
-         inform (DECL_SOURCE_LOCATION (decl), "a later -fabi-version= (or "
-                 "=0) avoids this error with a change in mangling");
+         if (id2 != id)
+           note_mangling_alias (decl, id2);
        }
 
-      save_ver = flag_abi_version;
-
-      flag_abi_version = flag_abi_compat_version;
-      id2 = mangle_decl_string (decl);
-      id2 = targetm.mangle_decl_assembler_name (decl, id2);
-
-      if (id2 != id)
-       note_mangling_alias (decl, id2);
-
       if (warn_abi)
        {
-         if (flag_abi_compat_version != warn_abi_version)
+         const char fabi_version[] = "-fabi-version";
+
+         if (flag_abi_compat_version != warn_abi_version
+             || id2 == NULL_TREE)
            {
              flag_abi_version = warn_abi_version;
              id2 = mangle_decl_string (decl);
              id2 = targetm.mangle_decl_assembler_name (decl, id2);
            }
+         flag_abi_version = save_ver;
 
          if (id2 == id)
            /* OK.  */;
@@ -3656,15 +4111,15 @@ mangle_decl (const tree decl)
                   && abi_version_at_least (warn_abi_version))
            warning_at (DECL_SOURCE_LOCATION (G.entity), OPT_Wabi,
                        "the mangled name of %qD changed between "
-                       "-fabi-version=%d (%D) and -fabi-version=%d (%D)",
-                       G.entity, warn_abi_version, id2,
-                       flag_abi_version, id);
+                       "%<%s=%d%> (%qD) and %<%s=%d%> (%qD)",
+                       G.entity, fabi_version, warn_abi_version, id2,
+                       fabi_version, save_ver, id);
          else
            warning_at (DECL_SOURCE_LOCATION (G.entity), OPT_Wabi,
                        "the mangled name of %qD changes between "
-                       "-fabi-version=%d (%D) and -fabi-version=%d (%D)",
-                       G.entity, flag_abi_version, id,
-                       warn_abi_version, id2);
+                       "%<%s=%d%> (%qD) and %<%s=%d%> (%qD)",
+                       G.entity, fabi_version, save_ver, id,
+                       fabi_version, warn_abi_version, id2);
        }
 
       flag_abi_version = save_ver;
@@ -3748,6 +4203,53 @@ mangle_vtt_for_type (const tree type)
   return mangle_special_for_type (type, "TT");
 }
 
+/* Returns an identifier for the mangled name of the decomposition
+   artificial variable DECL.  DECLS is the vector of the VAR_DECLs
+   for the identifier-list.  */
+
+tree
+mangle_decomp (const tree decl, vec<tree> &decls)
+{
+  gcc_assert (!type_dependent_expression_p (decl));
+
+  location_t saved_loc = input_location;
+  input_location = DECL_SOURCE_LOCATION (decl);
+
+  start_mangling (decl);
+  write_string ("_Z");
+
+  tree context = decl_mangling_context (decl);
+  gcc_assert (context != NULL_TREE);
+
+  bool nested = false;
+  if (DECL_NAMESPACE_STD_P (context))
+    write_string ("St");
+  else if (context != global_namespace)
+    {
+      nested = true;
+      write_char ('N');
+      write_prefix (decl_mangling_context (decl));
+    }
+
+  write_string ("DC");
+  unsigned int i;
+  tree d;
+  FOR_EACH_VEC_ELT (decls, i, d)
+    write_unqualified_name (d);
+  write_char ('E');
+
+  if (nested)
+    write_char ('E');
+
+  tree id = finish_mangling_get_identifier ();
+  if (DEBUG_MANGLE)
+    fprintf (stderr, "mangle_decomp = '%s'\n\n",
+             IDENTIFIER_POINTER (id));
+
+  input_location = saved_loc;
+  return id;
+}
+
 /* Return an identifier for a construction vtable group.  TYPE is
    the most derived class in the hierarchy; BINFO is the base
    subobject for which this construction vtable group will be used.
@@ -3820,10 +4322,13 @@ mangle_call_offset (const tree fixed_offset, const tree virtual_offset)
 
 tree
 mangle_thunk (tree fn_decl, const int this_adjusting, tree fixed_offset,
-             tree virtual_offset)
+             tree virtual_offset, tree thunk)
 {
   tree result;
 
+  if (abi_version_at_least (11))
+    maybe_check_abi_tags (fn_decl, thunk, 11);
+
   start_mangling (fn_decl);
 
   write_string ("_Z");
@@ -3861,74 +4366,43 @@ mangle_thunk (tree fn_decl, const int this_adjusting, tree fixed_offset,
   return result;
 }
 
-struct conv_type_hasher : ggc_ptr_hash<tree_node>
-{
-  static hashval_t hash (tree);
-  static bool equal (tree, tree);
-};
-
-/* This hash table maps TYPEs to the IDENTIFIER for a conversion
-   operator to TYPE.  The nodes are IDENTIFIERs whose TREE_TYPE is the
-   TYPE.  */
-
-static GTY (()) hash_table<conv_type_hasher> *conv_type_names;
-
-/* Hash a node (VAL1) in the table.  */
-
-hashval_t
-conv_type_hasher::hash (tree val)
-{
-  return (hashval_t) TYPE_UID (TREE_TYPE (val));
-}
-
-/* Compare VAL1 (a node in the table) with VAL2 (a TYPE).  */
+/* Handle ABI backwards compatibility for past bugs where we didn't call
+   check_abi_tags in places where it's needed: call check_abi_tags and warn if
+   it makes a difference.  If FOR_DECL is non-null, it's the declaration
+   that we're actually trying to mangle; if it's null, we're mangling the
+   guard variable for T.  */
 
-bool
-conv_type_hasher::equal (tree val1, tree val2)
-{
-  return TREE_TYPE (val1) == val2;
-}
-
-/* Return an identifier for the mangled unqualified name for a
-   conversion operator to TYPE.  This mangling is not specified by the
-   ABI spec; it is only used internally.  */
-
-tree
-mangle_conv_op_name_for_type (const tree type)
+static void
+maybe_check_abi_tags (tree t, tree for_decl, int ver)
 {
-  tree *slot;
-  tree identifier;
+  if (DECL_ASSEMBLER_NAME_SET_P (t))
+    return;
 
-  if (type == error_mark_node)
-    return error_mark_node;
+  tree oldtags = get_abi_tags (t);
 
-  if (conv_type_names == NULL)
-    conv_type_names = hash_table<conv_type_hasher>::create_ggc (31);
+  mangle_decl (t);
 
-  slot = conv_type_names->find_slot_with_hash (type,
-                                              (hashval_t) TYPE_UID (type),
-                                              INSERT);
-  identifier = *slot;
-  if (!identifier)
+  tree newtags = get_abi_tags (t);
+  if (newtags && newtags != oldtags
+      && abi_version_crosses (ver))
     {
-      char buffer[64];
-
-       /* Create a unique name corresponding to TYPE.  */
-      sprintf (buffer, "operator %lu",
-              (unsigned long) conv_type_names->elements ());
-      identifier = get_identifier (buffer);
-      *slot = identifier;
-
-      /* Hang TYPE off the identifier so it can be found easily later
-        when performing conversions.  */
-      TREE_TYPE (identifier) = type;
-
-      /* Set bits on the identifier so we know later it's a conversion.  */
-      IDENTIFIER_OPNAME_P (identifier) = 1;
-      IDENTIFIER_TYPENAME_P (identifier) = 1;
+      if (for_decl && DECL_THUNK_P (for_decl))
+       warning_at (DECL_SOURCE_LOCATION (t), OPT_Wabi,
+                   "the mangled name of a thunk for %qD changes between "
+                   "%<-fabi-version=%d%> and %<-fabi-version=%d%>",
+                   t, flag_abi_version, warn_abi_version);
+      else if (for_decl)
+       warning_at (DECL_SOURCE_LOCATION (for_decl), OPT_Wabi,
+                   "the mangled name of %qD changes between "
+                   "%<-fabi-version=%d%> and %<-fabi-version=%d%>",
+                   for_decl, flag_abi_version, warn_abi_version);
+      else
+       warning_at (DECL_SOURCE_LOCATION (t), OPT_Wabi,
+                   "the mangled name of the initialization guard variable "
+                   "for %qD changes between %<-fabi-version=%d%> and "
+                   "%<-fabi-version=%d%>",
+                   t, flag_abi_version, warn_abi_version);
     }
-
-  return identifier;
 }
 
 /* Write out the appropriate string for this variable when generating
@@ -3952,6 +4426,8 @@ write_guarded_var_name (const tree variable)
 tree
 mangle_guard_variable (const tree variable)
 {
+  if (abi_version_at_least (10))
+    maybe_check_abi_tags (variable);
   start_mangling (variable);
   write_string ("_ZGV");
   write_guarded_var_name (variable);
@@ -3964,6 +4440,7 @@ mangle_guard_variable (const tree variable)
 tree
 mangle_tls_init_fn (const tree variable)
 {
+  check_abi_tags (variable);
   start_mangling (variable);
   write_string ("_ZTH");
   write_guarded_var_name (variable);
@@ -3978,6 +4455,7 @@ mangle_tls_init_fn (const tree variable)
 tree
 mangle_tls_wrapper_fn (const tree variable)
 {
+  check_abi_tags (variable);
   start_mangling (variable);
   write_string (TLS_WRAPPER_PREFIX);
   write_guarded_var_name (variable);
@@ -3997,47 +4475,34 @@ decl_tls_wrapper_p (const tree fn)
 }
 
 /* Return an identifier for the name of a temporary variable used to
-   initialize a static reference.  This isn't part of the ABI, but we might
-   as well call them something readable.  */
-
-static GTY(()) int temp_count;
+   initialize a static reference.  This is now part of the ABI.  */
 
 tree
 mangle_ref_init_variable (const tree variable)
 {
   start_mangling (variable);
   write_string ("_ZGR");
+  check_abi_tags (variable);
   write_name (variable, /*ignore_local_scope=*/0);
   /* Avoid name clashes with aggregate initialization of multiple
      references at once.  */
-  write_unsigned_number (temp_count++);
+  write_compact_number (current_ref_temp_count++);
   return finish_mangling_get_identifier ();
 }
-\f
 
-/* Foreign language type mangling section.  */
+/* Return an identifier for the mangled name of a C++20 template parameter
+   object for template argument EXPR.  */
 
-/* How to write the type codes for the integer Java type.  */
-
-static void
-write_java_integer_type_codes (const tree type)
-{
-  if (type == java_int_type_node)
-    write_char ('i');
-  else if (type == java_short_type_node)
-    write_char ('s');
-  else if (type == java_byte_type_node)
-    write_char ('c');
-  else if (type == java_char_type_node)
-    write_char ('w');
-  else if (type == java_long_type_node)
-    write_char ('x');
-  else if (type == java_boolean_type_node)
-    write_char ('b');
-  else
-    gcc_unreachable ();
+tree
+mangle_template_parm_object (tree expr)
+{
+  start_mangling (expr);
+  write_string ("_ZTAX");
+  write_expression (expr);
+  write_char ('E');
+  return finish_mangling_get_identifier ();
 }
-
+\f
 /* Given a CLASS_TYPE, such as a record for std::bad_exception this
    function generates a mangled name for the vtable map variable of
    the class type.  For example, if the class type is