xref: /dragonfly/contrib/gcc-8.0/gcc/cp/mangle.c (revision e215fc28)
138fd1498Szrj /* Name mangling for the 3.0 -*- C++ -*- ABI.
238fd1498Szrj    Copyright (C) 2000-2018 Free Software Foundation, Inc.
338fd1498Szrj    Written by Alex Samuel <samuel@codesourcery.com>
438fd1498Szrj 
538fd1498Szrj    This file is part of GCC.
638fd1498Szrj 
738fd1498Szrj    GCC is free software; you can redistribute it and/or modify it
838fd1498Szrj    under the terms of the GNU General Public License as published by
938fd1498Szrj    the Free Software Foundation; either version 3, or (at your option)
1038fd1498Szrj    any later version.
1138fd1498Szrj 
1238fd1498Szrj    GCC is distributed in the hope that it will be useful, but
1338fd1498Szrj    WITHOUT ANY WARRANTY; without even the implied warranty of
1438fd1498Szrj    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
1538fd1498Szrj    General Public License for more details.
1638fd1498Szrj 
1738fd1498Szrj You should have received a copy of the GNU General Public License
1838fd1498Szrj along with GCC; see the file COPYING3.  If not see
1938fd1498Szrj <http://www.gnu.org/licenses/>.  */
2038fd1498Szrj 
2138fd1498Szrj /* This file implements mangling of C++ names according to the IA64
2238fd1498Szrj    C++ ABI specification.  A mangled name encodes a function or
2338fd1498Szrj    variable's name, scope, type, and/or template arguments into a text
2438fd1498Szrj    identifier.  This identifier is used as the function's or
2538fd1498Szrj    variable's linkage name, to preserve compatibility between C++'s
2638fd1498Szrj    language features (templates, scoping, and overloading) and C
2738fd1498Szrj    linkers.
2838fd1498Szrj 
2938fd1498Szrj    Additionally, g++ uses mangled names internally.  To support this,
3038fd1498Szrj    mangling of types is allowed, even though the mangled name of a
3138fd1498Szrj    type should not appear by itself as an exported name.  Ditto for
3238fd1498Szrj    uninstantiated templates.
3338fd1498Szrj 
3438fd1498Szrj    The primary entry point for this module is mangle_decl, which
3538fd1498Szrj    returns an identifier containing the mangled name for a decl.
3638fd1498Szrj    Additional entry points are provided to build mangled names of
3738fd1498Szrj    particular constructs when the appropriate decl for that construct
3838fd1498Szrj    is not available.  These are:
3938fd1498Szrj 
4038fd1498Szrj      mangle_typeinfo_for_type:		typeinfo data
4138fd1498Szrj      mangle_typeinfo_string_for_type:	typeinfo type name
4238fd1498Szrj      mangle_vtbl_for_type:		virtual table data
4338fd1498Szrj      mangle_vtt_for_type:		VTT data
4438fd1498Szrj      mangle_ctor_vtbl_for_type:		`C-in-B' constructor virtual table data
4538fd1498Szrj      mangle_thunk:			thunk function or entry  */
4638fd1498Szrj 
4738fd1498Szrj #include "config.h"
4838fd1498Szrj #include "system.h"
4938fd1498Szrj #include "coretypes.h"
5038fd1498Szrj #include "target.h"
5138fd1498Szrj #include "vtable-verify.h"
5238fd1498Szrj #include "cp-tree.h"
5338fd1498Szrj #include "stringpool.h"
5438fd1498Szrj #include "cgraph.h"
5538fd1498Szrj #include "stor-layout.h"
5638fd1498Szrj #include "flags.h"
5738fd1498Szrj #include "attribs.h"
5838fd1498Szrj 
5938fd1498Szrj /* Debugging support.  */
6038fd1498Szrj 
6138fd1498Szrj /* Define DEBUG_MANGLE to enable very verbose trace messages.  */
6238fd1498Szrj #ifndef DEBUG_MANGLE
6338fd1498Szrj #define DEBUG_MANGLE 0
6438fd1498Szrj #endif
6538fd1498Szrj 
6638fd1498Szrj /* Macros for tracing the write_* functions.  */
6738fd1498Szrj #if DEBUG_MANGLE
6838fd1498Szrj # define MANGLE_TRACE(FN, INPUT) \
6938fd1498Szrj   fprintf (stderr, "  %-24s: %-24s\n", (FN), (INPUT))
7038fd1498Szrj # define MANGLE_TRACE_TREE(FN, NODE) \
7138fd1498Szrj   fprintf (stderr, "  %-24s: %-24s (%p)\n", \
7238fd1498Szrj 	   (FN), get_tree_code_name (TREE_CODE (NODE)), (void *) (NODE))
7338fd1498Szrj #else
7438fd1498Szrj # define MANGLE_TRACE(FN, INPUT)
7538fd1498Szrj # define MANGLE_TRACE_TREE(FN, NODE)
7638fd1498Szrj #endif
7738fd1498Szrj 
7838fd1498Szrj /* Nonzero if NODE is a class template-id.  We can't rely on
7938fd1498Szrj    CLASSTYPE_USE_TEMPLATE here because of tricky bugs in the parser
8038fd1498Szrj    that hard to distinguish A<T> from A, where A<T> is the type as
8138fd1498Szrj    instantiated outside of the template, and A is the type used
8238fd1498Szrj    without parameters inside the template.  */
8338fd1498Szrj #define CLASSTYPE_TEMPLATE_ID_P(NODE)					\
8438fd1498Szrj   (TREE_CODE (NODE) == BOUND_TEMPLATE_TEMPLATE_PARM			\
8538fd1498Szrj    || (CLASS_TYPE_P (NODE)						\
8638fd1498Szrj        && CLASSTYPE_TEMPLATE_INFO (NODE) != NULL			\
8738fd1498Szrj        && PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (NODE))))
8838fd1498Szrj 
8938fd1498Szrj /* For deciding whether to set G.need_abi_warning, we need to consider both
9038fd1498Szrj    warn_abi_version and flag_abi_compat_version.  */
9138fd1498Szrj #define abi_warn_or_compat_version_crosses(N) \
9238fd1498Szrj   (abi_version_crosses (N) || abi_compat_version_crosses (N))
9338fd1498Szrj 
9438fd1498Szrj /* And sometimes we can simplify the code path if we don't need to worry about
9538fd1498Szrj    previous ABIs.  */
9638fd1498Szrj #define abi_flag_at_least(flag,N) (flag == 0 || flag >= N)
9738fd1498Szrj #define any_abi_below(N) \
9838fd1498Szrj   (!abi_version_at_least (N) \
9938fd1498Szrj    || !abi_flag_at_least (warn_abi_version, (N)) \
10038fd1498Szrj    || !abi_flag_at_least (flag_abi_compat_version, (N)))
10138fd1498Szrj 
10238fd1498Szrj /* Things we only need one of.  This module is not reentrant.  */
10338fd1498Szrj struct GTY(()) globals {
10438fd1498Szrj   /* An array of the current substitution candidates, in the order
10538fd1498Szrj      we've seen them.  */
10638fd1498Szrj   vec<tree, va_gc> *substitutions;
10738fd1498Szrj 
10838fd1498Szrj   /* The entity that is being mangled.  */
10938fd1498Szrj   tree GTY ((skip)) entity;
11038fd1498Szrj 
11138fd1498Szrj   /* How many parameter scopes we are inside.  */
11238fd1498Szrj   int parm_depth;
11338fd1498Szrj 
11438fd1498Szrj   /* True if the mangling will be different in a future version of the
11538fd1498Szrj      ABI.  */
11638fd1498Szrj   bool need_abi_warning;
11738fd1498Szrj 
11838fd1498Szrj   /* True if the mangling will be different in C++17 mode.  */
11938fd1498Szrj   bool need_cxx17_warning;
12038fd1498Szrj };
12138fd1498Szrj 
12238fd1498Szrj static GTY (()) globals G;
12338fd1498Szrj 
12438fd1498Szrj /* The obstack on which we build mangled names.  */
12538fd1498Szrj static struct obstack *mangle_obstack;
12638fd1498Szrj 
12738fd1498Szrj /* The obstack on which we build mangled names that are not going to
12838fd1498Szrj    be IDENTIFIER_NODEs.  */
12938fd1498Szrj static struct obstack name_obstack;
13038fd1498Szrj 
13138fd1498Szrj /* The first object on the name_obstack; we use this to free memory
13238fd1498Szrj    allocated on the name_obstack.  */
13338fd1498Szrj static void *name_base;
13438fd1498Szrj 
13538fd1498Szrj /* Indices into subst_identifiers.  These are identifiers used in
13638fd1498Szrj    special substitution rules.  */
13738fd1498Szrj typedef enum
13838fd1498Szrj {
13938fd1498Szrj   SUBID_ALLOCATOR,
14038fd1498Szrj   SUBID_BASIC_STRING,
14138fd1498Szrj   SUBID_CHAR_TRAITS,
14238fd1498Szrj   SUBID_BASIC_ISTREAM,
14338fd1498Szrj   SUBID_BASIC_OSTREAM,
14438fd1498Szrj   SUBID_BASIC_IOSTREAM,
14538fd1498Szrj   SUBID_MAX
14638fd1498Szrj }
14738fd1498Szrj substitution_identifier_index_t;
14838fd1498Szrj 
14938fd1498Szrj /* For quick substitution checks, look up these common identifiers
15038fd1498Szrj    once only.  */
15138fd1498Szrj static GTY(()) tree subst_identifiers[SUBID_MAX];
15238fd1498Szrj 
15338fd1498Szrj /* Single-letter codes for builtin integer types, defined in
15438fd1498Szrj    <builtin-type>.  These are indexed by integer_type_kind values.  */
15538fd1498Szrj static const char
15638fd1498Szrj integer_type_codes[itk_none] =
15738fd1498Szrj {
15838fd1498Szrj   'c',  /* itk_char */
15938fd1498Szrj   'a',  /* itk_signed_char */
16038fd1498Szrj   'h',  /* itk_unsigned_char */
16138fd1498Szrj   's',  /* itk_short */
16238fd1498Szrj   't',  /* itk_unsigned_short */
16338fd1498Szrj   'i',  /* itk_int */
16438fd1498Szrj   'j',  /* itk_unsigned_int */
16538fd1498Szrj   'l',  /* itk_long */
16638fd1498Szrj   'm',  /* itk_unsigned_long */
16738fd1498Szrj   'x',  /* itk_long_long */
16838fd1498Szrj   'y',  /* itk_unsigned_long_long */
16938fd1498Szrj   /* __intN types are handled separately */
17038fd1498Szrj   '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0'
17138fd1498Szrj };
17238fd1498Szrj 
17338fd1498Szrj static int decl_is_template_id (const tree, tree* const);
17438fd1498Szrj 
17538fd1498Szrj /* Functions for handling substitutions.  */
17638fd1498Szrj 
17738fd1498Szrj static inline tree canonicalize_for_substitution (tree);
17838fd1498Szrj static void add_substitution (tree);
17938fd1498Szrj static inline int is_std_substitution (const tree,
18038fd1498Szrj 				       const substitution_identifier_index_t);
18138fd1498Szrj static inline int is_std_substitution_char (const tree,
18238fd1498Szrj 					    const substitution_identifier_index_t);
18338fd1498Szrj static int find_substitution (tree);
18438fd1498Szrj static void mangle_call_offset (const tree, const tree);
18538fd1498Szrj 
18638fd1498Szrj /* Functions for emitting mangled representations of things.  */
18738fd1498Szrj 
18838fd1498Szrj static void write_mangled_name (const tree, bool);
18938fd1498Szrj static void write_encoding (const tree);
19038fd1498Szrj static void write_name (tree, const int);
19138fd1498Szrj static void write_abi_tags (tree);
19238fd1498Szrj static void write_unscoped_name (const tree);
19338fd1498Szrj static void write_unscoped_template_name (const tree);
19438fd1498Szrj static void write_nested_name (const tree);
19538fd1498Szrj static void write_prefix (const tree);
19638fd1498Szrj static void write_template_prefix (const tree);
19738fd1498Szrj static void write_unqualified_name (tree);
19838fd1498Szrj static void write_conversion_operator_name (const tree);
19938fd1498Szrj static void write_source_name (tree);
20038fd1498Szrj static void write_literal_operator_name (tree);
20138fd1498Szrj static void write_unnamed_type_name (const tree);
20238fd1498Szrj static void write_closure_type_name (const tree);
20338fd1498Szrj static int hwint_to_ascii (unsigned HOST_WIDE_INT, const unsigned int, char *,
20438fd1498Szrj 			   const unsigned int);
20538fd1498Szrj static void write_number (unsigned HOST_WIDE_INT, const int,
20638fd1498Szrj 			  const unsigned int);
20738fd1498Szrj static void write_compact_number (int num);
20838fd1498Szrj static void write_integer_cst (const tree);
20938fd1498Szrj static void write_real_cst (const tree);
21038fd1498Szrj static void write_identifier (const char *);
21138fd1498Szrj static void write_special_name_constructor (const tree);
21238fd1498Szrj static void write_special_name_destructor (const tree);
21338fd1498Szrj static void write_type (tree);
21438fd1498Szrj static int write_CV_qualifiers_for_type (const tree);
21538fd1498Szrj static void write_builtin_type (tree);
21638fd1498Szrj static void write_function_type (const tree);
21738fd1498Szrj static void write_bare_function_type (const tree, const int, const tree);
21838fd1498Szrj static void write_method_parms (tree, const int, const tree);
21938fd1498Szrj static void write_class_enum_type (const tree);
22038fd1498Szrj static void write_template_args (tree);
22138fd1498Szrj static void write_expression (tree);
22238fd1498Szrj static void write_template_arg_literal (const tree);
22338fd1498Szrj static void write_template_arg (tree);
22438fd1498Szrj static void write_template_template_arg (const tree);
22538fd1498Szrj static void write_array_type (const tree);
22638fd1498Szrj static void write_pointer_to_member_type (const tree);
22738fd1498Szrj static void write_template_param (const tree);
22838fd1498Szrj static void write_template_template_param (const tree);
22938fd1498Szrj static void write_substitution (const int);
23038fd1498Szrj static int discriminator_for_local_entity (tree);
23138fd1498Szrj static int discriminator_for_string_literal (tree, tree);
23238fd1498Szrj static void write_discriminator (const int);
23338fd1498Szrj static void write_local_name (tree, const tree, const tree);
23438fd1498Szrj static void dump_substitution_candidates (void);
23538fd1498Szrj static tree mangle_decl_string (const tree);
23638fd1498Szrj static int local_class_index (tree);
23738fd1498Szrj static void maybe_check_abi_tags (tree, tree = NULL_TREE, int = 10);
23838fd1498Szrj static bool equal_abi_tags (tree, tree);
23938fd1498Szrj 
24038fd1498Szrj /* Control functions.  */
24138fd1498Szrj 
24238fd1498Szrj static inline void start_mangling (const tree);
24338fd1498Szrj static tree mangle_special_for_type (const tree, const char *);
24438fd1498Szrj 
24538fd1498Szrj /* Append a single character to the end of the mangled
24638fd1498Szrj    representation.  */
24738fd1498Szrj #define write_char(CHAR)						\
24838fd1498Szrj   obstack_1grow (mangle_obstack, (CHAR))
24938fd1498Szrj 
25038fd1498Szrj /* Append a sized buffer to the end of the mangled representation.  */
25138fd1498Szrj #define write_chars(CHAR, LEN)						\
25238fd1498Szrj   obstack_grow (mangle_obstack, (CHAR), (LEN))
25338fd1498Szrj 
25438fd1498Szrj /* Append a NUL-terminated string to the end of the mangled
25538fd1498Szrj    representation.  */
25638fd1498Szrj #define write_string(STRING)						\
25738fd1498Szrj   obstack_grow (mangle_obstack, (STRING), strlen (STRING))
25838fd1498Szrj 
25938fd1498Szrj /* Nonzero if NODE1 and NODE2 are both TREE_LIST nodes and have the
26038fd1498Szrj    same purpose (context, which may be a type) and value (template
26138fd1498Szrj    decl).  See write_template_prefix for more information on what this
26238fd1498Szrj    is used for.  */
26338fd1498Szrj #define NESTED_TEMPLATE_MATCH(NODE1, NODE2)				\
26438fd1498Szrj   (TREE_CODE (NODE1) == TREE_LIST					\
26538fd1498Szrj    && TREE_CODE (NODE2) == TREE_LIST					\
26638fd1498Szrj    && ((TYPE_P (TREE_PURPOSE (NODE1))					\
26738fd1498Szrj 	&& same_type_p (TREE_PURPOSE (NODE1), TREE_PURPOSE (NODE2)))	\
26838fd1498Szrj        || TREE_PURPOSE (NODE1) == TREE_PURPOSE (NODE2))			\
26938fd1498Szrj    && TREE_VALUE (NODE1) == TREE_VALUE (NODE2))
27038fd1498Szrj 
27138fd1498Szrj /* Write out an unsigned quantity in base 10.  */
27238fd1498Szrj #define write_unsigned_number(NUMBER)					\
27338fd1498Szrj   write_number ((NUMBER), /*unsigned_p=*/1, 10)
27438fd1498Szrj 
27538fd1498Szrj /* If DECL is a template instance (including the uninstantiated template
27638fd1498Szrj    itself), return nonzero and, if TEMPLATE_INFO is non-NULL, set
27738fd1498Szrj    *TEMPLATE_INFO to its template info.  Otherwise return zero.  */
27838fd1498Szrj 
27938fd1498Szrj static int
decl_is_template_id(const tree decl,tree * const template_info)28038fd1498Szrj decl_is_template_id (const tree decl, tree* const template_info)
28138fd1498Szrj {
28238fd1498Szrj   if (TREE_CODE (decl) == TYPE_DECL)
28338fd1498Szrj     {
28438fd1498Szrj       /* TYPE_DECLs are handled specially.  Look at its type to decide
28538fd1498Szrj 	 if this is a template instantiation.  */
28638fd1498Szrj       const tree type = TREE_TYPE (decl);
28738fd1498Szrj 
28838fd1498Szrj       if (CLASS_TYPE_P (type) && CLASSTYPE_TEMPLATE_ID_P (type))
28938fd1498Szrj 	{
29038fd1498Szrj 	  if (template_info != NULL)
29138fd1498Szrj 	    /* For a templated TYPE_DECL, the template info is hanging
29238fd1498Szrj 	       off the type.  */
29338fd1498Szrj 	    *template_info = TYPE_TEMPLATE_INFO (type);
29438fd1498Szrj 	  return 1;
29538fd1498Szrj 	}
29638fd1498Szrj     }
29738fd1498Szrj   else
29838fd1498Szrj     {
29938fd1498Szrj       /* Check if this is a primary template.  */
30038fd1498Szrj       if (DECL_LANG_SPECIFIC (decl) != NULL
30138fd1498Szrj 	  && VAR_OR_FUNCTION_DECL_P (decl)
30238fd1498Szrj 	  && DECL_TEMPLATE_INFO (decl)
30338fd1498Szrj 	  && PRIMARY_TEMPLATE_P (DECL_TI_TEMPLATE (decl))
30438fd1498Szrj 	  && TREE_CODE (decl) != TEMPLATE_DECL)
30538fd1498Szrj 	{
30638fd1498Szrj 	  if (template_info != NULL)
30738fd1498Szrj 	    /* For most templated decls, the template info is hanging
30838fd1498Szrj 	       off the decl.  */
30938fd1498Szrj 	    *template_info = DECL_TEMPLATE_INFO (decl);
31038fd1498Szrj 	  return 1;
31138fd1498Szrj 	}
31238fd1498Szrj     }
31338fd1498Szrj 
31438fd1498Szrj   /* It's not a template id.  */
31538fd1498Szrj   return 0;
31638fd1498Szrj }
31738fd1498Szrj 
31838fd1498Szrj /* Produce debugging output of current substitution candidates.  */
31938fd1498Szrj 
32038fd1498Szrj static void
dump_substitution_candidates(void)32138fd1498Szrj dump_substitution_candidates (void)
32238fd1498Szrj {
32338fd1498Szrj   unsigned i;
32438fd1498Szrj   tree el;
32538fd1498Szrj 
32638fd1498Szrj   fprintf (stderr, "  ++ substitutions  ");
32738fd1498Szrj   FOR_EACH_VEC_ELT (*G.substitutions, i, el)
32838fd1498Szrj     {
32938fd1498Szrj       const char *name = "???";
33038fd1498Szrj 
33138fd1498Szrj       if (i > 0)
33238fd1498Szrj 	fprintf (stderr, "                    ");
33338fd1498Szrj       if (DECL_P (el))
33438fd1498Szrj 	name = IDENTIFIER_POINTER (DECL_NAME (el));
33538fd1498Szrj       else if (TREE_CODE (el) == TREE_LIST)
33638fd1498Szrj 	name = IDENTIFIER_POINTER (DECL_NAME (TREE_VALUE (el)));
33738fd1498Szrj       else if (TYPE_NAME (el))
33838fd1498Szrj 	name = TYPE_NAME_STRING (el);
33938fd1498Szrj       fprintf (stderr, " S%d_ = ", i - 1);
34038fd1498Szrj       if (TYPE_P (el) &&
34138fd1498Szrj 	  (CP_TYPE_RESTRICT_P (el)
34238fd1498Szrj 	   || CP_TYPE_VOLATILE_P (el)
34338fd1498Szrj 	   || CP_TYPE_CONST_P (el)))
34438fd1498Szrj 	fprintf (stderr, "CV-");
34538fd1498Szrj       fprintf (stderr, "%s (%s at %p)\n",
34638fd1498Szrj 	       name, get_tree_code_name (TREE_CODE (el)), (void *) el);
34738fd1498Szrj     }
34838fd1498Szrj }
34938fd1498Szrj 
35038fd1498Szrj /* <exception-spec> ::=
35138fd1498Szrj       Do  -- non-throwing exception specification
35238fd1498Szrj       DO <expression> E  -- computed (instantiation-dependent) noexcept
35338fd1498Szrj       Dw <type>* E  -- throw (types)  */
35438fd1498Szrj 
35538fd1498Szrj static void
write_exception_spec(tree spec)35638fd1498Szrj write_exception_spec (tree spec)
35738fd1498Szrj {
35838fd1498Szrj 
35938fd1498Szrj   if (!spec || spec == noexcept_false_spec)
36038fd1498Szrj     /* Nothing.  */
36138fd1498Szrj     return;
36238fd1498Szrj 
36338fd1498Szrj   if (!flag_noexcept_type)
36438fd1498Szrj     {
36538fd1498Szrj       G.need_cxx17_warning = true;
36638fd1498Szrj       return;
36738fd1498Szrj     }
36838fd1498Szrj 
36938fd1498Szrj   if (spec == noexcept_true_spec || spec == empty_except_spec)
37038fd1498Szrj     write_string ("Do");
37138fd1498Szrj   else if (tree expr = TREE_PURPOSE (spec))
37238fd1498Szrj     {
37338fd1498Szrj       /* noexcept (expr)  */
37438fd1498Szrj       gcc_assert (uses_template_parms (expr));
37538fd1498Szrj       write_string ("DO");
37638fd1498Szrj       write_expression (expr);
37738fd1498Szrj       write_char ('E');
37838fd1498Szrj     }
37938fd1498Szrj   else
38038fd1498Szrj     {
38138fd1498Szrj       /* throw (type-list) */
38238fd1498Szrj       write_string ("Dw");
38338fd1498Szrj       for (tree t = spec; t; t = TREE_CHAIN (t))
38438fd1498Szrj 	write_type (TREE_VALUE (t));
38538fd1498Szrj       write_char ('E');
38638fd1498Szrj     }
38738fd1498Szrj }
38838fd1498Szrj 
38938fd1498Szrj /* Both decls and types can be substitution candidates, but sometimes
39038fd1498Szrj    they refer to the same thing.  For instance, a TYPE_DECL and
39138fd1498Szrj    RECORD_TYPE for the same class refer to the same thing, and should
39238fd1498Szrj    be treated accordingly in substitutions.  This function returns a
39338fd1498Szrj    canonicalized tree node representing NODE that is used when adding
39438fd1498Szrj    and substitution candidates and finding matches.  */
39538fd1498Szrj 
39638fd1498Szrj static inline tree
canonicalize_for_substitution(tree node)39738fd1498Szrj canonicalize_for_substitution (tree node)
39838fd1498Szrj {
39938fd1498Szrj   /* For a TYPE_DECL, use the type instead.  */
40038fd1498Szrj   if (TREE_CODE (node) == TYPE_DECL)
40138fd1498Szrj     node = TREE_TYPE (node);
40238fd1498Szrj   if (TYPE_P (node)
40338fd1498Szrj       && TYPE_CANONICAL (node) != node
40438fd1498Szrj       && TYPE_MAIN_VARIANT (node) != node)
40538fd1498Szrj     {
40638fd1498Szrj       tree orig = node;
40738fd1498Szrj       /* Here we want to strip the topmost typedef only.
40838fd1498Szrj          We need to do that so is_std_substitution can do proper
40938fd1498Szrj          name matching.  */
41038fd1498Szrj       if (TREE_CODE (node) == FUNCTION_TYPE)
41138fd1498Szrj 	/* Use build_qualified_type and TYPE_QUALS here to preserve
41238fd1498Szrj 	   the old buggy mangling of attribute noreturn with abi<5.  */
41338fd1498Szrj 	node = build_qualified_type (TYPE_MAIN_VARIANT (node),
41438fd1498Szrj 				     TYPE_QUALS (node));
41538fd1498Szrj       else
41638fd1498Szrj 	node = cp_build_qualified_type (TYPE_MAIN_VARIANT (node),
41738fd1498Szrj 					cp_type_quals (node));
41838fd1498Szrj       if (TREE_CODE (node) == FUNCTION_TYPE
41938fd1498Szrj 	  || TREE_CODE (node) == METHOD_TYPE)
42038fd1498Szrj 	{
42138fd1498Szrj 	  node = build_ref_qualified_type (node, type_memfn_rqual (orig));
42238fd1498Szrj 	  tree r = canonical_eh_spec (TYPE_RAISES_EXCEPTIONS (orig));
42338fd1498Szrj 	  if (flag_noexcept_type)
42438fd1498Szrj 	    node = build_exception_variant (node, r);
42538fd1498Szrj 	  else
42638fd1498Szrj 	    /* Set the warning flag if appropriate.  */
42738fd1498Szrj 	    write_exception_spec (r);
42838fd1498Szrj 	}
42938fd1498Szrj     }
43038fd1498Szrj   return node;
43138fd1498Szrj }
43238fd1498Szrj 
43338fd1498Szrj /* Add NODE as a substitution candidate.  NODE must not already be on
43438fd1498Szrj    the list of candidates.  */
43538fd1498Szrj 
43638fd1498Szrj static void
add_substitution(tree node)43738fd1498Szrj add_substitution (tree node)
43838fd1498Szrj {
43938fd1498Szrj   tree c;
44038fd1498Szrj 
44138fd1498Szrj   if (DEBUG_MANGLE)
44238fd1498Szrj     fprintf (stderr, "  ++ add_substitution (%s at %10p)\n",
44338fd1498Szrj 	     get_tree_code_name (TREE_CODE (node)), (void *) node);
44438fd1498Szrj 
44538fd1498Szrj   /* Get the canonicalized substitution candidate for NODE.  */
44638fd1498Szrj   c = canonicalize_for_substitution (node);
44738fd1498Szrj   if (DEBUG_MANGLE && c != node)
44838fd1498Szrj     fprintf (stderr, "  ++ using candidate (%s at %10p)\n",
44938fd1498Szrj 	     get_tree_code_name (TREE_CODE (node)), (void *) node);
45038fd1498Szrj   node = c;
45138fd1498Szrj 
45238fd1498Szrj   /* Make sure NODE isn't already a candidate.  */
45338fd1498Szrj   if (flag_checking)
45438fd1498Szrj     {
45538fd1498Szrj       int i;
45638fd1498Szrj       tree candidate;
45738fd1498Szrj 
45838fd1498Szrj       FOR_EACH_VEC_SAFE_ELT (G.substitutions, i, candidate)
45938fd1498Szrj 	{
46038fd1498Szrj 	  gcc_assert (!(DECL_P (node) && node == candidate));
46138fd1498Szrj 	  gcc_assert (!(TYPE_P (node) && TYPE_P (candidate)
46238fd1498Szrj 		      && same_type_p (node, candidate)));
46338fd1498Szrj 	}
46438fd1498Szrj     }
46538fd1498Szrj 
46638fd1498Szrj   /* Put the decl onto the varray of substitution candidates.  */
46738fd1498Szrj   vec_safe_push (G.substitutions, node);
46838fd1498Szrj 
46938fd1498Szrj   if (DEBUG_MANGLE)
47038fd1498Szrj     dump_substitution_candidates ();
47138fd1498Szrj }
47238fd1498Szrj 
47338fd1498Szrj /* Helper function for find_substitution.  Returns nonzero if NODE,
47438fd1498Szrj    which may be a decl or a CLASS_TYPE, is a template-id with template
47538fd1498Szrj    name of substitution_index[INDEX] in the ::std namespace.  */
47638fd1498Szrj 
47738fd1498Szrj static inline int
is_std_substitution(const tree node,const substitution_identifier_index_t index)47838fd1498Szrj is_std_substitution (const tree node,
47938fd1498Szrj 		     const substitution_identifier_index_t index)
48038fd1498Szrj {
48138fd1498Szrj   tree type = NULL;
48238fd1498Szrj   tree decl = NULL;
48338fd1498Szrj 
48438fd1498Szrj   if (DECL_P (node))
48538fd1498Szrj     {
48638fd1498Szrj       type = TREE_TYPE (node);
48738fd1498Szrj       decl = node;
48838fd1498Szrj     }
48938fd1498Szrj   else if (CLASS_TYPE_P (node))
49038fd1498Szrj     {
49138fd1498Szrj       type = node;
49238fd1498Szrj       decl = TYPE_NAME (node);
49338fd1498Szrj     }
49438fd1498Szrj   else
49538fd1498Szrj     /* These are not the droids you're looking for.  */
49638fd1498Szrj     return 0;
49738fd1498Szrj 
49838fd1498Szrj   return (DECL_NAMESPACE_STD_P (CP_DECL_CONTEXT (decl))
49938fd1498Szrj 	  && TYPE_LANG_SPECIFIC (type)
50038fd1498Szrj 	  && TYPE_TEMPLATE_INFO (type)
50138fd1498Szrj 	  && (DECL_NAME (TYPE_TI_TEMPLATE (type))
50238fd1498Szrj 	      == subst_identifiers[index]));
50338fd1498Szrj }
50438fd1498Szrj 
50538fd1498Szrj /* Return the ABI tags (the TREE_VALUE of the "abi_tag" attribute entry) for T,
50638fd1498Szrj    which can be a decl or type.  */
50738fd1498Szrj 
50838fd1498Szrj static tree
get_abi_tags(tree t)50938fd1498Szrj get_abi_tags (tree t)
51038fd1498Szrj {
51138fd1498Szrj   if (!t || TREE_CODE (t) == NAMESPACE_DECL)
51238fd1498Szrj     return NULL_TREE;
51338fd1498Szrj 
51438fd1498Szrj   if (DECL_P (t) && DECL_DECLARES_TYPE_P (t))
51538fd1498Szrj     t = TREE_TYPE (t);
51638fd1498Szrj 
51738fd1498Szrj   tree attrs;
51838fd1498Szrj   if (TYPE_P (t))
51938fd1498Szrj     attrs = TYPE_ATTRIBUTES (t);
52038fd1498Szrj   else
52138fd1498Szrj     attrs = DECL_ATTRIBUTES (t);
52238fd1498Szrj 
52338fd1498Szrj   tree tags = lookup_attribute ("abi_tag", attrs);
52438fd1498Szrj   if (tags)
52538fd1498Szrj     tags = TREE_VALUE (tags);
52638fd1498Szrj   return tags;
52738fd1498Szrj }
52838fd1498Szrj 
52938fd1498Szrj /* Helper function for find_substitution.  Returns nonzero if NODE,
53038fd1498Szrj    which may be a decl or a CLASS_TYPE, is the template-id
53138fd1498Szrj    ::std::identifier<char>, where identifier is
53238fd1498Szrj    substitution_index[INDEX].  */
53338fd1498Szrj 
53438fd1498Szrj static inline int
is_std_substitution_char(const tree node,const substitution_identifier_index_t index)53538fd1498Szrj is_std_substitution_char (const tree node,
53638fd1498Szrj 			  const substitution_identifier_index_t index)
53738fd1498Szrj {
53838fd1498Szrj   tree args;
53938fd1498Szrj   /* Check NODE's name is ::std::identifier.  */
54038fd1498Szrj   if (!is_std_substitution (node, index))
54138fd1498Szrj     return 0;
54238fd1498Szrj   /* Figure out its template args.  */
54338fd1498Szrj   if (DECL_P (node))
54438fd1498Szrj     args = DECL_TI_ARGS (node);
54538fd1498Szrj   else if (CLASS_TYPE_P (node))
54638fd1498Szrj     args = CLASSTYPE_TI_ARGS (node);
54738fd1498Szrj   else
54838fd1498Szrj     /* Oops, not a template.  */
54938fd1498Szrj     return 0;
55038fd1498Szrj   /* NODE's template arg list should be <char>.  */
55138fd1498Szrj   return
55238fd1498Szrj     TREE_VEC_LENGTH (args) == 1
55338fd1498Szrj     && TREE_VEC_ELT (args, 0) == char_type_node;
55438fd1498Szrj }
55538fd1498Szrj 
55638fd1498Szrj /* Check whether a substitution should be used to represent NODE in
55738fd1498Szrj    the mangling.
55838fd1498Szrj 
55938fd1498Szrj    First, check standard special-case substitutions.
56038fd1498Szrj 
56138fd1498Szrj      <substitution> ::= St
56238fd1498Szrj 	 # ::std
56338fd1498Szrj 
56438fd1498Szrj 		    ::= Sa
56538fd1498Szrj 	 # ::std::allocator
56638fd1498Szrj 
56738fd1498Szrj 		    ::= Sb
56838fd1498Szrj 	 # ::std::basic_string
56938fd1498Szrj 
57038fd1498Szrj 		    ::= Ss
57138fd1498Szrj 	 # ::std::basic_string<char,
57238fd1498Szrj 			       ::std::char_traits<char>,
57338fd1498Szrj 			       ::std::allocator<char> >
57438fd1498Szrj 
57538fd1498Szrj 		    ::= Si
57638fd1498Szrj 	 # ::std::basic_istream<char, ::std::char_traits<char> >
57738fd1498Szrj 
57838fd1498Szrj 		    ::= So
57938fd1498Szrj 	 # ::std::basic_ostream<char, ::std::char_traits<char> >
58038fd1498Szrj 
58138fd1498Szrj 		    ::= Sd
58238fd1498Szrj 	 # ::std::basic_iostream<char, ::std::char_traits<char> >
58338fd1498Szrj 
58438fd1498Szrj    Then examine the stack of currently available substitution
58538fd1498Szrj    candidates for entities appearing earlier in the same mangling
58638fd1498Szrj 
58738fd1498Szrj    If a substitution is found, write its mangled representation and
58838fd1498Szrj    return nonzero.  If none is found, just return zero.  */
58938fd1498Szrj 
59038fd1498Szrj static int
find_substitution(tree node)59138fd1498Szrj find_substitution (tree node)
59238fd1498Szrj {
59338fd1498Szrj   int i;
59438fd1498Szrj   const int size = vec_safe_length (G.substitutions);
59538fd1498Szrj   tree decl;
59638fd1498Szrj   tree type;
59738fd1498Szrj   const char *abbr = NULL;
59838fd1498Szrj 
59938fd1498Szrj   if (DEBUG_MANGLE)
60038fd1498Szrj     fprintf (stderr, "  ++ find_substitution (%s at %p)\n",
60138fd1498Szrj 	     get_tree_code_name (TREE_CODE (node)), (void *) node);
60238fd1498Szrj 
60338fd1498Szrj   /* Obtain the canonicalized substitution representation for NODE.
60438fd1498Szrj      This is what we'll compare against.  */
60538fd1498Szrj   node = canonicalize_for_substitution (node);
60638fd1498Szrj 
60738fd1498Szrj   /* Check for builtin substitutions.  */
60838fd1498Szrj 
60938fd1498Szrj   decl = TYPE_P (node) ? TYPE_NAME (node) : node;
61038fd1498Szrj   type = TYPE_P (node) ? node : TREE_TYPE (node);
61138fd1498Szrj 
61238fd1498Szrj   /* Check for std::allocator.  */
61338fd1498Szrj   if (decl
61438fd1498Szrj       && is_std_substitution (decl, SUBID_ALLOCATOR)
61538fd1498Szrj       && !CLASSTYPE_USE_TEMPLATE (TREE_TYPE (decl)))
61638fd1498Szrj     abbr = "Sa";
61738fd1498Szrj 
61838fd1498Szrj   /* Check for std::basic_string.  */
61938fd1498Szrj   else if (decl && is_std_substitution (decl, SUBID_BASIC_STRING))
62038fd1498Szrj     {
62138fd1498Szrj       if (TYPE_P (node))
62238fd1498Szrj 	{
62338fd1498Szrj 	  /* If this is a type (i.e. a fully-qualified template-id),
62438fd1498Szrj 	     check for
62538fd1498Szrj 		 std::basic_string <char,
62638fd1498Szrj 				    std::char_traits<char>,
62738fd1498Szrj 				    std::allocator<char> > .  */
62838fd1498Szrj 	  if (cp_type_quals (type) == TYPE_UNQUALIFIED
62938fd1498Szrj 	      && CLASSTYPE_USE_TEMPLATE (type))
63038fd1498Szrj 	    {
63138fd1498Szrj 	      tree args = CLASSTYPE_TI_ARGS (type);
63238fd1498Szrj 	      if (TREE_VEC_LENGTH (args) == 3
63338fd1498Szrj 		  && same_type_p (TREE_VEC_ELT (args, 0), char_type_node)
63438fd1498Szrj 		  && is_std_substitution_char (TREE_VEC_ELT (args, 1),
63538fd1498Szrj 					       SUBID_CHAR_TRAITS)
63638fd1498Szrj 		  && is_std_substitution_char (TREE_VEC_ELT (args, 2),
63738fd1498Szrj 					       SUBID_ALLOCATOR))
63838fd1498Szrj 		abbr = "Ss";
63938fd1498Szrj 	    }
64038fd1498Szrj 	}
64138fd1498Szrj       else
64238fd1498Szrj 	/* Substitute for the template name only if this isn't a type.  */
64338fd1498Szrj 	abbr = "Sb";
64438fd1498Szrj     }
64538fd1498Szrj 
64638fd1498Szrj   /* Check for basic_{i,o,io}stream.  */
64738fd1498Szrj   else if (TYPE_P (node)
64838fd1498Szrj 	   && cp_type_quals (type) == TYPE_UNQUALIFIED
64938fd1498Szrj 	   && CLASS_TYPE_P (type)
65038fd1498Szrj 	   && CLASSTYPE_USE_TEMPLATE (type)
65138fd1498Szrj 	   && CLASSTYPE_TEMPLATE_INFO (type) != NULL)
65238fd1498Szrj     {
65338fd1498Szrj       /* First, check for the template
65438fd1498Szrj 	 args <char, std::char_traits<char> > .  */
65538fd1498Szrj       tree args = CLASSTYPE_TI_ARGS (type);
65638fd1498Szrj       if (TREE_VEC_LENGTH (args) == 2
65738fd1498Szrj 	  && TYPE_P (TREE_VEC_ELT (args, 0))
65838fd1498Szrj 	  && same_type_p (TREE_VEC_ELT (args, 0), char_type_node)
65938fd1498Szrj 	  && is_std_substitution_char (TREE_VEC_ELT (args, 1),
66038fd1498Szrj 				       SUBID_CHAR_TRAITS))
66138fd1498Szrj 	{
66238fd1498Szrj 	  /* Got them.  Is this basic_istream?  */
66338fd1498Szrj 	  if (is_std_substitution (decl, SUBID_BASIC_ISTREAM))
66438fd1498Szrj 	    abbr = "Si";
66538fd1498Szrj 	  /* Or basic_ostream?  */
66638fd1498Szrj 	  else if (is_std_substitution (decl, SUBID_BASIC_OSTREAM))
66738fd1498Szrj 	    abbr = "So";
66838fd1498Szrj 	  /* Or basic_iostream?  */
66938fd1498Szrj 	  else if (is_std_substitution (decl, SUBID_BASIC_IOSTREAM))
67038fd1498Szrj 	    abbr = "Sd";
67138fd1498Szrj 	}
67238fd1498Szrj     }
67338fd1498Szrj 
67438fd1498Szrj   /* Check for namespace std.  */
67538fd1498Szrj   else if (decl && DECL_NAMESPACE_STD_P (decl))
67638fd1498Szrj     {
67738fd1498Szrj       write_string ("St");
67838fd1498Szrj       return 1;
67938fd1498Szrj     }
68038fd1498Szrj 
68138fd1498Szrj   tree tags = NULL_TREE;
68238fd1498Szrj   if (OVERLOAD_TYPE_P (node) || DECL_CLASS_TEMPLATE_P (node))
68338fd1498Szrj     tags = get_abi_tags (type);
68438fd1498Szrj   /* Now check the list of available substitutions for this mangling
68538fd1498Szrj      operation.  */
68638fd1498Szrj   if (!abbr || tags) for (i = 0; i < size; ++i)
68738fd1498Szrj     {
68838fd1498Szrj       tree candidate = (*G.substitutions)[i];
68938fd1498Szrj       /* NODE is a matched to a candidate if it's the same decl node or
69038fd1498Szrj 	 if it's the same type.  */
69138fd1498Szrj       if (decl == candidate
69238fd1498Szrj 	  || (TYPE_P (candidate) && type && TYPE_P (node)
69338fd1498Szrj 	      && same_type_p (type, candidate))
69438fd1498Szrj 	  || NESTED_TEMPLATE_MATCH (node, candidate))
69538fd1498Szrj 	{
69638fd1498Szrj 	  write_substitution (i);
69738fd1498Szrj 	  return 1;
69838fd1498Szrj 	}
69938fd1498Szrj     }
70038fd1498Szrj 
70138fd1498Szrj   if (!abbr)
70238fd1498Szrj     /* No substitution found.  */
70338fd1498Szrj     return 0;
70438fd1498Szrj 
70538fd1498Szrj   write_string (abbr);
70638fd1498Szrj   if (tags)
70738fd1498Szrj     {
70838fd1498Szrj       /* If there are ABI tags on the abbreviation, it becomes
70938fd1498Szrj 	 a substitution candidate.  */
71038fd1498Szrj       write_abi_tags (tags);
71138fd1498Szrj       add_substitution (node);
71238fd1498Szrj     }
71338fd1498Szrj   return 1;
71438fd1498Szrj }
71538fd1498Szrj 
71638fd1498Szrj /* Returns whether DECL's symbol name should be the plain unqualified-id
71738fd1498Szrj    rather than a more complicated mangled name.  */
71838fd1498Szrj 
71938fd1498Szrj static bool
unmangled_name_p(const tree decl)72038fd1498Szrj unmangled_name_p (const tree decl)
72138fd1498Szrj {
72238fd1498Szrj   if (TREE_CODE (decl) == FUNCTION_DECL)
72338fd1498Szrj     {
72438fd1498Szrj       /* The names of `extern "C"' functions are not mangled.  */
72538fd1498Szrj       return (DECL_EXTERN_C_FUNCTION_P (decl)
72638fd1498Szrj 	      /* But overloaded operator names *are* mangled.  */
72738fd1498Szrj 	      && !DECL_OVERLOADED_OPERATOR_P (decl));
72838fd1498Szrj     }
72938fd1498Szrj   else if (VAR_P (decl))
73038fd1498Szrj     {
73138fd1498Szrj       /* static variables are mangled.  */
73238fd1498Szrj       if (!DECL_EXTERNAL_LINKAGE_P (decl))
73338fd1498Szrj 	return false;
73438fd1498Szrj 
73538fd1498Szrj       /* extern "C" declarations aren't mangled.  */
73638fd1498Szrj       if (DECL_EXTERN_C_P (decl))
73738fd1498Szrj 	return true;
73838fd1498Szrj 
73938fd1498Szrj       /* Other variables at non-global scope are mangled.  */
74038fd1498Szrj       if (CP_DECL_CONTEXT (decl) != global_namespace)
74138fd1498Szrj 	return false;
74238fd1498Szrj 
74338fd1498Szrj       /* Variable template instantiations are mangled.  */
74438fd1498Szrj       if (DECL_LANG_SPECIFIC (decl) && DECL_TEMPLATE_INFO (decl)
74538fd1498Szrj 	  && variable_template_p (DECL_TI_TEMPLATE (decl)))
74638fd1498Szrj 	return false;
74738fd1498Szrj 
74838fd1498Szrj       /* Declarations with ABI tags are mangled.  */
74938fd1498Szrj       if (get_abi_tags (decl))
75038fd1498Szrj 	return false;
75138fd1498Szrj 
75238fd1498Szrj       /* The names of non-static global variables aren't mangled.  */
75338fd1498Szrj       return true;
75438fd1498Szrj     }
75538fd1498Szrj 
75638fd1498Szrj   return false;
75738fd1498Szrj }
75838fd1498Szrj 
75938fd1498Szrj /* TOP_LEVEL is true, if this is being called at outermost level of
76038fd1498Szrj   mangling. It should be false when mangling a decl appearing in an
76138fd1498Szrj   expression within some other mangling.
76238fd1498Szrj 
76338fd1498Szrj   <mangled-name>      ::= _Z <encoding>  */
76438fd1498Szrj 
76538fd1498Szrj static void
write_mangled_name(const tree decl,bool top_level)76638fd1498Szrj write_mangled_name (const tree decl, bool top_level)
76738fd1498Szrj {
76838fd1498Szrj   MANGLE_TRACE_TREE ("mangled-name", decl);
76938fd1498Szrj 
77038fd1498Szrj   check_abi_tags (decl);
77138fd1498Szrj 
77238fd1498Szrj   if (unmangled_name_p (decl))
77338fd1498Szrj     {
77438fd1498Szrj       if (top_level)
77538fd1498Szrj 	write_string (IDENTIFIER_POINTER (DECL_NAME (decl)));
77638fd1498Szrj       else
77738fd1498Szrj 	{
77838fd1498Szrj 	  /* The standard notes: "The <encoding> of an extern "C"
77938fd1498Szrj 	     function is treated like global-scope data, i.e. as its
78038fd1498Szrj 	     <source-name> without a type."  We cannot write
78138fd1498Szrj 	     overloaded operators that way though, because it contains
78238fd1498Szrj 	     characters invalid in assembler.  */
78338fd1498Szrj 	  write_string ("_Z");
78438fd1498Szrj 	  write_source_name (DECL_NAME (decl));
78538fd1498Szrj 	}
78638fd1498Szrj     }
78738fd1498Szrj   else
78838fd1498Szrj     {
78938fd1498Szrj       write_string ("_Z");
79038fd1498Szrj       write_encoding (decl);
79138fd1498Szrj     }
79238fd1498Szrj }
79338fd1498Szrj 
79438fd1498Szrj /* Returns true if the return type of DECL is part of its signature, and
79538fd1498Szrj    therefore its mangling.  */
79638fd1498Szrj 
79738fd1498Szrj bool
mangle_return_type_p(tree decl)79838fd1498Szrj mangle_return_type_p (tree decl)
79938fd1498Szrj {
80038fd1498Szrj   return (!DECL_CONSTRUCTOR_P (decl)
80138fd1498Szrj 	  && !DECL_DESTRUCTOR_P (decl)
80238fd1498Szrj 	  && !DECL_CONV_FN_P (decl)
80338fd1498Szrj 	  && decl_is_template_id (decl, NULL));
80438fd1498Szrj }
80538fd1498Szrj 
80638fd1498Szrj /*   <encoding>		::= <function name> <bare-function-type>
80738fd1498Szrj 			::= <data name>  */
80838fd1498Szrj 
80938fd1498Szrj static void
write_encoding(const tree decl)81038fd1498Szrj write_encoding (const tree decl)
81138fd1498Szrj {
81238fd1498Szrj   MANGLE_TRACE_TREE ("encoding", decl);
81338fd1498Szrj 
81438fd1498Szrj   if (DECL_LANG_SPECIFIC (decl) && DECL_EXTERN_C_FUNCTION_P (decl))
81538fd1498Szrj     {
81638fd1498Szrj       /* For overloaded operators write just the mangled name
81738fd1498Szrj 	 without arguments.  */
81838fd1498Szrj       if (DECL_OVERLOADED_OPERATOR_P (decl))
81938fd1498Szrj 	write_name (decl, /*ignore_local_scope=*/0);
82038fd1498Szrj       else
82138fd1498Szrj 	write_source_name (DECL_NAME (decl));
82238fd1498Szrj       return;
82338fd1498Szrj     }
82438fd1498Szrj 
82538fd1498Szrj   write_name (decl, /*ignore_local_scope=*/0);
82638fd1498Szrj   if (TREE_CODE (decl) == FUNCTION_DECL)
82738fd1498Szrj     {
82838fd1498Szrj       tree fn_type;
82938fd1498Szrj       tree d;
83038fd1498Szrj       bool tmpl = decl_is_template_id (decl, NULL);
83138fd1498Szrj 
83238fd1498Szrj       if (tmpl)
83338fd1498Szrj 	{
83438fd1498Szrj 	  fn_type = get_mostly_instantiated_function_type (decl);
83538fd1498Szrj 	  /* FN_TYPE will not have parameter types for in-charge or
83638fd1498Szrj 	     VTT parameters.  Therefore, we pass NULL_TREE to
83738fd1498Szrj 	     write_bare_function_type -- otherwise, it will get
83838fd1498Szrj 	     confused about which artificial parameters to skip.  */
83938fd1498Szrj 	  d = NULL_TREE;
84038fd1498Szrj 	}
84138fd1498Szrj       else
84238fd1498Szrj 	{
84338fd1498Szrj 	  fn_type = TREE_TYPE (decl);
84438fd1498Szrj 	  d = decl;
84538fd1498Szrj 	}
84638fd1498Szrj 
84738fd1498Szrj       write_bare_function_type (fn_type,
84838fd1498Szrj 				mangle_return_type_p (decl),
84938fd1498Szrj 				d);
85038fd1498Szrj     }
85138fd1498Szrj }
85238fd1498Szrj 
85338fd1498Szrj /* Lambdas can have a bit more context for mangling, specifically VAR_DECL
85438fd1498Szrj    or PARM_DECL context, which doesn't belong in DECL_CONTEXT.  */
85538fd1498Szrj 
85638fd1498Szrj static tree
decl_mangling_context(tree decl)85738fd1498Szrj decl_mangling_context (tree decl)
85838fd1498Szrj {
85938fd1498Szrj   tree tcontext = targetm.cxx.decl_mangling_context (decl);
86038fd1498Szrj 
86138fd1498Szrj   if (tcontext != NULL_TREE)
86238fd1498Szrj     return tcontext;
86338fd1498Szrj 
86438fd1498Szrj   if (TREE_CODE (decl) == TEMPLATE_DECL
86538fd1498Szrj       && DECL_TEMPLATE_RESULT (decl))
86638fd1498Szrj     decl = DECL_TEMPLATE_RESULT (decl);
86738fd1498Szrj 
86838fd1498Szrj   if (TREE_CODE (decl) == TYPE_DECL
86938fd1498Szrj       && LAMBDA_TYPE_P (TREE_TYPE (decl)))
87038fd1498Szrj     {
87138fd1498Szrj       tree extra = LAMBDA_TYPE_EXTRA_SCOPE (TREE_TYPE (decl));
87238fd1498Szrj       if (extra)
87338fd1498Szrj 	return extra;
87438fd1498Szrj     }
87538fd1498Szrj   else if (template_type_parameter_p (decl))
87638fd1498Szrj      /* template type parms have no mangling context.  */
87738fd1498Szrj       return NULL_TREE;
87838fd1498Szrj   return CP_DECL_CONTEXT (decl);
87938fd1498Szrj }
88038fd1498Szrj 
88138fd1498Szrj /* <name> ::= <unscoped-name>
88238fd1498Szrj 	  ::= <unscoped-template-name> <template-args>
88338fd1498Szrj 	  ::= <nested-name>
88438fd1498Szrj 	  ::= <local-name>
88538fd1498Szrj 
88638fd1498Szrj    If IGNORE_LOCAL_SCOPE is nonzero, this production of <name> is
88738fd1498Szrj    called from <local-name>, which mangles the enclosing scope
88838fd1498Szrj    elsewhere and then uses this function to mangle just the part
88938fd1498Szrj    underneath the function scope.  So don't use the <local-name>
89038fd1498Szrj    production, to avoid an infinite recursion.  */
89138fd1498Szrj 
89238fd1498Szrj static void
write_name(tree decl,const int ignore_local_scope)89338fd1498Szrj write_name (tree decl, const int ignore_local_scope)
89438fd1498Szrj {
89538fd1498Szrj   tree context;
89638fd1498Szrj 
89738fd1498Szrj   MANGLE_TRACE_TREE ("name", decl);
89838fd1498Szrj 
89938fd1498Szrj   if (TREE_CODE (decl) == TYPE_DECL)
90038fd1498Szrj     {
90138fd1498Szrj       /* In case this is a typedef, fish out the corresponding
90238fd1498Szrj 	 TYPE_DECL for the main variant.  */
90338fd1498Szrj       decl = TYPE_NAME (TYPE_MAIN_VARIANT (TREE_TYPE (decl)));
90438fd1498Szrj     }
90538fd1498Szrj 
90638fd1498Szrj   context = decl_mangling_context (decl);
90738fd1498Szrj 
90838fd1498Szrj   gcc_assert (context != NULL_TREE);
90938fd1498Szrj 
91038fd1498Szrj   if (abi_warn_or_compat_version_crosses (7)
91138fd1498Szrj       && ignore_local_scope
91238fd1498Szrj       && TREE_CODE (context) == PARM_DECL)
91338fd1498Szrj     G.need_abi_warning = 1;
91438fd1498Szrj 
91538fd1498Szrj   /* A decl in :: or ::std scope is treated specially.  The former is
91638fd1498Szrj      mangled using <unscoped-name> or <unscoped-template-name>, the
91738fd1498Szrj      latter with a special substitution.  Also, a name that is
91838fd1498Szrj      directly in a local function scope is also mangled with
91938fd1498Szrj      <unscoped-name> rather than a full <nested-name>.  */
92038fd1498Szrj   if (context == global_namespace
92138fd1498Szrj       || DECL_NAMESPACE_STD_P (context)
92238fd1498Szrj       || (ignore_local_scope
92338fd1498Szrj 	  && (TREE_CODE (context) == FUNCTION_DECL
92438fd1498Szrj 	      || (abi_version_at_least (7)
92538fd1498Szrj 		  && TREE_CODE (context) == PARM_DECL))))
92638fd1498Szrj     {
92738fd1498Szrj       tree template_info;
92838fd1498Szrj       /* Is this a template instance?  */
92938fd1498Szrj       if (decl_is_template_id (decl, &template_info))
93038fd1498Szrj 	{
93138fd1498Szrj 	  /* Yes: use <unscoped-template-name>.  */
93238fd1498Szrj 	  write_unscoped_template_name (TI_TEMPLATE (template_info));
93338fd1498Szrj 	  write_template_args (TI_ARGS (template_info));
93438fd1498Szrj 	}
93538fd1498Szrj       else
93638fd1498Szrj 	/* Everything else gets an <unqualified-name>.  */
93738fd1498Szrj 	write_unscoped_name (decl);
93838fd1498Szrj     }
93938fd1498Szrj   else
94038fd1498Szrj     {
94138fd1498Szrj       /* Handle local names, unless we asked not to (that is, invoked
94238fd1498Szrj 	 under <local-name>, to handle only the part of the name under
94338fd1498Szrj 	 the local scope).  */
94438fd1498Szrj       if (!ignore_local_scope)
94538fd1498Szrj 	{
94638fd1498Szrj 	  /* Scan up the list of scope context, looking for a
94738fd1498Szrj 	     function.  If we find one, this entity is in local
94838fd1498Szrj 	     function scope.  local_entity tracks context one scope
94938fd1498Szrj 	     level down, so it will contain the element that's
95038fd1498Szrj 	     directly in that function's scope, either decl or one of
95138fd1498Szrj 	     its enclosing scopes.  */
95238fd1498Szrj 	  tree local_entity = decl;
95338fd1498Szrj 	  while (context != global_namespace)
95438fd1498Szrj 	    {
95538fd1498Szrj 	      /* Make sure we're always dealing with decls.  */
95638fd1498Szrj 	      if (TYPE_P (context))
95738fd1498Szrj 		context = TYPE_NAME (context);
95838fd1498Szrj 	      /* Is this a function?  */
95938fd1498Szrj 	      if (TREE_CODE (context) == FUNCTION_DECL
96038fd1498Szrj 		  || TREE_CODE (context) == PARM_DECL)
96138fd1498Szrj 		{
96238fd1498Szrj 		  /* Yes, we have local scope.  Use the <local-name>
96338fd1498Szrj 		     production for the innermost function scope.  */
96438fd1498Szrj 		  write_local_name (context, local_entity, decl);
96538fd1498Szrj 		  return;
96638fd1498Szrj 		}
96738fd1498Szrj 	      /* Up one scope level.  */
96838fd1498Szrj 	      local_entity = context;
96938fd1498Szrj 	      context = decl_mangling_context (context);
97038fd1498Szrj 	    }
97138fd1498Szrj 
97238fd1498Szrj 	  /* No local scope found?  Fall through to <nested-name>.  */
97338fd1498Szrj 	}
97438fd1498Szrj 
97538fd1498Szrj       /* Other decls get a <nested-name> to encode their scope.  */
97638fd1498Szrj       write_nested_name (decl);
97738fd1498Szrj     }
97838fd1498Szrj }
97938fd1498Szrj 
98038fd1498Szrj /* <unscoped-name> ::= <unqualified-name>
98138fd1498Szrj 		   ::= St <unqualified-name>   # ::std::  */
98238fd1498Szrj 
98338fd1498Szrj static void
write_unscoped_name(const tree decl)98438fd1498Szrj write_unscoped_name (const tree decl)
98538fd1498Szrj {
98638fd1498Szrj   tree context = decl_mangling_context (decl);
98738fd1498Szrj 
98838fd1498Szrj   MANGLE_TRACE_TREE ("unscoped-name", decl);
98938fd1498Szrj 
99038fd1498Szrj   /* Is DECL in ::std?  */
99138fd1498Szrj   if (DECL_NAMESPACE_STD_P (context))
99238fd1498Szrj     {
99338fd1498Szrj       write_string ("St");
99438fd1498Szrj       write_unqualified_name (decl);
99538fd1498Szrj     }
99638fd1498Szrj   else
99738fd1498Szrj     {
99838fd1498Szrj       /* If not, it should be either in the global namespace, or directly
99938fd1498Szrj 	 in a local function scope.  A lambda can also be mangled in the
100038fd1498Szrj 	 scope of a default argument.  */
100138fd1498Szrj       gcc_assert (context == global_namespace
100238fd1498Szrj 		  || TREE_CODE (context) == PARM_DECL
100338fd1498Szrj 		  || TREE_CODE (context) == FUNCTION_DECL);
100438fd1498Szrj 
100538fd1498Szrj       write_unqualified_name (decl);
100638fd1498Szrj     }
100738fd1498Szrj }
100838fd1498Szrj 
100938fd1498Szrj /* <unscoped-template-name> ::= <unscoped-name>
101038fd1498Szrj 			    ::= <substitution>  */
101138fd1498Szrj 
101238fd1498Szrj static void
write_unscoped_template_name(const tree decl)101338fd1498Szrj write_unscoped_template_name (const tree decl)
101438fd1498Szrj {
101538fd1498Szrj   MANGLE_TRACE_TREE ("unscoped-template-name", decl);
101638fd1498Szrj 
101738fd1498Szrj   if (find_substitution (decl))
101838fd1498Szrj     return;
101938fd1498Szrj   write_unscoped_name (decl);
102038fd1498Szrj   add_substitution (decl);
102138fd1498Szrj }
102238fd1498Szrj 
102338fd1498Szrj /* Write the nested name, including CV-qualifiers, of DECL.
102438fd1498Szrj 
102538fd1498Szrj    <nested-name> ::= N [<CV-qualifiers>] [<ref-qualifier>] <prefix> <unqualified-name> E
102638fd1498Szrj 		 ::= N [<CV-qualifiers>] [<ref-qualifier>] <template-prefix> <template-args> E
102738fd1498Szrj 
102838fd1498Szrj    <ref-qualifier> ::= R # & ref-qualifier
102938fd1498Szrj                    ::= O # && ref-qualifier
103038fd1498Szrj    <CV-qualifiers> ::= [r] [V] [K]  */
103138fd1498Szrj 
103238fd1498Szrj static void
write_nested_name(const tree decl)103338fd1498Szrj write_nested_name (const tree decl)
103438fd1498Szrj {
103538fd1498Szrj   tree template_info;
103638fd1498Szrj 
103738fd1498Szrj   MANGLE_TRACE_TREE ("nested-name", decl);
103838fd1498Szrj 
103938fd1498Szrj   write_char ('N');
104038fd1498Szrj 
104138fd1498Szrj   /* Write CV-qualifiers, if this is a member function.  */
104238fd1498Szrj   if (TREE_CODE (decl) == FUNCTION_DECL
104338fd1498Szrj       && DECL_NONSTATIC_MEMBER_FUNCTION_P (decl))
104438fd1498Szrj     {
104538fd1498Szrj       if (DECL_VOLATILE_MEMFUNC_P (decl))
104638fd1498Szrj 	write_char ('V');
104738fd1498Szrj       if (DECL_CONST_MEMFUNC_P (decl))
104838fd1498Szrj 	write_char ('K');
104938fd1498Szrj       if (FUNCTION_REF_QUALIFIED (TREE_TYPE (decl)))
105038fd1498Szrj 	{
105138fd1498Szrj 	  if (FUNCTION_RVALUE_QUALIFIED (TREE_TYPE (decl)))
105238fd1498Szrj 	    write_char ('O');
105338fd1498Szrj 	  else
105438fd1498Szrj 	    write_char ('R');
105538fd1498Szrj 	}
105638fd1498Szrj     }
105738fd1498Szrj 
105838fd1498Szrj   /* Is this a template instance?  */
105938fd1498Szrj   if (decl_is_template_id (decl, &template_info))
106038fd1498Szrj     {
106138fd1498Szrj       /* Yes, use <template-prefix>.  */
106238fd1498Szrj       write_template_prefix (decl);
106338fd1498Szrj       write_template_args (TI_ARGS (template_info));
106438fd1498Szrj     }
106538fd1498Szrj   else if ((!abi_version_at_least (10) || TREE_CODE (decl) == TYPE_DECL)
106638fd1498Szrj 	   && TREE_CODE (TREE_TYPE (decl)) == TYPENAME_TYPE)
106738fd1498Szrj     {
106838fd1498Szrj       tree name = TYPENAME_TYPE_FULLNAME (TREE_TYPE (decl));
106938fd1498Szrj       if (TREE_CODE (name) == TEMPLATE_ID_EXPR)
107038fd1498Szrj 	{
107138fd1498Szrj 	  write_template_prefix (decl);
107238fd1498Szrj 	  write_template_args (TREE_OPERAND (name, 1));
107338fd1498Szrj 	}
107438fd1498Szrj       else
107538fd1498Szrj 	{
107638fd1498Szrj 	  write_prefix (decl_mangling_context (decl));
107738fd1498Szrj 	  write_unqualified_name (decl);
107838fd1498Szrj 	}
107938fd1498Szrj     }
108038fd1498Szrj   else
108138fd1498Szrj     {
108238fd1498Szrj       /* No, just use <prefix>  */
108338fd1498Szrj       write_prefix (decl_mangling_context (decl));
108438fd1498Szrj       write_unqualified_name (decl);
108538fd1498Szrj     }
108638fd1498Szrj   write_char ('E');
108738fd1498Szrj }
108838fd1498Szrj 
108938fd1498Szrj /* <prefix> ::= <prefix> <unqualified-name>
109038fd1498Szrj 	    ::= <template-param>
109138fd1498Szrj 	    ::= <template-prefix> <template-args>
109238fd1498Szrj 	    ::= <decltype>
109338fd1498Szrj 	    ::= # empty
109438fd1498Szrj 	    ::= <substitution>  */
109538fd1498Szrj 
109638fd1498Szrj static void
write_prefix(const tree node)109738fd1498Szrj write_prefix (const tree node)
109838fd1498Szrj {
109938fd1498Szrj   tree decl;
110038fd1498Szrj   /* Non-NULL if NODE represents a template-id.  */
110138fd1498Szrj   tree template_info = NULL;
110238fd1498Szrj 
110338fd1498Szrj   if (node == NULL
110438fd1498Szrj       || node == global_namespace)
110538fd1498Szrj     return;
110638fd1498Szrj 
110738fd1498Szrj   MANGLE_TRACE_TREE ("prefix", node);
110838fd1498Szrj 
110938fd1498Szrj   if (TREE_CODE (node) == DECLTYPE_TYPE)
111038fd1498Szrj     {
111138fd1498Szrj       write_type (node);
111238fd1498Szrj       return;
111338fd1498Szrj     }
111438fd1498Szrj 
111538fd1498Szrj   if (find_substitution (node))
111638fd1498Szrj     return;
111738fd1498Szrj 
111838fd1498Szrj   if (DECL_P (node))
111938fd1498Szrj     {
112038fd1498Szrj       /* If this is a function or parm decl, that means we've hit function
112138fd1498Szrj 	 scope, so this prefix must be for a local name.  In this
112238fd1498Szrj 	 case, we're under the <local-name> production, which encodes
112338fd1498Szrj 	 the enclosing function scope elsewhere.  So don't continue
112438fd1498Szrj 	 here.  */
112538fd1498Szrj       if (TREE_CODE (node) == FUNCTION_DECL
112638fd1498Szrj 	  || TREE_CODE (node) == PARM_DECL)
112738fd1498Szrj 	return;
112838fd1498Szrj 
112938fd1498Szrj       decl = node;
113038fd1498Szrj       decl_is_template_id (decl, &template_info);
113138fd1498Szrj     }
113238fd1498Szrj   else
113338fd1498Szrj     {
113438fd1498Szrj       /* Node is a type.  */
113538fd1498Szrj       decl = TYPE_NAME (node);
113638fd1498Szrj       if (CLASSTYPE_TEMPLATE_ID_P (node))
113738fd1498Szrj 	template_info = TYPE_TEMPLATE_INFO (node);
113838fd1498Szrj     }
113938fd1498Szrj 
114038fd1498Szrj   if (TREE_CODE (node) == TEMPLATE_TYPE_PARM)
114138fd1498Szrj     write_template_param (node);
114238fd1498Szrj   else if (template_info != NULL)
114338fd1498Szrj     /* Templated.  */
114438fd1498Szrj     {
114538fd1498Szrj       write_template_prefix (decl);
114638fd1498Szrj       write_template_args (TI_ARGS (template_info));
114738fd1498Szrj     }
114838fd1498Szrj   else if (TREE_CODE (TREE_TYPE (decl)) == TYPENAME_TYPE)
114938fd1498Szrj     {
115038fd1498Szrj       tree name = TYPENAME_TYPE_FULLNAME (TREE_TYPE (decl));
115138fd1498Szrj       if (TREE_CODE (name) == TEMPLATE_ID_EXPR)
115238fd1498Szrj 	{
115338fd1498Szrj 	  write_template_prefix (decl);
115438fd1498Szrj 	  write_template_args (TREE_OPERAND (name, 1));
115538fd1498Szrj 	}
115638fd1498Szrj       else
115738fd1498Szrj 	{
115838fd1498Szrj 	  write_prefix (decl_mangling_context (decl));
115938fd1498Szrj 	  write_unqualified_name (decl);
116038fd1498Szrj 	}
116138fd1498Szrj     }
116238fd1498Szrj   else
116338fd1498Szrj     /* Not templated.  */
116438fd1498Szrj     {
116538fd1498Szrj       write_prefix (decl_mangling_context (decl));
116638fd1498Szrj       write_unqualified_name (decl);
116738fd1498Szrj       if (VAR_P (decl)
116838fd1498Szrj 	  || TREE_CODE (decl) == FIELD_DECL)
116938fd1498Szrj 	{
117038fd1498Szrj 	  /* <data-member-prefix> := <member source-name> M */
117138fd1498Szrj 	  write_char ('M');
117238fd1498Szrj 	  return;
117338fd1498Szrj 	}
117438fd1498Szrj     }
117538fd1498Szrj 
117638fd1498Szrj   add_substitution (node);
117738fd1498Szrj }
117838fd1498Szrj 
117938fd1498Szrj /* <template-prefix> ::= <prefix> <template component>
118038fd1498Szrj 		     ::= <template-param>
118138fd1498Szrj 		     ::= <substitution>  */
118238fd1498Szrj 
118338fd1498Szrj static void
write_template_prefix(const tree node)118438fd1498Szrj write_template_prefix (const tree node)
118538fd1498Szrj {
118638fd1498Szrj   tree decl = DECL_P (node) ? node : TYPE_NAME (node);
118738fd1498Szrj   tree type = DECL_P (node) ? TREE_TYPE (node) : node;
118838fd1498Szrj   tree context = decl_mangling_context (decl);
118938fd1498Szrj   tree template_info;
119038fd1498Szrj   tree templ;
119138fd1498Szrj   tree substitution;
119238fd1498Szrj 
119338fd1498Szrj   MANGLE_TRACE_TREE ("template-prefix", node);
119438fd1498Szrj 
119538fd1498Szrj   /* Find the template decl.  */
119638fd1498Szrj   if (decl_is_template_id (decl, &template_info))
119738fd1498Szrj     templ = TI_TEMPLATE (template_info);
119838fd1498Szrj   else if (TREE_CODE (type) == TYPENAME_TYPE)
119938fd1498Szrj     /* For a typename type, all we have is the name.  */
120038fd1498Szrj     templ = DECL_NAME (decl);
120138fd1498Szrj   else
120238fd1498Szrj     {
120338fd1498Szrj       gcc_assert (CLASSTYPE_TEMPLATE_ID_P (type));
120438fd1498Szrj 
120538fd1498Szrj       templ = TYPE_TI_TEMPLATE (type);
120638fd1498Szrj     }
120738fd1498Szrj 
120838fd1498Szrj   /* For a member template, though, the template name for the
120938fd1498Szrj      innermost name must have all the outer template levels
121038fd1498Szrj      instantiated.  For instance, consider
121138fd1498Szrj 
121238fd1498Szrj        template<typename T> struct Outer {
121338fd1498Szrj 	 template<typename U> struct Inner {};
121438fd1498Szrj        };
121538fd1498Szrj 
121638fd1498Szrj      The template name for `Inner' in `Outer<int>::Inner<float>' is
121738fd1498Szrj      `Outer<int>::Inner<U>'.  In g++, we don't instantiate the template
121838fd1498Szrj      levels separately, so there's no TEMPLATE_DECL available for this
121938fd1498Szrj      (there's only `Outer<T>::Inner<U>').
122038fd1498Szrj 
122138fd1498Szrj      In order to get the substitutions right, we create a special
122238fd1498Szrj      TREE_LIST to represent the substitution candidate for a nested
122338fd1498Szrj      template.  The TREE_PURPOSE is the template's context, fully
122438fd1498Szrj      instantiated, and the TREE_VALUE is the TEMPLATE_DECL for the inner
122538fd1498Szrj      template.
122638fd1498Szrj 
122738fd1498Szrj      So, for the example above, `Outer<int>::Inner' is represented as a
122838fd1498Szrj      substitution candidate by a TREE_LIST whose purpose is `Outer<int>'
122938fd1498Szrj      and whose value is `Outer<T>::Inner<U>'.  */
123038fd1498Szrj   if (context && TYPE_P (context))
123138fd1498Szrj     substitution = build_tree_list (context, templ);
123238fd1498Szrj   else
123338fd1498Szrj     substitution = templ;
123438fd1498Szrj 
123538fd1498Szrj   if (find_substitution (substitution))
123638fd1498Szrj     return;
123738fd1498Szrj 
123838fd1498Szrj   if (TREE_TYPE (templ)
123938fd1498Szrj       && TREE_CODE (TREE_TYPE (templ)) == TEMPLATE_TEMPLATE_PARM)
124038fd1498Szrj     write_template_param (TREE_TYPE (templ));
124138fd1498Szrj   else
124238fd1498Szrj     {
124338fd1498Szrj       write_prefix (context);
124438fd1498Szrj       write_unqualified_name (decl);
124538fd1498Szrj     }
124638fd1498Szrj 
124738fd1498Szrj   add_substitution (substitution);
124838fd1498Szrj }
124938fd1498Szrj 
125038fd1498Szrj /* As the list of identifiers for the structured binding declaration
125138fd1498Szrj    DECL is likely gone, try to recover the DC <source-name>+ E portion
125238fd1498Szrj    from its mangled name.  Return pointer to the DC and set len to
125338fd1498Szrj    the length up to and including the terminating E.  On failure
125438fd1498Szrj    return NULL.  */
125538fd1498Szrj 
125638fd1498Szrj static const char *
find_decomp_unqualified_name(tree decl,size_t * len)125738fd1498Szrj find_decomp_unqualified_name (tree decl, size_t *len)
125838fd1498Szrj {
125938fd1498Szrj   const char *p = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
126038fd1498Szrj   const char *end = p + IDENTIFIER_LENGTH (DECL_ASSEMBLER_NAME (decl));
126138fd1498Szrj   bool nested = false;
126238fd1498Szrj   if (strncmp (p, "_Z", 2))
126338fd1498Szrj     return NULL;
126438fd1498Szrj   p += 2;
126538fd1498Szrj   if (!strncmp (p, "St", 2))
126638fd1498Szrj     p += 2;
126738fd1498Szrj   else if (*p == 'N')
126838fd1498Szrj     {
126938fd1498Szrj       nested = true;
127038fd1498Szrj       ++p;
127138fd1498Szrj       while (ISDIGIT (p[0]))
127238fd1498Szrj 	{
127338fd1498Szrj 	  char *e;
127438fd1498Szrj 	  long num = strtol (p, &e, 10);
127538fd1498Szrj 	  if (num >= 1 && num < end - e)
127638fd1498Szrj 	    p = e + num;
127738fd1498Szrj 	  else
127838fd1498Szrj 	    break;
127938fd1498Szrj 	}
128038fd1498Szrj     }
128138fd1498Szrj   if (strncmp (p, "DC", 2))
128238fd1498Szrj     return NULL;
128338fd1498Szrj   if (nested)
128438fd1498Szrj     {
128538fd1498Szrj       if (end[-1] != 'E')
128638fd1498Szrj 	return NULL;
128738fd1498Szrj       --end;
128838fd1498Szrj     }
128938fd1498Szrj   if (end[-1] != 'E')
129038fd1498Szrj     return NULL;
129138fd1498Szrj   *len = end - p;
129238fd1498Szrj   return p;
129338fd1498Szrj }
129438fd1498Szrj 
129538fd1498Szrj /* We don't need to handle thunks, vtables, or VTTs here.  Those are
129638fd1498Szrj    mangled through special entry points.
129738fd1498Szrj 
129838fd1498Szrj     <unqualified-name>  ::= <operator-name>
129938fd1498Szrj 			::= <special-name>
130038fd1498Szrj 			::= <source-name>
130138fd1498Szrj 			::= <unnamed-type-name>
130238fd1498Szrj 			::= <local-source-name>
130338fd1498Szrj 
130438fd1498Szrj     <local-source-name>	::= L <source-name> <discriminator> */
130538fd1498Szrj 
130638fd1498Szrj static void
write_unqualified_id(tree identifier)130738fd1498Szrj write_unqualified_id (tree identifier)
130838fd1498Szrj {
130938fd1498Szrj   if (IDENTIFIER_CONV_OP_P (identifier))
131038fd1498Szrj     write_conversion_operator_name (TREE_TYPE (identifier));
131138fd1498Szrj   else if (IDENTIFIER_OVL_OP_P (identifier))
131238fd1498Szrj     {
131338fd1498Szrj       const ovl_op_info_t *ovl_op = IDENTIFIER_OVL_OP_INFO (identifier);
131438fd1498Szrj       write_string (ovl_op->mangled_name);
131538fd1498Szrj     }
131638fd1498Szrj   else if (UDLIT_OPER_P (identifier))
131738fd1498Szrj     write_literal_operator_name (identifier);
131838fd1498Szrj   else
131938fd1498Szrj     write_source_name (identifier);
132038fd1498Szrj }
132138fd1498Szrj 
132238fd1498Szrj static void
write_unqualified_name(tree decl)132338fd1498Szrj write_unqualified_name (tree decl)
132438fd1498Szrj {
132538fd1498Szrj   MANGLE_TRACE_TREE ("unqualified-name", decl);
132638fd1498Szrj 
132738fd1498Szrj   if (identifier_p (decl))
132838fd1498Szrj     {
132938fd1498Szrj       write_unqualified_id (decl);
133038fd1498Szrj       return;
133138fd1498Szrj     }
133238fd1498Szrj 
133338fd1498Szrj   bool found = false;
133438fd1498Szrj 
133538fd1498Szrj   if (DECL_NAME (decl) == NULL_TREE)
133638fd1498Szrj     {
133738fd1498Szrj       found = true;
133838fd1498Szrj       gcc_assert (DECL_ASSEMBLER_NAME_SET_P (decl));
133938fd1498Szrj       const char *decomp_str = NULL;
134038fd1498Szrj       size_t decomp_len = 0;
134138fd1498Szrj       if (VAR_P (decl)
134238fd1498Szrj 	  && DECL_DECOMPOSITION_P (decl)
134338fd1498Szrj 	  && DECL_NAME (decl) == NULL_TREE
134438fd1498Szrj 	  && DECL_NAMESPACE_SCOPE_P (decl))
134538fd1498Szrj 	decomp_str = find_decomp_unqualified_name (decl, &decomp_len);
134638fd1498Szrj       if (decomp_str)
134738fd1498Szrj 	write_chars (decomp_str, decomp_len);
134838fd1498Szrj       else
134938fd1498Szrj 	write_source_name (DECL_ASSEMBLER_NAME (decl));
135038fd1498Szrj     }
135138fd1498Szrj   else if (DECL_DECLARES_FUNCTION_P (decl))
135238fd1498Szrj     {
135338fd1498Szrj       found = true;
135438fd1498Szrj       if (DECL_CONSTRUCTOR_P (decl))
135538fd1498Szrj 	write_special_name_constructor (decl);
135638fd1498Szrj       else if (DECL_DESTRUCTOR_P (decl))
135738fd1498Szrj 	write_special_name_destructor (decl);
135838fd1498Szrj       else if (DECL_CONV_FN_P (decl))
135938fd1498Szrj 	{
136038fd1498Szrj 	  /* Conversion operator. Handle it right here.
136138fd1498Szrj 	     <operator> ::= cv <type>  */
136238fd1498Szrj 	  tree type;
136338fd1498Szrj 	  if (decl_is_template_id (decl, NULL))
136438fd1498Szrj 	    {
136538fd1498Szrj 	      tree fn_type;
136638fd1498Szrj 	      fn_type = get_mostly_instantiated_function_type (decl);
136738fd1498Szrj 	      type = TREE_TYPE (fn_type);
136838fd1498Szrj 	    }
136938fd1498Szrj 	  else if (FNDECL_USED_AUTO (decl))
137038fd1498Szrj 	    type = (DECL_STRUCT_FUNCTION (decl)->language
137138fd1498Szrj 		    ->x_auto_return_pattern);
137238fd1498Szrj 	  else
137338fd1498Szrj 	    type = DECL_CONV_FN_TYPE (decl);
137438fd1498Szrj 	  write_conversion_operator_name (type);
137538fd1498Szrj 	}
137638fd1498Szrj       else if (DECL_OVERLOADED_OPERATOR_P (decl))
137738fd1498Szrj 	{
137838fd1498Szrj 	  const char *mangled_name
137938fd1498Szrj 	    = (ovl_op_info[DECL_ASSIGNMENT_OPERATOR_P (decl)]
138038fd1498Szrj 	       [DECL_OVERLOADED_OPERATOR_CODE_RAW (decl)].mangled_name);
138138fd1498Szrj 	  write_string (mangled_name);
138238fd1498Szrj 	}
138338fd1498Szrj       else if (UDLIT_OPER_P (DECL_NAME (decl)))
138438fd1498Szrj 	write_literal_operator_name (DECL_NAME (decl));
138538fd1498Szrj       else
138638fd1498Szrj 	found = false;
138738fd1498Szrj     }
138838fd1498Szrj 
138938fd1498Szrj   if (found)
139038fd1498Szrj     /* OK */;
139138fd1498Szrj   else if (VAR_OR_FUNCTION_DECL_P (decl) && ! TREE_PUBLIC (decl)
139238fd1498Szrj 	   && DECL_NAMESPACE_SCOPE_P (decl)
139338fd1498Szrj 	   && decl_linkage (decl) == lk_internal)
139438fd1498Szrj     {
139538fd1498Szrj       MANGLE_TRACE_TREE ("local-source-name", decl);
139638fd1498Szrj       write_char ('L');
139738fd1498Szrj       write_source_name (DECL_NAME (decl));
139838fd1498Szrj       /* The default discriminator is 1, and that's all we ever use,
139938fd1498Szrj 	 so there's no code to output one here.  */
140038fd1498Szrj     }
140138fd1498Szrj   else
140238fd1498Szrj     {
140338fd1498Szrj       tree type = TREE_TYPE (decl);
140438fd1498Szrj 
140538fd1498Szrj       if (TREE_CODE (decl) == TYPE_DECL
140638fd1498Szrj           && TYPE_UNNAMED_P (type))
140738fd1498Szrj         write_unnamed_type_name (type);
140838fd1498Szrj       else if (TREE_CODE (decl) == TYPE_DECL
140938fd1498Szrj                && LAMBDA_TYPE_P (type))
141038fd1498Szrj         write_closure_type_name (type);
141138fd1498Szrj       else
141238fd1498Szrj         write_source_name (DECL_NAME (decl));
141338fd1498Szrj     }
141438fd1498Szrj 
141538fd1498Szrj   /* We use the ABI tags from the primary class template, ignoring tags on any
141638fd1498Szrj      specializations.  This is necessary because C++ doesn't require a
141738fd1498Szrj      specialization to be declared before it is used unless the use requires a
141838fd1498Szrj      complete type, but we need to get the tags right on incomplete types as
141938fd1498Szrj      well.  */
142038fd1498Szrj   if (tree tmpl = most_general_template (decl))
142138fd1498Szrj     {
142238fd1498Szrj       tree res = DECL_TEMPLATE_RESULT (tmpl);
142338fd1498Szrj       if (res == NULL_TREE)
142438fd1498Szrj 	/* UNBOUND_CLASS_TEMPLATE.  */;
142538fd1498Szrj       else if (DECL_DECLARES_TYPE_P (decl))
142638fd1498Szrj 	decl = res;
142738fd1498Szrj       else if (any_abi_below (11))
142838fd1498Szrj 	{
142938fd1498Szrj 	  /* ABI v10 implicit tags on the template.  */
143038fd1498Szrj 	  tree mtags = missing_abi_tags (res);
143138fd1498Szrj 	  /* Explicit tags on the template.  */
143238fd1498Szrj 	  tree ttags = get_abi_tags (res);
143338fd1498Szrj 	  /* Tags on the instantiation.  */
143438fd1498Szrj 	  tree dtags = get_abi_tags (decl);
143538fd1498Szrj 
143638fd1498Szrj 	  if (mtags && abi_warn_or_compat_version_crosses (10))
143738fd1498Szrj 	    G.need_abi_warning = 1;
143838fd1498Szrj 
143938fd1498Szrj 	  /* Add the v10 tags to the explicit tags now.  */
144038fd1498Szrj 	  mtags = chainon (mtags, ttags);
144138fd1498Szrj 
144238fd1498Szrj 	  if (!G.need_abi_warning
144338fd1498Szrj 	      && abi_warn_or_compat_version_crosses (11)
144438fd1498Szrj 	      && !equal_abi_tags (dtags, mtags))
144538fd1498Szrj 	    G.need_abi_warning = 1;
144638fd1498Szrj 
144738fd1498Szrj 	  if (!abi_version_at_least (10))
144838fd1498Szrj 	    /* In abi <10, we only got the explicit tags.  */
144938fd1498Szrj 	    decl = res;
145038fd1498Szrj 	  else if (flag_abi_version == 10)
145138fd1498Szrj 	    {
145238fd1498Szrj 	      /* In ABI 10, we want explict and implicit tags.  */
145338fd1498Szrj 	      write_abi_tags (mtags);
145438fd1498Szrj 	      return;
145538fd1498Szrj 	    }
145638fd1498Szrj 	}
145738fd1498Szrj     }
145838fd1498Szrj 
145938fd1498Szrj   tree tags = get_abi_tags (decl);
146038fd1498Szrj   if (TREE_CODE (decl) == FUNCTION_DECL && DECL_CONV_FN_P (decl)
146138fd1498Szrj       && any_abi_below (11))
146238fd1498Szrj     if (tree mtags = missing_abi_tags (decl))
146338fd1498Szrj       {
146438fd1498Szrj 	if (abi_warn_or_compat_version_crosses (11))
146538fd1498Szrj 	  G.need_abi_warning = true;
146638fd1498Szrj 	if (!abi_version_at_least (11))
146738fd1498Szrj 	  tags = chainon (mtags, tags);
146838fd1498Szrj       }
146938fd1498Szrj   write_abi_tags (tags);
147038fd1498Szrj }
147138fd1498Szrj 
147238fd1498Szrj /* Write the unqualified-name for a conversion operator to TYPE.  */
147338fd1498Szrj 
147438fd1498Szrj static void
write_conversion_operator_name(const tree type)147538fd1498Szrj write_conversion_operator_name (const tree type)
147638fd1498Szrj {
147738fd1498Szrj   write_string ("cv");
147838fd1498Szrj   write_type (type);
147938fd1498Szrj }
148038fd1498Szrj 
148138fd1498Szrj /* Non-terminal <source-name>.  IDENTIFIER is an IDENTIFIER_NODE.
148238fd1498Szrj 
148338fd1498Szrj      <source-name> ::= </length/ number> <identifier>  */
148438fd1498Szrj 
148538fd1498Szrj static void
write_source_name(tree identifier)148638fd1498Szrj write_source_name (tree identifier)
148738fd1498Szrj {
148838fd1498Szrj   MANGLE_TRACE_TREE ("source-name", identifier);
148938fd1498Szrj 
149038fd1498Szrj   write_unsigned_number (IDENTIFIER_LENGTH (identifier));
149138fd1498Szrj   write_identifier (IDENTIFIER_POINTER (identifier));
149238fd1498Szrj }
149338fd1498Szrj 
149438fd1498Szrj /* Compare two TREE_STRINGs like strcmp.  */
149538fd1498Szrj 
149638fd1498Szrj int
tree_string_cmp(const void * p1,const void * p2)149738fd1498Szrj tree_string_cmp (const void *p1, const void *p2)
149838fd1498Szrj {
149938fd1498Szrj   if (p1 == p2)
150038fd1498Szrj     return 0;
150138fd1498Szrj   tree s1 = *(const tree*)p1;
150238fd1498Szrj   tree s2 = *(const tree*)p2;
150338fd1498Szrj   return strcmp (TREE_STRING_POINTER (s1),
150438fd1498Szrj 		 TREE_STRING_POINTER (s2));
150538fd1498Szrj }
150638fd1498Szrj 
150738fd1498Szrj /* Return the TREE_LIST of TAGS as a sorted VEC.  */
150838fd1498Szrj 
150938fd1498Szrj static vec<tree, va_gc> *
sorted_abi_tags(tree tags)151038fd1498Szrj sorted_abi_tags (tree tags)
151138fd1498Szrj {
151238fd1498Szrj   vec<tree, va_gc> * vec = make_tree_vector();
151338fd1498Szrj 
151438fd1498Szrj   for (tree t = tags; t; t = TREE_CHAIN (t))
151538fd1498Szrj     {
151638fd1498Szrj       if (ABI_TAG_IMPLICIT (t))
151738fd1498Szrj 	continue;
151838fd1498Szrj       tree str = TREE_VALUE (t);
151938fd1498Szrj       vec_safe_push (vec, str);
152038fd1498Szrj     }
152138fd1498Szrj 
152238fd1498Szrj   vec->qsort (tree_string_cmp);
152338fd1498Szrj 
152438fd1498Szrj   return vec;
152538fd1498Szrj }
152638fd1498Szrj 
152738fd1498Szrj /* ID is the name of a function or type with abi_tags attribute TAGS.
152838fd1498Szrj    Write out the name, suitably decorated.  */
152938fd1498Szrj 
153038fd1498Szrj static void
write_abi_tags(tree tags)153138fd1498Szrj write_abi_tags (tree tags)
153238fd1498Szrj {
153338fd1498Szrj   if (tags == NULL_TREE)
153438fd1498Szrj     return;
153538fd1498Szrj 
153638fd1498Szrj   vec<tree, va_gc> * vec = sorted_abi_tags (tags);
153738fd1498Szrj 
153838fd1498Szrj   unsigned i; tree str;
153938fd1498Szrj   FOR_EACH_VEC_ELT (*vec, i, str)
154038fd1498Szrj     {
154138fd1498Szrj       write_string ("B");
154238fd1498Szrj       write_unsigned_number (TREE_STRING_LENGTH (str) - 1);
154338fd1498Szrj       write_identifier (TREE_STRING_POINTER (str));
154438fd1498Szrj     }
154538fd1498Szrj 
154638fd1498Szrj   release_tree_vector (vec);
154738fd1498Szrj }
154838fd1498Szrj 
154938fd1498Szrj /* Simplified unique_ptr clone to release a tree vec on exit.  */
155038fd1498Szrj 
155138fd1498Szrj struct releasing_vec
155238fd1498Szrj {
155338fd1498Szrj   typedef vec<tree, va_gc> vec_t;
155438fd1498Szrj 
releasing_vecreleasing_vec155538fd1498Szrj   releasing_vec (vec_t *v): v(v) { }
releasing_vecreleasing_vec155638fd1498Szrj   releasing_vec (): v(make_tree_vector ()) { }
155738fd1498Szrj 
155838fd1498Szrj   vec_t &operator* () const { return *v; }
155938fd1498Szrj   vec_t *operator-> () const { return v; }
getreleasing_vec156038fd1498Szrj   vec_t *get () const { return v; }
156138fd1498Szrj   operator vec_t *() const { return v; }
156238fd1498Szrj   tree& operator[] (unsigned i) const { return (*v)[i]; }
156338fd1498Szrj 
~releasing_vecreleasing_vec156438fd1498Szrj   ~releasing_vec() { release_tree_vector (v); }
156538fd1498Szrj private:
156638fd1498Szrj   vec_t *v;
156738fd1498Szrj };
156838fd1498Szrj 
156938fd1498Szrj /* True iff the TREE_LISTS T1 and T2 of ABI tags are equivalent.  */
157038fd1498Szrj 
157138fd1498Szrj static bool
equal_abi_tags(tree t1,tree t2)157238fd1498Szrj equal_abi_tags (tree t1, tree t2)
157338fd1498Szrj {
157438fd1498Szrj   releasing_vec v1 = sorted_abi_tags (t1);
157538fd1498Szrj   releasing_vec v2 = sorted_abi_tags (t2);
157638fd1498Szrj 
157738fd1498Szrj   unsigned len1 = v1->length();
157838fd1498Szrj   if (len1 != v2->length())
157938fd1498Szrj     return false;
158038fd1498Szrj   for (unsigned i = 0; i < len1; ++i)
158138fd1498Szrj     if (tree_string_cmp (v1[i], v2[i]) != 0)
158238fd1498Szrj       return false;
158338fd1498Szrj   return true;
158438fd1498Szrj }
158538fd1498Szrj 
158638fd1498Szrj /* Write a user-defined literal operator.
158738fd1498Szrj           ::= li <source-name>    # "" <source-name>
158838fd1498Szrj    IDENTIFIER is an LITERAL_IDENTIFIER_NODE.  */
158938fd1498Szrj 
159038fd1498Szrj static void
write_literal_operator_name(tree identifier)159138fd1498Szrj write_literal_operator_name (tree identifier)
159238fd1498Szrj {
159338fd1498Szrj   const char* suffix = UDLIT_OP_SUFFIX (identifier);
159438fd1498Szrj   write_identifier (UDLIT_OP_MANGLED_PREFIX);
159538fd1498Szrj   write_unsigned_number (strlen (suffix));
159638fd1498Szrj   write_identifier (suffix);
159738fd1498Szrj }
159838fd1498Szrj 
159938fd1498Szrj /* Encode 0 as _, and 1+ as n-1_.  */
160038fd1498Szrj 
160138fd1498Szrj static void
write_compact_number(int num)160238fd1498Szrj write_compact_number (int num)
160338fd1498Szrj {
160438fd1498Szrj   if (num > 0)
160538fd1498Szrj     write_unsigned_number (num - 1);
160638fd1498Szrj   write_char ('_');
160738fd1498Szrj }
160838fd1498Szrj 
160938fd1498Szrj /* Return how many unnamed types precede TYPE in its enclosing class.  */
161038fd1498Szrj 
161138fd1498Szrj static int
nested_anon_class_index(tree type)161238fd1498Szrj nested_anon_class_index (tree type)
161338fd1498Szrj {
161438fd1498Szrj   int index = 0;
161538fd1498Szrj   tree member = TYPE_FIELDS (TYPE_CONTEXT (type));
161638fd1498Szrj   for (; member; member = DECL_CHAIN (member))
161738fd1498Szrj     if (DECL_IMPLICIT_TYPEDEF_P (member))
161838fd1498Szrj       {
161938fd1498Szrj 	tree memtype = TREE_TYPE (member);
162038fd1498Szrj 	if (memtype == type)
162138fd1498Szrj 	  return index;
162238fd1498Szrj 	else if (TYPE_UNNAMED_P (memtype))
162338fd1498Szrj 	  ++index;
162438fd1498Szrj       }
162538fd1498Szrj 
162638fd1498Szrj   if (seen_error ())
162738fd1498Szrj     return -1;
162838fd1498Szrj 
162938fd1498Szrj   gcc_unreachable ();
163038fd1498Szrj }
163138fd1498Szrj 
163238fd1498Szrj /* <unnamed-type-name> ::= Ut [ <nonnegative number> ] _ */
163338fd1498Szrj 
163438fd1498Szrj static void
write_unnamed_type_name(const tree type)163538fd1498Szrj write_unnamed_type_name (const tree type)
163638fd1498Szrj {
163738fd1498Szrj   int discriminator;
163838fd1498Szrj   MANGLE_TRACE_TREE ("unnamed-type-name", type);
163938fd1498Szrj 
164038fd1498Szrj   if (TYPE_FUNCTION_SCOPE_P (type))
164138fd1498Szrj     discriminator = local_class_index (type);
164238fd1498Szrj   else if (TYPE_CLASS_SCOPE_P (type))
164338fd1498Szrj     discriminator = nested_anon_class_index (type);
164438fd1498Szrj   else
164538fd1498Szrj     {
164638fd1498Szrj       gcc_assert (no_linkage_check (type, /*relaxed_p=*/true));
164738fd1498Szrj       /* Just use the old mangling at namespace scope.  */
164838fd1498Szrj       write_source_name (TYPE_IDENTIFIER (type));
164938fd1498Szrj       return;
165038fd1498Szrj     }
165138fd1498Szrj 
165238fd1498Szrj   write_string ("Ut");
165338fd1498Szrj   write_compact_number (discriminator);
165438fd1498Szrj }
165538fd1498Szrj 
165638fd1498Szrj /* <closure-type-name> ::= Ul <lambda-sig> E [ <nonnegative number> ] _
165738fd1498Szrj    <lambda-sig> ::= <parameter type>+  # Parameter types or "v" if the lambda has no parameters */
165838fd1498Szrj 
165938fd1498Szrj static void
write_closure_type_name(const tree type)166038fd1498Szrj write_closure_type_name (const tree type)
166138fd1498Szrj {
166238fd1498Szrj   tree fn = lambda_function (type);
166338fd1498Szrj   tree lambda = CLASSTYPE_LAMBDA_EXPR (type);
166438fd1498Szrj   tree parms = TYPE_ARG_TYPES (TREE_TYPE (fn));
166538fd1498Szrj 
166638fd1498Szrj   MANGLE_TRACE_TREE ("closure-type-name", type);
166738fd1498Szrj 
166838fd1498Szrj   write_string ("Ul");
166938fd1498Szrj   write_method_parms (parms, /*method_p=*/1, fn);
167038fd1498Szrj   write_char ('E');
167138fd1498Szrj   write_compact_number (LAMBDA_EXPR_DISCRIMINATOR (lambda));
167238fd1498Szrj }
167338fd1498Szrj 
167438fd1498Szrj /* Convert NUMBER to ascii using base BASE and generating at least
167538fd1498Szrj    MIN_DIGITS characters. BUFFER points to the _end_ of the buffer
167638fd1498Szrj    into which to store the characters. Returns the number of
167738fd1498Szrj    characters generated (these will be laid out in advance of where
167838fd1498Szrj    BUFFER points).  */
167938fd1498Szrj 
168038fd1498Szrj static int
hwint_to_ascii(unsigned HOST_WIDE_INT number,const unsigned int base,char * buffer,const unsigned int min_digits)168138fd1498Szrj hwint_to_ascii (unsigned HOST_WIDE_INT number, const unsigned int base,
168238fd1498Szrj 		char *buffer, const unsigned int min_digits)
168338fd1498Szrj {
168438fd1498Szrj   static const char base_digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
168538fd1498Szrj   unsigned digits = 0;
168638fd1498Szrj 
168738fd1498Szrj   while (number)
168838fd1498Szrj     {
168938fd1498Szrj       unsigned HOST_WIDE_INT d = number / base;
169038fd1498Szrj 
169138fd1498Szrj       *--buffer = base_digits[number - d * base];
169238fd1498Szrj       digits++;
169338fd1498Szrj       number = d;
169438fd1498Szrj     }
169538fd1498Szrj   while (digits < min_digits)
169638fd1498Szrj     {
169738fd1498Szrj       *--buffer = base_digits[0];
169838fd1498Szrj       digits++;
169938fd1498Szrj     }
170038fd1498Szrj   return digits;
170138fd1498Szrj }
170238fd1498Szrj 
170338fd1498Szrj /* Non-terminal <number>.
170438fd1498Szrj 
170538fd1498Szrj      <number> ::= [n] </decimal integer/>  */
170638fd1498Szrj 
170738fd1498Szrj static void
write_number(unsigned HOST_WIDE_INT number,const int unsigned_p,const unsigned int base)170838fd1498Szrj write_number (unsigned HOST_WIDE_INT number, const int unsigned_p,
170938fd1498Szrj 	      const unsigned int base)
171038fd1498Szrj {
171138fd1498Szrj   char buffer[sizeof (HOST_WIDE_INT) * 8];
171238fd1498Szrj   unsigned count = 0;
171338fd1498Szrj 
171438fd1498Szrj   if (!unsigned_p && (HOST_WIDE_INT) number < 0)
171538fd1498Szrj     {
171638fd1498Szrj       write_char ('n');
171738fd1498Szrj       number = -((HOST_WIDE_INT) number);
171838fd1498Szrj     }
171938fd1498Szrj   count = hwint_to_ascii (number, base, buffer + sizeof (buffer), 1);
172038fd1498Szrj   write_chars (buffer + sizeof (buffer) - count, count);
172138fd1498Szrj }
172238fd1498Szrj 
172338fd1498Szrj /* Write out an integral CST in decimal. Most numbers are small, and
172438fd1498Szrj    representable in a HOST_WIDE_INT. Occasionally we'll have numbers
172538fd1498Szrj    bigger than that, which we must deal with.  */
172638fd1498Szrj 
172738fd1498Szrj static inline void
write_integer_cst(const tree cst)172838fd1498Szrj write_integer_cst (const tree cst)
172938fd1498Szrj {
173038fd1498Szrj   int sign = tree_int_cst_sgn (cst);
173138fd1498Szrj   widest_int abs_value = wi::abs (wi::to_widest (cst));
173238fd1498Szrj   if (!wi::fits_uhwi_p (abs_value))
173338fd1498Szrj     {
173438fd1498Szrj       /* A bignum. We do this in chunks, each of which fits in a
173538fd1498Szrj 	 HOST_WIDE_INT.  */
173638fd1498Szrj       char buffer[sizeof (HOST_WIDE_INT) * 8 * 2];
173738fd1498Szrj       unsigned HOST_WIDE_INT chunk;
173838fd1498Szrj       unsigned chunk_digits;
173938fd1498Szrj       char *ptr = buffer + sizeof (buffer);
174038fd1498Szrj       unsigned count = 0;
174138fd1498Szrj       tree n, base, type;
174238fd1498Szrj       int done;
174338fd1498Szrj 
174438fd1498Szrj       /* HOST_WIDE_INT must be at least 32 bits, so 10^9 is
174538fd1498Szrj 	 representable.  */
174638fd1498Szrj       chunk = 1000000000;
174738fd1498Szrj       chunk_digits = 9;
174838fd1498Szrj 
174938fd1498Szrj       if (sizeof (HOST_WIDE_INT) >= 8)
175038fd1498Szrj 	{
175138fd1498Szrj 	  /* It is at least 64 bits, so 10^18 is representable.  */
175238fd1498Szrj 	  chunk_digits = 18;
175338fd1498Szrj 	  chunk *= chunk;
175438fd1498Szrj 	}
175538fd1498Szrj 
175638fd1498Szrj       type = c_common_signed_or_unsigned_type (1, TREE_TYPE (cst));
175738fd1498Szrj       base = build_int_cstu (type, chunk);
175838fd1498Szrj       n = wide_int_to_tree (type, wi::to_wide (cst));
175938fd1498Szrj 
176038fd1498Szrj       if (sign < 0)
176138fd1498Szrj 	{
176238fd1498Szrj 	  write_char ('n');
176338fd1498Szrj 	  n = fold_build1_loc (input_location, NEGATE_EXPR, type, n);
176438fd1498Szrj 	}
176538fd1498Szrj       do
176638fd1498Szrj 	{
176738fd1498Szrj 	  tree d = fold_build2_loc (input_location, FLOOR_DIV_EXPR, type, n, base);
176838fd1498Szrj 	  tree tmp = fold_build2_loc (input_location, MULT_EXPR, type, d, base);
176938fd1498Szrj 	  unsigned c;
177038fd1498Szrj 
177138fd1498Szrj 	  done = integer_zerop (d);
177238fd1498Szrj 	  tmp = fold_build2_loc (input_location, MINUS_EXPR, type, n, tmp);
177338fd1498Szrj 	  c = hwint_to_ascii (TREE_INT_CST_LOW (tmp), 10, ptr,
177438fd1498Szrj 			      done ? 1 : chunk_digits);
177538fd1498Szrj 	  ptr -= c;
177638fd1498Szrj 	  count += c;
177738fd1498Szrj 	  n = d;
177838fd1498Szrj 	}
177938fd1498Szrj       while (!done);
178038fd1498Szrj       write_chars (ptr, count);
178138fd1498Szrj     }
178238fd1498Szrj   else
178338fd1498Szrj     {
178438fd1498Szrj       /* A small num.  */
178538fd1498Szrj       if (sign < 0)
178638fd1498Szrj 	write_char ('n');
178738fd1498Szrj       write_unsigned_number (abs_value.to_uhwi ());
178838fd1498Szrj     }
178938fd1498Szrj }
179038fd1498Szrj 
179138fd1498Szrj /* Write out a floating-point literal.
179238fd1498Szrj 
179338fd1498Szrj     "Floating-point literals are encoded using the bit pattern of the
179438fd1498Szrj     target processor's internal representation of that number, as a
179538fd1498Szrj     fixed-length lowercase hexadecimal string, high-order bytes first
179638fd1498Szrj     (even if the target processor would store low-order bytes first).
179738fd1498Szrj     The "n" prefix is not used for floating-point literals; the sign
179838fd1498Szrj     bit is encoded with the rest of the number.
179938fd1498Szrj 
180038fd1498Szrj     Here are some examples, assuming the IEEE standard representation
180138fd1498Szrj     for floating point numbers.  (Spaces are for readability, not
180238fd1498Szrj     part of the encoding.)
180338fd1498Szrj 
180438fd1498Szrj 	1.0f			Lf 3f80 0000 E
180538fd1498Szrj        -1.0f			Lf bf80 0000 E
180638fd1498Szrj 	1.17549435e-38f		Lf 0080 0000 E
180738fd1498Szrj 	1.40129846e-45f		Lf 0000 0001 E
180838fd1498Szrj 	0.0f			Lf 0000 0000 E"
180938fd1498Szrj 
181038fd1498Szrj    Caller is responsible for the Lx and the E.  */
181138fd1498Szrj static void
write_real_cst(const tree value)181238fd1498Szrj write_real_cst (const tree value)
181338fd1498Szrj {
181438fd1498Szrj   long target_real[4];  /* largest supported float */
181538fd1498Szrj   /* Buffer for eight hex digits in a 32-bit number but big enough
181638fd1498Szrj      even for 64-bit long to avoid warnings.  */
181738fd1498Szrj   char buffer[17];
181838fd1498Szrj   int i, limit, dir;
181938fd1498Szrj 
182038fd1498Szrj   tree type = TREE_TYPE (value);
182138fd1498Szrj   int words = GET_MODE_BITSIZE (SCALAR_FLOAT_TYPE_MODE (type)) / 32;
182238fd1498Szrj 
182338fd1498Szrj   real_to_target (target_real, &TREE_REAL_CST (value),
182438fd1498Szrj 		  TYPE_MODE (type));
182538fd1498Szrj 
182638fd1498Szrj   /* The value in target_real is in the target word order,
182738fd1498Szrj      so we must write it out backward if that happens to be
182838fd1498Szrj      little-endian.  write_number cannot be used, it will
182938fd1498Szrj      produce uppercase.  */
183038fd1498Szrj   if (FLOAT_WORDS_BIG_ENDIAN)
183138fd1498Szrj     i = 0, limit = words, dir = 1;
183238fd1498Szrj   else
183338fd1498Szrj     i = words - 1, limit = -1, dir = -1;
183438fd1498Szrj 
183538fd1498Szrj   for (; i != limit; i += dir)
183638fd1498Szrj     {
183738fd1498Szrj       sprintf (buffer, "%08lx", (unsigned long) target_real[i]);
183838fd1498Szrj       write_chars (buffer, 8);
183938fd1498Szrj     }
184038fd1498Szrj }
184138fd1498Szrj 
184238fd1498Szrj /* Non-terminal <identifier>.
184338fd1498Szrj 
184438fd1498Szrj      <identifier> ::= </unqualified source code identifier>  */
184538fd1498Szrj 
184638fd1498Szrj static void
write_identifier(const char * identifier)184738fd1498Szrj write_identifier (const char *identifier)
184838fd1498Szrj {
184938fd1498Szrj   MANGLE_TRACE ("identifier", identifier);
185038fd1498Szrj   write_string (identifier);
185138fd1498Szrj }
185238fd1498Szrj 
185338fd1498Szrj /* Handle constructor productions of non-terminal <special-name>.
185438fd1498Szrj    CTOR is a constructor FUNCTION_DECL.
185538fd1498Szrj 
185638fd1498Szrj      <special-name> ::= C1   # complete object constructor
185738fd1498Szrj 		    ::= C2   # base object constructor
185838fd1498Szrj 		    ::= C3   # complete object allocating constructor
185938fd1498Szrj 
186038fd1498Szrj    Currently, allocating constructors are never used.  */
186138fd1498Szrj 
186238fd1498Szrj static void
write_special_name_constructor(const tree ctor)186338fd1498Szrj write_special_name_constructor (const tree ctor)
186438fd1498Szrj {
186538fd1498Szrj   write_char ('C');
186638fd1498Szrj   bool new_inh = (flag_new_inheriting_ctors
186738fd1498Szrj 		  && DECL_INHERITED_CTOR (ctor));
186838fd1498Szrj   if (new_inh)
186938fd1498Szrj     write_char ('I');
187038fd1498Szrj   if (DECL_BASE_CONSTRUCTOR_P (ctor))
187138fd1498Szrj     write_char ('2');
187238fd1498Szrj   /* This is the old-style "[unified]" constructor.
187338fd1498Szrj      In some cases, we may emit this function and call
187438fd1498Szrj      it from the clones in order to share code and save space.  */
187538fd1498Szrj   else if (DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (ctor))
187638fd1498Szrj     write_char ('4');
187738fd1498Szrj   else
187838fd1498Szrj     {
187938fd1498Szrj       gcc_assert (DECL_COMPLETE_CONSTRUCTOR_P (ctor));
188038fd1498Szrj       write_char ('1');
188138fd1498Szrj     }
188238fd1498Szrj   if (new_inh)
188338fd1498Szrj     write_type (DECL_INHERITED_CTOR_BASE (ctor));
188438fd1498Szrj }
188538fd1498Szrj 
188638fd1498Szrj /* Handle destructor productions of non-terminal <special-name>.
188738fd1498Szrj    DTOR is a destructor FUNCTION_DECL.
188838fd1498Szrj 
188938fd1498Szrj      <special-name> ::= D0 # deleting (in-charge) destructor
189038fd1498Szrj 		    ::= D1 # complete object (in-charge) destructor
189138fd1498Szrj 		    ::= D2 # base object (not-in-charge) destructor  */
189238fd1498Szrj 
189338fd1498Szrj static void
write_special_name_destructor(const tree dtor)189438fd1498Szrj write_special_name_destructor (const tree dtor)
189538fd1498Szrj {
189638fd1498Szrj   if (DECL_DELETING_DESTRUCTOR_P (dtor))
189738fd1498Szrj     write_string ("D0");
189838fd1498Szrj   else if (DECL_BASE_DESTRUCTOR_P (dtor))
189938fd1498Szrj     write_string ("D2");
190038fd1498Szrj   else if (DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P (dtor))
190138fd1498Szrj     /* This is the old-style "[unified]" destructor.
190238fd1498Szrj        In some cases, we may emit this function and call
190338fd1498Szrj        it from the clones in order to share code and save space.  */
190438fd1498Szrj     write_string ("D4");
190538fd1498Szrj   else
190638fd1498Szrj     {
190738fd1498Szrj       gcc_assert (DECL_COMPLETE_DESTRUCTOR_P (dtor));
190838fd1498Szrj       write_string ("D1");
190938fd1498Szrj     }
191038fd1498Szrj }
191138fd1498Szrj 
191238fd1498Szrj /* Scan the vector of local classes and return how many others with the
191338fd1498Szrj    same name (or same no name) and context precede ENTITY.  */
191438fd1498Szrj 
191538fd1498Szrj static int
local_class_index(tree entity)191638fd1498Szrj local_class_index (tree entity)
191738fd1498Szrj {
191838fd1498Szrj   int ix, discriminator = 0;
191938fd1498Szrj   tree name = (TYPE_UNNAMED_P (entity) ? NULL_TREE
192038fd1498Szrj 	       : TYPE_IDENTIFIER (entity));
192138fd1498Szrj   tree ctx = TYPE_CONTEXT (entity);
192238fd1498Szrj   for (ix = 0; ; ix++)
192338fd1498Szrj     {
192438fd1498Szrj       tree type = (*local_classes)[ix];
192538fd1498Szrj       if (type == entity)
192638fd1498Szrj 	return discriminator;
192738fd1498Szrj       if (TYPE_CONTEXT (type) == ctx
192838fd1498Szrj 	  && (name ? TYPE_IDENTIFIER (type) == name
192938fd1498Szrj 	      : TYPE_UNNAMED_P (type)))
193038fd1498Szrj 	++discriminator;
193138fd1498Szrj     }
193238fd1498Szrj   gcc_unreachable ();
193338fd1498Szrj }
193438fd1498Szrj 
193538fd1498Szrj /* Return the discriminator for ENTITY appearing inside
193638fd1498Szrj    FUNCTION.  The discriminator is the lexical ordinal of VAR among
193738fd1498Szrj    entities with the same name in the same FUNCTION.  */
193838fd1498Szrj 
193938fd1498Szrj static int
discriminator_for_local_entity(tree entity)194038fd1498Szrj discriminator_for_local_entity (tree entity)
194138fd1498Szrj {
194238fd1498Szrj   if (DECL_DISCRIMINATOR_P (entity))
194338fd1498Szrj     {
194438fd1498Szrj       if (DECL_DISCRIMINATOR_SET_P (entity))
194538fd1498Szrj 	return DECL_DISCRIMINATOR (entity);
194638fd1498Szrj       else
194738fd1498Szrj 	/* The first entity with a particular name doesn't get
194838fd1498Szrj 	   DECL_DISCRIMINATOR set up.  */
194938fd1498Szrj 	return 0;
195038fd1498Szrj     }
195138fd1498Szrj   else if (TREE_CODE (entity) == TYPE_DECL)
195238fd1498Szrj     {
195338fd1498Szrj       /* Scan the list of local classes.  */
195438fd1498Szrj       entity = TREE_TYPE (entity);
195538fd1498Szrj 
195638fd1498Szrj       /* Lambdas and unnamed types have their own discriminators.  */
195738fd1498Szrj       if (LAMBDA_TYPE_P (entity) || TYPE_UNNAMED_P (entity))
195838fd1498Szrj 	return 0;
195938fd1498Szrj 
196038fd1498Szrj       return local_class_index (entity);
196138fd1498Szrj     }
196238fd1498Szrj   else
196338fd1498Szrj     gcc_unreachable ();
196438fd1498Szrj }
196538fd1498Szrj 
196638fd1498Szrj /* Return the discriminator for STRING, a string literal used inside
196738fd1498Szrj    FUNCTION.  The discriminator is the lexical ordinal of STRING among
196838fd1498Szrj    string literals used in FUNCTION.  */
196938fd1498Szrj 
197038fd1498Szrj static int
discriminator_for_string_literal(tree,tree)197138fd1498Szrj discriminator_for_string_literal (tree /*function*/,
197238fd1498Szrj 				  tree /*string*/)
197338fd1498Szrj {
197438fd1498Szrj   /* For now, we don't discriminate amongst string literals.  */
197538fd1498Szrj   return 0;
197638fd1498Szrj }
197738fd1498Szrj 
197838fd1498Szrj /*   <discriminator> := _ <number>    # when number < 10
197938fd1498Szrj                      := __ <number> _ # when number >= 10
198038fd1498Szrj 
198138fd1498Szrj    The discriminator is used only for the second and later occurrences
198238fd1498Szrj    of the same name within a single function. In this case <number> is
198338fd1498Szrj    n - 2, if this is the nth occurrence, in lexical order.  */
198438fd1498Szrj 
198538fd1498Szrj static void
write_discriminator(const int discriminator)198638fd1498Szrj write_discriminator (const int discriminator)
198738fd1498Szrj {
198838fd1498Szrj   /* If discriminator is zero, don't write anything.  Otherwise...  */
198938fd1498Szrj   if (discriminator > 0)
199038fd1498Szrj     {
199138fd1498Szrj       write_char ('_');
199238fd1498Szrj       if (discriminator - 1 >= 10)
199338fd1498Szrj 	{
199438fd1498Szrj 	  if (abi_warn_or_compat_version_crosses (11))
199538fd1498Szrj 	    G.need_abi_warning = 1;
199638fd1498Szrj 	  if (abi_version_at_least (11))
199738fd1498Szrj 	    write_char ('_');
199838fd1498Szrj 	}
199938fd1498Szrj       write_unsigned_number (discriminator - 1);
200038fd1498Szrj       if (abi_version_at_least (11) && discriminator - 1 >= 10)
200138fd1498Szrj 	write_char ('_');
200238fd1498Szrj     }
200338fd1498Szrj }
200438fd1498Szrj 
200538fd1498Szrj /* Mangle the name of a function-scope entity.  FUNCTION is the
200638fd1498Szrj    FUNCTION_DECL for the enclosing function, or a PARM_DECL for lambdas in
200738fd1498Szrj    default argument scope.  ENTITY is the decl for the entity itself.
200838fd1498Szrj    LOCAL_ENTITY is the entity that's directly scoped in FUNCTION_DECL,
200938fd1498Szrj    either ENTITY itself or an enclosing scope of ENTITY.
201038fd1498Szrj 
201138fd1498Szrj      <local-name> := Z <function encoding> E <entity name> [<discriminator>]
201238fd1498Szrj 		  := Z <function encoding> E s [<discriminator>]
201338fd1498Szrj 		  := Z <function encoding> Ed [ <parameter number> ] _ <entity name> */
201438fd1498Szrj 
201538fd1498Szrj static void
write_local_name(tree function,const tree local_entity,const tree entity)201638fd1498Szrj write_local_name (tree function, const tree local_entity,
201738fd1498Szrj 		  const tree entity)
201838fd1498Szrj {
201938fd1498Szrj   tree parm = NULL_TREE;
202038fd1498Szrj 
202138fd1498Szrj   MANGLE_TRACE_TREE ("local-name", entity);
202238fd1498Szrj 
202338fd1498Szrj   if (TREE_CODE (function) == PARM_DECL)
202438fd1498Szrj     {
202538fd1498Szrj       parm = function;
202638fd1498Szrj       function = DECL_CONTEXT (parm);
202738fd1498Szrj     }
202838fd1498Szrj 
202938fd1498Szrj   write_char ('Z');
203038fd1498Szrj   write_encoding (function);
203138fd1498Szrj   write_char ('E');
203238fd1498Szrj 
203338fd1498Szrj   /* For this purpose, parameters are numbered from right-to-left.  */
203438fd1498Szrj   if (parm)
203538fd1498Szrj     {
203638fd1498Szrj       tree t;
203738fd1498Szrj       int i = 0;
203838fd1498Szrj       for (t = DECL_ARGUMENTS (function); t; t = DECL_CHAIN (t))
203938fd1498Szrj 	{
204038fd1498Szrj 	  if (t == parm)
204138fd1498Szrj 	    i = 1;
204238fd1498Szrj 	  else if (i)
204338fd1498Szrj 	    ++i;
204438fd1498Szrj 	}
204538fd1498Szrj       write_char ('d');
204638fd1498Szrj       write_compact_number (i - 1);
204738fd1498Szrj     }
204838fd1498Szrj 
204938fd1498Szrj   if (TREE_CODE (entity) == STRING_CST)
205038fd1498Szrj     {
205138fd1498Szrj       write_char ('s');
205238fd1498Szrj       write_discriminator (discriminator_for_string_literal (function,
205338fd1498Szrj 							     entity));
205438fd1498Szrj     }
205538fd1498Szrj   else
205638fd1498Szrj     {
205738fd1498Szrj       /* Now the <entity name>.  Let write_name know its being called
205838fd1498Szrj 	 from <local-name>, so it doesn't try to process the enclosing
205938fd1498Szrj 	 function scope again.  */
206038fd1498Szrj       write_name (entity, /*ignore_local_scope=*/1);
206138fd1498Szrj       write_discriminator (discriminator_for_local_entity (local_entity));
206238fd1498Szrj     }
206338fd1498Szrj }
206438fd1498Szrj 
206538fd1498Szrj /* Non-terminals <type> and <CV-qualifier>.
206638fd1498Szrj 
206738fd1498Szrj      <type> ::= <builtin-type>
206838fd1498Szrj 	    ::= <function-type>
206938fd1498Szrj 	    ::= <class-enum-type>
207038fd1498Szrj 	    ::= <array-type>
207138fd1498Szrj 	    ::= <pointer-to-member-type>
207238fd1498Szrj 	    ::= <template-param>
207338fd1498Szrj 	    ::= <substitution>
207438fd1498Szrj 	    ::= <CV-qualifier>
207538fd1498Szrj 	    ::= P <type>    # pointer-to
207638fd1498Szrj 	    ::= R <type>    # reference-to
207738fd1498Szrj 	    ::= C <type>    # complex pair (C 2000)
207838fd1498Szrj 	    ::= G <type>    # imaginary (C 2000)     [not supported]
207938fd1498Szrj 	    ::= U <source-name> <type>   # vendor extended type qualifier
208038fd1498Szrj 
208138fd1498Szrj    C++0x extensions
208238fd1498Szrj 
208338fd1498Szrj      <type> ::= RR <type>   # rvalue reference-to
208438fd1498Szrj      <type> ::= Dt <expression> # decltype of an id-expression or
208538fd1498Szrj                                 # class member access
208638fd1498Szrj      <type> ::= DT <expression> # decltype of an expression
208738fd1498Szrj      <type> ::= Dn              # decltype of nullptr
208838fd1498Szrj 
208938fd1498Szrj    TYPE is a type node.  */
209038fd1498Szrj 
209138fd1498Szrj static void
write_type(tree type)209238fd1498Szrj write_type (tree type)
209338fd1498Szrj {
209438fd1498Szrj   /* This gets set to nonzero if TYPE turns out to be a (possibly
209538fd1498Szrj      CV-qualified) builtin type.  */
209638fd1498Szrj   int is_builtin_type = 0;
209738fd1498Szrj 
209838fd1498Szrj   MANGLE_TRACE_TREE ("type", type);
209938fd1498Szrj 
210038fd1498Szrj   if (type == error_mark_node)
210138fd1498Szrj     return;
210238fd1498Szrj 
210338fd1498Szrj   type = canonicalize_for_substitution (type);
210438fd1498Szrj   if (find_substitution (type))
210538fd1498Szrj     return;
210638fd1498Szrj 
210738fd1498Szrj 
210838fd1498Szrj   if (write_CV_qualifiers_for_type (type) > 0)
210938fd1498Szrj     /* If TYPE was CV-qualified, we just wrote the qualifiers; now
211038fd1498Szrj        mangle the unqualified type.  The recursive call is needed here
211138fd1498Szrj        since both the qualified and unqualified types are substitution
211238fd1498Szrj        candidates.  */
211338fd1498Szrj     {
211438fd1498Szrj       tree t = TYPE_MAIN_VARIANT (type);
211538fd1498Szrj       if (TYPE_ATTRIBUTES (t) && !OVERLOAD_TYPE_P (t))
211638fd1498Szrj 	{
211738fd1498Szrj 	  tree attrs = NULL_TREE;
211838fd1498Szrj 	  if (tx_safe_fn_type_p (type))
211938fd1498Szrj 	    attrs = tree_cons (get_identifier ("transaction_safe"),
212038fd1498Szrj 			       NULL_TREE, attrs);
212138fd1498Szrj 	  t = cp_build_type_attribute_variant (t, attrs);
212238fd1498Szrj 	}
212338fd1498Szrj       gcc_assert (t != type);
212438fd1498Szrj       if (TREE_CODE (t) == FUNCTION_TYPE
212538fd1498Szrj 	  || TREE_CODE (t) == METHOD_TYPE)
212638fd1498Szrj 	{
212738fd1498Szrj 	  t = build_ref_qualified_type (t, type_memfn_rqual (type));
212838fd1498Szrj 	  if (flag_noexcept_type)
212938fd1498Szrj 	    {
213038fd1498Szrj 	      tree r = TYPE_RAISES_EXCEPTIONS (type);
213138fd1498Szrj 	      t = build_exception_variant (t, r);
213238fd1498Szrj 	    }
213338fd1498Szrj 	  if (abi_version_at_least (8)
213438fd1498Szrj 	      || type == TYPE_MAIN_VARIANT (type))
213538fd1498Szrj 	    /* Avoid adding the unqualified function type as a substitution.  */
213638fd1498Szrj 	    write_function_type (t);
213738fd1498Szrj 	  else
213838fd1498Szrj 	    write_type (t);
213938fd1498Szrj 	  if (abi_warn_or_compat_version_crosses (8))
214038fd1498Szrj 	    G.need_abi_warning = 1;
214138fd1498Szrj 	}
214238fd1498Szrj       else
214338fd1498Szrj 	write_type (t);
214438fd1498Szrj     }
214538fd1498Szrj   else if (TREE_CODE (type) == ARRAY_TYPE)
214638fd1498Szrj     /* It is important not to use the TYPE_MAIN_VARIANT of TYPE here
214738fd1498Szrj        so that the cv-qualification of the element type is available
214838fd1498Szrj        in write_array_type.  */
214938fd1498Szrj     write_array_type (type);
215038fd1498Szrj   else
215138fd1498Szrj     {
215238fd1498Szrj       tree type_orig = type;
215338fd1498Szrj 
215438fd1498Szrj       /* See through any typedefs.  */
215538fd1498Szrj       type = TYPE_MAIN_VARIANT (type);
215638fd1498Szrj       if (TREE_CODE (type) == FUNCTION_TYPE
215738fd1498Szrj 	  || TREE_CODE (type) == METHOD_TYPE)
215838fd1498Szrj 	{
215938fd1498Szrj 	  type = build_ref_qualified_type (type, type_memfn_rqual (type_orig));
216038fd1498Szrj 	  type = build_exception_variant (type,
216138fd1498Szrj 					  TYPE_RAISES_EXCEPTIONS (type_orig));
216238fd1498Szrj 	}
216338fd1498Szrj 
216438fd1498Szrj       /* According to the C++ ABI, some library classes are passed the
216538fd1498Szrj 	 same as the scalar type of their single member and use the same
216638fd1498Szrj 	 mangling.  */
216738fd1498Szrj       if (TREE_CODE (type) == RECORD_TYPE && TYPE_TRANSPARENT_AGGR (type))
216838fd1498Szrj 	type = TREE_TYPE (first_field (type));
216938fd1498Szrj 
217038fd1498Szrj       if (TYPE_PTRDATAMEM_P (type))
217138fd1498Szrj 	write_pointer_to_member_type (type);
217238fd1498Szrj       else
217338fd1498Szrj         {
217438fd1498Szrj 	  /* Handle any target-specific fundamental types.  */
217538fd1498Szrj 	  const char *target_mangling
217638fd1498Szrj 	    = targetm.mangle_type (type_orig);
217738fd1498Szrj 
217838fd1498Szrj 	  if (target_mangling)
217938fd1498Szrj 	    {
218038fd1498Szrj 	      write_string (target_mangling);
218138fd1498Szrj 	      /* Add substitutions for types other than fundamental
218238fd1498Szrj 		 types.  */
218338fd1498Szrj 	      if (!VOID_TYPE_P (type)
218438fd1498Szrj 		  && TREE_CODE (type) != INTEGER_TYPE
218538fd1498Szrj 		  && TREE_CODE (type) != REAL_TYPE
218638fd1498Szrj 		  && TREE_CODE (type) != BOOLEAN_TYPE)
218738fd1498Szrj 		add_substitution (type);
218838fd1498Szrj 	      return;
218938fd1498Szrj 	    }
219038fd1498Szrj 
219138fd1498Szrj 	  switch (TREE_CODE (type))
219238fd1498Szrj 	    {
219338fd1498Szrj 	    case VOID_TYPE:
219438fd1498Szrj 	    case BOOLEAN_TYPE:
219538fd1498Szrj 	    case INTEGER_TYPE:  /* Includes wchar_t.  */
219638fd1498Szrj 	    case REAL_TYPE:
219738fd1498Szrj 	    case FIXED_POINT_TYPE:
219838fd1498Szrj 	      {
219938fd1498Szrj 		/* If this is a typedef, TYPE may not be one of
220038fd1498Szrj 		   the standard builtin type nodes, but an alias of one.  Use
220138fd1498Szrj 		   TYPE_MAIN_VARIANT to get to the underlying builtin type.  */
220238fd1498Szrj 		write_builtin_type (TYPE_MAIN_VARIANT (type));
220338fd1498Szrj 		++is_builtin_type;
220438fd1498Szrj 	      }
220538fd1498Szrj 	      break;
220638fd1498Szrj 
220738fd1498Szrj 	    case COMPLEX_TYPE:
220838fd1498Szrj 	      write_char ('C');
220938fd1498Szrj 	      write_type (TREE_TYPE (type));
221038fd1498Szrj 	      break;
221138fd1498Szrj 
221238fd1498Szrj 	    case FUNCTION_TYPE:
221338fd1498Szrj 	    case METHOD_TYPE:
221438fd1498Szrj 	      write_function_type (type);
221538fd1498Szrj 	      break;
221638fd1498Szrj 
221738fd1498Szrj 	    case UNION_TYPE:
221838fd1498Szrj 	    case RECORD_TYPE:
221938fd1498Szrj 	    case ENUMERAL_TYPE:
222038fd1498Szrj 	      /* A pointer-to-member function is represented as a special
222138fd1498Szrj 		 RECORD_TYPE, so check for this first.  */
222238fd1498Szrj 	      if (TYPE_PTRMEMFUNC_P (type))
222338fd1498Szrj 		write_pointer_to_member_type (type);
222438fd1498Szrj 	      else
222538fd1498Szrj 		write_class_enum_type (type);
222638fd1498Szrj 	      break;
222738fd1498Szrj 
222838fd1498Szrj 	    case TYPENAME_TYPE:
222938fd1498Szrj 	    case UNBOUND_CLASS_TEMPLATE:
223038fd1498Szrj 	      /* We handle TYPENAME_TYPEs and UNBOUND_CLASS_TEMPLATEs like
223138fd1498Szrj 		 ordinary nested names.  */
223238fd1498Szrj 	      write_nested_name (TYPE_STUB_DECL (type));
223338fd1498Szrj 	      break;
223438fd1498Szrj 
223538fd1498Szrj 	    case POINTER_TYPE:
223638fd1498Szrj 	    case REFERENCE_TYPE:
223738fd1498Szrj 	      if (TYPE_PTR_P (type))
223838fd1498Szrj 		write_char ('P');
223938fd1498Szrj 	      else if (TYPE_REF_IS_RVALUE (type))
224038fd1498Szrj 		write_char ('O');
224138fd1498Szrj               else
224238fd1498Szrj                 write_char ('R');
224338fd1498Szrj 	      {
224438fd1498Szrj 		tree target = TREE_TYPE (type);
224538fd1498Szrj 		/* Attribute const/noreturn are not reflected in mangling.
224638fd1498Szrj 		   We strip them here rather than at a lower level because
224738fd1498Szrj 		   a typedef or template argument can have function type
224838fd1498Szrj 		   with function-cv-quals (that use the same representation),
224938fd1498Szrj 		   but you can't have a pointer/reference to such a type.  */
225038fd1498Szrj 		if (TREE_CODE (target) == FUNCTION_TYPE)
225138fd1498Szrj 		  {
225238fd1498Szrj 		    if (abi_warn_or_compat_version_crosses (5)
225338fd1498Szrj 			&& TYPE_QUALS (target) != TYPE_UNQUALIFIED)
225438fd1498Szrj 		      G.need_abi_warning = 1;
225538fd1498Szrj 		    if (abi_version_at_least (5))
225638fd1498Szrj 		      target = build_qualified_type (target, TYPE_UNQUALIFIED);
225738fd1498Szrj 		  }
225838fd1498Szrj 		write_type (target);
225938fd1498Szrj 	      }
226038fd1498Szrj 	      break;
226138fd1498Szrj 
226238fd1498Szrj 	    case TEMPLATE_TYPE_PARM:
226338fd1498Szrj 	      if (is_auto (type))
226438fd1498Szrj 		{
226538fd1498Szrj 		  if (AUTO_IS_DECLTYPE (type))
226638fd1498Szrj 		    write_identifier ("Dc");
226738fd1498Szrj 		  else
226838fd1498Szrj 		    write_identifier ("Da");
226938fd1498Szrj 		  ++is_builtin_type;
227038fd1498Szrj 		  break;
227138fd1498Szrj 		}
227238fd1498Szrj 	      /* fall through.  */
227338fd1498Szrj 	    case TEMPLATE_PARM_INDEX:
227438fd1498Szrj 	      write_template_param (type);
227538fd1498Szrj 	      break;
227638fd1498Szrj 
227738fd1498Szrj 	    case TEMPLATE_TEMPLATE_PARM:
227838fd1498Szrj 	      write_template_template_param (type);
227938fd1498Szrj 	      break;
228038fd1498Szrj 
228138fd1498Szrj 	    case BOUND_TEMPLATE_TEMPLATE_PARM:
228238fd1498Szrj 	      write_template_template_param (type);
228338fd1498Szrj 	      write_template_args
228438fd1498Szrj 		(TI_ARGS (TEMPLATE_TEMPLATE_PARM_TEMPLATE_INFO (type)));
228538fd1498Szrj 	      break;
228638fd1498Szrj 
228738fd1498Szrj 	    case VECTOR_TYPE:
228838fd1498Szrj 	      if (abi_version_at_least (4))
228938fd1498Szrj 		{
229038fd1498Szrj 		  write_string ("Dv");
229138fd1498Szrj 		  /* Non-constant vector size would be encoded with
229238fd1498Szrj 		     _ expression, but we don't support that yet.  */
229338fd1498Szrj 		  write_unsigned_number (TYPE_VECTOR_SUBPARTS (type)
229438fd1498Szrj 					 .to_constant ());
229538fd1498Szrj 		  write_char ('_');
229638fd1498Szrj 		}
229738fd1498Szrj 	      else
229838fd1498Szrj 		write_string ("U8__vector");
229938fd1498Szrj 	      if (abi_warn_or_compat_version_crosses (4))
230038fd1498Szrj 		G.need_abi_warning = 1;
230138fd1498Szrj 	      write_type (TREE_TYPE (type));
230238fd1498Szrj 	      break;
230338fd1498Szrj 
230438fd1498Szrj             case TYPE_PACK_EXPANSION:
230538fd1498Szrj               write_string ("Dp");
230638fd1498Szrj               write_type (PACK_EXPANSION_PATTERN (type));
230738fd1498Szrj               break;
230838fd1498Szrj 
230938fd1498Szrj             case DECLTYPE_TYPE:
231038fd1498Szrj 	      /* These shouldn't make it into mangling.  */
231138fd1498Szrj 	      gcc_assert (!DECLTYPE_FOR_LAMBDA_CAPTURE (type)
231238fd1498Szrj 			  && !DECLTYPE_FOR_LAMBDA_PROXY (type));
231338fd1498Szrj 
231438fd1498Szrj 	      /* In ABI <5, we stripped decltype of a plain decl.  */
231538fd1498Szrj 	      if (DECLTYPE_TYPE_ID_EXPR_OR_MEMBER_ACCESS_P (type))
231638fd1498Szrj 		{
231738fd1498Szrj 		  tree expr = DECLTYPE_TYPE_EXPR (type);
231838fd1498Szrj 		  tree etype = NULL_TREE;
231938fd1498Szrj 		  switch (TREE_CODE (expr))
232038fd1498Szrj 		    {
232138fd1498Szrj 		    case VAR_DECL:
232238fd1498Szrj 		    case PARM_DECL:
232338fd1498Szrj 		    case RESULT_DECL:
232438fd1498Szrj 		    case FUNCTION_DECL:
232538fd1498Szrj 		    case CONST_DECL:
232638fd1498Szrj 		    case TEMPLATE_PARM_INDEX:
232738fd1498Szrj 		      etype = TREE_TYPE (expr);
232838fd1498Szrj 		      break;
232938fd1498Szrj 
233038fd1498Szrj 		    default:
233138fd1498Szrj 		      break;
233238fd1498Szrj 		    }
233338fd1498Szrj 
233438fd1498Szrj 		  if (etype && !type_uses_auto (etype))
233538fd1498Szrj 		    {
233638fd1498Szrj 		      if (abi_warn_or_compat_version_crosses (5))
233738fd1498Szrj 			G.need_abi_warning = 1;
233838fd1498Szrj 		      if (!abi_version_at_least (5))
233938fd1498Szrj 			{
234038fd1498Szrj 			  write_type (etype);
234138fd1498Szrj 			  return;
234238fd1498Szrj 			}
234338fd1498Szrj 		    }
234438fd1498Szrj 		}
234538fd1498Szrj 
234638fd1498Szrj               write_char ('D');
234738fd1498Szrj               if (DECLTYPE_TYPE_ID_EXPR_OR_MEMBER_ACCESS_P (type))
234838fd1498Szrj                 write_char ('t');
234938fd1498Szrj               else
235038fd1498Szrj                 write_char ('T');
235138fd1498Szrj 	      ++cp_unevaluated_operand;
235238fd1498Szrj               write_expression (DECLTYPE_TYPE_EXPR (type));
235338fd1498Szrj 	      --cp_unevaluated_operand;
235438fd1498Szrj               write_char ('E');
235538fd1498Szrj               break;
235638fd1498Szrj 
235738fd1498Szrj 	    case NULLPTR_TYPE:
235838fd1498Szrj 	      write_string ("Dn");
235938fd1498Szrj 	      if (abi_version_at_least (7))
236038fd1498Szrj 		++is_builtin_type;
236138fd1498Szrj 	      if (abi_warn_or_compat_version_crosses (7))
236238fd1498Szrj 		G.need_abi_warning = 1;
236338fd1498Szrj 	      break;
236438fd1498Szrj 
236538fd1498Szrj 	    case TYPEOF_TYPE:
236638fd1498Szrj 	      sorry ("mangling typeof, use decltype instead");
236738fd1498Szrj 	      break;
236838fd1498Szrj 
236938fd1498Szrj 	    case UNDERLYING_TYPE:
237038fd1498Szrj 	      sorry ("mangling __underlying_type");
237138fd1498Szrj 	      break;
237238fd1498Szrj 
237338fd1498Szrj 	    case LANG_TYPE:
237438fd1498Szrj 	      /* fall through.  */
237538fd1498Szrj 
237638fd1498Szrj 	    default:
237738fd1498Szrj 	      gcc_unreachable ();
237838fd1498Szrj 	    }
237938fd1498Szrj 	}
238038fd1498Szrj     }
238138fd1498Szrj 
238238fd1498Szrj   /* Types other than builtin types are substitution candidates.  */
238338fd1498Szrj   if (!is_builtin_type)
238438fd1498Szrj     add_substitution (type);
238538fd1498Szrj }
238638fd1498Szrj 
238738fd1498Szrj /* qsort callback for sorting a vector of attribute entries.  */
238838fd1498Szrj 
238938fd1498Szrj static int
attr_strcmp(const void * p1,const void * p2)239038fd1498Szrj attr_strcmp (const void *p1, const void *p2)
239138fd1498Szrj {
239238fd1498Szrj   tree a1 = *(const tree*)p1;
239338fd1498Szrj   tree a2 = *(const tree*)p2;
239438fd1498Szrj 
239538fd1498Szrj   const attribute_spec *as1 = lookup_attribute_spec (get_attribute_name (a1));
239638fd1498Szrj   const attribute_spec *as2 = lookup_attribute_spec (get_attribute_name (a2));
239738fd1498Szrj 
239838fd1498Szrj   return strcmp (as1->name, as2->name);
239938fd1498Szrj }
240038fd1498Szrj 
240138fd1498Szrj /* Non-terminal <CV-qualifiers> for type nodes.  Returns the number of
240238fd1498Szrj    CV-qualifiers written for TYPE.
240338fd1498Szrj 
240438fd1498Szrj      <CV-qualifiers> ::= [r] [V] [K]  */
240538fd1498Szrj 
240638fd1498Szrj static int
write_CV_qualifiers_for_type(const tree type)240738fd1498Szrj write_CV_qualifiers_for_type (const tree type)
240838fd1498Szrj {
240938fd1498Szrj   int num_qualifiers = 0;
241038fd1498Szrj 
241138fd1498Szrj   /* The order is specified by:
241238fd1498Szrj 
241338fd1498Szrj        "In cases where multiple order-insensitive qualifiers are
241438fd1498Szrj        present, they should be ordered 'K' (closest to the base type),
241538fd1498Szrj        'V', 'r', and 'U' (farthest from the base type) ..."  */
241638fd1498Szrj 
241738fd1498Szrj   /* Mangle attributes that affect type identity as extended qualifiers.
241838fd1498Szrj 
241938fd1498Szrj      We don't do this with classes and enums because their attributes
242038fd1498Szrj      are part of their definitions, not something added on.  */
242138fd1498Szrj 
242238fd1498Szrj   if (!OVERLOAD_TYPE_P (type))
242338fd1498Szrj     {
242438fd1498Szrj       auto_vec<tree> vec;
242538fd1498Szrj       for (tree a = TYPE_ATTRIBUTES (type); a; a = TREE_CHAIN (a))
242638fd1498Szrj 	{
242738fd1498Szrj 	  tree name = get_attribute_name (a);
242838fd1498Szrj 	  const attribute_spec *as = lookup_attribute_spec (name);
242938fd1498Szrj 	  if (as && as->affects_type_identity
243038fd1498Szrj 	      && !is_attribute_p ("transaction_safe", name)
243138fd1498Szrj 	      && !is_attribute_p ("abi_tag", name))
243238fd1498Szrj 	    vec.safe_push (a);
243338fd1498Szrj 	}
243438fd1498Szrj       if (abi_warn_or_compat_version_crosses (10) && !vec.is_empty ())
243538fd1498Szrj 	G.need_abi_warning = true;
243638fd1498Szrj       if (abi_version_at_least (10))
243738fd1498Szrj 	{
243838fd1498Szrj 	  vec.qsort (attr_strcmp);
243938fd1498Szrj 	  while (!vec.is_empty())
244038fd1498Szrj 	    {
244138fd1498Szrj 	      tree a = vec.pop();
244238fd1498Szrj 	      const attribute_spec *as
244338fd1498Szrj 		= lookup_attribute_spec (get_attribute_name (a));
244438fd1498Szrj 
244538fd1498Szrj 	      write_char ('U');
244638fd1498Szrj 	      write_unsigned_number (strlen (as->name));
244738fd1498Szrj 	      write_string (as->name);
244838fd1498Szrj 	      if (TREE_VALUE (a))
244938fd1498Szrj 		{
245038fd1498Szrj 		  write_char ('I');
245138fd1498Szrj 		  for (tree args = TREE_VALUE (a); args;
245238fd1498Szrj 		       args = TREE_CHAIN (args))
245338fd1498Szrj 		    {
245438fd1498Szrj 		      tree arg = TREE_VALUE (args);
245538fd1498Szrj 		      write_template_arg (arg);
245638fd1498Szrj 		    }
245738fd1498Szrj 		  write_char ('E');
245838fd1498Szrj 		}
245938fd1498Szrj 
246038fd1498Szrj 	      ++num_qualifiers;
246138fd1498Szrj 	    }
246238fd1498Szrj 	}
246338fd1498Szrj     }
246438fd1498Szrj 
246538fd1498Szrj   /* Note that we do not use cp_type_quals below; given "const
246638fd1498Szrj      int[3]", the "const" is emitted with the "int", not with the
246738fd1498Szrj      array.  */
246838fd1498Szrj   cp_cv_quals quals = TYPE_QUALS (type);
246938fd1498Szrj 
247038fd1498Szrj   if (quals & TYPE_QUAL_RESTRICT)
247138fd1498Szrj     {
247238fd1498Szrj       write_char ('r');
247338fd1498Szrj       ++num_qualifiers;
247438fd1498Szrj     }
247538fd1498Szrj   if (quals & TYPE_QUAL_VOLATILE)
247638fd1498Szrj     {
247738fd1498Szrj       write_char ('V');
247838fd1498Szrj       ++num_qualifiers;
247938fd1498Szrj     }
248038fd1498Szrj   if (quals & TYPE_QUAL_CONST)
248138fd1498Szrj     {
248238fd1498Szrj       write_char ('K');
248338fd1498Szrj       ++num_qualifiers;
248438fd1498Szrj     }
248538fd1498Szrj 
248638fd1498Szrj   return num_qualifiers;
248738fd1498Szrj }
248838fd1498Szrj 
248938fd1498Szrj /* Non-terminal <builtin-type>.
249038fd1498Szrj 
249138fd1498Szrj      <builtin-type> ::= v   # void
249238fd1498Szrj 		    ::= b   # bool
249338fd1498Szrj 		    ::= w   # wchar_t
249438fd1498Szrj 		    ::= c   # char
249538fd1498Szrj 		    ::= a   # signed char
249638fd1498Szrj 		    ::= h   # unsigned char
249738fd1498Szrj 		    ::= s   # short
249838fd1498Szrj 		    ::= t   # unsigned short
249938fd1498Szrj 		    ::= i   # int
250038fd1498Szrj 		    ::= j   # unsigned int
250138fd1498Szrj 		    ::= l   # long
250238fd1498Szrj 		    ::= m   # unsigned long
250338fd1498Szrj 		    ::= x   # long long, __int64
250438fd1498Szrj 		    ::= y   # unsigned long long, __int64
250538fd1498Szrj 		    ::= n   # __int128
250638fd1498Szrj 		    ::= o   # unsigned __int128
250738fd1498Szrj 		    ::= f   # float
250838fd1498Szrj 		    ::= d   # double
250938fd1498Szrj 		    ::= e   # long double, __float80
251038fd1498Szrj 		    ::= g   # __float128          [not supported]
251138fd1498Szrj 		    ::= u <source-name>  # vendor extended type */
251238fd1498Szrj 
251338fd1498Szrj static void
write_builtin_type(tree type)251438fd1498Szrj write_builtin_type (tree type)
251538fd1498Szrj {
251638fd1498Szrj   if (TYPE_CANONICAL (type))
251738fd1498Szrj     type = TYPE_CANONICAL (type);
251838fd1498Szrj 
251938fd1498Szrj   switch (TREE_CODE (type))
252038fd1498Szrj     {
252138fd1498Szrj     case VOID_TYPE:
252238fd1498Szrj       write_char ('v');
252338fd1498Szrj       break;
252438fd1498Szrj 
252538fd1498Szrj     case BOOLEAN_TYPE:
252638fd1498Szrj       write_char ('b');
252738fd1498Szrj       break;
252838fd1498Szrj 
252938fd1498Szrj     case INTEGER_TYPE:
253038fd1498Szrj       /* TYPE may still be wchar_t, char16_t, or char32_t, since that
253138fd1498Szrj 	 isn't in integer_type_nodes.  */
253238fd1498Szrj       if (type == wchar_type_node)
253338fd1498Szrj 	write_char ('w');
253438fd1498Szrj       else if (type == char16_type_node)
253538fd1498Szrj 	write_string ("Ds");
253638fd1498Szrj       else if (type == char32_type_node)
253738fd1498Szrj 	write_string ("Di");
253838fd1498Szrj       else
253938fd1498Szrj 	{
254038fd1498Szrj 	  size_t itk;
254138fd1498Szrj 	  /* Assume TYPE is one of the shared integer type nodes.  Find
254238fd1498Szrj 	     it in the array of these nodes.  */
254338fd1498Szrj 	iagain:
254438fd1498Szrj 	  for (itk = 0; itk < itk_none; ++itk)
254538fd1498Szrj 	    if (integer_types[itk] != NULL_TREE
254638fd1498Szrj 		&& integer_type_codes[itk] != '\0'
254738fd1498Szrj 		&& type == integer_types[itk])
254838fd1498Szrj 	      {
254938fd1498Szrj 		/* Print the corresponding single-letter code.  */
255038fd1498Szrj 		write_char (integer_type_codes[itk]);
255138fd1498Szrj 		break;
255238fd1498Szrj 	      }
255338fd1498Szrj 
255438fd1498Szrj 	  if (itk == itk_none)
255538fd1498Szrj 	    {
255638fd1498Szrj 	      tree t = c_common_type_for_mode (TYPE_MODE (type),
255738fd1498Szrj 					       TYPE_UNSIGNED (type));
255838fd1498Szrj 	      if (type != t)
255938fd1498Szrj 		{
256038fd1498Szrj 		  type = t;
256138fd1498Szrj 		  goto iagain;
256238fd1498Szrj 		}
256338fd1498Szrj 
256438fd1498Szrj 	      if (TYPE_PRECISION (type) == 128)
256538fd1498Szrj 		write_char (TYPE_UNSIGNED (type) ? 'o' : 'n');
256638fd1498Szrj 	      else
256738fd1498Szrj 		{
256838fd1498Szrj 		  /* Allow for cases where TYPE is not one of the shared
256938fd1498Szrj 		     integer type nodes and write a "vendor extended builtin
257038fd1498Szrj 		     type" with a name the form intN or uintN, respectively.
257138fd1498Szrj 		     Situations like this can happen if you have an
257238fd1498Szrj 		     __attribute__((__mode__(__SI__))) type and use exotic
257338fd1498Szrj 		     switches like '-mint8' on AVR.  Of course, this is
257438fd1498Szrj 		     undefined by the C++ ABI (and '-mint8' is not even
257538fd1498Szrj 		     Standard C conforming), but when using such special
257638fd1498Szrj 		     options you're pretty much in nowhere land anyway.  */
257738fd1498Szrj 		  const char *prefix;
257838fd1498Szrj 		  char prec[11];	/* up to ten digits for an unsigned */
257938fd1498Szrj 
258038fd1498Szrj 		  prefix = TYPE_UNSIGNED (type) ? "uint" : "int";
258138fd1498Szrj 		  sprintf (prec, "%u", (unsigned) TYPE_PRECISION (type));
258238fd1498Szrj 		  write_char ('u');	/* "vendor extended builtin type" */
258338fd1498Szrj 		  write_unsigned_number (strlen (prefix) + strlen (prec));
258438fd1498Szrj 		  write_string (prefix);
258538fd1498Szrj 		  write_string (prec);
258638fd1498Szrj 		}
258738fd1498Szrj 	    }
258838fd1498Szrj 	}
258938fd1498Szrj       break;
259038fd1498Szrj 
259138fd1498Szrj     case REAL_TYPE:
259238fd1498Szrj       if (type == float_type_node)
259338fd1498Szrj 	write_char ('f');
259438fd1498Szrj       else if (type == double_type_node)
259538fd1498Szrj 	write_char ('d');
259638fd1498Szrj       else if (type == long_double_type_node)
259738fd1498Szrj 	write_char ('e');
259838fd1498Szrj       else if (type == dfloat32_type_node)
259938fd1498Szrj 	write_string ("Df");
260038fd1498Szrj       else if (type == dfloat64_type_node)
260138fd1498Szrj 	write_string ("Dd");
260238fd1498Szrj       else if (type == dfloat128_type_node)
260338fd1498Szrj 	write_string ("De");
260438fd1498Szrj       else
260538fd1498Szrj 	gcc_unreachable ();
260638fd1498Szrj       break;
260738fd1498Szrj 
260838fd1498Szrj     case FIXED_POINT_TYPE:
260938fd1498Szrj       write_string ("DF");
261038fd1498Szrj       if (GET_MODE_IBIT (TYPE_MODE (type)) > 0)
261138fd1498Szrj 	write_unsigned_number (GET_MODE_IBIT (TYPE_MODE (type)));
261238fd1498Szrj       if (type == fract_type_node
261338fd1498Szrj 	  || type == sat_fract_type_node
261438fd1498Szrj 	  || type == accum_type_node
261538fd1498Szrj 	  || type == sat_accum_type_node)
261638fd1498Szrj 	write_char ('i');
261738fd1498Szrj       else if (type == unsigned_fract_type_node
261838fd1498Szrj 	       || type == sat_unsigned_fract_type_node
261938fd1498Szrj 	       || type == unsigned_accum_type_node
262038fd1498Szrj 	       || type == sat_unsigned_accum_type_node)
262138fd1498Szrj 	write_char ('j');
262238fd1498Szrj       else if (type == short_fract_type_node
262338fd1498Szrj 	       || type == sat_short_fract_type_node
262438fd1498Szrj 	       || type == short_accum_type_node
262538fd1498Szrj 	       || type == sat_short_accum_type_node)
262638fd1498Szrj 	write_char ('s');
262738fd1498Szrj       else if (type == unsigned_short_fract_type_node
262838fd1498Szrj 	       || type == sat_unsigned_short_fract_type_node
262938fd1498Szrj 	       || type == unsigned_short_accum_type_node
263038fd1498Szrj 	       || type == sat_unsigned_short_accum_type_node)
263138fd1498Szrj 	write_char ('t');
263238fd1498Szrj       else if (type == long_fract_type_node
263338fd1498Szrj 	       || type == sat_long_fract_type_node
263438fd1498Szrj 	       || type == long_accum_type_node
263538fd1498Szrj 	       || type == sat_long_accum_type_node)
263638fd1498Szrj 	write_char ('l');
263738fd1498Szrj       else if (type == unsigned_long_fract_type_node
263838fd1498Szrj 	       || type == sat_unsigned_long_fract_type_node
263938fd1498Szrj 	       || type == unsigned_long_accum_type_node
264038fd1498Szrj 	       || type == sat_unsigned_long_accum_type_node)
264138fd1498Szrj 	write_char ('m');
264238fd1498Szrj       else if (type == long_long_fract_type_node
264338fd1498Szrj 	       || type == sat_long_long_fract_type_node
264438fd1498Szrj 	       || type == long_long_accum_type_node
264538fd1498Szrj 	       || type == sat_long_long_accum_type_node)
264638fd1498Szrj 	write_char ('x');
264738fd1498Szrj       else if (type == unsigned_long_long_fract_type_node
264838fd1498Szrj 	       || type == sat_unsigned_long_long_fract_type_node
264938fd1498Szrj 	       || type == unsigned_long_long_accum_type_node
265038fd1498Szrj 	       || type == sat_unsigned_long_long_accum_type_node)
265138fd1498Szrj 	write_char ('y');
265238fd1498Szrj       else
265338fd1498Szrj 	sorry ("mangling unknown fixed point type");
265438fd1498Szrj       write_unsigned_number (GET_MODE_FBIT (TYPE_MODE (type)));
265538fd1498Szrj       if (TYPE_SATURATING (type))
265638fd1498Szrj 	write_char ('s');
265738fd1498Szrj       else
265838fd1498Szrj 	write_char ('n');
265938fd1498Szrj       break;
266038fd1498Szrj 
266138fd1498Szrj     default:
266238fd1498Szrj       gcc_unreachable ();
266338fd1498Szrj     }
266438fd1498Szrj }
266538fd1498Szrj 
266638fd1498Szrj /* Non-terminal <function-type>.  NODE is a FUNCTION_TYPE or
266738fd1498Szrj    METHOD_TYPE.  The return type is mangled before the parameter
266838fd1498Szrj    types.
266938fd1498Szrj 
267038fd1498Szrj      <function-type> ::= F [Y] <bare-function-type> [<ref-qualifier>] E   */
267138fd1498Szrj 
267238fd1498Szrj static void
write_function_type(const tree type)267338fd1498Szrj write_function_type (const tree type)
267438fd1498Szrj {
267538fd1498Szrj   MANGLE_TRACE_TREE ("function-type", type);
267638fd1498Szrj 
267738fd1498Szrj   /* For a pointer to member function, the function type may have
267838fd1498Szrj      cv-qualifiers, indicating the quals for the artificial 'this'
267938fd1498Szrj      parameter.  */
268038fd1498Szrj   if (TREE_CODE (type) == METHOD_TYPE)
268138fd1498Szrj     {
268238fd1498Szrj       /* The first parameter must be a POINTER_TYPE pointing to the
268338fd1498Szrj 	 `this' parameter.  */
268438fd1498Szrj       tree this_type = class_of_this_parm (type);
268538fd1498Szrj       write_CV_qualifiers_for_type (this_type);
268638fd1498Szrj     }
268738fd1498Szrj 
268838fd1498Szrj   write_exception_spec (TYPE_RAISES_EXCEPTIONS (type));
268938fd1498Szrj 
269038fd1498Szrj   if (tx_safe_fn_type_p (type))
269138fd1498Szrj     write_string ("Dx");
269238fd1498Szrj 
269338fd1498Szrj   write_char ('F');
269438fd1498Szrj   /* We don't track whether or not a type is `extern "C"'.  Note that
269538fd1498Szrj      you can have an `extern "C"' function that does not have
269638fd1498Szrj      `extern "C"' type, and vice versa:
269738fd1498Szrj 
269838fd1498Szrj        extern "C" typedef void function_t();
269938fd1498Szrj        function_t f; // f has C++ linkage, but its type is
270038fd1498Szrj 		     // `extern "C"'
270138fd1498Szrj 
270238fd1498Szrj        typedef void function_t();
270338fd1498Szrj        extern "C" function_t f; // Vice versa.
270438fd1498Szrj 
270538fd1498Szrj      See [dcl.link].  */
270638fd1498Szrj   write_bare_function_type (type, /*include_return_type_p=*/1,
270738fd1498Szrj 			    /*decl=*/NULL);
270838fd1498Szrj   if (FUNCTION_REF_QUALIFIED (type))
270938fd1498Szrj     {
271038fd1498Szrj       if (FUNCTION_RVALUE_QUALIFIED (type))
271138fd1498Szrj 	write_char ('O');
271238fd1498Szrj       else
271338fd1498Szrj 	write_char ('R');
271438fd1498Szrj     }
271538fd1498Szrj   write_char ('E');
271638fd1498Szrj }
271738fd1498Szrj 
271838fd1498Szrj /* Non-terminal <bare-function-type>.  TYPE is a FUNCTION_TYPE or
271938fd1498Szrj    METHOD_TYPE.  If INCLUDE_RETURN_TYPE is nonzero, the return value
272038fd1498Szrj    is mangled before the parameter types.  If non-NULL, DECL is
272138fd1498Szrj    FUNCTION_DECL for the function whose type is being emitted.  */
272238fd1498Szrj 
272338fd1498Szrj static void
write_bare_function_type(const tree type,const int include_return_type_p,const tree decl)272438fd1498Szrj write_bare_function_type (const tree type, const int include_return_type_p,
272538fd1498Szrj 			  const tree decl)
272638fd1498Szrj {
272738fd1498Szrj   MANGLE_TRACE_TREE ("bare-function-type", type);
272838fd1498Szrj 
272938fd1498Szrj   /* Mangle the return type, if requested.  */
273038fd1498Szrj   if (include_return_type_p)
273138fd1498Szrj     write_type (TREE_TYPE (type));
273238fd1498Szrj 
273338fd1498Szrj   /* Now mangle the types of the arguments.  */
273438fd1498Szrj   ++G.parm_depth;
273538fd1498Szrj   write_method_parms (TYPE_ARG_TYPES (type),
273638fd1498Szrj 		      TREE_CODE (type) == METHOD_TYPE,
273738fd1498Szrj 		      decl);
273838fd1498Szrj   --G.parm_depth;
273938fd1498Szrj }
274038fd1498Szrj 
274138fd1498Szrj /* Write the mangled representation of a method parameter list of
274238fd1498Szrj    types given in PARM_TYPES.  If METHOD_P is nonzero, the function is
274338fd1498Szrj    considered a non-static method, and the this parameter is omitted.
274438fd1498Szrj    If non-NULL, DECL is the FUNCTION_DECL for the function whose
274538fd1498Szrj    parameters are being emitted.  */
274638fd1498Szrj 
274738fd1498Szrj static void
write_method_parms(tree parm_types,const int method_p,const tree decl)274838fd1498Szrj write_method_parms (tree parm_types, const int method_p, const tree decl)
274938fd1498Szrj {
275038fd1498Szrj   tree first_parm_type;
275138fd1498Szrj   tree parm_decl = decl ? DECL_ARGUMENTS (decl) : NULL_TREE;
275238fd1498Szrj 
275338fd1498Szrj   /* Assume this parameter type list is variable-length.  If it ends
275438fd1498Szrj      with a void type, then it's not.  */
275538fd1498Szrj   int varargs_p = 1;
275638fd1498Szrj 
275738fd1498Szrj   /* If this is a member function, skip the first arg, which is the
275838fd1498Szrj      this pointer.
275938fd1498Szrj        "Member functions do not encode the type of their implicit this
276038fd1498Szrj        parameter."
276138fd1498Szrj 
276238fd1498Szrj      Similarly, there's no need to mangle artificial parameters, like
276338fd1498Szrj      the VTT parameters for constructors and destructors.  */
276438fd1498Szrj   if (method_p)
276538fd1498Szrj     {
276638fd1498Szrj       parm_types = TREE_CHAIN (parm_types);
276738fd1498Szrj       parm_decl = parm_decl ? DECL_CHAIN (parm_decl) : NULL_TREE;
276838fd1498Szrj 
276938fd1498Szrj       while (parm_decl && DECL_ARTIFICIAL (parm_decl))
277038fd1498Szrj 	{
277138fd1498Szrj 	  parm_types = TREE_CHAIN (parm_types);
277238fd1498Szrj 	  parm_decl = DECL_CHAIN (parm_decl);
277338fd1498Szrj 	}
277438fd1498Szrj 
277538fd1498Szrj       if (decl && ctor_omit_inherited_parms (decl))
277638fd1498Szrj 	/* Bring back parameters omitted from an inherited ctor.  */
277738fd1498Szrj 	parm_types = FUNCTION_FIRST_USER_PARMTYPE (DECL_ORIGIN (decl));
277838fd1498Szrj     }
277938fd1498Szrj 
278038fd1498Szrj   for (first_parm_type = parm_types;
278138fd1498Szrj        parm_types;
278238fd1498Szrj        parm_types = TREE_CHAIN (parm_types))
278338fd1498Szrj     {
278438fd1498Szrj       tree parm = TREE_VALUE (parm_types);
278538fd1498Szrj       if (parm == void_type_node)
278638fd1498Szrj 	{
278738fd1498Szrj 	  /* "Empty parameter lists, whether declared as () or
278838fd1498Szrj 	     conventionally as (void), are encoded with a void parameter
278938fd1498Szrj 	     (v)."  */
279038fd1498Szrj 	  if (parm_types == first_parm_type)
279138fd1498Szrj 	    write_type (parm);
279238fd1498Szrj 	  /* If the parm list is terminated with a void type, it's
279338fd1498Szrj 	     fixed-length.  */
279438fd1498Szrj 	  varargs_p = 0;
279538fd1498Szrj 	  /* A void type better be the last one.  */
279638fd1498Szrj 	  gcc_assert (TREE_CHAIN (parm_types) == NULL);
279738fd1498Szrj 	}
279838fd1498Szrj       else
279938fd1498Szrj 	write_type (parm);
280038fd1498Szrj     }
280138fd1498Szrj 
280238fd1498Szrj   if (varargs_p)
280338fd1498Szrj     /* <builtin-type> ::= z  # ellipsis  */
280438fd1498Szrj     write_char ('z');
280538fd1498Szrj }
280638fd1498Szrj 
280738fd1498Szrj /* <class-enum-type> ::= <name>  */
280838fd1498Szrj 
280938fd1498Szrj static void
write_class_enum_type(const tree type)281038fd1498Szrj write_class_enum_type (const tree type)
281138fd1498Szrj {
281238fd1498Szrj   write_name (TYPE_NAME (type), /*ignore_local_scope=*/0);
281338fd1498Szrj }
281438fd1498Szrj 
281538fd1498Szrj /* Non-terminal <template-args>.  ARGS is a TREE_VEC of template
281638fd1498Szrj    arguments.
281738fd1498Szrj 
281838fd1498Szrj      <template-args> ::= I <template-arg>* E  */
281938fd1498Szrj 
282038fd1498Szrj static void
write_template_args(tree args)282138fd1498Szrj write_template_args (tree args)
282238fd1498Szrj {
282338fd1498Szrj   int i;
282438fd1498Szrj   int length = 0;
282538fd1498Szrj 
282638fd1498Szrj   MANGLE_TRACE_TREE ("template-args", args);
282738fd1498Szrj 
282838fd1498Szrj   write_char ('I');
282938fd1498Szrj 
283038fd1498Szrj   if (args)
283138fd1498Szrj     length = TREE_VEC_LENGTH (args);
283238fd1498Szrj 
283338fd1498Szrj   if (args && length && TREE_CODE (TREE_VEC_ELT (args, 0)) == TREE_VEC)
283438fd1498Szrj     {
283538fd1498Szrj       /* We have nested template args.  We want the innermost template
283638fd1498Szrj 	 argument list.  */
283738fd1498Szrj       args = TREE_VEC_ELT (args, length - 1);
283838fd1498Szrj       length = TREE_VEC_LENGTH (args);
283938fd1498Szrj     }
284038fd1498Szrj   for (i = 0; i < length; ++i)
284138fd1498Szrj     write_template_arg (TREE_VEC_ELT (args, i));
284238fd1498Szrj 
284338fd1498Szrj   write_char ('E');
284438fd1498Szrj }
284538fd1498Szrj 
284638fd1498Szrj /* Write out the
284738fd1498Szrj    <unqualified-name>
284838fd1498Szrj    <unqualified-name> <template-args>
284938fd1498Szrj    part of SCOPE_REF or COMPONENT_REF mangling.  */
285038fd1498Szrj 
285138fd1498Szrj static void
write_member_name(tree member)285238fd1498Szrj write_member_name (tree member)
285338fd1498Szrj {
285438fd1498Szrj   if (identifier_p (member))
285538fd1498Szrj     {
285638fd1498Szrj       if (abi_version_at_least (11) && IDENTIFIER_ANY_OP_P (member))
285738fd1498Szrj 	{
285838fd1498Szrj 	  write_string ("on");
285938fd1498Szrj 	  if (abi_warn_or_compat_version_crosses (11))
286038fd1498Szrj 	    G.need_abi_warning = 1;
286138fd1498Szrj 	}
286238fd1498Szrj       write_unqualified_id (member);
286338fd1498Szrj     }
286438fd1498Szrj   else if (DECL_P (member))
286538fd1498Szrj     write_unqualified_name (member);
286638fd1498Szrj   else if (TREE_CODE (member) == TEMPLATE_ID_EXPR)
286738fd1498Szrj     {
286838fd1498Szrj       tree name = TREE_OPERAND (member, 0);
286938fd1498Szrj       name = OVL_FIRST (name);
287038fd1498Szrj       write_member_name (name);
287138fd1498Szrj       write_template_args (TREE_OPERAND (member, 1));
287238fd1498Szrj     }
287338fd1498Szrj   else
287438fd1498Szrj     write_expression (member);
287538fd1498Szrj }
287638fd1498Szrj 
287738fd1498Szrj /* <expression> ::= <unary operator-name> <expression>
287838fd1498Szrj 		::= <binary operator-name> <expression> <expression>
287938fd1498Szrj 		::= <expr-primary>
288038fd1498Szrj 
288138fd1498Szrj    <expr-primary> ::= <template-param>
288238fd1498Szrj 		  ::= L <type> <value number> E		# literal
288338fd1498Szrj 		  ::= L <mangled-name> E		# external name
288438fd1498Szrj 		  ::= st <type>				# sizeof
288538fd1498Szrj 		  ::= sr <type> <unqualified-name>	# dependent name
288638fd1498Szrj 		  ::= sr <type> <unqualified-name> <template-args> */
288738fd1498Szrj 
288838fd1498Szrj static void
write_expression(tree expr)288938fd1498Szrj write_expression (tree expr)
289038fd1498Szrj {
289138fd1498Szrj   enum tree_code code = TREE_CODE (expr);
289238fd1498Szrj 
289338fd1498Szrj   /* Skip NOP_EXPR and CONVERT_EXPR.  They can occur when (say) a pointer
289438fd1498Szrj      argument is converted (via qualification conversions) to another type.  */
289538fd1498Szrj   while (CONVERT_EXPR_CODE_P (code)
289638fd1498Szrj 	 || location_wrapper_p (expr)
289738fd1498Szrj 	 /* Parentheses aren't mangled.  */
289838fd1498Szrj 	 || code == PAREN_EXPR
289938fd1498Szrj 	 || code == NON_LVALUE_EXPR)
290038fd1498Szrj     {
290138fd1498Szrj       expr = TREE_OPERAND (expr, 0);
290238fd1498Szrj       code = TREE_CODE (expr);
290338fd1498Szrj     }
290438fd1498Szrj 
290538fd1498Szrj   if (code == BASELINK
290638fd1498Szrj       && (!type_unknown_p (expr)
290738fd1498Szrj 	  || !BASELINK_QUALIFIED_P (expr)))
290838fd1498Szrj     {
290938fd1498Szrj       expr = BASELINK_FUNCTIONS (expr);
291038fd1498Szrj       code = TREE_CODE (expr);
291138fd1498Szrj     }
291238fd1498Szrj 
291338fd1498Szrj   /* Handle pointers-to-members by making them look like expression
291438fd1498Szrj      nodes.  */
291538fd1498Szrj   if (code == PTRMEM_CST)
291638fd1498Szrj     {
291738fd1498Szrj       expr = build_nt (ADDR_EXPR,
291838fd1498Szrj 		       build_qualified_name (/*type=*/NULL_TREE,
291938fd1498Szrj 					     PTRMEM_CST_CLASS (expr),
292038fd1498Szrj 					     PTRMEM_CST_MEMBER (expr),
292138fd1498Szrj 					     /*template_p=*/false));
292238fd1498Szrj       code = TREE_CODE (expr);
292338fd1498Szrj     }
292438fd1498Szrj 
292538fd1498Szrj   /* Handle template parameters.  */
292638fd1498Szrj   if (code == TEMPLATE_TYPE_PARM
292738fd1498Szrj       || code == TEMPLATE_TEMPLATE_PARM
292838fd1498Szrj       || code == BOUND_TEMPLATE_TEMPLATE_PARM
292938fd1498Szrj       || code == TEMPLATE_PARM_INDEX)
293038fd1498Szrj     write_template_param (expr);
293138fd1498Szrj   /* Handle literals.  */
293238fd1498Szrj   else if (TREE_CODE_CLASS (code) == tcc_constant
293338fd1498Szrj 	   || code == CONST_DECL)
293438fd1498Szrj     write_template_arg_literal (expr);
293538fd1498Szrj   else if (code == PARM_DECL && DECL_ARTIFICIAL (expr))
293638fd1498Szrj     {
293738fd1498Szrj       gcc_assert (id_equal (DECL_NAME (expr), "this"));
293838fd1498Szrj       write_string ("fpT");
293938fd1498Szrj     }
294038fd1498Szrj   else if (code == PARM_DECL)
294138fd1498Szrj     {
294238fd1498Szrj       /* A function parameter used in a late-specified return type.  */
294338fd1498Szrj       int index = DECL_PARM_INDEX (expr);
294438fd1498Szrj       int level = DECL_PARM_LEVEL (expr);
294538fd1498Szrj       int delta = G.parm_depth - level + 1;
294638fd1498Szrj       gcc_assert (index >= 1);
294738fd1498Szrj       write_char ('f');
294838fd1498Szrj       if (delta != 0)
294938fd1498Szrj 	{
295038fd1498Szrj 	  if (abi_version_at_least (5))
295138fd1498Szrj 	    {
295238fd1498Szrj 	      /* Let L be the number of function prototype scopes from the
295338fd1498Szrj 		 innermost one (in which the parameter reference occurs) up
295438fd1498Szrj 		 to (and including) the one containing the declaration of
295538fd1498Szrj 		 the referenced parameter.  If the parameter declaration
295638fd1498Szrj 		 clause of the innermost function prototype scope has been
295738fd1498Szrj 		 completely seen, it is not counted (in that case -- which
295838fd1498Szrj 		 is perhaps the most common -- L can be zero).  */
295938fd1498Szrj 	      write_char ('L');
296038fd1498Szrj 	      write_unsigned_number (delta - 1);
296138fd1498Szrj 	    }
296238fd1498Szrj 	  if (abi_warn_or_compat_version_crosses (5))
296338fd1498Szrj 	    G.need_abi_warning = true;
296438fd1498Szrj 	}
296538fd1498Szrj       write_char ('p');
296638fd1498Szrj       write_compact_number (index - 1);
296738fd1498Szrj     }
296838fd1498Szrj   else if (DECL_P (expr))
296938fd1498Szrj     {
297038fd1498Szrj       write_char ('L');
297138fd1498Szrj       write_mangled_name (expr, false);
297238fd1498Szrj       write_char ('E');
297338fd1498Szrj     }
297438fd1498Szrj   else if (TREE_CODE (expr) == SIZEOF_EXPR)
297538fd1498Szrj     {
297638fd1498Szrj       tree op = TREE_OPERAND (expr, 0);
297738fd1498Szrj 
297838fd1498Szrj       if (PACK_EXPANSION_P (op))
297938fd1498Szrj 	{
298038fd1498Szrj 	  if (abi_warn_or_compat_version_crosses (11))
298138fd1498Szrj 	    G.need_abi_warning = true;
298238fd1498Szrj 	  if (abi_version_at_least (11))
298338fd1498Szrj 	    {
298438fd1498Szrj 	      /* sZ rather than szDp.  */
298538fd1498Szrj 	      write_string ("sZ");
298638fd1498Szrj 	      write_expression (PACK_EXPANSION_PATTERN (op));
298738fd1498Szrj 	      return;
298838fd1498Szrj 	    }
298938fd1498Szrj 	}
299038fd1498Szrj 
299138fd1498Szrj       if (SIZEOF_EXPR_TYPE_P (expr))
299238fd1498Szrj 	{
299338fd1498Szrj 	  write_string ("st");
299438fd1498Szrj 	  write_type (TREE_TYPE (op));
299538fd1498Szrj 	}
299638fd1498Szrj       else if (ARGUMENT_PACK_P (op))
299738fd1498Szrj 	{
299838fd1498Szrj 	  tree args = ARGUMENT_PACK_ARGS (op);
299938fd1498Szrj 	  int length = TREE_VEC_LENGTH (args);
300038fd1498Szrj 	  if (abi_warn_or_compat_version_crosses (10))
300138fd1498Szrj 	    G.need_abi_warning = true;
300238fd1498Szrj 	  if (abi_version_at_least (10))
300338fd1498Szrj 	    {
300438fd1498Szrj 	      /* sP <template-arg>* E # sizeof...(T), size of a captured
300538fd1498Szrj 		 template parameter pack from an alias template */
300638fd1498Szrj 	      write_string ("sP");
300738fd1498Szrj 	      for (int i = 0; i < length; ++i)
300838fd1498Szrj 		write_template_arg (TREE_VEC_ELT (args, i));
300938fd1498Szrj 	      write_char ('E');
301038fd1498Szrj 	    }
301138fd1498Szrj 	  else
301238fd1498Szrj 	    {
301338fd1498Szrj 	      /* In GCC 5 we represented this sizeof wrong, with the effect
301438fd1498Szrj 		 that we mangled it as the last element of the pack.  */
301538fd1498Szrj 	      tree arg = TREE_VEC_ELT (args, length-1);
301638fd1498Szrj 	      if (TYPE_P (op))
301738fd1498Szrj 		{
301838fd1498Szrj 		  write_string ("st");
301938fd1498Szrj 		  write_type (arg);
302038fd1498Szrj 		}
302138fd1498Szrj 	      else
302238fd1498Szrj 		{
302338fd1498Szrj 		  write_string ("sz");
302438fd1498Szrj 		  write_expression (arg);
302538fd1498Szrj 		}
302638fd1498Szrj 	    }
302738fd1498Szrj 	}
302838fd1498Szrj       else if (TYPE_P (TREE_OPERAND (expr, 0)))
302938fd1498Szrj 	{
303038fd1498Szrj 	  write_string ("st");
303138fd1498Szrj 	  write_type (TREE_OPERAND (expr, 0));
303238fd1498Szrj 	}
303338fd1498Szrj       else
303438fd1498Szrj 	goto normal_expr;
303538fd1498Szrj     }
303638fd1498Szrj   else if (TREE_CODE (expr) == ALIGNOF_EXPR
303738fd1498Szrj 	   && TYPE_P (TREE_OPERAND (expr, 0)))
303838fd1498Szrj     {
303938fd1498Szrj       write_string ("at");
304038fd1498Szrj       write_type (TREE_OPERAND (expr, 0));
304138fd1498Szrj     }
304238fd1498Szrj   else if (code == SCOPE_REF
304338fd1498Szrj 	   || code == BASELINK)
304438fd1498Szrj     {
304538fd1498Szrj       tree scope, member;
304638fd1498Szrj       if (code == SCOPE_REF)
304738fd1498Szrj 	{
304838fd1498Szrj 	  scope = TREE_OPERAND (expr, 0);
304938fd1498Szrj 	  member = TREE_OPERAND (expr, 1);
3050*e215fc28Szrj 	  if (BASELINK_P (member))
3051*e215fc28Szrj 	    member = BASELINK_FUNCTIONS (member);
305238fd1498Szrj 	}
305338fd1498Szrj       else
305438fd1498Szrj 	{
305538fd1498Szrj 	  scope = BINFO_TYPE (BASELINK_ACCESS_BINFO (expr));
305638fd1498Szrj 	  member = BASELINK_FUNCTIONS (expr);
305738fd1498Szrj 	}
305838fd1498Szrj 
305938fd1498Szrj       /* If the MEMBER is a real declaration, then the qualifying
306038fd1498Szrj 	 scope was not dependent.  Ideally, we would not have a
306138fd1498Szrj 	 SCOPE_REF in those cases, but sometimes we do.  If the second
306238fd1498Szrj 	 argument is a DECL, then the name must not have been
306338fd1498Szrj 	 dependent.  */
306438fd1498Szrj       if (DECL_P (member))
306538fd1498Szrj 	write_expression (member);
306638fd1498Szrj       else
306738fd1498Szrj 	{
306838fd1498Szrj 	  write_string ("sr");
306938fd1498Szrj 	  write_type (scope);
307038fd1498Szrj 	  write_member_name (member);
307138fd1498Szrj 	}
307238fd1498Szrj     }
307338fd1498Szrj   else if (INDIRECT_REF_P (expr)
307438fd1498Szrj 	   && TREE_TYPE (TREE_OPERAND (expr, 0))
307538fd1498Szrj 	   && TREE_CODE (TREE_TYPE (TREE_OPERAND (expr, 0))) == REFERENCE_TYPE)
307638fd1498Szrj     {
307738fd1498Szrj       write_expression (TREE_OPERAND (expr, 0));
307838fd1498Szrj     }
307938fd1498Szrj   else if (identifier_p (expr))
308038fd1498Szrj     {
308138fd1498Szrj       /* An operator name appearing as a dependent name needs to be
308238fd1498Szrj 	 specially marked to disambiguate between a use of the operator
308338fd1498Szrj 	 name and a use of the operator in an expression.  */
308438fd1498Szrj       if (IDENTIFIER_ANY_OP_P (expr))
308538fd1498Szrj 	write_string ("on");
308638fd1498Szrj       write_unqualified_id (expr);
308738fd1498Szrj     }
308838fd1498Szrj   else if (TREE_CODE (expr) == TEMPLATE_ID_EXPR)
308938fd1498Szrj     {
309038fd1498Szrj       tree fn = TREE_OPERAND (expr, 0);
309138fd1498Szrj       fn = OVL_NAME (fn);
309238fd1498Szrj       if (IDENTIFIER_ANY_OP_P (fn))
309338fd1498Szrj 	write_string ("on");
309438fd1498Szrj       write_unqualified_id (fn);
309538fd1498Szrj       write_template_args (TREE_OPERAND (expr, 1));
309638fd1498Szrj     }
309738fd1498Szrj   else if (TREE_CODE (expr) == MODOP_EXPR)
309838fd1498Szrj     {
309938fd1498Szrj       enum tree_code subop = TREE_CODE (TREE_OPERAND (expr, 1));
310038fd1498Szrj       const char *name = OVL_OP_INFO (true, subop)->mangled_name;
310138fd1498Szrj 
310238fd1498Szrj       write_string (name);
310338fd1498Szrj       write_expression (TREE_OPERAND (expr, 0));
310438fd1498Szrj       write_expression (TREE_OPERAND (expr, 2));
310538fd1498Szrj     }
310638fd1498Szrj   else if (code == NEW_EXPR || code == VEC_NEW_EXPR)
310738fd1498Szrj     {
310838fd1498Szrj       /* ::= [gs] nw <expression>* _ <type> E
310938fd1498Szrj 	 ::= [gs] nw <expression>* _ <type> <initializer>
311038fd1498Szrj 	 ::= [gs] na <expression>* _ <type> E
311138fd1498Szrj 	 ::= [gs] na <expression>* _ <type> <initializer>
311238fd1498Szrj 	 <initializer> ::= pi <expression>* E  */
311338fd1498Szrj       tree placement = TREE_OPERAND (expr, 0);
311438fd1498Szrj       tree type = TREE_OPERAND (expr, 1);
311538fd1498Szrj       tree nelts = TREE_OPERAND (expr, 2);
311638fd1498Szrj       tree init = TREE_OPERAND (expr, 3);
311738fd1498Szrj       tree t;
311838fd1498Szrj 
311938fd1498Szrj       gcc_assert (code == NEW_EXPR);
312038fd1498Szrj       if (TREE_OPERAND (expr, 2))
312138fd1498Szrj 	code = VEC_NEW_EXPR;
312238fd1498Szrj 
312338fd1498Szrj       if (NEW_EXPR_USE_GLOBAL (expr))
312438fd1498Szrj 	write_string ("gs");
312538fd1498Szrj 
312638fd1498Szrj       write_string (OVL_OP_INFO (false, code)->mangled_name);
312738fd1498Szrj 
312838fd1498Szrj       for (t = placement; t; t = TREE_CHAIN (t))
312938fd1498Szrj 	write_expression (TREE_VALUE (t));
313038fd1498Szrj 
313138fd1498Szrj       write_char ('_');
313238fd1498Szrj 
313338fd1498Szrj       if (nelts)
313438fd1498Szrj 	{
313538fd1498Szrj 	  tree domain;
313638fd1498Szrj 	  ++processing_template_decl;
313738fd1498Szrj 	  domain = compute_array_index_type (NULL_TREE, nelts,
313838fd1498Szrj 					     tf_warning_or_error);
313938fd1498Szrj 	  type = build_cplus_array_type (type, domain);
314038fd1498Szrj 	  --processing_template_decl;
314138fd1498Szrj 	}
314238fd1498Szrj       write_type (type);
314338fd1498Szrj 
314438fd1498Szrj       if (init && TREE_CODE (init) == TREE_LIST
314538fd1498Szrj 	  && DIRECT_LIST_INIT_P (TREE_VALUE (init)))
314638fd1498Szrj 	write_expression (TREE_VALUE (init));
314738fd1498Szrj       else
314838fd1498Szrj 	{
314938fd1498Szrj 	  if (init)
315038fd1498Szrj 	    write_string ("pi");
315138fd1498Szrj 	  if (init && init != void_node)
315238fd1498Szrj 	    for (t = init; t; t = TREE_CHAIN (t))
315338fd1498Szrj 	      write_expression (TREE_VALUE (t));
315438fd1498Szrj 	  write_char ('E');
315538fd1498Szrj 	}
315638fd1498Szrj     }
315738fd1498Szrj   else if (code == DELETE_EXPR || code == VEC_DELETE_EXPR)
315838fd1498Szrj     {
315938fd1498Szrj       gcc_assert (code == DELETE_EXPR);
316038fd1498Szrj       if (DELETE_EXPR_USE_VEC (expr))
316138fd1498Szrj 	code = VEC_DELETE_EXPR;
316238fd1498Szrj 
316338fd1498Szrj       if (DELETE_EXPR_USE_GLOBAL (expr))
316438fd1498Szrj 	write_string ("gs");
316538fd1498Szrj 
316638fd1498Szrj       write_string (OVL_OP_INFO (false, code)->mangled_name);
316738fd1498Szrj 
316838fd1498Szrj       write_expression (TREE_OPERAND (expr, 0));
316938fd1498Szrj     }
317038fd1498Szrj   else if (code == THROW_EXPR)
317138fd1498Szrj     {
317238fd1498Szrj       tree op = TREE_OPERAND (expr, 0);
317338fd1498Szrj       if (op)
317438fd1498Szrj 	{
317538fd1498Szrj 	  write_string ("tw");
317638fd1498Szrj 	  write_expression (op);
317738fd1498Szrj 	}
317838fd1498Szrj       else
317938fd1498Szrj 	write_string ("tr");
318038fd1498Szrj     }
318138fd1498Szrj   else if (code == CONSTRUCTOR)
318238fd1498Szrj     {
318338fd1498Szrj       vec<constructor_elt, va_gc> *elts = CONSTRUCTOR_ELTS (expr);
318438fd1498Szrj       unsigned i; tree val;
318538fd1498Szrj 
318638fd1498Szrj       if (BRACE_ENCLOSED_INITIALIZER_P (expr))
318738fd1498Szrj 	write_string ("il");
318838fd1498Szrj       else
318938fd1498Szrj 	{
319038fd1498Szrj 	  write_string ("tl");
319138fd1498Szrj 	  write_type (TREE_TYPE (expr));
319238fd1498Szrj 	}
319338fd1498Szrj       FOR_EACH_CONSTRUCTOR_VALUE (elts, i, val)
319438fd1498Szrj 	write_expression (val);
319538fd1498Szrj       write_char ('E');
319638fd1498Szrj     }
319738fd1498Szrj   else if (dependent_name (expr))
319838fd1498Szrj     {
319938fd1498Szrj       write_unqualified_id (dependent_name (expr));
320038fd1498Szrj     }
320138fd1498Szrj   else
320238fd1498Szrj     {
320338fd1498Szrj     normal_expr:
320438fd1498Szrj       int i, len;
320538fd1498Szrj       const char *name;
320638fd1498Szrj 
320738fd1498Szrj       /* When we bind a variable or function to a non-type template
320838fd1498Szrj 	 argument with reference type, we create an ADDR_EXPR to show
320938fd1498Szrj 	 the fact that the entity's address has been taken.  But, we
321038fd1498Szrj 	 don't actually want to output a mangling code for the `&'.  */
321138fd1498Szrj       if (TREE_CODE (expr) == ADDR_EXPR
321238fd1498Szrj 	  && TREE_TYPE (expr)
321338fd1498Szrj 	  && TREE_CODE (TREE_TYPE (expr)) == REFERENCE_TYPE)
321438fd1498Szrj 	{
321538fd1498Szrj 	  expr = TREE_OPERAND (expr, 0);
321638fd1498Szrj 	  if (DECL_P (expr))
321738fd1498Szrj 	    {
321838fd1498Szrj 	      write_expression (expr);
321938fd1498Szrj 	      return;
322038fd1498Szrj 	    }
322138fd1498Szrj 
322238fd1498Szrj 	  code = TREE_CODE (expr);
322338fd1498Szrj 	}
322438fd1498Szrj 
322538fd1498Szrj       if (code == COMPONENT_REF)
322638fd1498Szrj 	{
322738fd1498Szrj 	  tree ob = TREE_OPERAND (expr, 0);
322838fd1498Szrj 
322938fd1498Szrj 	  if (TREE_CODE (ob) == ARROW_EXPR)
323038fd1498Szrj 	    {
323138fd1498Szrj 	      write_string (OVL_OP_INFO (false, code)->mangled_name);
323238fd1498Szrj 	      ob = TREE_OPERAND (ob, 0);
323338fd1498Szrj 	      write_expression (ob);
323438fd1498Szrj 	    }
323538fd1498Szrj 	  else if (!is_dummy_object (ob))
323638fd1498Szrj 	    {
323738fd1498Szrj 	      write_string ("dt");
323838fd1498Szrj 	      write_expression (ob);
323938fd1498Szrj 	    }
324038fd1498Szrj 	  /* else, for a non-static data member with no associated object (in
324138fd1498Szrj 	     unevaluated context), use the unresolved-name mangling.  */
324238fd1498Szrj 
324338fd1498Szrj 	  write_member_name (TREE_OPERAND (expr, 1));
324438fd1498Szrj 	  return;
324538fd1498Szrj 	}
324638fd1498Szrj 
324738fd1498Szrj       /* If it wasn't any of those, recursively expand the expression.  */
324838fd1498Szrj       name = OVL_OP_INFO (false, code)->mangled_name;
324938fd1498Szrj 
325038fd1498Szrj       /* We used to mangle const_cast and static_cast like a C cast.  */
325138fd1498Szrj       if (code == CONST_CAST_EXPR
325238fd1498Szrj 	  || code == STATIC_CAST_EXPR)
325338fd1498Szrj 	{
325438fd1498Szrj 	  if (abi_warn_or_compat_version_crosses (6))
325538fd1498Szrj 	    G.need_abi_warning = 1;
325638fd1498Szrj 	  if (!abi_version_at_least (6))
325738fd1498Szrj 	    name = OVL_OP_INFO (false, CAST_EXPR)->mangled_name;
325838fd1498Szrj 	}
325938fd1498Szrj 
326038fd1498Szrj       if (name == NULL)
326138fd1498Szrj 	{
326238fd1498Szrj 	  switch (code)
326338fd1498Szrj 	    {
326438fd1498Szrj 	    case TRAIT_EXPR:
326538fd1498Szrj 	      error ("use of built-in trait %qE in function signature; "
326638fd1498Szrj 		     "use library traits instead", expr);
326738fd1498Szrj 	      break;
326838fd1498Szrj 
326938fd1498Szrj 	    default:
327038fd1498Szrj 	      sorry ("mangling %C", code);
327138fd1498Szrj 	      break;
327238fd1498Szrj 	    }
327338fd1498Szrj 	  return;
327438fd1498Szrj 	}
327538fd1498Szrj       else
327638fd1498Szrj 	write_string (name);
327738fd1498Szrj 
327838fd1498Szrj       switch (code)
327938fd1498Szrj 	{
328038fd1498Szrj 	case CALL_EXPR:
328138fd1498Szrj 	  {
328238fd1498Szrj 	    tree fn = CALL_EXPR_FN (expr);
328338fd1498Szrj 
328438fd1498Szrj 	    if (TREE_CODE (fn) == ADDR_EXPR)
328538fd1498Szrj 	      fn = TREE_OPERAND (fn, 0);
328638fd1498Szrj 
328738fd1498Szrj 	    /* Mangle a dependent name as the name, not whatever happens to
328838fd1498Szrj 	       be the first function in the overload set.  */
328938fd1498Szrj 	    if ((TREE_CODE (fn) == FUNCTION_DECL
329038fd1498Szrj 		 || TREE_CODE (fn) == OVERLOAD)
329138fd1498Szrj 		&& type_dependent_expression_p_push (expr))
329238fd1498Szrj 	      fn = OVL_NAME (fn);
329338fd1498Szrj 
329438fd1498Szrj 	    write_expression (fn);
329538fd1498Szrj 	  }
329638fd1498Szrj 
329738fd1498Szrj 	  for (i = 0; i < call_expr_nargs (expr); ++i)
329838fd1498Szrj 	    write_expression (CALL_EXPR_ARG (expr, i));
329938fd1498Szrj 	  write_char ('E');
330038fd1498Szrj 	  break;
330138fd1498Szrj 
330238fd1498Szrj 	case CAST_EXPR:
330338fd1498Szrj 	  write_type (TREE_TYPE (expr));
330438fd1498Szrj 	  if (list_length (TREE_OPERAND (expr, 0)) == 1)
330538fd1498Szrj 	    write_expression (TREE_VALUE (TREE_OPERAND (expr, 0)));
330638fd1498Szrj 	  else
330738fd1498Szrj 	    {
330838fd1498Szrj 	      tree args = TREE_OPERAND (expr, 0);
330938fd1498Szrj 	      write_char ('_');
331038fd1498Szrj 	      for (; args; args = TREE_CHAIN (args))
331138fd1498Szrj 		write_expression (TREE_VALUE (args));
331238fd1498Szrj 	      write_char ('E');
331338fd1498Szrj 	    }
331438fd1498Szrj 	  break;
331538fd1498Szrj 
331638fd1498Szrj 	case DYNAMIC_CAST_EXPR:
331738fd1498Szrj 	case REINTERPRET_CAST_EXPR:
331838fd1498Szrj 	case STATIC_CAST_EXPR:
331938fd1498Szrj 	case CONST_CAST_EXPR:
332038fd1498Szrj 	  write_type (TREE_TYPE (expr));
332138fd1498Szrj 	  write_expression (TREE_OPERAND (expr, 0));
332238fd1498Szrj 	  break;
332338fd1498Szrj 
332438fd1498Szrj 	case PREINCREMENT_EXPR:
332538fd1498Szrj 	case PREDECREMENT_EXPR:
332638fd1498Szrj 	  if (abi_version_at_least (6))
332738fd1498Szrj 	    write_char ('_');
332838fd1498Szrj 	  if (abi_warn_or_compat_version_crosses (6))
332938fd1498Szrj 	    G.need_abi_warning = 1;
333038fd1498Szrj 	  /* Fall through.  */
333138fd1498Szrj 
333238fd1498Szrj 	default:
333338fd1498Szrj 	  /* In the middle-end, some expressions have more operands than
333438fd1498Szrj 	     they do in templates (and mangling).  */
333538fd1498Szrj 	  len = cp_tree_operand_length (expr);
333638fd1498Szrj 
333738fd1498Szrj 	  for (i = 0; i < len; ++i)
333838fd1498Szrj 	    {
333938fd1498Szrj 	      tree operand = TREE_OPERAND (expr, i);
334038fd1498Szrj 	      /* As a GNU extension, the middle operand of a
334138fd1498Szrj 		 conditional may be omitted.  Since expression
334238fd1498Szrj 		 manglings are supposed to represent the input token
334338fd1498Szrj 		 stream, there's no good way to mangle such an
334438fd1498Szrj 		 expression without extending the C++ ABI.  */
334538fd1498Szrj 	      if (code == COND_EXPR && i == 1 && !operand)
334638fd1498Szrj 		{
334738fd1498Szrj 		  error ("omitted middle operand to %<?:%> operand "
334838fd1498Szrj 			 "cannot be mangled");
334938fd1498Szrj 		  continue;
335038fd1498Szrj 		}
335138fd1498Szrj 	      else if (FOLD_EXPR_P (expr))
335238fd1498Szrj 		{
335338fd1498Szrj 		  /* The first 'operand' of a fold-expression is the operator
335438fd1498Szrj 		     that it folds over.  */
335538fd1498Szrj 		  if (i == 0)
335638fd1498Szrj 		    {
335738fd1498Szrj 		      int fcode = TREE_INT_CST_LOW (operand);
335838fd1498Szrj 		      write_string (OVL_OP_INFO (false, fcode)->mangled_name);
335938fd1498Szrj 		      continue;
336038fd1498Szrj 		    }
336138fd1498Szrj 		  else if (code == BINARY_LEFT_FOLD_EXPR)
336238fd1498Szrj 		    {
336338fd1498Szrj 		      /* The order of operands of the binary left and right
336438fd1498Szrj 			 folds is the same, but we want to mangle them in
336538fd1498Szrj 			 lexical order, i.e. non-pack first.  */
336638fd1498Szrj 		      if (i == 1)
336738fd1498Szrj 			operand = FOLD_EXPR_INIT (expr);
336838fd1498Szrj 		      else
336938fd1498Szrj 			operand = FOLD_EXPR_PACK (expr);
337038fd1498Szrj 		    }
337138fd1498Szrj 		  if (PACK_EXPANSION_P (operand))
337238fd1498Szrj 		    operand = PACK_EXPANSION_PATTERN (operand);
337338fd1498Szrj 		}
337438fd1498Szrj 	      write_expression (operand);
337538fd1498Szrj 	    }
337638fd1498Szrj 	}
337738fd1498Szrj     }
337838fd1498Szrj }
337938fd1498Szrj 
338038fd1498Szrj /* Literal subcase of non-terminal <template-arg>.
338138fd1498Szrj 
338238fd1498Szrj      "Literal arguments, e.g. "A<42L>", are encoded with their type
338338fd1498Szrj      and value. Negative integer values are preceded with "n"; for
338438fd1498Szrj      example, "A<-42L>" becomes "1AILln42EE". The bool value false is
338538fd1498Szrj      encoded as 0, true as 1."  */
338638fd1498Szrj 
338738fd1498Szrj static void
write_template_arg_literal(const tree value)338838fd1498Szrj write_template_arg_literal (const tree value)
338938fd1498Szrj {
339038fd1498Szrj   write_char ('L');
339138fd1498Szrj   write_type (TREE_TYPE (value));
339238fd1498Szrj 
339338fd1498Szrj   /* Write a null member pointer value as (type)0, regardless of its
339438fd1498Szrj      real representation.  */
339538fd1498Szrj   if (null_member_pointer_value_p (value))
339638fd1498Szrj     write_integer_cst (integer_zero_node);
339738fd1498Szrj   else
339838fd1498Szrj     switch (TREE_CODE (value))
339938fd1498Szrj       {
340038fd1498Szrj       case CONST_DECL:
340138fd1498Szrj 	write_integer_cst (DECL_INITIAL (value));
340238fd1498Szrj 	break;
340338fd1498Szrj 
340438fd1498Szrj       case INTEGER_CST:
340538fd1498Szrj 	gcc_assert (!same_type_p (TREE_TYPE (value), boolean_type_node)
340638fd1498Szrj 		    || integer_zerop (value) || integer_onep (value));
340738fd1498Szrj 	write_integer_cst (value);
340838fd1498Szrj 	break;
340938fd1498Szrj 
341038fd1498Szrj       case REAL_CST:
341138fd1498Szrj 	write_real_cst (value);
341238fd1498Szrj 	break;
341338fd1498Szrj 
341438fd1498Szrj       case COMPLEX_CST:
341538fd1498Szrj 	if (TREE_CODE (TREE_REALPART (value)) == INTEGER_CST
341638fd1498Szrj 	    && TREE_CODE (TREE_IMAGPART (value)) == INTEGER_CST)
341738fd1498Szrj 	  {
341838fd1498Szrj 	    write_integer_cst (TREE_REALPART (value));
341938fd1498Szrj 	    write_char ('_');
342038fd1498Szrj 	    write_integer_cst (TREE_IMAGPART (value));
342138fd1498Szrj 	  }
342238fd1498Szrj 	else if (TREE_CODE (TREE_REALPART (value)) == REAL_CST
342338fd1498Szrj 		 && TREE_CODE (TREE_IMAGPART (value)) == REAL_CST)
342438fd1498Szrj 	  {
342538fd1498Szrj 	    write_real_cst (TREE_REALPART (value));
342638fd1498Szrj 	    write_char ('_');
342738fd1498Szrj 	    write_real_cst (TREE_IMAGPART (value));
342838fd1498Szrj 	  }
342938fd1498Szrj 	else
343038fd1498Szrj 	  gcc_unreachable ();
343138fd1498Szrj 	break;
343238fd1498Szrj 
343338fd1498Szrj       case STRING_CST:
343438fd1498Szrj 	sorry ("string literal in function template signature");
343538fd1498Szrj 	break;
343638fd1498Szrj 
343738fd1498Szrj       default:
343838fd1498Szrj 	gcc_unreachable ();
343938fd1498Szrj       }
344038fd1498Szrj 
344138fd1498Szrj   write_char ('E');
344238fd1498Szrj }
344338fd1498Szrj 
344438fd1498Szrj /* Non-terminal <template-arg>.
344538fd1498Szrj 
344638fd1498Szrj      <template-arg> ::= <type>				# type
344738fd1498Szrj 		    ::= L <type> </value/ number> E	# literal
344838fd1498Szrj 		    ::= LZ <name> E			# external name
344938fd1498Szrj 		    ::= X <expression> E		# expression  */
345038fd1498Szrj 
345138fd1498Szrj static void
write_template_arg(tree node)345238fd1498Szrj write_template_arg (tree node)
345338fd1498Szrj {
345438fd1498Szrj   enum tree_code code = TREE_CODE (node);
345538fd1498Szrj 
345638fd1498Szrj   MANGLE_TRACE_TREE ("template-arg", node);
345738fd1498Szrj 
345838fd1498Szrj   /* A template template parameter's argument list contains TREE_LIST
345938fd1498Szrj      nodes of which the value field is the actual argument.  */
346038fd1498Szrj   if (code == TREE_LIST)
346138fd1498Szrj     {
346238fd1498Szrj       node = TREE_VALUE (node);
346338fd1498Szrj       /* If it's a decl, deal with its type instead.  */
346438fd1498Szrj       if (DECL_P (node))
346538fd1498Szrj 	{
346638fd1498Szrj 	  node = TREE_TYPE (node);
346738fd1498Szrj 	  code = TREE_CODE (node);
346838fd1498Szrj 	}
346938fd1498Szrj     }
347038fd1498Szrj 
347138fd1498Szrj   /* Strip a conversion added by convert_nontype_argument.  */
347238fd1498Szrj   if (TREE_CODE (node) == IMPLICIT_CONV_EXPR)
347338fd1498Szrj     node = TREE_OPERAND (node, 0);
347438fd1498Szrj   if (REFERENCE_REF_P (node))
347538fd1498Szrj     node = TREE_OPERAND (node, 0);
347638fd1498Szrj   if (TREE_CODE (node) == NOP_EXPR
347738fd1498Szrj       && TREE_CODE (TREE_TYPE (node)) == REFERENCE_TYPE)
347838fd1498Szrj     {
347938fd1498Szrj       /* Template parameters can be of reference type. To maintain
348038fd1498Szrj 	 internal consistency, such arguments use a conversion from
348138fd1498Szrj 	 address of object to reference type.  */
348238fd1498Szrj       gcc_assert (TREE_CODE (TREE_OPERAND (node, 0)) == ADDR_EXPR);
348338fd1498Szrj       node = TREE_OPERAND (TREE_OPERAND (node, 0), 0);
348438fd1498Szrj     }
348538fd1498Szrj 
348638fd1498Szrj   if (TREE_CODE (node) == BASELINK
348738fd1498Szrj       && !type_unknown_p (node))
348838fd1498Szrj     {
348938fd1498Szrj       if (abi_version_at_least (6))
349038fd1498Szrj 	node = BASELINK_FUNCTIONS (node);
349138fd1498Szrj       if (abi_warn_or_compat_version_crosses (6))
349238fd1498Szrj 	/* We wrongly wrapped a class-scope function in X/E.  */
349338fd1498Szrj 	G.need_abi_warning = 1;
349438fd1498Szrj     }
349538fd1498Szrj 
349638fd1498Szrj   if (ARGUMENT_PACK_P (node))
349738fd1498Szrj     {
349838fd1498Szrj       /* Expand the template argument pack. */
349938fd1498Szrj       tree args = ARGUMENT_PACK_ARGS (node);
350038fd1498Szrj       int i, length = TREE_VEC_LENGTH (args);
350138fd1498Szrj       if (abi_version_at_least (6))
350238fd1498Szrj 	write_char ('J');
350338fd1498Szrj       else
350438fd1498Szrj 	write_char ('I');
350538fd1498Szrj       if (abi_warn_or_compat_version_crosses (6))
350638fd1498Szrj 	G.need_abi_warning = 1;
350738fd1498Szrj       for (i = 0; i < length; ++i)
350838fd1498Szrj         write_template_arg (TREE_VEC_ELT (args, i));
350938fd1498Szrj       write_char ('E');
351038fd1498Szrj     }
351138fd1498Szrj   else if (TYPE_P (node))
351238fd1498Szrj     write_type (node);
351338fd1498Szrj   else if (code == TEMPLATE_DECL)
351438fd1498Szrj     /* A template appearing as a template arg is a template template arg.  */
351538fd1498Szrj     write_template_template_arg (node);
351638fd1498Szrj   else if ((TREE_CODE_CLASS (code) == tcc_constant && code != PTRMEM_CST)
351738fd1498Szrj 	   || code == CONST_DECL
351838fd1498Szrj 	   || null_member_pointer_value_p (node))
351938fd1498Szrj     write_template_arg_literal (node);
352038fd1498Szrj   else if (DECL_P (node))
352138fd1498Szrj     {
352238fd1498Szrj       write_char ('L');
352338fd1498Szrj       /* Until ABI version 3, the underscore before the mangled name
352438fd1498Szrj 	 was incorrectly omitted.  */
352538fd1498Szrj       if (!abi_version_at_least (3))
352638fd1498Szrj 	write_char ('Z');
352738fd1498Szrj       else
352838fd1498Szrj 	write_string ("_Z");
352938fd1498Szrj       if (abi_warn_or_compat_version_crosses (3))
353038fd1498Szrj 	G.need_abi_warning = 1;
353138fd1498Szrj       write_encoding (node);
353238fd1498Szrj       write_char ('E');
353338fd1498Szrj     }
353438fd1498Szrj   else
353538fd1498Szrj     {
353638fd1498Szrj       /* Template arguments may be expressions.  */
353738fd1498Szrj       write_char ('X');
353838fd1498Szrj       write_expression (node);
353938fd1498Szrj       write_char ('E');
354038fd1498Szrj     }
354138fd1498Szrj }
354238fd1498Szrj 
354338fd1498Szrj /*  <template-template-arg>
354438fd1498Szrj 			::= <name>
354538fd1498Szrj 			::= <substitution>  */
354638fd1498Szrj 
354738fd1498Szrj static void
write_template_template_arg(const tree decl)354838fd1498Szrj write_template_template_arg (const tree decl)
354938fd1498Szrj {
355038fd1498Szrj   MANGLE_TRACE_TREE ("template-template-arg", decl);
355138fd1498Szrj 
355238fd1498Szrj   if (find_substitution (decl))
355338fd1498Szrj     return;
355438fd1498Szrj   write_name (decl, /*ignore_local_scope=*/0);
355538fd1498Szrj   add_substitution (decl);
355638fd1498Szrj }
355738fd1498Szrj 
355838fd1498Szrj 
355938fd1498Szrj /* Non-terminal <array-type>.  TYPE is an ARRAY_TYPE.
356038fd1498Szrj 
356138fd1498Szrj      <array-type> ::= A [</dimension/ number>] _ </element/ type>
356238fd1498Szrj 		  ::= A <expression> _ </element/ type>
356338fd1498Szrj 
356438fd1498Szrj      "Array types encode the dimension (number of elements) and the
356538fd1498Szrj      element type.  For variable length arrays, the dimension (but not
356638fd1498Szrj      the '_' separator) is omitted."
356738fd1498Szrj      Note that for flexible array members, like for other arrays of
356838fd1498Szrj      unspecified size, the dimension is also omitted.  */
356938fd1498Szrj 
357038fd1498Szrj static void
write_array_type(const tree type)357138fd1498Szrj write_array_type (const tree type)
357238fd1498Szrj {
357338fd1498Szrj   write_char ('A');
357438fd1498Szrj   if (TYPE_DOMAIN (type))
357538fd1498Szrj     {
357638fd1498Szrj       tree index_type;
357738fd1498Szrj 
357838fd1498Szrj       index_type = TYPE_DOMAIN (type);
357938fd1498Szrj       /* The INDEX_TYPE gives the upper and lower bounds of the array.
358038fd1498Szrj 	 It's null for flexible array members which have no upper bound
358138fd1498Szrj 	 (this is a change from GCC 5 and prior where such members were
358238fd1498Szrj 	 incorrectly mangled as zero-length arrays).  */
358338fd1498Szrj       if (tree max = TYPE_MAX_VALUE (index_type))
358438fd1498Szrj 	{
358538fd1498Szrj 	  if (TREE_CODE (max) == INTEGER_CST)
358638fd1498Szrj 	    {
358738fd1498Szrj 	      /* The ABI specifies that we should mangle the number of
358838fd1498Szrj 		 elements in the array, not the largest allowed index.  */
358938fd1498Szrj 	      offset_int wmax = wi::to_offset (max) + 1;
359038fd1498Szrj 	      /* Truncate the result - this will mangle [0, SIZE_INT_MAX]
359138fd1498Szrj 		 number of elements as zero.  */
359238fd1498Szrj 	      wmax = wi::zext (wmax, TYPE_PRECISION (TREE_TYPE (max)));
359338fd1498Szrj 	      gcc_assert (wi::fits_uhwi_p (wmax));
359438fd1498Szrj 	      write_unsigned_number (wmax.to_uhwi ());
359538fd1498Szrj 	    }
359638fd1498Szrj 	  else
359738fd1498Szrj 	    {
359838fd1498Szrj 	      max = TREE_OPERAND (max, 0);
359938fd1498Szrj 	      write_expression (max);
360038fd1498Szrj 	    }
360138fd1498Szrj 	}
360238fd1498Szrj     }
360338fd1498Szrj   write_char ('_');
360438fd1498Szrj   write_type (TREE_TYPE (type));
360538fd1498Szrj }
360638fd1498Szrj 
360738fd1498Szrj /* Non-terminal <pointer-to-member-type> for pointer-to-member
360838fd1498Szrj    variables.  TYPE is a pointer-to-member POINTER_TYPE.
360938fd1498Szrj 
361038fd1498Szrj      <pointer-to-member-type> ::= M </class/ type> </member/ type>  */
361138fd1498Szrj 
361238fd1498Szrj static void
write_pointer_to_member_type(const tree type)361338fd1498Szrj write_pointer_to_member_type (const tree type)
361438fd1498Szrj {
361538fd1498Szrj   write_char ('M');
361638fd1498Szrj   write_type (TYPE_PTRMEM_CLASS_TYPE (type));
361738fd1498Szrj   write_type (TYPE_PTRMEM_POINTED_TO_TYPE (type));
361838fd1498Szrj }
361938fd1498Szrj 
362038fd1498Szrj /* Non-terminal <template-param>.  PARM is a TEMPLATE_TYPE_PARM,
362138fd1498Szrj    TEMPLATE_TEMPLATE_PARM, BOUND_TEMPLATE_TEMPLATE_PARM or a
362238fd1498Szrj    TEMPLATE_PARM_INDEX.
362338fd1498Szrj 
362438fd1498Szrj      <template-param> ::= T </parameter/ number> _  */
362538fd1498Szrj 
362638fd1498Szrj static void
write_template_param(const tree parm)362738fd1498Szrj write_template_param (const tree parm)
362838fd1498Szrj {
362938fd1498Szrj   int parm_index;
363038fd1498Szrj 
363138fd1498Szrj   MANGLE_TRACE_TREE ("template-parm", parm);
363238fd1498Szrj 
363338fd1498Szrj   switch (TREE_CODE (parm))
363438fd1498Szrj     {
363538fd1498Szrj     case TEMPLATE_TYPE_PARM:
363638fd1498Szrj     case TEMPLATE_TEMPLATE_PARM:
363738fd1498Szrj     case BOUND_TEMPLATE_TEMPLATE_PARM:
363838fd1498Szrj       parm_index = TEMPLATE_TYPE_IDX (parm);
363938fd1498Szrj       break;
364038fd1498Szrj 
364138fd1498Szrj     case TEMPLATE_PARM_INDEX:
364238fd1498Szrj       parm_index = TEMPLATE_PARM_IDX (parm);
364338fd1498Szrj       break;
364438fd1498Szrj 
364538fd1498Szrj     default:
364638fd1498Szrj       gcc_unreachable ();
364738fd1498Szrj     }
364838fd1498Szrj 
364938fd1498Szrj   write_char ('T');
365038fd1498Szrj   /* NUMBER as it appears in the mangling is (-1)-indexed, with the
365138fd1498Szrj      earliest template param denoted by `_'.  */
365238fd1498Szrj   write_compact_number (parm_index);
365338fd1498Szrj }
365438fd1498Szrj 
365538fd1498Szrj /*  <template-template-param>
365638fd1498Szrj 			::= <template-param>
365738fd1498Szrj 			::= <substitution>  */
365838fd1498Szrj 
365938fd1498Szrj static void
write_template_template_param(const tree parm)366038fd1498Szrj write_template_template_param (const tree parm)
366138fd1498Szrj {
366238fd1498Szrj   tree templ = NULL_TREE;
366338fd1498Szrj 
366438fd1498Szrj   /* PARM, a TEMPLATE_TEMPLATE_PARM, is an instantiation of the
366538fd1498Szrj      template template parameter.  The substitution candidate here is
366638fd1498Szrj      only the template.  */
366738fd1498Szrj   if (TREE_CODE (parm) == BOUND_TEMPLATE_TEMPLATE_PARM)
366838fd1498Szrj     {
366938fd1498Szrj       templ
367038fd1498Szrj 	= TI_TEMPLATE (TEMPLATE_TEMPLATE_PARM_TEMPLATE_INFO (parm));
367138fd1498Szrj       if (find_substitution (templ))
367238fd1498Szrj 	return;
367338fd1498Szrj     }
367438fd1498Szrj 
367538fd1498Szrj   /* <template-param> encodes only the template parameter position,
367638fd1498Szrj      not its template arguments, which is fine here.  */
367738fd1498Szrj   write_template_param (parm);
367838fd1498Szrj   if (templ)
367938fd1498Szrj     add_substitution (templ);
368038fd1498Szrj }
368138fd1498Szrj 
368238fd1498Szrj /* Non-terminal <substitution>.
368338fd1498Szrj 
368438fd1498Szrj       <substitution> ::= S <seq-id> _
368538fd1498Szrj 		     ::= S_  */
368638fd1498Szrj 
368738fd1498Szrj static void
write_substitution(const int seq_id)368838fd1498Szrj write_substitution (const int seq_id)
368938fd1498Szrj {
369038fd1498Szrj   MANGLE_TRACE ("substitution", "");
369138fd1498Szrj 
369238fd1498Szrj   write_char ('S');
369338fd1498Szrj   if (seq_id > 0)
369438fd1498Szrj     write_number (seq_id - 1, /*unsigned=*/1, 36);
369538fd1498Szrj   write_char ('_');
369638fd1498Szrj }
369738fd1498Szrj 
369838fd1498Szrj /* Start mangling ENTITY.  */
369938fd1498Szrj 
370038fd1498Szrj static inline void
start_mangling(const tree entity)370138fd1498Szrj start_mangling (const tree entity)
370238fd1498Szrj {
370338fd1498Szrj   G.entity = entity;
370438fd1498Szrj   G.need_abi_warning = false;
370538fd1498Szrj   G.need_cxx17_warning = false;
370638fd1498Szrj   obstack_free (&name_obstack, name_base);
370738fd1498Szrj   mangle_obstack = &name_obstack;
370838fd1498Szrj   name_base = obstack_alloc (&name_obstack, 0);
370938fd1498Szrj }
371038fd1498Szrj 
371138fd1498Szrj /* Done with mangling. If WARN is true, and the name of G.entity will
371238fd1498Szrj    be mangled differently in a future version of the ABI, issue a
371338fd1498Szrj    warning.  */
371438fd1498Szrj 
371538fd1498Szrj static void
finish_mangling_internal(void)371638fd1498Szrj finish_mangling_internal (void)
371738fd1498Szrj {
371838fd1498Szrj   /* Clear all the substitutions.  */
371938fd1498Szrj   vec_safe_truncate (G.substitutions, 0);
372038fd1498Szrj 
372138fd1498Szrj   /* Null-terminate the string.  */
372238fd1498Szrj   write_char ('\0');
372338fd1498Szrj }
372438fd1498Szrj 
372538fd1498Szrj 
372638fd1498Szrj /* Like finish_mangling_internal, but return the mangled string.  */
372738fd1498Szrj 
372838fd1498Szrj static inline const char *
finish_mangling(void)372938fd1498Szrj finish_mangling (void)
373038fd1498Szrj {
373138fd1498Szrj   finish_mangling_internal ();
373238fd1498Szrj   return (const char *) obstack_finish (mangle_obstack);
373338fd1498Szrj }
373438fd1498Szrj 
373538fd1498Szrj /* Like finish_mangling_internal, but return an identifier.  */
373638fd1498Szrj 
373738fd1498Szrj static tree
finish_mangling_get_identifier(void)373838fd1498Szrj finish_mangling_get_identifier (void)
373938fd1498Szrj {
374038fd1498Szrj   finish_mangling_internal ();
374138fd1498Szrj   /* Don't obstack_finish here, and the next start_mangling will
374238fd1498Szrj      remove the identifier.  */
374338fd1498Szrj   return get_identifier ((const char *) obstack_base (mangle_obstack));
374438fd1498Szrj }
374538fd1498Szrj 
374638fd1498Szrj /* Initialize data structures for mangling.  */
374738fd1498Szrj 
374838fd1498Szrj void
init_mangle(void)374938fd1498Szrj init_mangle (void)
375038fd1498Szrj {
375138fd1498Szrj   gcc_obstack_init (&name_obstack);
375238fd1498Szrj   name_base = obstack_alloc (&name_obstack, 0);
375338fd1498Szrj   vec_alloc (G.substitutions, 0);
375438fd1498Szrj 
375538fd1498Szrj   /* Cache these identifiers for quick comparison when checking for
375638fd1498Szrj      standard substitutions.  */
375738fd1498Szrj   subst_identifiers[SUBID_ALLOCATOR] = get_identifier ("allocator");
375838fd1498Szrj   subst_identifiers[SUBID_BASIC_STRING] = get_identifier ("basic_string");
375938fd1498Szrj   subst_identifiers[SUBID_CHAR_TRAITS] = get_identifier ("char_traits");
376038fd1498Szrj   subst_identifiers[SUBID_BASIC_ISTREAM] = get_identifier ("basic_istream");
376138fd1498Szrj   subst_identifiers[SUBID_BASIC_OSTREAM] = get_identifier ("basic_ostream");
376238fd1498Szrj   subst_identifiers[SUBID_BASIC_IOSTREAM] = get_identifier ("basic_iostream");
376338fd1498Szrj }
376438fd1498Szrj 
376538fd1498Szrj /* Generate the mangled name of DECL.  */
376638fd1498Szrj 
376738fd1498Szrj static tree
mangle_decl_string(const tree decl)376838fd1498Szrj mangle_decl_string (const tree decl)
376938fd1498Szrj {
377038fd1498Szrj   tree result;
377138fd1498Szrj   location_t saved_loc = input_location;
377238fd1498Szrj   tree saved_fn = NULL_TREE;
377338fd1498Szrj   bool template_p = false;
377438fd1498Szrj 
377538fd1498Szrj   /* We shouldn't be trying to mangle an uninstantiated template.  */
377638fd1498Szrj   gcc_assert (!type_dependent_expression_p (decl));
377738fd1498Szrj 
377838fd1498Szrj   if (DECL_LANG_SPECIFIC (decl) && DECL_USE_TEMPLATE (decl))
377938fd1498Szrj     {
378038fd1498Szrj       struct tinst_level *tl = current_instantiation ();
378138fd1498Szrj       if ((!tl || tl->maybe_get_node () != decl)
378238fd1498Szrj 	  && push_tinst_level (decl))
378338fd1498Szrj 	{
378438fd1498Szrj 	  template_p = true;
378538fd1498Szrj 	  saved_fn = current_function_decl;
378638fd1498Szrj 	  current_function_decl = NULL_TREE;
378738fd1498Szrj 	}
378838fd1498Szrj     }
378938fd1498Szrj   input_location = DECL_SOURCE_LOCATION (decl);
379038fd1498Szrj 
379138fd1498Szrj   start_mangling (decl);
379238fd1498Szrj 
379338fd1498Szrj   if (TREE_CODE (decl) == TYPE_DECL)
379438fd1498Szrj     write_type (TREE_TYPE (decl));
379538fd1498Szrj   else
379638fd1498Szrj     write_mangled_name (decl, true);
379738fd1498Szrj 
379838fd1498Szrj   result = finish_mangling_get_identifier ();
379938fd1498Szrj   if (DEBUG_MANGLE)
380038fd1498Szrj     fprintf (stderr, "mangle_decl_string = '%s'\n\n",
380138fd1498Szrj 	     IDENTIFIER_POINTER (result));
380238fd1498Szrj 
380338fd1498Szrj   if (template_p)
380438fd1498Szrj     {
380538fd1498Szrj       pop_tinst_level ();
380638fd1498Szrj       current_function_decl = saved_fn;
380738fd1498Szrj     }
380838fd1498Szrj   input_location = saved_loc;
380938fd1498Szrj 
381038fd1498Szrj   return result;
381138fd1498Szrj }
381238fd1498Szrj 
381338fd1498Szrj /* Return an identifier for the external mangled name of DECL.  */
381438fd1498Szrj 
381538fd1498Szrj static tree
get_mangled_id(tree decl)381638fd1498Szrj get_mangled_id (tree decl)
381738fd1498Szrj {
381838fd1498Szrj   tree id = mangle_decl_string (decl);
381938fd1498Szrj   return targetm.mangle_decl_assembler_name (decl, id);
382038fd1498Szrj }
382138fd1498Szrj 
382238fd1498Szrj /* Create an identifier for the external mangled name of DECL.  */
382338fd1498Szrj 
382438fd1498Szrj void
mangle_decl(const tree decl)382538fd1498Szrj mangle_decl (const tree decl)
382638fd1498Szrj {
382738fd1498Szrj   tree id;
382838fd1498Szrj   bool dep;
382938fd1498Szrj 
383038fd1498Szrj   /* Don't bother mangling uninstantiated templates.  */
383138fd1498Szrj   ++processing_template_decl;
383238fd1498Szrj   if (TREE_CODE (decl) == TYPE_DECL)
383338fd1498Szrj     dep = dependent_type_p (TREE_TYPE (decl));
383438fd1498Szrj   else
383538fd1498Szrj     dep = (DECL_LANG_SPECIFIC (decl) && DECL_TEMPLATE_INFO (decl)
383638fd1498Szrj 	   && any_dependent_template_arguments_p (DECL_TI_ARGS (decl)));
383738fd1498Szrj   --processing_template_decl;
383838fd1498Szrj   if (dep)
383938fd1498Szrj     return;
384038fd1498Szrj 
384138fd1498Szrj   /* During LTO we keep mangled names of TYPE_DECLs for ODR type merging.
384238fd1498Szrj      It is not needed to assign names to anonymous namespace, but we use the
384338fd1498Szrj      "<anon>" marker to be able to tell if type is C++ ODR type or type
384438fd1498Szrj      produced by other language.  */
384538fd1498Szrj   if (TREE_CODE (decl) == TYPE_DECL
384638fd1498Szrj       && TYPE_STUB_DECL (TREE_TYPE (decl))
384738fd1498Szrj       && !TREE_PUBLIC (TYPE_STUB_DECL (TREE_TYPE (decl))))
384838fd1498Szrj     id = get_identifier ("<anon>");
384938fd1498Szrj   else
385038fd1498Szrj     {
385138fd1498Szrj       gcc_assert (TREE_CODE (decl) != TYPE_DECL
385238fd1498Szrj 		  || !no_linkage_check (TREE_TYPE (decl), true));
385338fd1498Szrj       if (abi_version_at_least (10))
385438fd1498Szrj 	if (tree fn = decl_function_context (decl))
385538fd1498Szrj 	  maybe_check_abi_tags (fn, decl);
385638fd1498Szrj       id = get_mangled_id (decl);
385738fd1498Szrj     }
385838fd1498Szrj   SET_DECL_ASSEMBLER_NAME (decl, id);
385938fd1498Szrj 
386038fd1498Szrj   if (G.need_cxx17_warning
386138fd1498Szrj       && (TREE_PUBLIC (decl) || DECL_REALLY_EXTERN (decl)))
386238fd1498Szrj     warning_at (DECL_SOURCE_LOCATION (decl), OPT_Wnoexcept_type,
386338fd1498Szrj 		"mangled name for %qD will change in C++17 because the "
386438fd1498Szrj 		"exception specification is part of a function type",
386538fd1498Szrj 		decl);
386638fd1498Szrj 
386738fd1498Szrj   if (id != DECL_NAME (decl)
386838fd1498Szrj       /* Don't do this for a fake symbol we aren't going to emit anyway.  */
386938fd1498Szrj       && TREE_CODE (decl) != TYPE_DECL
387038fd1498Szrj       && !DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (decl)
387138fd1498Szrj       && !DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P (decl))
387238fd1498Szrj     {
387338fd1498Szrj       int save_ver = flag_abi_version;
387438fd1498Szrj       tree id2 = NULL_TREE;
387538fd1498Szrj 
387638fd1498Szrj       if (!DECL_REALLY_EXTERN (decl))
387738fd1498Szrj 	{
387838fd1498Szrj 	  record_mangling (decl, G.need_abi_warning);
387938fd1498Szrj 
388038fd1498Szrj 	  if (!G.need_abi_warning)
388138fd1498Szrj 	    return;
388238fd1498Szrj 
388338fd1498Szrj 	  flag_abi_version = flag_abi_compat_version;
388438fd1498Szrj 	  id2 = mangle_decl_string (decl);
388538fd1498Szrj 	  id2 = targetm.mangle_decl_assembler_name (decl, id2);
388638fd1498Szrj 	  flag_abi_version = save_ver;
388738fd1498Szrj 
388838fd1498Szrj 	  if (id2 != id)
388938fd1498Szrj 	    note_mangling_alias (decl, id2);
389038fd1498Szrj 	}
389138fd1498Szrj 
389238fd1498Szrj       if (warn_abi)
389338fd1498Szrj 	{
389438fd1498Szrj 	  const char fabi_version[] = "-fabi-version";
389538fd1498Szrj 
389638fd1498Szrj 	  if (flag_abi_compat_version != warn_abi_version
389738fd1498Szrj 	      || id2 == NULL_TREE)
389838fd1498Szrj 	    {
389938fd1498Szrj 	      flag_abi_version = warn_abi_version;
390038fd1498Szrj 	      id2 = mangle_decl_string (decl);
390138fd1498Szrj 	      id2 = targetm.mangle_decl_assembler_name (decl, id2);
390238fd1498Szrj 	    }
390338fd1498Szrj 	  flag_abi_version = save_ver;
390438fd1498Szrj 
390538fd1498Szrj 	  if (id2 == id)
390638fd1498Szrj 	    /* OK.  */;
390738fd1498Szrj 	  else if (warn_abi_version != 0
390838fd1498Szrj 		   && abi_version_at_least (warn_abi_version))
390938fd1498Szrj 	    warning_at (DECL_SOURCE_LOCATION (G.entity), OPT_Wabi,
391038fd1498Szrj 			"the mangled name of %qD changed between "
391138fd1498Szrj 			"%<%s=%d%> (%qD) and %<%s=%d%> (%qD)",
391238fd1498Szrj 			G.entity, fabi_version, warn_abi_version, id2,
391338fd1498Szrj 			fabi_version, save_ver, id);
391438fd1498Szrj 	  else
391538fd1498Szrj 	    warning_at (DECL_SOURCE_LOCATION (G.entity), OPT_Wabi,
391638fd1498Szrj 			"the mangled name of %qD changes between "
391738fd1498Szrj 			"%<%s=%d%> (%qD) and %<%s=%d%> (%qD)",
391838fd1498Szrj 			G.entity, fabi_version, save_ver, id,
391938fd1498Szrj 			fabi_version, warn_abi_version, id2);
392038fd1498Szrj 	}
392138fd1498Szrj 
392238fd1498Szrj       flag_abi_version = save_ver;
392338fd1498Szrj     }
392438fd1498Szrj }
392538fd1498Szrj 
392638fd1498Szrj /* Generate the mangled representation of TYPE.  */
392738fd1498Szrj 
392838fd1498Szrj const char *
mangle_type_string(const tree type)392938fd1498Szrj mangle_type_string (const tree type)
393038fd1498Szrj {
393138fd1498Szrj   const char *result;
393238fd1498Szrj 
393338fd1498Szrj   start_mangling (type);
393438fd1498Szrj   write_type (type);
393538fd1498Szrj   result = finish_mangling ();
393638fd1498Szrj   if (DEBUG_MANGLE)
393738fd1498Szrj     fprintf (stderr, "mangle_type_string = '%s'\n\n", result);
393838fd1498Szrj   return result;
393938fd1498Szrj }
394038fd1498Szrj 
394138fd1498Szrj /* Create an identifier for the mangled name of a special component
394238fd1498Szrj    for belonging to TYPE.  CODE is the ABI-specified code for this
394338fd1498Szrj    component.  */
394438fd1498Szrj 
394538fd1498Szrj static tree
mangle_special_for_type(const tree type,const char * code)394638fd1498Szrj mangle_special_for_type (const tree type, const char *code)
394738fd1498Szrj {
394838fd1498Szrj   tree result;
394938fd1498Szrj 
395038fd1498Szrj   /* We don't have an actual decl here for the special component, so
395138fd1498Szrj      we can't just process the <encoded-name>.  Instead, fake it.  */
395238fd1498Szrj   start_mangling (type);
395338fd1498Szrj 
395438fd1498Szrj   /* Start the mangling.  */
395538fd1498Szrj   write_string ("_Z");
395638fd1498Szrj   write_string (code);
395738fd1498Szrj 
395838fd1498Szrj   /* Add the type.  */
395938fd1498Szrj   write_type (type);
396038fd1498Szrj   result = finish_mangling_get_identifier ();
396138fd1498Szrj 
396238fd1498Szrj   if (DEBUG_MANGLE)
396338fd1498Szrj     fprintf (stderr, "mangle_special_for_type = %s\n\n",
396438fd1498Szrj 	     IDENTIFIER_POINTER (result));
396538fd1498Szrj 
396638fd1498Szrj   return result;
396738fd1498Szrj }
396838fd1498Szrj 
396938fd1498Szrj /* Create an identifier for the mangled representation of the typeinfo
397038fd1498Szrj    structure for TYPE.  */
397138fd1498Szrj 
397238fd1498Szrj tree
mangle_typeinfo_for_type(const tree type)397338fd1498Szrj mangle_typeinfo_for_type (const tree type)
397438fd1498Szrj {
397538fd1498Szrj   return mangle_special_for_type (type, "TI");
397638fd1498Szrj }
397738fd1498Szrj 
397838fd1498Szrj /* Create an identifier for the mangled name of the NTBS containing
397938fd1498Szrj    the mangled name of TYPE.  */
398038fd1498Szrj 
398138fd1498Szrj tree
mangle_typeinfo_string_for_type(const tree type)398238fd1498Szrj mangle_typeinfo_string_for_type (const tree type)
398338fd1498Szrj {
398438fd1498Szrj   return mangle_special_for_type (type, "TS");
398538fd1498Szrj }
398638fd1498Szrj 
398738fd1498Szrj /* Create an identifier for the mangled name of the vtable for TYPE.  */
398838fd1498Szrj 
398938fd1498Szrj tree
mangle_vtbl_for_type(const tree type)399038fd1498Szrj mangle_vtbl_for_type (const tree type)
399138fd1498Szrj {
399238fd1498Szrj   return mangle_special_for_type (type, "TV");
399338fd1498Szrj }
399438fd1498Szrj 
399538fd1498Szrj /* Returns an identifier for the mangled name of the VTT for TYPE.  */
399638fd1498Szrj 
399738fd1498Szrj tree
mangle_vtt_for_type(const tree type)399838fd1498Szrj mangle_vtt_for_type (const tree type)
399938fd1498Szrj {
400038fd1498Szrj   return mangle_special_for_type (type, "TT");
400138fd1498Szrj }
400238fd1498Szrj 
400338fd1498Szrj /* Returns an identifier for the mangled name of the decomposition
400438fd1498Szrj    artificial variable DECL.  DECLS is the vector of the VAR_DECLs
400538fd1498Szrj    for the identifier-list.  */
400638fd1498Szrj 
400738fd1498Szrj tree
mangle_decomp(const tree decl,vec<tree> & decls)400838fd1498Szrj mangle_decomp (const tree decl, vec<tree> &decls)
400938fd1498Szrj {
401038fd1498Szrj   gcc_assert (!type_dependent_expression_p (decl));
401138fd1498Szrj 
401238fd1498Szrj   location_t saved_loc = input_location;
401338fd1498Szrj   input_location = DECL_SOURCE_LOCATION (decl);
401438fd1498Szrj 
401538fd1498Szrj   start_mangling (decl);
401638fd1498Szrj   write_string ("_Z");
401738fd1498Szrj 
401838fd1498Szrj   tree context = decl_mangling_context (decl);
401938fd1498Szrj   gcc_assert (context != NULL_TREE);
402038fd1498Szrj 
402138fd1498Szrj   bool nested = false;
402238fd1498Szrj   if (DECL_NAMESPACE_STD_P (context))
402338fd1498Szrj     write_string ("St");
402438fd1498Szrj   else if (context != global_namespace)
402538fd1498Szrj     {
402638fd1498Szrj       nested = true;
402738fd1498Szrj       write_char ('N');
402838fd1498Szrj       write_prefix (decl_mangling_context (decl));
402938fd1498Szrj     }
403038fd1498Szrj 
403138fd1498Szrj   write_string ("DC");
403238fd1498Szrj   unsigned int i;
403338fd1498Szrj   tree d;
403438fd1498Szrj   FOR_EACH_VEC_ELT (decls, i, d)
403538fd1498Szrj     write_unqualified_name (d);
403638fd1498Szrj   write_char ('E');
403738fd1498Szrj 
403838fd1498Szrj   if (nested)
403938fd1498Szrj     write_char ('E');
404038fd1498Szrj 
404138fd1498Szrj   tree id = finish_mangling_get_identifier ();
404238fd1498Szrj   if (DEBUG_MANGLE)
404338fd1498Szrj     fprintf (stderr, "mangle_decomp = '%s'\n\n",
404438fd1498Szrj              IDENTIFIER_POINTER (id));
404538fd1498Szrj 
404638fd1498Szrj   input_location = saved_loc;
404738fd1498Szrj   return id;
404838fd1498Szrj }
404938fd1498Szrj 
405038fd1498Szrj /* Return an identifier for a construction vtable group.  TYPE is
405138fd1498Szrj    the most derived class in the hierarchy; BINFO is the base
405238fd1498Szrj    subobject for which this construction vtable group will be used.
405338fd1498Szrj 
405438fd1498Szrj    This mangling isn't part of the ABI specification; in the ABI
405538fd1498Szrj    specification, the vtable group is dumped in the same COMDAT as the
405638fd1498Szrj    main vtable, and is referenced only from that vtable, so it doesn't
405738fd1498Szrj    need an external name.  For binary formats without COMDAT sections,
405838fd1498Szrj    though, we need external names for the vtable groups.
405938fd1498Szrj 
406038fd1498Szrj    We use the production
406138fd1498Szrj 
406238fd1498Szrj     <special-name> ::= CT <type> <offset number> _ <base type>  */
406338fd1498Szrj 
406438fd1498Szrj tree
mangle_ctor_vtbl_for_type(const tree type,const tree binfo)406538fd1498Szrj mangle_ctor_vtbl_for_type (const tree type, const tree binfo)
406638fd1498Szrj {
406738fd1498Szrj   tree result;
406838fd1498Szrj 
406938fd1498Szrj   start_mangling (type);
407038fd1498Szrj 
407138fd1498Szrj   write_string ("_Z");
407238fd1498Szrj   write_string ("TC");
407338fd1498Szrj   write_type (type);
407438fd1498Szrj   write_integer_cst (BINFO_OFFSET (binfo));
407538fd1498Szrj   write_char ('_');
407638fd1498Szrj   write_type (BINFO_TYPE (binfo));
407738fd1498Szrj 
407838fd1498Szrj   result = finish_mangling_get_identifier ();
407938fd1498Szrj   if (DEBUG_MANGLE)
408038fd1498Szrj     fprintf (stderr, "mangle_ctor_vtbl_for_type = %s\n\n",
408138fd1498Szrj 	     IDENTIFIER_POINTER (result));
408238fd1498Szrj   return result;
408338fd1498Szrj }
408438fd1498Szrj 
408538fd1498Szrj /* Mangle a this pointer or result pointer adjustment.
408638fd1498Szrj 
408738fd1498Szrj    <call-offset> ::= h <fixed offset number> _
408838fd1498Szrj 		 ::= v <fixed offset number> _ <virtual offset number> _ */
408938fd1498Szrj 
409038fd1498Szrj static void
mangle_call_offset(const tree fixed_offset,const tree virtual_offset)409138fd1498Szrj mangle_call_offset (const tree fixed_offset, const tree virtual_offset)
409238fd1498Szrj {
409338fd1498Szrj   write_char (virtual_offset ? 'v' : 'h');
409438fd1498Szrj 
409538fd1498Szrj   /* For either flavor, write the fixed offset.  */
409638fd1498Szrj   write_integer_cst (fixed_offset);
409738fd1498Szrj   write_char ('_');
409838fd1498Szrj 
409938fd1498Szrj   /* For a virtual thunk, add the virtual offset.  */
410038fd1498Szrj   if (virtual_offset)
410138fd1498Szrj     {
410238fd1498Szrj       write_integer_cst (virtual_offset);
410338fd1498Szrj       write_char ('_');
410438fd1498Szrj     }
410538fd1498Szrj }
410638fd1498Szrj 
410738fd1498Szrj /* Return an identifier for the mangled name of a this-adjusting or
410838fd1498Szrj    covariant thunk to FN_DECL.  FIXED_OFFSET is the initial adjustment
410938fd1498Szrj    to this used to find the vptr.  If VIRTUAL_OFFSET is non-NULL, this
411038fd1498Szrj    is a virtual thunk, and it is the vtbl offset in
411138fd1498Szrj    bytes. THIS_ADJUSTING is nonzero for a this adjusting thunk and
411238fd1498Szrj    zero for a covariant thunk. Note, that FN_DECL might be a covariant
411338fd1498Szrj    thunk itself. A covariant thunk name always includes the adjustment
411438fd1498Szrj    for the this pointer, even if there is none.
411538fd1498Szrj 
411638fd1498Szrj    <special-name> ::= T <call-offset> <base encoding>
411738fd1498Szrj 		  ::= Tc <this_adjust call-offset> <result_adjust call-offset>
411838fd1498Szrj 					<base encoding>  */
411938fd1498Szrj 
412038fd1498Szrj tree
mangle_thunk(tree fn_decl,const int this_adjusting,tree fixed_offset,tree virtual_offset,tree thunk)412138fd1498Szrj mangle_thunk (tree fn_decl, const int this_adjusting, tree fixed_offset,
412238fd1498Szrj 	      tree virtual_offset, tree thunk)
412338fd1498Szrj {
412438fd1498Szrj   tree result;
412538fd1498Szrj 
412638fd1498Szrj   if (abi_version_at_least (11))
412738fd1498Szrj     maybe_check_abi_tags (fn_decl, thunk, 11);
412838fd1498Szrj 
412938fd1498Szrj   start_mangling (fn_decl);
413038fd1498Szrj 
413138fd1498Szrj   write_string ("_Z");
413238fd1498Szrj   write_char ('T');
413338fd1498Szrj 
413438fd1498Szrj   if (!this_adjusting)
413538fd1498Szrj     {
413638fd1498Szrj       /* Covariant thunk with no this adjustment */
413738fd1498Szrj       write_char ('c');
413838fd1498Szrj       mangle_call_offset (integer_zero_node, NULL_TREE);
413938fd1498Szrj       mangle_call_offset (fixed_offset, virtual_offset);
414038fd1498Szrj     }
414138fd1498Szrj   else if (!DECL_THUNK_P (fn_decl))
414238fd1498Szrj     /* Plain this adjusting thunk.  */
414338fd1498Szrj     mangle_call_offset (fixed_offset, virtual_offset);
414438fd1498Szrj   else
414538fd1498Szrj     {
414638fd1498Szrj       /* This adjusting thunk to covariant thunk.  */
414738fd1498Szrj       write_char ('c');
414838fd1498Szrj       mangle_call_offset (fixed_offset, virtual_offset);
414938fd1498Szrj       fixed_offset = ssize_int (THUNK_FIXED_OFFSET (fn_decl));
415038fd1498Szrj       virtual_offset = THUNK_VIRTUAL_OFFSET (fn_decl);
415138fd1498Szrj       if (virtual_offset)
415238fd1498Szrj 	virtual_offset = BINFO_VPTR_FIELD (virtual_offset);
415338fd1498Szrj       mangle_call_offset (fixed_offset, virtual_offset);
415438fd1498Szrj       fn_decl = THUNK_TARGET (fn_decl);
415538fd1498Szrj     }
415638fd1498Szrj 
415738fd1498Szrj   /* Scoped name.  */
415838fd1498Szrj   write_encoding (fn_decl);
415938fd1498Szrj 
416038fd1498Szrj   result = finish_mangling_get_identifier ();
416138fd1498Szrj   if (DEBUG_MANGLE)
416238fd1498Szrj     fprintf (stderr, "mangle_thunk = %s\n\n", IDENTIFIER_POINTER (result));
416338fd1498Szrj   return result;
416438fd1498Szrj }
416538fd1498Szrj 
416638fd1498Szrj /* Handle ABI backwards compatibility for past bugs where we didn't call
416738fd1498Szrj    check_abi_tags in places where it's needed: call check_abi_tags and warn if
416838fd1498Szrj    it makes a difference.  If FOR_DECL is non-null, it's the declaration
416938fd1498Szrj    that we're actually trying to mangle; if it's null, we're mangling the
417038fd1498Szrj    guard variable for T.  */
417138fd1498Szrj 
417238fd1498Szrj static void
maybe_check_abi_tags(tree t,tree for_decl,int ver)417338fd1498Szrj maybe_check_abi_tags (tree t, tree for_decl, int ver)
417438fd1498Szrj {
417538fd1498Szrj   if (DECL_ASSEMBLER_NAME_SET_P (t))
417638fd1498Szrj     return;
417738fd1498Szrj 
417838fd1498Szrj   tree oldtags = get_abi_tags (t);
417938fd1498Szrj 
418038fd1498Szrj   mangle_decl (t);
418138fd1498Szrj 
418238fd1498Szrj   tree newtags = get_abi_tags (t);
418338fd1498Szrj   if (newtags && newtags != oldtags
418438fd1498Szrj       && abi_version_crosses (ver))
418538fd1498Szrj     {
418638fd1498Szrj       if (for_decl && DECL_THUNK_P (for_decl))
418738fd1498Szrj 	warning_at (DECL_SOURCE_LOCATION (t), OPT_Wabi,
418838fd1498Szrj 		    "the mangled name of a thunk for %qD changes between "
418938fd1498Szrj 		    "-fabi-version=%d and -fabi-version=%d",
419038fd1498Szrj 		    t, flag_abi_version, warn_abi_version);
419138fd1498Szrj       else if (for_decl)
419238fd1498Szrj 	warning_at (DECL_SOURCE_LOCATION (for_decl), OPT_Wabi,
419338fd1498Szrj 		    "the mangled name of %qD changes between "
419438fd1498Szrj 		    "-fabi-version=%d and -fabi-version=%d",
419538fd1498Szrj 		    for_decl, flag_abi_version, warn_abi_version);
419638fd1498Szrj       else
419738fd1498Szrj 	warning_at (DECL_SOURCE_LOCATION (t), OPT_Wabi,
419838fd1498Szrj 		    "the mangled name of the initialization guard variable "
419938fd1498Szrj 		    "for %qD changes between -fabi-version=%d and "
420038fd1498Szrj 		    "-fabi-version=%d",
420138fd1498Szrj 		    t, flag_abi_version, warn_abi_version);
420238fd1498Szrj     }
420338fd1498Szrj }
420438fd1498Szrj 
420538fd1498Szrj /* Write out the appropriate string for this variable when generating
420638fd1498Szrj    another mangled name based on this one.  */
420738fd1498Szrj 
420838fd1498Szrj static void
write_guarded_var_name(const tree variable)420938fd1498Szrj write_guarded_var_name (const tree variable)
421038fd1498Szrj {
421138fd1498Szrj   if (DECL_NAME (variable)
421238fd1498Szrj       && strncmp (IDENTIFIER_POINTER (DECL_NAME (variable)), "_ZGR", 4) == 0)
421338fd1498Szrj     /* The name of a guard variable for a reference temporary should refer
421438fd1498Szrj        to the reference, not the temporary.  */
421538fd1498Szrj     write_string (IDENTIFIER_POINTER (DECL_NAME (variable)) + 4);
421638fd1498Szrj   else
421738fd1498Szrj     write_name (variable, /*ignore_local_scope=*/0);
421838fd1498Szrj }
421938fd1498Szrj 
422038fd1498Szrj /* Return an identifier for the name of an initialization guard
422138fd1498Szrj    variable for indicated VARIABLE.  */
422238fd1498Szrj 
422338fd1498Szrj tree
mangle_guard_variable(const tree variable)422438fd1498Szrj mangle_guard_variable (const tree variable)
422538fd1498Szrj {
422638fd1498Szrj   if (abi_version_at_least (10))
422738fd1498Szrj     maybe_check_abi_tags (variable);
422838fd1498Szrj   start_mangling (variable);
422938fd1498Szrj   write_string ("_ZGV");
423038fd1498Szrj   write_guarded_var_name (variable);
423138fd1498Szrj   return finish_mangling_get_identifier ();
423238fd1498Szrj }
423338fd1498Szrj 
423438fd1498Szrj /* Return an identifier for the name of a thread_local initialization
423538fd1498Szrj    function for VARIABLE.  */
423638fd1498Szrj 
423738fd1498Szrj tree
mangle_tls_init_fn(const tree variable)423838fd1498Szrj mangle_tls_init_fn (const tree variable)
423938fd1498Szrj {
424038fd1498Szrj   check_abi_tags (variable);
424138fd1498Szrj   start_mangling (variable);
424238fd1498Szrj   write_string ("_ZTH");
424338fd1498Szrj   write_guarded_var_name (variable);
424438fd1498Szrj   return finish_mangling_get_identifier ();
424538fd1498Szrj }
424638fd1498Szrj 
424738fd1498Szrj /* Return an identifier for the name of a thread_local wrapper
424838fd1498Szrj    function for VARIABLE.  */
424938fd1498Szrj 
425038fd1498Szrj #define TLS_WRAPPER_PREFIX "_ZTW"
425138fd1498Szrj 
425238fd1498Szrj tree
mangle_tls_wrapper_fn(const tree variable)425338fd1498Szrj mangle_tls_wrapper_fn (const tree variable)
425438fd1498Szrj {
425538fd1498Szrj   check_abi_tags (variable);
425638fd1498Szrj   start_mangling (variable);
425738fd1498Szrj   write_string (TLS_WRAPPER_PREFIX);
425838fd1498Szrj   write_guarded_var_name (variable);
425938fd1498Szrj   return finish_mangling_get_identifier ();
426038fd1498Szrj }
426138fd1498Szrj 
426238fd1498Szrj /* Return true iff FN is a thread_local wrapper function.  */
426338fd1498Szrj 
426438fd1498Szrj bool
decl_tls_wrapper_p(const tree fn)426538fd1498Szrj decl_tls_wrapper_p (const tree fn)
426638fd1498Szrj {
426738fd1498Szrj   if (TREE_CODE (fn) != FUNCTION_DECL)
426838fd1498Szrj     return false;
426938fd1498Szrj   tree name = DECL_NAME (fn);
427038fd1498Szrj   return strncmp (IDENTIFIER_POINTER (name), TLS_WRAPPER_PREFIX,
427138fd1498Szrj 		  strlen (TLS_WRAPPER_PREFIX)) == 0;
427238fd1498Szrj }
427338fd1498Szrj 
427438fd1498Szrj /* Return an identifier for the name of a temporary variable used to
427538fd1498Szrj    initialize a static reference.  This isn't part of the ABI, but we might
427638fd1498Szrj    as well call them something readable.  */
427738fd1498Szrj 
427838fd1498Szrj static GTY(()) int temp_count;
427938fd1498Szrj 
428038fd1498Szrj tree
mangle_ref_init_variable(const tree variable)428138fd1498Szrj mangle_ref_init_variable (const tree variable)
428238fd1498Szrj {
428338fd1498Szrj   start_mangling (variable);
428438fd1498Szrj   write_string ("_ZGR");
428538fd1498Szrj   check_abi_tags (variable);
428638fd1498Szrj   write_name (variable, /*ignore_local_scope=*/0);
428738fd1498Szrj   /* Avoid name clashes with aggregate initialization of multiple
428838fd1498Szrj      references at once.  */
428938fd1498Szrj   write_unsigned_number (temp_count++);
429038fd1498Szrj   return finish_mangling_get_identifier ();
429138fd1498Szrj }
429238fd1498Szrj 
429338fd1498Szrj /* Given a CLASS_TYPE, such as a record for std::bad_exception this
429438fd1498Szrj    function generates a mangled name for the vtable map variable of
429538fd1498Szrj    the class type.  For example, if the class type is
429638fd1498Szrj    "std::bad_exception", the mangled name for the class is
429738fd1498Szrj    "St13bad_exception".  This function would generate the name
429838fd1498Szrj    "_ZN4_VTVISt13bad_exceptionE12__vtable_mapE", which unmangles as:
429938fd1498Szrj    "_VTV<std::bad_exception>::__vtable_map".  */
430038fd1498Szrj 
430138fd1498Szrj 
430238fd1498Szrj char *
get_mangled_vtable_map_var_name(tree class_type)430338fd1498Szrj get_mangled_vtable_map_var_name (tree class_type)
430438fd1498Szrj {
430538fd1498Szrj   char *var_name = NULL;
430638fd1498Szrj   const char *prefix = "_ZN4_VTVI";
430738fd1498Szrj   const char *postfix = "E12__vtable_mapE";
430838fd1498Szrj 
430938fd1498Szrj   gcc_assert (TREE_CODE (class_type) == RECORD_TYPE);
431038fd1498Szrj 
431138fd1498Szrj   tree class_id = DECL_ASSEMBLER_NAME (TYPE_NAME (class_type));
431238fd1498Szrj 
431338fd1498Szrj   if (strstr (IDENTIFIER_POINTER (class_id), "<anon>") != NULL)
431438fd1498Szrj     {
431538fd1498Szrj       class_id = get_mangled_id (TYPE_NAME (class_type));
431638fd1498Szrj       vtbl_register_mangled_name (TYPE_NAME (class_type), class_id);
431738fd1498Szrj     }
431838fd1498Szrj 
431938fd1498Szrj   unsigned int len = strlen (IDENTIFIER_POINTER (class_id)) +
432038fd1498Szrj                      strlen (prefix) +
432138fd1498Szrj                      strlen (postfix) + 1;
432238fd1498Szrj 
432338fd1498Szrj   var_name = (char *) xmalloc (len);
432438fd1498Szrj 
432538fd1498Szrj   sprintf (var_name, "%s%s%s", prefix, IDENTIFIER_POINTER (class_id), postfix);
432638fd1498Szrj 
432738fd1498Szrj   return var_name;
432838fd1498Szrj }
432938fd1498Szrj 
433038fd1498Szrj #include "gt-cp-mangle.h"
4331