]> git.ipfire.org Git - thirdparty/gcc.git/blobdiff - gcc/cp/mangle.c
Update copyright years.
[thirdparty/gcc.git] / gcc / cp / mangle.c
index b9d8ee2011606f8dfa250187fe5c203817bbe8a5..11eb8962d2848765e482fe5054e1f0e7c97bd243 100644 (file)
@@ -1,5 +1,5 @@
 /* Name mangling for the 3.0 -*- C++ -*- ABI.
-   Copyright (C) 2000-2018 Free Software Foundation, Inc.
+   Copyright (C) 2000-2021 Free Software Foundation, Inc.
    Written by Alex Samuel <samuel@codesourcery.com>
 
    This file is part of GCC.
@@ -117,6 +117,9 @@ struct GTY(()) globals {
 
   /* 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;
@@ -170,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.  */
 
@@ -272,11 +275,10 @@ static tree mangle_special_for_type (const tree, const char *);
   write_number ((NUMBER), /*unsigned_p=*/1, 10)
 
 /* If DECL is a template instance (including the uninstantiated template
-   itself), return nonzero and, if TEMPLATE_INFO is non-NULL, set
-   *TEMPLATE_INFO to its template info.  Otherwise return zero.  */
+   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)
     {
@@ -285,33 +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
          && VAR_OR_FUNCTION_DECL_P (decl)
          && DECL_TEMPLATE_INFO (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;
-       }
+         && 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.  */
@@ -414,8 +403,7 @@ 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)
+      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));
@@ -629,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),
@@ -653,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))
        {
@@ -799,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>
@@ -826,9 +813,8 @@ write_encoding (const tree decl)
     {
       tree fn_type;
       tree d;
-      bool tmpl = decl_is_template_id (decl, NULL);
 
-      if (tmpl)
+      if (maybe_template_info (decl))
        {
          fn_type = get_mostly_instantiated_function_type (decl);
          /* FN_TYPE will not have parameter types for in-charge or
@@ -849,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.  */
 
@@ -874,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>
@@ -902,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);
@@ -923,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>.  */
@@ -1031,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');
@@ -1055,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)
@@ -1096,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)
@@ -1114,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
@@ -1126,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);
@@ -1185,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);
@@ -1359,15 +1409,14 @@ 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);
@@ -1404,8 +1453,7 @@ write_unqualified_name (tree decl)
       if (TREE_CODE (decl) == TYPE_DECL
           && 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));
@@ -2006,8 +2054,7 @@ write_local_name (tree function, const tree local_entity,
       write_name (entity, /*ignore_local_scope=*/1);
       if (DECL_DISCRIMINATOR_P (local_entity)
          && !(TREE_CODE (local_entity) == TYPE_DECL
-              && (LAMBDA_TYPE_P (TREE_TYPE (local_entity))
-                  || TYPE_UNNAMED_P (TREE_TYPE (local_entity)))))
+              && TYPE_ANON_P (TREE_TYPE (local_entity))))
        write_discriminator (discriminator_for_local_entity (local_entity));
     }
 }
@@ -2071,8 +2118,7 @@ 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)
@@ -2103,8 +2149,7 @@ write_type (tree type)
 
       /* See through any typedefs.  */
       type = TYPE_MAIN_VARIANT (type);
-      if (TREE_CODE (type) == FUNCTION_TYPE
-         || TREE_CODE (type) == METHOD_TYPE)
+      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
@@ -2309,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:
@@ -2344,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.
 
@@ -2369,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))
@@ -2473,10 +2540,12 @@ 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)
@@ -2541,11 +2610,11 @@ write_builtin_type (tree type)
        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 ();
@@ -2808,7 +2877,10 @@ write_member_name (tree member)
       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);
@@ -2820,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>
@@ -2836,13 +2962,22 @@ write_expression (tree expr)
 {
   enum tree_code code = TREE_CODE (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
-        || code == 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);
@@ -2979,11 +3114,30 @@ write_expression (tree expr)
       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)
@@ -2993,7 +3147,8 @@ write_expression (tree expr)
        {
          scope = TREE_OPERAND (expr, 0);
          member = TREE_OPERAND (expr, 1);
-         gcc_assert (!BASELINK_P (member));
+         if (BASELINK_P (member))
+           member = BASELINK_FUNCTIONS (member);
        }
       else
        {
@@ -3010,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);
@@ -3125,23 +3281,76 @@ 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
     {
@@ -3177,6 +3386,8 @@ write_expression (tree expr)
              ob = TREE_OPERAND (ob, 0);
              write_expression (ob);
            }
+         else if (write_base_ref (expr))
+           return;
          else if (!is_dummy_object (ob))
            {
              write_string ("dt");
@@ -3231,8 +3442,7 @@ 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 = OVL_NAME (fn);
 
@@ -3332,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.  */
@@ -3349,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:
@@ -3376,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 ();
@@ -3415,7 +3656,7 @@ 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 = DECL_INITIAL (node);
+    node = tparm_object_argument (node);
 
   /* Strip a conversion added by convert_nontype_argument.  */
   if (TREE_CODE (node) == IMPLICIT_CONV_EXPR)
@@ -3652,14 +3893,13 @@ 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)
@@ -3667,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');
 }
@@ -3711,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;
 
@@ -3735,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);
 
@@ -3754,7 +4010,6 @@ mangle_decl_string (const tree decl)
       pop_tinst_level ();
       current_function_decl = saved_fn;
     }
-  input_location = saved_loc;
 
   return result;
 }
@@ -4134,18 +4389,18 @@ maybe_check_abi_tags (tree t, tree for_decl, int ver)
       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",
+                   "%<-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",
+                   "%<-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",
+                   "for %qD changes between %<-fabi-version=%d%> and "
+                   "%<-fabi-version=%d%>",
                    t, flag_abi_version, warn_abi_version);
     }
 }
@@ -4220,10 +4475,7 @@ 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)
@@ -4234,7 +4486,7 @@ mangle_ref_init_variable (const tree 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 ();
 }