mangle.c revision 90075
190075Sobrien/* Name mangling for the 3.0 C++ ABI.
290075Sobrien   Copyright (C) 2000, 2001, 2002 Free Software Foundation, Inc.
390075Sobrien   Written by Alex Samuel <sameul@codesourcery.com>
490075Sobrien
590075Sobrien   This file is part of GNU CC.
690075Sobrien
790075Sobrien   GNU CC is free software; you can redistribute it and/or modify it
890075Sobrien   under the terms of the GNU General Public License as published by
990075Sobrien   the Free Software Foundation; either version 2, or (at your option)
1090075Sobrien   any later version.
1190075Sobrien
1290075Sobrien   GNU CC is distributed in the hope that it will be useful, but
1390075Sobrien   WITHOUT ANY WARRANTY; without even the implied warranty of
1490075Sobrien   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
1590075Sobrien   General Public License for more details.
1690075Sobrien
1790075Sobrien   You should have received a copy of the GNU General Public License
1890075Sobrien   along with GNU CC; see the file COPYING.  If not, write to the Free
1990075Sobrien   Software Foundation, 59 Temple Place - Suite 330, Boston, MA
2090075Sobrien   02111-1307, USA.  */
2190075Sobrien
2290075Sobrien/* This file implements mangling of C++ names according to the IA64
2390075Sobrien   C++ ABI specification.  A mangled name encodes a function or
2490075Sobrien   variable's name, scope, type, and/or template arguments into a text
2590075Sobrien   identifier.  This identifier is used as the function's or
2690075Sobrien   variable's linkage name, to preserve compatibility between C++'s
2790075Sobrien   language features (templates, scoping, and overloading) and C
2890075Sobrien   linkers.
2990075Sobrien
3090075Sobrien   Additionally, g++ uses mangled names internally.  To support this,
3190075Sobrien   mangling of types is allowed, even though the mangled name of a
3290075Sobrien   type should not appear by itself as an exported name.  Ditto for
3390075Sobrien   uninstantiated templates.
3490075Sobrien
3590075Sobrien   The primary entry point for this module is mangle_decl, which
3690075Sobrien   returns an identifier containing the mangled name for a decl.
3790075Sobrien   Additional entry points are provided to build mangled names of
3890075Sobrien   particular constructs when the appropriate decl for that construct
3990075Sobrien   is not available.  These are:
4090075Sobrien
4190075Sobrien     mangle_typeinfo_for_type:        typeinfo data
4290075Sobrien     mangle_typeinfo_string_for_type: typeinfo type name
4390075Sobrien     mangle_vtbl_for_type:            virtual table data
4490075Sobrien     mangle_vtt_for_type:             VTT data
4590075Sobrien     mangle_ctor_vtbl_for_type:       `C-in-B' constructor virtual table data
4690075Sobrien     mangle_thunk:                    thunk function or entry
4790075Sobrien
4890075Sobrien*/
4990075Sobrien
5090075Sobrien#include "config.h"
5190075Sobrien#include "system.h"
5290075Sobrien#include "tree.h"
5390075Sobrien#include "cp-tree.h"
5490075Sobrien#include "obstack.h"
5590075Sobrien#include "toplev.h"
5690075Sobrien#include "varray.h"
5790075Sobrien
5890075Sobrien/* Debugging support.  */
5990075Sobrien
6090075Sobrien/* Define DEBUG_MANGLE to enable very verbose trace messages.  */
6190075Sobrien#ifndef DEBUG_MANGLE
6290075Sobrien#define DEBUG_MANGLE 0
6390075Sobrien#endif
6490075Sobrien
6590075Sobrien/* Macros for tracing the write_* functions.  */
6690075Sobrien#if DEBUG_MANGLE
6790075Sobrien# define MANGLE_TRACE(FN, INPUT) \
6890075Sobrien  fprintf (stderr, "  %-24s: %-24s\n", (FN), (INPUT))
6990075Sobrien# define MANGLE_TRACE_TREE(FN, NODE) \
7090075Sobrien  fprintf (stderr, "  %-24s: %-24s (%p)\n", \
7190075Sobrien           (FN), tree_code_name[TREE_CODE (NODE)], (void *) (NODE))
7290075Sobrien#else
7390075Sobrien# define MANGLE_TRACE(FN, INPUT)
7490075Sobrien# define MANGLE_TRACE_TREE(FN, NODE)
7590075Sobrien#endif
7690075Sobrien
7790075Sobrien/* Non-zero if NODE is a class template-id.  We can't rely on
7890075Sobrien   CLASSTYPE_USE_TEMPLATE here because of tricky bugs in the parser
7990075Sobrien   that hard to distinguish A<T> from A, where A<T> is the type as
8090075Sobrien   instantiated outside of the template, and A is the type used
8190075Sobrien   without parameters inside the template.  */
8290075Sobrien#define CLASSTYPE_TEMPLATE_ID_P(NODE)				      \
8390075Sobrien  (TYPE_LANG_SPECIFIC (NODE) != NULL 				      \
8490075Sobrien   && CLASSTYPE_TEMPLATE_INFO (NODE) != NULL                          \
8590075Sobrien   && (PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (NODE))))
8690075Sobrien
8790075Sobrien/* Things we only need one of.  This module is not reentrant.  */
8890075Sobrienstatic struct globals
8990075Sobrien{
9090075Sobrien  /* The name in which we're building the mangled name.  */
9190075Sobrien  struct obstack name_obstack;
9290075Sobrien
9390075Sobrien  /* An array of the current substitution candidates, in the order
9490075Sobrien     we've seen them.  */
9590075Sobrien  varray_type substitutions;
9690075Sobrien} G;
9790075Sobrien
9890075Sobrien/* Indices into subst_identifiers.  These are identifiers used in
9990075Sobrien   special substitution rules.  */
10090075Sobrientypedef enum
10190075Sobrien{
10290075Sobrien  SUBID_ALLOCATOR,
10390075Sobrien  SUBID_BASIC_STRING,
10490075Sobrien  SUBID_CHAR_TRAITS,
10590075Sobrien  SUBID_BASIC_ISTREAM,
10690075Sobrien  SUBID_BASIC_OSTREAM,
10790075Sobrien  SUBID_BASIC_IOSTREAM,
10890075Sobrien  SUBID_MAX
10990075Sobrien}
11090075Sobriensubstitution_identifier_index_t;
11190075Sobrien
11290075Sobrien/* For quick substitution checks, look up these common identifiers
11390075Sobrien   once only.  */
11490075Sobrienstatic tree subst_identifiers[SUBID_MAX];
11590075Sobrien
11690075Sobrien/* Single-letter codes for builtin integer types, defined in
11790075Sobrien   <builtin-type>.  These are indexed by integer_type_kind values.  */
11890075Sobrienstatic char
11990075Sobrieninteger_type_codes[itk_none] =
12090075Sobrien{
12190075Sobrien  'c',  /* itk_char */
12290075Sobrien  'a',  /* itk_signed_char */
12390075Sobrien  'h',  /* itk_unsigned_char */
12490075Sobrien  's',  /* itk_short */
12590075Sobrien  't',  /* itk_unsigned_short */
12690075Sobrien  'i',  /* itk_int */
12790075Sobrien  'j',  /* itk_unsigned_int */
12890075Sobrien  'l',  /* itk_long */
12990075Sobrien  'm',  /* itk_unsigned_long */
13090075Sobrien  'x',  /* itk_long_long */
13190075Sobrien  'y'   /* itk_unsigned_long_long */
13290075Sobrien};
13390075Sobrien
13490075Sobrienstatic int decl_is_template_id PARAMS ((tree, tree*));
13590075Sobrien
13690075Sobrien/* Functions for handling substitutions.  */
13790075Sobrien
13890075Sobrienstatic inline tree canonicalize_for_substitution PARAMS ((tree));
13990075Sobrienstatic void add_substitution PARAMS ((tree));
14090075Sobrienstatic inline int is_std_substitution PARAMS ((tree, substitution_identifier_index_t));
14190075Sobrienstatic inline int is_std_substitution_char PARAMS ((tree, substitution_identifier_index_t));
14290075Sobrienstatic int find_substitution PARAMS ((tree));
14390075Sobrien
14490075Sobrien/* Functions for emitting mangled representations of things.  */
14590075Sobrien
14690075Sobrienstatic void write_mangled_name PARAMS ((tree));
14790075Sobrienstatic void write_encoding PARAMS ((tree));
14890075Sobrienstatic void write_name PARAMS ((tree, int));
14990075Sobrienstatic void write_unscoped_name PARAMS ((tree));
15090075Sobrienstatic void write_unscoped_template_name PARAMS ((tree));
15190075Sobrienstatic void write_nested_name PARAMS ((tree));
15290075Sobrienstatic void write_prefix PARAMS ((tree));
15390075Sobrienstatic void write_template_prefix PARAMS ((tree));
15490075Sobrienstatic void write_unqualified_name PARAMS ((tree));
15590075Sobrienstatic void write_source_name PARAMS ((tree));
15690075Sobrienstatic int hwint_to_ascii PARAMS ((unsigned HOST_WIDE_INT, unsigned int, char *, unsigned));
15790075Sobrienstatic void write_number PARAMS ((unsigned HOST_WIDE_INT, int,
15890075Sobrien				  unsigned int));
15990075Sobrienstatic void write_integer_cst PARAMS ((tree));
16090075Sobrienstatic void write_identifier PARAMS ((const char *));
16190075Sobrienstatic void write_special_name_constructor PARAMS ((tree));
16290075Sobrienstatic void write_special_name_destructor PARAMS ((tree));
16390075Sobrienstatic void write_type PARAMS ((tree));
16490075Sobrienstatic int write_CV_qualifiers_for_type PARAMS ((tree));
16590075Sobrienstatic void write_builtin_type PARAMS ((tree));
16690075Sobrienstatic void write_function_type PARAMS ((tree));
16790075Sobrienstatic void write_bare_function_type PARAMS ((tree, int, tree));
16890075Sobrienstatic void write_method_parms PARAMS ((tree, int, tree));
16990075Sobrienstatic void write_class_enum_type PARAMS ((tree));
17090075Sobrienstatic void write_template_args PARAMS ((tree));
17190075Sobrienstatic void write_expression PARAMS ((tree));
17290075Sobrienstatic void write_template_arg_literal PARAMS ((tree));
17390075Sobrienstatic void write_template_arg PARAMS ((tree));
17490075Sobrienstatic void write_template_template_arg PARAMS ((tree));
17590075Sobrienstatic void write_array_type PARAMS ((tree));
17690075Sobrienstatic void write_pointer_to_member_type PARAMS ((tree));
17790075Sobrienstatic void write_template_param PARAMS ((tree));
17890075Sobrienstatic void write_template_template_param PARAMS ((tree));
17990075Sobrienstatic void write_substitution PARAMS ((int));
18090075Sobrienstatic int discriminator_for_local_entity PARAMS ((tree));
18190075Sobrienstatic int discriminator_for_string_literal PARAMS ((tree, tree));
18290075Sobrienstatic void write_discriminator PARAMS ((int));
18390075Sobrienstatic void write_local_name PARAMS ((tree, tree, tree));
18490075Sobrienstatic void dump_substitution_candidates PARAMS ((void));
18590075Sobrienstatic const char *mangle_decl_string PARAMS ((tree));
18690075Sobrien
18790075Sobrien/* Control functions.  */
18890075Sobrien
18990075Sobrienstatic inline void start_mangling PARAMS ((void));
19090075Sobrienstatic inline const char *finish_mangling PARAMS ((void));
19190075Sobrienstatic tree mangle_special_for_type PARAMS ((tree, const char *));
19290075Sobrien
19390075Sobrien/* Foreign language functions. */
19490075Sobrien
19590075Sobrienstatic void write_java_integer_type_codes PARAMS ((tree));
19690075Sobrien
19790075Sobrien/* Append a single character to the end of the mangled
19890075Sobrien   representation.  */
19990075Sobrien#define write_char(CHAR)                                              \
20090075Sobrien  obstack_1grow (&G.name_obstack, (CHAR))
20190075Sobrien
20290075Sobrien/* Append a sized buffer to the end of the mangled representation. */
20390075Sobrien#define write_chars(CHAR, LEN)                                        \
20490075Sobrien  obstack_grow (&G.name_obstack, (CHAR), (LEN))
20590075Sobrien
20690075Sobrien/* Append a NUL-terminated string to the end of the mangled
20790075Sobrien   representation.  */
20890075Sobrien#define write_string(STRING)                                          \
20990075Sobrien  obstack_grow (&G.name_obstack, (STRING), strlen (STRING))
21090075Sobrien
21190075Sobrien/* Return the position at which the next character will be appended to
21290075Sobrien   the mangled representation.  */
21390075Sobrien#define mangled_position()                                              \
21490075Sobrien  obstack_object_size (&G.name_obstack)
21590075Sobrien
21690075Sobrien/* Non-zero if NODE1 and NODE2 are both TREE_LIST nodes and have the
21790075Sobrien   same purpose (context, which may be a type) and value (template
21890075Sobrien   decl).  See write_template_prefix for more information on what this
21990075Sobrien   is used for.  */
22090075Sobrien#define NESTED_TEMPLATE_MATCH(NODE1, NODE2)                         \
22190075Sobrien  (TREE_CODE (NODE1) == TREE_LIST                                     \
22290075Sobrien   && TREE_CODE (NODE2) == TREE_LIST                                  \
22390075Sobrien   && ((TYPE_P (TREE_PURPOSE (NODE1))                                 \
22490075Sobrien        && same_type_p (TREE_PURPOSE (NODE1), TREE_PURPOSE (NODE2)))\
22590075Sobrien       || TREE_PURPOSE (NODE1) == TREE_PURPOSE (NODE2))             \
22690075Sobrien   && TREE_VALUE (NODE1) == TREE_VALUE (NODE2))
22790075Sobrien
22890075Sobrien/* Write out a signed quantity in base 10.  */
22990075Sobrien#define write_signed_number(NUMBER) \
23090075Sobrien  write_number ((NUMBER), /*unsigned_p=*/0, 10)
23190075Sobrien
23290075Sobrien/* Write out an unsigned quantity in base 10.  */
23390075Sobrien#define write_unsigned_number(NUMBER) \
23490075Sobrien  write_number ((NUMBER), /*unsigned_p=*/1, 10)
23590075Sobrien
23690075Sobrien/* If DECL is a template instance, return non-zero and, if
23790075Sobrien   TEMPLATE_INFO is non-NULL, set *TEMPLATE_INFO to its template info.
23890075Sobrien   Otherwise return zero.  */
23990075Sobrien
24090075Sobrienstatic int
24190075Sobriendecl_is_template_id (decl, template_info)
24290075Sobrien     tree decl;
24390075Sobrien     tree* template_info;
24490075Sobrien{
24590075Sobrien  if (TREE_CODE (decl) == TYPE_DECL)
24690075Sobrien    {
24790075Sobrien      /* TYPE_DECLs are handled specially.  Look at its type to decide
24890075Sobrien	 if this is a template instantiation.  */
24990075Sobrien      tree type = TREE_TYPE (decl);
25090075Sobrien
25190075Sobrien      if (CLASS_TYPE_P (type) && CLASSTYPE_TEMPLATE_ID_P (type))
25290075Sobrien	{
25390075Sobrien	  if (template_info != NULL)
25490075Sobrien	    /* For a templated TYPE_DECL, the template info is hanging
25590075Sobrien	       off the type.  */
25690075Sobrien	    *template_info = CLASSTYPE_TEMPLATE_INFO (type);
25790075Sobrien	  return 1;
25890075Sobrien	}
25990075Sobrien    }
26090075Sobrien  else
26190075Sobrien    {
26290075Sobrien      /* Check if this is a primary template.  */
26390075Sobrien      if (DECL_LANG_SPECIFIC (decl) != NULL
26490075Sobrien	  && DECL_USE_TEMPLATE (decl)
26590075Sobrien	  && PRIMARY_TEMPLATE_P (DECL_TI_TEMPLATE (decl))
26690075Sobrien	  && TREE_CODE (decl) != TEMPLATE_DECL)
26790075Sobrien	{
26890075Sobrien	  if (template_info != NULL)
26990075Sobrien	    /* For most templated decls, the template info is hanging
27090075Sobrien	       off the decl.  */
27190075Sobrien	    *template_info = DECL_TEMPLATE_INFO (decl);
27290075Sobrien	  return 1;
27390075Sobrien	}
27490075Sobrien    }
27590075Sobrien
27690075Sobrien  /* It's not a template id.  */
27790075Sobrien  return 0;
27890075Sobrien}
27990075Sobrien
28090075Sobrien/* Produce debugging output of current substitution candidates.  */
28190075Sobrien
28290075Sobrienstatic void
28390075Sobriendump_substitution_candidates ()
28490075Sobrien{
28590075Sobrien  unsigned i;
28690075Sobrien
28790075Sobrien  fprintf (stderr, "  ++ substitutions  ");
28890075Sobrien  for (i = 0; i < VARRAY_ACTIVE_SIZE (G.substitutions); ++i)
28990075Sobrien    {
29090075Sobrien      tree el = VARRAY_TREE (G.substitutions, i);
29190075Sobrien      const char *name = "???";
29290075Sobrien
29390075Sobrien      if (i > 0)
29490075Sobrien	fprintf (stderr, "                    ");
29590075Sobrien      if (DECL_P (el))
29690075Sobrien	name = IDENTIFIER_POINTER (DECL_NAME (el));
29790075Sobrien      else if (TREE_CODE (el) == TREE_LIST)
29890075Sobrien	name = IDENTIFIER_POINTER (DECL_NAME (TREE_VALUE (el)));
29990075Sobrien      else if (TYPE_NAME (el))
30090075Sobrien	name = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (el)));
30190075Sobrien      fprintf (stderr, " S%d_ = ", i - 1);
30290075Sobrien      if (TYPE_P (el) &&
30390075Sobrien	  (CP_TYPE_RESTRICT_P (el)
30490075Sobrien	   || CP_TYPE_VOLATILE_P (el)
30590075Sobrien	   || CP_TYPE_CONST_P (el)))
30690075Sobrien	fprintf (stderr, "CV-");
30790075Sobrien      fprintf (stderr, "%s (%s at %p)\n",
30890075Sobrien	       name, tree_code_name[TREE_CODE (el)], (void *) el);
30990075Sobrien    }
31090075Sobrien}
31190075Sobrien
31290075Sobrien/* Both decls and types can be substitution candidates, but sometimes
31390075Sobrien   they refer to the same thing.  For instance, a TYPE_DECL and
31490075Sobrien   RECORD_TYPE for the same class refer to the same thing, and should
31590075Sobrien   be treated accordinginly in substitutions.  This function returns a
31690075Sobrien   canonicalized tree node representing NODE that is used when adding
31790075Sobrien   and substitution candidates and finding matches.  */
31890075Sobrien
31990075Sobrienstatic inline tree
32090075Sobriencanonicalize_for_substitution (node)
32190075Sobrien     tree node;
32290075Sobrien{
32390075Sobrien  /* For a TYPE_DECL, use the type instead.  */
32490075Sobrien  if (TREE_CODE (node) == TYPE_DECL)
32590075Sobrien    node = TREE_TYPE (node);
32690075Sobrien  if (TYPE_P (node))
32790075Sobrien    node = canonical_type_variant (node);
32890075Sobrien
32990075Sobrien  return node;
33090075Sobrien}
33190075Sobrien
33290075Sobrien/* Add NODE as a substitution candidate.  NODE must not already be on
33390075Sobrien   the list of candidates.  */
33490075Sobrien
33590075Sobrienstatic void
33690075Sobrienadd_substitution (node)
33790075Sobrien     tree node;
33890075Sobrien{
33990075Sobrien  tree c;
34090075Sobrien
34190075Sobrien  if (DEBUG_MANGLE)
34290075Sobrien    fprintf (stderr, "  ++ add_substitution (%s at %10p)\n",
34390075Sobrien	     tree_code_name[TREE_CODE (node)], (void *) node);
34490075Sobrien
34590075Sobrien  /* Get the canonicalized substitution candidate for NODE.  */
34690075Sobrien  c = canonicalize_for_substitution (node);
34790075Sobrien  if (DEBUG_MANGLE && c != node)
34890075Sobrien    fprintf (stderr, "  ++ using candidate (%s at %10p)\n",
34990075Sobrien	     tree_code_name[TREE_CODE (node)], (void *) node);
35090075Sobrien  node = c;
35190075Sobrien
35290075Sobrien#if ENABLE_CHECKING
35390075Sobrien  /* Make sure NODE isn't already a candidate.  */
35490075Sobrien  {
35590075Sobrien    int i;
35690075Sobrien    for (i = VARRAY_ACTIVE_SIZE (G.substitutions); --i >= 0; )
35790075Sobrien      {
35890075Sobrien	tree candidate = VARRAY_TREE (G.substitutions, i);
35990075Sobrien	if ((DECL_P (node)
36090075Sobrien	     && node == candidate)
36190075Sobrien	    || (TYPE_P (node)
36290075Sobrien		&& TYPE_P (candidate)
36390075Sobrien		&& same_type_p (node, candidate)))
36490075Sobrien	  abort ();
36590075Sobrien      }
36690075Sobrien  }
36790075Sobrien#endif /* ENABLE_CHECKING */
36890075Sobrien
36990075Sobrien  /* Put the decl onto the varray of substitution candidates.  */
37090075Sobrien  VARRAY_PUSH_TREE (G.substitutions, node);
37190075Sobrien
37290075Sobrien  if (DEBUG_MANGLE)
37390075Sobrien    dump_substitution_candidates ();
37490075Sobrien}
37590075Sobrien
37690075Sobrien/* Helper function for find_substitution.  Returns non-zero if NODE,
37790075Sobrien   which may be a decl or a CLASS_TYPE, is a template-id with template
37890075Sobrien   name of substitution_index[INDEX] in the ::std namespace.  */
37990075Sobrien
38090075Sobrienstatic inline int
38190075Sobrienis_std_substitution (node, index)
38290075Sobrien     tree node;
38390075Sobrien     substitution_identifier_index_t index;
38490075Sobrien{
38590075Sobrien  tree type = NULL;
38690075Sobrien  tree decl = NULL;
38790075Sobrien
38890075Sobrien  if (DECL_P (node))
38990075Sobrien    {
39090075Sobrien      type = TREE_TYPE (node);
39190075Sobrien      decl = node;
39290075Sobrien    }
39390075Sobrien  else if (CLASS_TYPE_P (node))
39490075Sobrien    {
39590075Sobrien      type = node;
39690075Sobrien      decl = TYPE_NAME (node);
39790075Sobrien    }
39890075Sobrien  else
39990075Sobrien    /* These are not the droids you're looking for.  */
40090075Sobrien    return 0;
40190075Sobrien
40290075Sobrien  return (DECL_NAMESPACE_STD_P (CP_DECL_CONTEXT (decl))
40390075Sobrien	  && TYPE_LANG_SPECIFIC (type)
40490075Sobrien	  && CLASSTYPE_TEMPLATE_INFO (type)
40590075Sobrien	  && (DECL_NAME (CLASSTYPE_TI_TEMPLATE (type))
40690075Sobrien	      == subst_identifiers[index]));
40790075Sobrien}
40890075Sobrien
40990075Sobrien/* Helper function for find_substitution.  Returns non-zero if NODE,
41090075Sobrien   which may be a decl or a CLASS_TYPE, is the template-id
41190075Sobrien   ::std::identifier<char>, where identifier is
41290075Sobrien   substitution_index[INDEX].  */
41390075Sobrien
41490075Sobrienstatic inline int
41590075Sobrienis_std_substitution_char (node, index)
41690075Sobrien     tree node;
41790075Sobrien     substitution_identifier_index_t index;
41890075Sobrien{
41990075Sobrien  tree args;
42090075Sobrien  /* Check NODE's name is ::std::identifier.  */
42190075Sobrien  if (!is_std_substitution (node, index))
42290075Sobrien    return 0;
42390075Sobrien  /* Figure out its template args.  */
42490075Sobrien  if (DECL_P (node))
42590075Sobrien    args = DECL_TI_ARGS (node);
42690075Sobrien  else if (CLASS_TYPE_P (node))
42790075Sobrien    args = CLASSTYPE_TI_ARGS (node);
42890075Sobrien  else
42990075Sobrien    /* Oops, not a template.  */
43090075Sobrien    return 0;
43190075Sobrien  /* NODE's template arg list should be <char>.  */
43290075Sobrien  return
43390075Sobrien    TREE_VEC_LENGTH (args) == 1
43490075Sobrien    && TREE_VEC_ELT (args, 0) == char_type_node;
43590075Sobrien}
43690075Sobrien
43790075Sobrien/* Check whether a substitution should be used to represent NODE in
43890075Sobrien   the mangling.
43990075Sobrien
44090075Sobrien   First, check standard special-case substitutions.
44190075Sobrien
44290075Sobrien     <substitution> ::= St
44390075Sobrien         # ::std
44490075Sobrien
44590075Sobrien                    ::= Sa
44690075Sobrien	 # ::std::allocator
44790075Sobrien
44890075Sobrien                    ::= Sb
44990075Sobrien         # ::std::basic_string
45090075Sobrien
45190075Sobrien                    ::= Ss
45290075Sobrien         # ::std::basic_string<char,
45390075Sobrien			       ::std::char_traits<char>,
45490075Sobrien			       ::std::allocator<char> >
45590075Sobrien
45690075Sobrien                    ::= Si
45790075Sobrien         # ::std::basic_istream<char, ::std::char_traits<char> >
45890075Sobrien
45990075Sobrien                    ::= So
46090075Sobrien         # ::std::basic_ostream<char, ::std::char_traits<char> >
46190075Sobrien
46290075Sobrien                    ::= Sd
46390075Sobrien         # ::std::basic_iostream<char, ::std::char_traits<char> >
46490075Sobrien
46590075Sobrien   Then examine the stack of currently available substitution
46690075Sobrien   candidates for entities appearing earlier in the same mangling
46790075Sobrien
46890075Sobrien   If a substitution is found, write its mangled representation and
46990075Sobrien   return non-zero.  If none is found, just return zero.  */
47090075Sobrien
47190075Sobrienstatic int
47290075Sobrienfind_substitution (node)
47390075Sobrien     tree node;
47490075Sobrien{
47590075Sobrien  int i;
47690075Sobrien  int size = VARRAY_ACTIVE_SIZE (G.substitutions);
47790075Sobrien  tree decl;
47890075Sobrien  tree type;
47990075Sobrien
48090075Sobrien  if (DEBUG_MANGLE)
48190075Sobrien    fprintf (stderr, "  ++ find_substitution (%s at %p)\n",
48290075Sobrien	     tree_code_name[TREE_CODE (node)], (void *) node);
48390075Sobrien
48490075Sobrien  /* Obtain the canonicalized substitution representation for NODE.
48590075Sobrien     This is what we'll compare against.  */
48690075Sobrien  node = canonicalize_for_substitution (node);
48790075Sobrien
48890075Sobrien  /* Check for builtin substitutions.  */
48990075Sobrien
49090075Sobrien  decl = TYPE_P (node) ? TYPE_NAME (node) : node;
49190075Sobrien  type = TYPE_P (node) ? node : TREE_TYPE (node);
49290075Sobrien
49390075Sobrien  /* Check for std::allocator.  */
49490075Sobrien  if (decl
49590075Sobrien      && is_std_substitution (decl, SUBID_ALLOCATOR)
49690075Sobrien      && !CLASSTYPE_USE_TEMPLATE (TREE_TYPE (decl)))
49790075Sobrien    {
49890075Sobrien      write_string ("Sa");
49990075Sobrien      return 1;
50090075Sobrien    }
50190075Sobrien
50290075Sobrien  /* Check for std::basic_string.  */
50390075Sobrien  if (decl && is_std_substitution (decl, SUBID_BASIC_STRING))
50490075Sobrien    {
50590075Sobrien      if (TYPE_P (node))
50690075Sobrien	{
50790075Sobrien	  /* If this is a type (i.e. a fully-qualified template-id),
50890075Sobrien	     check for
50990075Sobrien  	         std::basic_string <char,
51090075Sobrien		 		    std::char_traits<char>,
51190075Sobrien				    std::allocator<char> > .  */
51290075Sobrien	  if (cp_type_quals (type) == TYPE_UNQUALIFIED
51390075Sobrien	      && CLASSTYPE_USE_TEMPLATE (type))
51490075Sobrien	    {
51590075Sobrien	      tree args = CLASSTYPE_TI_ARGS (type);
51690075Sobrien	      if (TREE_VEC_LENGTH (args) == 3
51790075Sobrien		  && same_type_p (TREE_VEC_ELT (args, 0), char_type_node)
51890075Sobrien		  && is_std_substitution_char (TREE_VEC_ELT (args, 1),
51990075Sobrien					       SUBID_CHAR_TRAITS)
52090075Sobrien		  && is_std_substitution_char (TREE_VEC_ELT (args, 2),
52190075Sobrien					       SUBID_ALLOCATOR))
52290075Sobrien		{
52390075Sobrien		  write_string ("Ss");
52490075Sobrien		  return 1;
52590075Sobrien		}
52690075Sobrien	    }
52790075Sobrien	}
52890075Sobrien      else
52990075Sobrien	/* Substitute for the template name only if this isn't a type.  */
53090075Sobrien	{
53190075Sobrien	  write_string ("Sb");
53290075Sobrien	  return 1;
53390075Sobrien	}
53490075Sobrien    }
53590075Sobrien
53690075Sobrien  /* Check for basic_{i,o,io}stream.  */
53790075Sobrien  if (TYPE_P (node)
53890075Sobrien      && cp_type_quals (type) == TYPE_UNQUALIFIED
53990075Sobrien      && CLASS_TYPE_P (type)
54090075Sobrien      && CLASSTYPE_USE_TEMPLATE (type)
54190075Sobrien      && CLASSTYPE_TEMPLATE_INFO (type) != NULL)
54290075Sobrien    {
54390075Sobrien      /* First, check for the template
54490075Sobrien	 args <char, std::char_traits<char> > .  */
54590075Sobrien      tree args = CLASSTYPE_TI_ARGS (type);
54690075Sobrien      if (TREE_VEC_LENGTH (args) == 2
54790075Sobrien	  && same_type_p (TREE_VEC_ELT (args, 0), char_type_node)
54890075Sobrien	  && is_std_substitution_char (TREE_VEC_ELT (args, 1),
54990075Sobrien				       SUBID_CHAR_TRAITS))
55090075Sobrien	{
55190075Sobrien	  /* Got them.  Is this basic_istream?  */
55290075Sobrien	  tree name = DECL_NAME (CLASSTYPE_TI_TEMPLATE (type));
55390075Sobrien	  if (name == subst_identifiers[SUBID_BASIC_ISTREAM])
55490075Sobrien	    {
55590075Sobrien	      write_string ("Si");
55690075Sobrien	      return 1;
55790075Sobrien	    }
55890075Sobrien	  /* Or basic_ostream?  */
55990075Sobrien	  else if (name == subst_identifiers[SUBID_BASIC_OSTREAM])
56090075Sobrien	    {
56190075Sobrien	      write_string ("So");
56290075Sobrien	      return 1;
56390075Sobrien	    }
56490075Sobrien	  /* Or basic_iostream?  */
56590075Sobrien	  else if (name == subst_identifiers[SUBID_BASIC_IOSTREAM])
56690075Sobrien	    {
56790075Sobrien	      write_string ("Sd");
56890075Sobrien	      return 1;
56990075Sobrien	    }
57090075Sobrien	}
57190075Sobrien    }
57290075Sobrien
57390075Sobrien  /* Check for namespace std.  */
57490075Sobrien  if (decl && DECL_NAMESPACE_STD_P (decl))
57590075Sobrien    {
57690075Sobrien      write_string ("St");
57790075Sobrien      return 1;
57890075Sobrien    }
57990075Sobrien
58090075Sobrien  /* Now check the list of available substitutions for this mangling
58190075Sobrien     operation.    */
58290075Sobrien  for (i = 0; i < size; ++i)
58390075Sobrien    {
58490075Sobrien      tree candidate = VARRAY_TREE (G.substitutions, i);
58590075Sobrien      /* NODE is a matched to a candidate if it's the same decl node or
58690075Sobrien	 if it's the same type.  */
58790075Sobrien      if (decl == candidate
58890075Sobrien	  || (TYPE_P (candidate) && type && TYPE_P (type)
58990075Sobrien	      && same_type_p (type, candidate))
59090075Sobrien	  || NESTED_TEMPLATE_MATCH (node, candidate))
59190075Sobrien	{
59290075Sobrien	  write_substitution (i);
59390075Sobrien	  return 1;
59490075Sobrien	}
59590075Sobrien    }
59690075Sobrien
59790075Sobrien  /* No substitution found.  */
59890075Sobrien  return 0;
59990075Sobrien}
60090075Sobrien
60190075Sobrien
60290075Sobrien/*  <mangled-name>      ::= _Z <encoding>  */
60390075Sobrien
60490075Sobrienstatic inline void
60590075Sobrienwrite_mangled_name (decl)
60690075Sobrien     tree decl;
60790075Sobrien{
60890075Sobrien  MANGLE_TRACE_TREE ("mangled-name", decl);
60990075Sobrien
61090075Sobrien  if (DECL_LANG_SPECIFIC (decl)
61190075Sobrien      && DECL_EXTERN_C_FUNCTION_P (decl)
61290075Sobrien      && ! DECL_OVERLOADED_OPERATOR_P (decl))
61390075Sobrien    /* The standard notes:
61490075Sobrien         "The <encoding> of an extern "C" function is treated like
61590075Sobrien	 global-scope data, i.e. as its <source-name> without a type."
61690075Sobrien       We cannot write overloaded operators that way though,
61790075Sobrien       because it contains characters invalid in assembler.  */
61890075Sobrien    write_source_name (DECL_NAME (decl));
61990075Sobrien  else
62090075Sobrien    /* C++ name; needs to be mangled.  */
62190075Sobrien    {
62290075Sobrien      write_string ("_Z");
62390075Sobrien      write_encoding (decl);
62490075Sobrien    }
62590075Sobrien}
62690075Sobrien
62790075Sobrien/*   <encoding>		::= <function name> <bare-function-type>
62890075Sobrien			::= <data name>  */
62990075Sobrien
63090075Sobrienstatic void
63190075Sobrienwrite_encoding (decl)
63290075Sobrien     tree decl;
63390075Sobrien{
63490075Sobrien  MANGLE_TRACE_TREE ("encoding", decl);
63590075Sobrien
63690075Sobrien  if (DECL_LANG_SPECIFIC (decl) && DECL_EXTERN_C_FUNCTION_P (decl))
63790075Sobrien    {
63890075Sobrien      /* For overloaded operators write just the mangled name
63990075Sobrien	 without arguments.  */
64090075Sobrien      if (DECL_OVERLOADED_OPERATOR_P (decl))
64190075Sobrien	write_name (decl, /*ignore_local_scope=*/0);
64290075Sobrien      else
64390075Sobrien	write_source_name (DECL_NAME (decl));
64490075Sobrien      return;
64590075Sobrien    }
64690075Sobrien
64790075Sobrien  write_name (decl, /*ignore_local_scope=*/0);
64890075Sobrien  if (TREE_CODE (decl) == FUNCTION_DECL)
64990075Sobrien    {
65090075Sobrien      tree fn_type;
65190075Sobrien
65290075Sobrien      if (decl_is_template_id (decl, NULL))
65390075Sobrien	fn_type = get_mostly_instantiated_function_type (decl, NULL, NULL);
65490075Sobrien      else
65590075Sobrien	fn_type = TREE_TYPE (decl);
65690075Sobrien
65790075Sobrien      write_bare_function_type (fn_type,
65890075Sobrien				(!DECL_CONSTRUCTOR_P (decl)
65990075Sobrien				 && !DECL_DESTRUCTOR_P (decl)
66090075Sobrien				 && !DECL_CONV_FN_P (decl)
66190075Sobrien				 && decl_is_template_id (decl, NULL)),
66290075Sobrien				decl);
66390075Sobrien    }
66490075Sobrien}
66590075Sobrien
66690075Sobrien/* <name> ::= <unscoped-name>
66790075Sobrien          ::= <unscoped-template-name> <template-args>
66890075Sobrien	  ::= <nested-name>
66990075Sobrien	  ::= <local-name>
67090075Sobrien
67190075Sobrien   If IGNORE_LOCAL_SCOPE is non-zero, this production of <name> is
67290075Sobrien   called from <local-name>, which mangles the enclosing scope
67390075Sobrien   elsewhere and then uses this function to mangle just the part
67490075Sobrien   underneath the function scope.  So don't use the <local-name>
67590075Sobrien   production, to avoid an infinite recursion.  */
67690075Sobrien
67790075Sobrienstatic void
67890075Sobrienwrite_name (decl, ignore_local_scope)
67990075Sobrien     tree decl;
68090075Sobrien     int ignore_local_scope;
68190075Sobrien{
68290075Sobrien  tree context;
68390075Sobrien
68490075Sobrien  MANGLE_TRACE_TREE ("name", decl);
68590075Sobrien
68690075Sobrien  if (TREE_CODE (decl) == TYPE_DECL)
68790075Sobrien    {
68890075Sobrien      /* In case this is a typedef, fish out the corresponding
68990075Sobrien	 TYPE_DECL for the main variant.  */
69090075Sobrien      decl = TYPE_NAME (TYPE_MAIN_VARIANT (TREE_TYPE (decl)));
69190075Sobrien      context = TYPE_CONTEXT (TYPE_MAIN_VARIANT (TREE_TYPE (decl)));
69290075Sobrien    }
69390075Sobrien  else
69490075Sobrien    context = (DECL_CONTEXT (decl) == NULL) ? NULL : CP_DECL_CONTEXT (decl);
69590075Sobrien
69690075Sobrien  /* A decl in :: or ::std scope is treated specially.  The former is
69790075Sobrien     mangled using <unscoped-name> or <unscoped-template-name>, the
69890075Sobrien     latter with a special substitution.  Also, a name that is
69990075Sobrien     directly in a local function scope is also mangled with
70090075Sobrien     <unscoped-name> rather than a full <nested-name>.  */
70190075Sobrien  if (context == NULL
70290075Sobrien      || context == global_namespace
70390075Sobrien      || DECL_NAMESPACE_STD_P (context)
70490075Sobrien      || (ignore_local_scope && TREE_CODE (context) == FUNCTION_DECL))
70590075Sobrien    {
70690075Sobrien      tree template_info;
70790075Sobrien      /* Is this a template instance?  */
70890075Sobrien      if (decl_is_template_id (decl, &template_info))
70990075Sobrien	{
71090075Sobrien	  /* Yes: use <unscoped-template-name>.  */
71190075Sobrien	  write_unscoped_template_name (TI_TEMPLATE (template_info));
71290075Sobrien	  write_template_args (TI_ARGS (template_info));
71390075Sobrien	}
71490075Sobrien      else
71590075Sobrien	/* Everything else gets an <unqualified-name>.  */
71690075Sobrien	write_unscoped_name (decl);
71790075Sobrien    }
71890075Sobrien  else
71990075Sobrien    {
72090075Sobrien      /* Handle local names, unless we asked not to (that is, invoked
72190075Sobrien         under <local-name>, to handle only the part of the name under
72290075Sobrien         the local scope).  */
72390075Sobrien      if (!ignore_local_scope)
72490075Sobrien        {
72590075Sobrien	  /* Scan up the list of scope context, looking for a
72690075Sobrien	     function.  If we find one, this entity is in local
72790075Sobrien	     function scope.  local_entity tracks context one scope
72890075Sobrien	     level down, so it will contain the element that's
72990075Sobrien	     directly in that function's scope, either decl or one of
73090075Sobrien	     its enclosing scopes.  */
73190075Sobrien	  tree local_entity = decl;
73290075Sobrien	  while (context != NULL && context != global_namespace)
73390075Sobrien	    {
73490075Sobrien	      /* Make sure we're always dealing with decls.  */
73590075Sobrien	      if (context != NULL && TYPE_P (context))
73690075Sobrien		context = TYPE_NAME (context);
73790075Sobrien	      /* Is this a function?  */
73890075Sobrien	      if (TREE_CODE (context) == FUNCTION_DECL)
73990075Sobrien		{
74090075Sobrien		  /* Yes, we have local scope.  Use the <local-name>
74190075Sobrien		     production for the innermost function scope.  */
74290075Sobrien		  write_local_name (context, local_entity, decl);
74390075Sobrien		  return;
74490075Sobrien		}
74590075Sobrien	      /* Up one scope level.  */
74690075Sobrien	      local_entity = context;
74790075Sobrien	      context = CP_DECL_CONTEXT (context);
74890075Sobrien	    }
74990075Sobrien
75090075Sobrien	  /* No local scope found?  Fall through to <nested-name>.  */
75190075Sobrien	}
75290075Sobrien
75390075Sobrien      /* Other decls get a <nested-name> to encode their scope.  */
75490075Sobrien      write_nested_name (decl);
75590075Sobrien    }
75690075Sobrien}
75790075Sobrien
75890075Sobrien/* <unscoped-name> ::= <unqualified-name>
75990075Sobrien                   ::= St <unqualified-name>   # ::std::  */
76090075Sobrien
76190075Sobrienstatic void
76290075Sobrienwrite_unscoped_name (decl)
76390075Sobrien     tree decl;
76490075Sobrien{
76590075Sobrien  tree context = CP_DECL_CONTEXT (decl);
76690075Sobrien
76790075Sobrien  MANGLE_TRACE_TREE ("unscoped-name", decl);
76890075Sobrien
76990075Sobrien  /* Is DECL in ::std?  */
77090075Sobrien  if (DECL_NAMESPACE_STD_P (context))
77190075Sobrien    {
77290075Sobrien      write_string ("St");
77390075Sobrien      write_unqualified_name (decl);
77490075Sobrien    }
77590075Sobrien  /* If not, it should be either in the global namespace, or directly
77690075Sobrien     in a local function scope.  */
77790075Sobrien  else if (context == global_namespace
77890075Sobrien	   || context == NULL
77990075Sobrien	   || TREE_CODE (context) == FUNCTION_DECL)
78090075Sobrien    write_unqualified_name (decl);
78190075Sobrien  else
78290075Sobrien    abort ();
78390075Sobrien}
78490075Sobrien
78590075Sobrien/* <unscoped-template-name> ::= <unscoped-name>
78690075Sobrien                            ::= <substitution>  */
78790075Sobrien
78890075Sobrienstatic void
78990075Sobrienwrite_unscoped_template_name (decl)
79090075Sobrien     tree decl;
79190075Sobrien{
79290075Sobrien  MANGLE_TRACE_TREE ("unscoped-template-name", decl);
79390075Sobrien
79490075Sobrien  if (find_substitution (decl))
79590075Sobrien    return;
79690075Sobrien  write_unscoped_name (decl);
79790075Sobrien  add_substitution (decl);
79890075Sobrien}
79990075Sobrien
80090075Sobrien/* Write the nested name, including CV-qualifiers, of DECL.
80190075Sobrien
80290075Sobrien   <nested-name> ::= N [<CV-qualifiers>] <prefix> <unqualified-name> E
80390075Sobrien                 ::= N [<CV-qualifiers>] <template-prefix> <template-args> E
80490075Sobrien
80590075Sobrien   <CV-qualifiers> ::= [r] [V] [K]  */
80690075Sobrien
80790075Sobrienstatic void
80890075Sobrienwrite_nested_name (decl)
80990075Sobrien     tree decl;
81090075Sobrien{
81190075Sobrien  tree template_info;
81290075Sobrien
81390075Sobrien  MANGLE_TRACE_TREE ("nested-name", decl);
81490075Sobrien
81590075Sobrien  write_char ('N');
81690075Sobrien
81790075Sobrien  /* Write CV-qualifiers, if this is a member function.  */
81890075Sobrien  if (TREE_CODE (decl) == FUNCTION_DECL
81990075Sobrien      && DECL_NONSTATIC_MEMBER_FUNCTION_P (decl))
82090075Sobrien    {
82190075Sobrien      if (DECL_VOLATILE_MEMFUNC_P (decl))
82290075Sobrien	write_char ('V');
82390075Sobrien      if (DECL_CONST_MEMFUNC_P (decl))
82490075Sobrien	write_char ('K');
82590075Sobrien    }
82690075Sobrien
82790075Sobrien  /* Is this a template instance?  */
82890075Sobrien  if (decl_is_template_id (decl, &template_info))
82990075Sobrien    {
83090075Sobrien      /* Yes, use <template-prefix>.  */
83190075Sobrien      write_template_prefix (decl);
83290075Sobrien      write_template_args (TI_ARGS (template_info));
83390075Sobrien    }
83490075Sobrien  else
83590075Sobrien    {
83690075Sobrien      /* No, just use <prefix>  */
83790075Sobrien      write_prefix (DECL_CONTEXT (decl));
83890075Sobrien      write_unqualified_name (decl);
83990075Sobrien    }
84090075Sobrien  write_char ('E');
84190075Sobrien}
84290075Sobrien
84390075Sobrien/* <prefix> ::= <prefix> <unqualified-name>>
84490075Sobrien            ::= <template-prefix> <template-args>
84590075Sobrien	    ::= # empty
84690075Sobrien	    ::= <substitution>  */
84790075Sobrien
84890075Sobrienstatic void
84990075Sobrienwrite_prefix (node)
85090075Sobrien     tree node;
85190075Sobrien{
85290075Sobrien  tree decl;
85390075Sobrien  /* Non-NULL if NODE represents a template-id.  */
85490075Sobrien  tree template_info = NULL;
85590075Sobrien
85690075Sobrien  MANGLE_TRACE_TREE ("prefix", node);
85790075Sobrien
85890075Sobrien  if (node == NULL
85990075Sobrien      || node == global_namespace)
86090075Sobrien    return;
86190075Sobrien
86290075Sobrien  if (find_substitution (node))
86390075Sobrien    return;
86490075Sobrien
86590075Sobrien  if (DECL_P (node))
86690075Sobrien    /* Node is a decl.  */
86790075Sobrien    {
86890075Sobrien      /* If this is a function decl, that means we've hit function
86990075Sobrien	 scope, so this prefix must be for a local name.  In this
87090075Sobrien	 case, we're under the <local-name> production, which encodes
87190075Sobrien	 the enclosing function scope elsewhere.  So don't continue
87290075Sobrien	 here.  */
87390075Sobrien      if (TREE_CODE (node) == FUNCTION_DECL)
87490075Sobrien	return;
87590075Sobrien
87690075Sobrien      decl = node;
87790075Sobrien      decl_is_template_id (decl, &template_info);
87890075Sobrien    }
87990075Sobrien  else
88090075Sobrien    /* Node is a type.  */
88190075Sobrien    {
88290075Sobrien      decl = TYPE_NAME (node);
88390075Sobrien      if (CLASSTYPE_TEMPLATE_ID_P (node))
88490075Sobrien	template_info = CLASSTYPE_TEMPLATE_INFO (node);
88590075Sobrien    }
88690075Sobrien
88790075Sobrien  if (template_info != NULL)
88890075Sobrien    /* Templated.  */
88990075Sobrien    {
89090075Sobrien      write_template_prefix (decl);
89190075Sobrien      write_template_args (TI_ARGS (template_info));
89290075Sobrien    }
89390075Sobrien  else
89490075Sobrien    /* Not templated.  */
89590075Sobrien    {
89690075Sobrien      write_prefix (CP_DECL_CONTEXT (decl));
89790075Sobrien      write_unqualified_name (decl);
89890075Sobrien    }
89990075Sobrien
90090075Sobrien  add_substitution (node);
90190075Sobrien}
90290075Sobrien
90390075Sobrien/* <template-prefix> ::= <prefix> <template component>
90490075Sobrien                     ::= <substitution>  */
90590075Sobrien
90690075Sobrienstatic void
90790075Sobrienwrite_template_prefix (node)
90890075Sobrien     tree node;
90990075Sobrien{
91090075Sobrien  tree decl = DECL_P (node) ? node : TYPE_NAME (node);
91190075Sobrien  tree type = DECL_P (node) ? TREE_TYPE (node) : node;
91290075Sobrien  tree context = CP_DECL_CONTEXT (decl);
91390075Sobrien  tree template_info;
91490075Sobrien  tree template;
91590075Sobrien  tree substitution;
91690075Sobrien
91790075Sobrien  MANGLE_TRACE_TREE ("template-prefix", node);
91890075Sobrien
91990075Sobrien  /* Find the template decl.  */
92090075Sobrien  if (decl_is_template_id (decl, &template_info))
92190075Sobrien    template = TI_TEMPLATE (template_info);
92290075Sobrien  else if (CLASSTYPE_TEMPLATE_ID_P (type))
92390075Sobrien    template = CLASSTYPE_TI_TEMPLATE (type);
92490075Sobrien  else
92590075Sobrien    /* Oops, not a template.  */
92690075Sobrien    abort ();
92790075Sobrien
92890075Sobrien  /* For a member template, though, the template name for the
92990075Sobrien     innermost name must have all the outer template levels
93090075Sobrien     instantiated.  For instance, consider
93190075Sobrien
93290075Sobrien       template<typename T> struct Outer {
93390075Sobrien	 template<typename U> struct Inner {};
93490075Sobrien       };
93590075Sobrien
93690075Sobrien     The template name for `Inner' in `Outer<int>::Inner<float>' is
93790075Sobrien     `Outer<int>::Inner<U>'.  In g++, we don't instantiate the template
93890075Sobrien     levels separately, so there's no TEMPLATE_DECL available for this
93990075Sobrien     (there's only `Outer<T>::Inner<U>').
94090075Sobrien
94190075Sobrien     In order to get the substitutions right, we create a special
94290075Sobrien     TREE_LIST to represent the substitution candidate for a nested
94390075Sobrien     template.  The TREE_PURPOSE is the template's context, fully
94490075Sobrien     instantiated, and the TREE_VALUE is the TEMPLATE_DECL for the inner
94590075Sobrien     template.
94690075Sobrien
94790075Sobrien     So, for the example above, `Outer<int>::Inner' is represented as a
94890075Sobrien     substitution candidate by a TREE_LIST whose purpose is `Outer<int>'
94990075Sobrien     and whose value is `Outer<T>::Inner<U>'.  */
95090075Sobrien  if (TYPE_P (context))
95190075Sobrien    substitution = build_tree_list (context, template);
95290075Sobrien  else
95390075Sobrien    substitution = template;
95490075Sobrien
95590075Sobrien  if (find_substitution (substitution))
95690075Sobrien    return;
95790075Sobrien
95890075Sobrien  write_prefix (context);
95990075Sobrien  write_unqualified_name (decl);
96090075Sobrien
96190075Sobrien  add_substitution (substitution);
96290075Sobrien}
96390075Sobrien
96490075Sobrien/* We don't need to handle thunks, vtables, or VTTs here.  Those are
96590075Sobrien   mangled through special entry points.
96690075Sobrien
96790075Sobrien    <unqualified-name>  ::= <operator-name>
96890075Sobrien			::= <special-name>
96990075Sobrien			::= <source-name>  */
97090075Sobrien
97190075Sobrienstatic void
97290075Sobrienwrite_unqualified_name (decl)
97390075Sobrien     tree decl;
97490075Sobrien{
97590075Sobrien  MANGLE_TRACE_TREE ("unqualified-name", decl);
97690075Sobrien
97790075Sobrien  if (DECL_LANG_SPECIFIC (decl) != NULL && DECL_CONSTRUCTOR_P (decl))
97890075Sobrien    write_special_name_constructor (decl);
97990075Sobrien  else if (DECL_LANG_SPECIFIC (decl) != NULL && DECL_DESTRUCTOR_P (decl))
98090075Sobrien    write_special_name_destructor (decl);
98190075Sobrien  else if (DECL_CONV_FN_P (decl))
98290075Sobrien    {
98390075Sobrien      /* Conversion operator. Handle it right here.
98490075Sobrien           <operator> ::= cv <type>  */
98590075Sobrien      write_string ("cv");
98690075Sobrien      write_type (TREE_TYPE (DECL_NAME (decl)));
98790075Sobrien    }
98890075Sobrien  else if (DECL_OVERLOADED_OPERATOR_P (decl))
98990075Sobrien    {
99090075Sobrien      operator_name_info_t *oni;
99190075Sobrien      if (DECL_ASSIGNMENT_OPERATOR_P (decl))
99290075Sobrien	oni = assignment_operator_name_info;
99390075Sobrien      else
99490075Sobrien	oni = operator_name_info;
99590075Sobrien
99690075Sobrien      write_string (oni[DECL_OVERLOADED_OPERATOR_P (decl)].mangled_name);
99790075Sobrien    }
99890075Sobrien  else
99990075Sobrien    write_source_name (DECL_NAME (decl));
100090075Sobrien}
100190075Sobrien
100290075Sobrien/* Non-termial <source-name>.  IDENTIFIER is an IDENTIFIER_NODE.
100390075Sobrien
100490075Sobrien     <source-name> ::= </length/ number> <identifier>  */
100590075Sobrien
100690075Sobrienstatic void
100790075Sobrienwrite_source_name (identifier)
100890075Sobrien     tree identifier;
100990075Sobrien{
101090075Sobrien  MANGLE_TRACE_TREE ("source-name", identifier);
101190075Sobrien
101290075Sobrien  /* Never write the whole template-id name including the template
101390075Sobrien     arguments; we only want the template name.  */
101490075Sobrien  if (IDENTIFIER_TEMPLATE (identifier))
101590075Sobrien    identifier = IDENTIFIER_TEMPLATE (identifier);
101690075Sobrien
101790075Sobrien  write_unsigned_number (IDENTIFIER_LENGTH (identifier));
101890075Sobrien  write_identifier (IDENTIFIER_POINTER (identifier));
101990075Sobrien}
102090075Sobrien
102190075Sobrien/* Convert NUMBER to ascii using base BASE and generating at least
102290075Sobrien   MIN_DIGITS characters. BUFFER points to the _end_ of the buffer
102390075Sobrien   into which to store the characters. Returns the number of
102490075Sobrien   characters generated (these will be layed out in advance of where
102590075Sobrien   BUFFER points).  */
102690075Sobrien
102790075Sobrienstatic int
102890075Sobrienhwint_to_ascii (number, base, buffer, min_digits)
102990075Sobrien     unsigned HOST_WIDE_INT number;
103090075Sobrien     unsigned int base;
103190075Sobrien     char *buffer;
103290075Sobrien     unsigned min_digits;
103390075Sobrien{
103490075Sobrien  static const char base_digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
103590075Sobrien  unsigned digits = 0;
103690075Sobrien
103790075Sobrien  while (number)
103890075Sobrien    {
103990075Sobrien      unsigned HOST_WIDE_INT d = number / base;
104090075Sobrien
104190075Sobrien      *--buffer = base_digits[number - d * base];
104290075Sobrien      digits++;
104390075Sobrien      number = d;
104490075Sobrien    }
104590075Sobrien  while (digits < min_digits)
104690075Sobrien    {
104790075Sobrien      *--buffer = base_digits[0];
104890075Sobrien      digits++;
104990075Sobrien    }
105090075Sobrien  return digits;
105190075Sobrien}
105290075Sobrien
105390075Sobrien/* Non-terminal <number>.
105490075Sobrien
105590075Sobrien     <number> ::= [n] </decimal integer/>  */
105690075Sobrien
105790075Sobrienstatic void
105890075Sobrienwrite_number (number, unsigned_p, base)
105990075Sobrien     unsigned HOST_WIDE_INT number;
106090075Sobrien     int unsigned_p;
106190075Sobrien     unsigned int base;
106290075Sobrien{
106390075Sobrien  char buffer[sizeof (HOST_WIDE_INT) * 8];
106490075Sobrien  unsigned count = 0;
106590075Sobrien
106690075Sobrien  if (!unsigned_p && (HOST_WIDE_INT) number < 0)
106790075Sobrien    {
106890075Sobrien      write_char ('n');
106990075Sobrien      number = -((HOST_WIDE_INT) number);
107090075Sobrien    }
107190075Sobrien  count = hwint_to_ascii (number, base, buffer + sizeof (buffer), 1);
107290075Sobrien  write_chars (buffer + sizeof (buffer) - count, count);
107390075Sobrien}
107490075Sobrien
107590075Sobrien/* Write out an integral CST in decimal. Most numbers are small, and
107690075Sobrien   representable in a HOST_WIDE_INT. Occasionally we'll have numbers
107790075Sobrien   bigger than that, which we must deal with. */
107890075Sobrien
107990075Sobrienstatic inline void
108090075Sobrienwrite_integer_cst (cst)
108190075Sobrien     tree cst;
108290075Sobrien{
108390075Sobrien  int sign = tree_int_cst_sgn (cst);
108490075Sobrien
108590075Sobrien  if (TREE_INT_CST_HIGH (cst) + (sign < 0))
108690075Sobrien    {
108790075Sobrien      /* A bignum. We do this in chunks, each of which fits in a
108890075Sobrien	 HOST_WIDE_INT. */
108990075Sobrien      char buffer[sizeof (HOST_WIDE_INT) * 8 * 2];
109090075Sobrien      unsigned HOST_WIDE_INT chunk;
109190075Sobrien      unsigned chunk_digits;
109290075Sobrien      char *ptr = buffer + sizeof (buffer);
109390075Sobrien      unsigned count = 0;
109490075Sobrien      tree n, base, type;
109590075Sobrien      int done;
109690075Sobrien
109790075Sobrien      /* HOST_WIDE_INT must be at least 32 bits, so 10^9 is
109890075Sobrien	 representable. */
109990075Sobrien      chunk = 1000000000;
110090075Sobrien      chunk_digits = 9;
110190075Sobrien
110290075Sobrien      if (sizeof (HOST_WIDE_INT) >= 8)
110390075Sobrien	{
110490075Sobrien	  /* It is at least 64 bits, so 10^18 is representable. */
110590075Sobrien	  chunk_digits = 18;
110690075Sobrien	  chunk *= chunk;
110790075Sobrien	}
110890075Sobrien
110990075Sobrien      type = signed_or_unsigned_type (1, TREE_TYPE (cst));
111090075Sobrien      base = build_int_2 (chunk, 0);
111190075Sobrien      n = build_int_2 (TREE_INT_CST_LOW (cst), TREE_INT_CST_HIGH (cst));
111290075Sobrien      TREE_TYPE (n) = TREE_TYPE (base) = type;
111390075Sobrien
111490075Sobrien      if (sign < 0)
111590075Sobrien	{
111690075Sobrien	  write_char ('n');
111790075Sobrien	  n = fold (build1 (NEGATE_EXPR, type, n));
111890075Sobrien	}
111990075Sobrien      do
112090075Sobrien	{
112190075Sobrien	  tree d = fold (build (FLOOR_DIV_EXPR, type, n, base));
112290075Sobrien	  tree tmp = fold (build (MULT_EXPR, type, d, base));
112390075Sobrien	  unsigned c;
112490075Sobrien
112590075Sobrien	  done = integer_zerop (d);
112690075Sobrien	  tmp = fold (build (MINUS_EXPR, type, n, tmp));
112790075Sobrien	  c = hwint_to_ascii (TREE_INT_CST_LOW (tmp), 10, ptr,
112890075Sobrien				done ? 1 : chunk_digits);
112990075Sobrien	  ptr -= c;
113090075Sobrien	  count += c;
113190075Sobrien	  n = d;
113290075Sobrien	}
113390075Sobrien      while (!done);
113490075Sobrien      write_chars (ptr, count);
113590075Sobrien    }
113690075Sobrien  else
113790075Sobrien    {
113890075Sobrien      /* A small num.  */
113990075Sobrien      unsigned HOST_WIDE_INT low = TREE_INT_CST_LOW (cst);
114090075Sobrien
114190075Sobrien      if (sign < 0)
114290075Sobrien	{
114390075Sobrien	  write_char ('n');
114490075Sobrien	  low = -low;
114590075Sobrien	}
114690075Sobrien      write_unsigned_number (low);
114790075Sobrien    }
114890075Sobrien}
114990075Sobrien
115090075Sobrien/* Non-terminal <identifier>.
115190075Sobrien
115290075Sobrien     <identifier> ::= </unqualified source code identifier>  */
115390075Sobrien
115490075Sobrienstatic void
115590075Sobrienwrite_identifier (identifier)
115690075Sobrien     const char *identifier;
115790075Sobrien{
115890075Sobrien  MANGLE_TRACE ("identifier", identifier);
115990075Sobrien  write_string (identifier);
116090075Sobrien}
116190075Sobrien
116290075Sobrien/* Handle constructor productions of non-terminal <special-name>.
116390075Sobrien   CTOR is a constructor FUNCTION_DECL.
116490075Sobrien
116590075Sobrien     <special-name> ::= C1   # complete object constructor
116690075Sobrien                    ::= C2   # base object constructor
116790075Sobrien                    ::= C3   # complete object allocating constructor
116890075Sobrien
116990075Sobrien   Currently, allocating constructors are never used.
117090075Sobrien
117190075Sobrien   We also need to provide mangled names for the maybe-in-charge
117290075Sobrien   constructor, so we treat it here too.  mangle_decl_string will
117390075Sobrien   append *INTERNAL* to that, to make sure we never emit it.  */
117490075Sobrien
117590075Sobrienstatic void
117690075Sobrienwrite_special_name_constructor (ctor)
117790075Sobrien     tree ctor;
117890075Sobrien{
117990075Sobrien  if (DECL_COMPLETE_CONSTRUCTOR_P (ctor)
118090075Sobrien      /* Even though we don't ever emit a definition of the
118190075Sobrien	 old-style destructor, we still have to consider entities
118290075Sobrien	 (like static variables) nested inside it.  */
118390075Sobrien      || DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (ctor))
118490075Sobrien    write_string ("C1");
118590075Sobrien  else if (DECL_BASE_CONSTRUCTOR_P (ctor))
118690075Sobrien    write_string ("C2");
118790075Sobrien  else
118890075Sobrien    abort ();
118990075Sobrien}
119090075Sobrien
119190075Sobrien/* Handle destructor productions of non-terminal <special-name>.
119290075Sobrien   DTOR is a destructor FUNCTION_DECL.
119390075Sobrien
119490075Sobrien     <special-name> ::= D0 # deleting (in-charge) destructor
119590075Sobrien                    ::= D1 # complete object (in-charge) destructor
119690075Sobrien                    ::= D2 # base object (not-in-charge) destructor
119790075Sobrien
119890075Sobrien   We also need to provide mangled names for the maybe-incharge
119990075Sobrien   destructor, so we treat it here too.  mangle_decl_string will
120090075Sobrien   append *INTERNAL* to that, to make sure we never emit it.  */
120190075Sobrien
120290075Sobrienstatic void
120390075Sobrienwrite_special_name_destructor (dtor)
120490075Sobrien     tree dtor;
120590075Sobrien{
120690075Sobrien  if (DECL_DELETING_DESTRUCTOR_P (dtor))
120790075Sobrien    write_string ("D0");
120890075Sobrien  else if (DECL_COMPLETE_DESTRUCTOR_P (dtor)
120990075Sobrien	   /* Even though we don't ever emit a definition of the
121090075Sobrien	      old-style destructor, we still have to consider entities
121190075Sobrien	      (like static variables) nested inside it.  */
121290075Sobrien	   || DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P (dtor))
121390075Sobrien    write_string ("D1");
121490075Sobrien  else if (DECL_BASE_DESTRUCTOR_P (dtor))
121590075Sobrien    write_string ("D2");
121690075Sobrien  else
121790075Sobrien    abort ();
121890075Sobrien}
121990075Sobrien
122090075Sobrien/* Return the discriminator for ENTITY appearing inside
122190075Sobrien   FUNCTION.  The discriminator is the lexical ordinal of VAR among
122290075Sobrien   entities with the same name in the same FUNCTION.  */
122390075Sobrien
122490075Sobrienstatic int
122590075Sobriendiscriminator_for_local_entity (entity)
122690075Sobrien     tree entity;
122790075Sobrien{
122890075Sobrien  tree *type;
122990075Sobrien  int discriminator;
123090075Sobrien
123190075Sobrien  /* Assume this is the only local entity with this name.  */
123290075Sobrien  discriminator = 0;
123390075Sobrien
123490075Sobrien  if (DECL_DISCRIMINATOR_P (entity) && DECL_LANG_SPECIFIC (entity))
123590075Sobrien    discriminator = DECL_DISCRIMINATOR (entity);
123690075Sobrien  else if (TREE_CODE (entity) == TYPE_DECL)
123790075Sobrien    {
123890075Sobrien      /* Scan the list of local classes.  */
123990075Sobrien      entity = TREE_TYPE (entity);
124090075Sobrien      for (type = &VARRAY_TREE (local_classes, 0); *type != entity; ++type)
124190075Sobrien        if (TYPE_IDENTIFIER (*type) == TYPE_IDENTIFIER (entity)
124290075Sobrien            && TYPE_CONTEXT (*type) == TYPE_CONTEXT (entity))
124390075Sobrien	  ++discriminator;
124490075Sobrien    }
124590075Sobrien
124690075Sobrien  return discriminator;
124790075Sobrien}
124890075Sobrien
124990075Sobrien/* Return the discriminator for STRING, a string literal used inside
125090075Sobrien   FUNCTION.  The disciminator is the lexical ordinal of STRING among
125190075Sobrien   string literals used in FUNCTION.  */
125290075Sobrien
125390075Sobrienstatic int
125490075Sobriendiscriminator_for_string_literal (function, string)
125590075Sobrien     tree function ATTRIBUTE_UNUSED;
125690075Sobrien     tree string ATTRIBUTE_UNUSED;
125790075Sobrien{
125890075Sobrien  /* For now, we don't discriminate amongst string literals.  */
125990075Sobrien  return 0;
126090075Sobrien}
126190075Sobrien
126290075Sobrien/*   <discriminator> := _ <number>
126390075Sobrien
126490075Sobrien   The discriminator is used only for the second and later occurrences
126590075Sobrien   of the same name within a single function. In this case <number> is
126690075Sobrien   n - 2, if this is the nth occurrence, in lexical order.  */
126790075Sobrien
126890075Sobrienstatic void
126990075Sobrienwrite_discriminator (discriminator)
127090075Sobrien     int discriminator;
127190075Sobrien{
127290075Sobrien  /* If discriminator is zero, don't write anything.  Otherwise... */
127390075Sobrien  if (discriminator > 0)
127490075Sobrien    {
127590075Sobrien      write_char ('_');
127690075Sobrien      write_unsigned_number (discriminator - 1);
127790075Sobrien    }
127890075Sobrien}
127990075Sobrien
128090075Sobrien/* Mangle the name of a function-scope entity.  FUNCTION is the
128190075Sobrien   FUNCTION_DECL for the enclosing function.  ENTITY is the decl for
128290075Sobrien   the entity itself.  LOCAL_ENTITY is the entity that's directly
128390075Sobrien   scoped in FUNCTION_DECL, either ENTITY itself or an enclosing scope
128490075Sobrien   of ENTITY.
128590075Sobrien
128690075Sobrien     <local-name> := Z <function encoding> E <entity name> [<discriminator>]
128790075Sobrien                  := Z <function encoding> E s [<discriminator>]  */
128890075Sobrien
128990075Sobrienstatic void
129090075Sobrienwrite_local_name (function, local_entity, entity)
129190075Sobrien     tree function;
129290075Sobrien     tree local_entity;
129390075Sobrien     tree entity;
129490075Sobrien{
129590075Sobrien  MANGLE_TRACE_TREE ("local-name", entity);
129690075Sobrien
129790075Sobrien  write_char ('Z');
129890075Sobrien  write_encoding (function);
129990075Sobrien  write_char ('E');
130090075Sobrien  if (TREE_CODE (entity) == STRING_CST)
130190075Sobrien    {
130290075Sobrien      write_char ('s');
130390075Sobrien      write_discriminator (discriminator_for_string_literal (function,
130490075Sobrien							     entity));
130590075Sobrien    }
130690075Sobrien  else
130790075Sobrien    {
130890075Sobrien      /* Now the <entity name>.  Let write_name know its being called
130990075Sobrien	 from <local-name>, so it doesn't try to process the enclosing
131090075Sobrien	 function scope again.  */
131190075Sobrien      write_name (entity, /*ignore_local_scope=*/1);
131290075Sobrien      write_discriminator (discriminator_for_local_entity (local_entity));
131390075Sobrien    }
131490075Sobrien}
131590075Sobrien
131690075Sobrien/* Non-terminals <type> and <CV-qualifier>.
131790075Sobrien
131890075Sobrien     <type> ::= <builtin-type>
131990075Sobrien            ::= <function-type>
132090075Sobrien            ::= <class-enum-type>
132190075Sobrien            ::= <array-type>
132290075Sobrien            ::= <pointer-to-member-type>
132390075Sobrien            ::= <template-param>
132490075Sobrien            ::= <substitution>
132590075Sobrien            ::= <CV-qualifier>
132690075Sobrien            ::= P <type>    # pointer-to
132790075Sobrien            ::= R <type>    # reference-to
132890075Sobrien            ::= C <type>    # complex pair (C 2000)
132990075Sobrien            ::= G <type>    # imaginary (C 2000)     [not supported]
133090075Sobrien            ::= U <source-name> <type>   # vendor extended type qualifier
133190075Sobrien
133290075Sobrien   TYPE is a type node.  */
133390075Sobrien
133490075Sobrienstatic void
133590075Sobrienwrite_type (type)
133690075Sobrien     tree type;
133790075Sobrien{
133890075Sobrien  /* This gets set to non-zero if TYPE turns out to be a (possibly
133990075Sobrien     CV-qualified) builtin type.  */
134090075Sobrien  int is_builtin_type = 0;
134190075Sobrien
134290075Sobrien  MANGLE_TRACE_TREE ("type", type);
134390075Sobrien
134490075Sobrien  if (type == error_mark_node)
134590075Sobrien    return;
134690075Sobrien
134790075Sobrien  if (find_substitution (type))
134890075Sobrien    return;
134990075Sobrien
135090075Sobrien  if (write_CV_qualifiers_for_type (type) > 0)
135190075Sobrien    /* If TYPE was CV-qualified, we just wrote the qualifiers; now
135290075Sobrien       mangle the unqualified type.  The recursive call is needed here
135390075Sobrien       since both the qualified and uqualified types are substitution
135490075Sobrien       candidates.  */
135590075Sobrien    write_type (TYPE_MAIN_VARIANT (type));
135690075Sobrien  else
135790075Sobrien    {
135890075Sobrien      /* See through any typedefs.  */
135990075Sobrien      type = TYPE_MAIN_VARIANT (type);
136090075Sobrien
136190075Sobrien      switch (TREE_CODE (type))
136290075Sobrien	{
136390075Sobrien	case VOID_TYPE:
136490075Sobrien	case BOOLEAN_TYPE:
136590075Sobrien	case INTEGER_TYPE:  /* Includes wchar_t.  */
136690075Sobrien	case REAL_TYPE:
136790075Sobrien	  /* If this is a typedef, TYPE may not be one of
136890075Sobrien	     the standard builtin type nodes, but an alias of one.  Use
136990075Sobrien	     TYPE_MAIN_VARIANT to get to the underlying builtin type.  */
137090075Sobrien	  write_builtin_type (TYPE_MAIN_VARIANT (type));
137190075Sobrien	  ++is_builtin_type;
137290075Sobrien	  break;
137390075Sobrien
137490075Sobrien	case COMPLEX_TYPE:
137590075Sobrien	  write_char ('C');
137690075Sobrien	  write_type (TREE_TYPE (type));
137790075Sobrien	  break;
137890075Sobrien
137990075Sobrien	case FUNCTION_TYPE:
138090075Sobrien	case METHOD_TYPE:
138190075Sobrien	  write_function_type (type);
138290075Sobrien	  break;
138390075Sobrien
138490075Sobrien	case UNION_TYPE:
138590075Sobrien	case RECORD_TYPE:
138690075Sobrien	case ENUMERAL_TYPE:
138790075Sobrien	  /* A pointer-to-member function is represented as a special
138890075Sobrien	     RECORD_TYPE, so check for this first.  */
138990075Sobrien	  if (TYPE_PTRMEMFUNC_P (type))
139090075Sobrien	    write_pointer_to_member_type (type);
139190075Sobrien	  else
139290075Sobrien	    write_class_enum_type (type);
139390075Sobrien	  break;
139490075Sobrien
139590075Sobrien	case TYPENAME_TYPE:
139690075Sobrien	case UNBOUND_CLASS_TEMPLATE:
139790075Sobrien	  /* We handle TYPENAME_TYPEs and UNBOUND_CLASS_TEMPLATEs like
139890075Sobrien	     ordinary nested names.  */
139990075Sobrien	  write_nested_name (TYPE_STUB_DECL (type));
140090075Sobrien	  break;
140190075Sobrien
140290075Sobrien	case ARRAY_TYPE:
140390075Sobrien	  write_array_type (type);
140490075Sobrien	  break;
140590075Sobrien
140690075Sobrien	case POINTER_TYPE:
140790075Sobrien	  /* A pointer-to-member variable is represented by a POINTER_TYPE
140890075Sobrien	     to an OFFSET_TYPE, so check for this first.  */
140990075Sobrien	  if (TYPE_PTRMEM_P (type))
141090075Sobrien	    write_pointer_to_member_type (type);
141190075Sobrien	  else
141290075Sobrien	    {
141390075Sobrien	      write_char ('P');
141490075Sobrien	      write_type (TREE_TYPE (type));
141590075Sobrien	    }
141690075Sobrien	  break;
141790075Sobrien
141890075Sobrien	case REFERENCE_TYPE:
141990075Sobrien	  write_char ('R');
142090075Sobrien	  write_type (TREE_TYPE (type));
142190075Sobrien	  break;
142290075Sobrien
142390075Sobrien	case TEMPLATE_TYPE_PARM:
142490075Sobrien	case TEMPLATE_PARM_INDEX:
142590075Sobrien	  write_template_param (type);
142690075Sobrien	  break;
142790075Sobrien
142890075Sobrien	case TEMPLATE_TEMPLATE_PARM:
142990075Sobrien	  write_template_template_param (type);
143090075Sobrien	  break;
143190075Sobrien
143290075Sobrien	case BOUND_TEMPLATE_TEMPLATE_PARM:
143390075Sobrien	  write_template_template_param (type);
143490075Sobrien	  write_template_args
143590075Sobrien	    (TI_ARGS (TEMPLATE_TEMPLATE_PARM_TEMPLATE_INFO (type)));
143690075Sobrien	  break;
143790075Sobrien
143890075Sobrien	case OFFSET_TYPE:
143990075Sobrien	  write_pointer_to_member_type (build_pointer_type (type));
144090075Sobrien	  break;
144190075Sobrien
144290075Sobrien	case VECTOR_TYPE:
144390075Sobrien	  write_string ("U8__vector");
144490075Sobrien	  write_type (TREE_TYPE (type));
144590075Sobrien	  break;
144690075Sobrien
144790075Sobrien	default:
144890075Sobrien	  abort ();
144990075Sobrien	}
145090075Sobrien    }
145190075Sobrien
145290075Sobrien  /* Types other than builtin types are substitution candidates.  */
145390075Sobrien  if (!is_builtin_type)
145490075Sobrien    add_substitution (type);
145590075Sobrien}
145690075Sobrien
145790075Sobrien/* Non-terminal <CV-qualifiers> for type nodes.  Returns the number of
145890075Sobrien   CV-qualifiers written for TYPE.
145990075Sobrien
146090075Sobrien     <CV-qualifiers> ::= [r] [V] [K]  */
146190075Sobrien
146290075Sobrienstatic int
146390075Sobrienwrite_CV_qualifiers_for_type (type)
146490075Sobrien     tree type;
146590075Sobrien{
146690075Sobrien  int num_qualifiers = 0;
146790075Sobrien
146890075Sobrien  /* The order is specified by:
146990075Sobrien
147090075Sobrien       "In cases where multiple order-insensitive qualifiers are
147190075Sobrien       present, they should be ordered 'K' (closest to the base type),
147290075Sobrien       'V', 'r', and 'U' (farthest from the base type) ..."  */
147390075Sobrien
147490075Sobrien  if (CP_TYPE_RESTRICT_P (type))
147590075Sobrien    {
147690075Sobrien      write_char ('r');
147790075Sobrien      ++num_qualifiers;
147890075Sobrien    }
147990075Sobrien  if (CP_TYPE_VOLATILE_P (type))
148090075Sobrien    {
148190075Sobrien      write_char ('V');
148290075Sobrien      ++num_qualifiers;
148390075Sobrien    }
148490075Sobrien  if (CP_TYPE_CONST_P (type))
148590075Sobrien    {
148690075Sobrien      write_char ('K');
148790075Sobrien      ++num_qualifiers;
148890075Sobrien    }
148990075Sobrien
149090075Sobrien  return num_qualifiers;
149190075Sobrien}
149290075Sobrien
149390075Sobrien/* Non-terminal <builtin-type>.
149490075Sobrien
149590075Sobrien     <builtin-type> ::= v   # void
149690075Sobrien                    ::= b   # bool
149790075Sobrien                    ::= w   # wchar_t
149890075Sobrien                    ::= c   # char
149990075Sobrien                    ::= a   # signed char
150090075Sobrien                    ::= h   # unsigned char
150190075Sobrien                    ::= s   # short
150290075Sobrien                    ::= t   # unsigned short
150390075Sobrien                    ::= i   # int
150490075Sobrien                    ::= j   # unsigned int
150590075Sobrien                    ::= l   # long
150690075Sobrien                    ::= m   # unsigned long
150790075Sobrien                    ::= x   # long long, __int64
150890075Sobrien                    ::= y   # unsigned long long, __int64
150990075Sobrien                    ::= n   # __int128            [not supported]
151090075Sobrien                    ::= o   # unsigned __int128   [not supported]
151190075Sobrien                    ::= f   # float
151290075Sobrien                    ::= d   # double
151390075Sobrien                    ::= e   # long double, __float80
151490075Sobrien                    ::= g   # __float128          [not supported]
151590075Sobrien                    ::= u <source-name>  # vendor extended type */
151690075Sobrien
151790075Sobrienstatic void
151890075Sobrienwrite_builtin_type (type)
151990075Sobrien     tree type;
152090075Sobrien{
152190075Sobrien  switch (TREE_CODE (type))
152290075Sobrien    {
152390075Sobrien    case VOID_TYPE:
152490075Sobrien      write_char ('v');
152590075Sobrien      break;
152690075Sobrien
152790075Sobrien    case BOOLEAN_TYPE:
152890075Sobrien      write_char ('b');
152990075Sobrien      break;
153090075Sobrien
153190075Sobrien    case INTEGER_TYPE:
153290075Sobrien      /* If this is size_t, get the underlying int type.  */
153390075Sobrien      if (TYPE_IS_SIZETYPE (type))
153490075Sobrien	type = TYPE_DOMAIN (type);
153590075Sobrien
153690075Sobrien      /* TYPE may still be wchar_t, since that isn't in
153790075Sobrien	 integer_type_nodes.  */
153890075Sobrien      if (type == wchar_type_node)
153990075Sobrien	write_char ('w');
154090075Sobrien      else if (TYPE_FOR_JAVA (type))
154190075Sobrien	write_java_integer_type_codes (type);
154290075Sobrien      else
154390075Sobrien	{
154490075Sobrien	  size_t itk;
154590075Sobrien	  /* Assume TYPE is one of the shared integer type nodes.  Find
154690075Sobrien	     it in the array of these nodes.  */
154790075Sobrien	iagain:
154890075Sobrien	  for (itk = 0; itk < itk_none; ++itk)
154990075Sobrien	    if (type == integer_types[itk])
155090075Sobrien	      {
155190075Sobrien		/* Print the corresponding single-letter code.  */
155290075Sobrien		write_char (integer_type_codes[itk]);
155390075Sobrien		break;
155490075Sobrien	      }
155590075Sobrien
155690075Sobrien	  if (itk == itk_none)
155790075Sobrien	    {
155890075Sobrien	      tree t = type_for_mode (TYPE_MODE (type), TREE_UNSIGNED (type));
155990075Sobrien	      if (type == t)
156090075Sobrien		/* Couldn't find this type.  */
156190075Sobrien		abort ();
156290075Sobrien	      type = t;
156390075Sobrien	      goto iagain;
156490075Sobrien	    }
156590075Sobrien	}
156690075Sobrien      break;
156790075Sobrien
156890075Sobrien    case REAL_TYPE:
156990075Sobrien      if (type == float_type_node
157090075Sobrien	  || type == java_float_type_node)
157190075Sobrien	write_char ('f');
157290075Sobrien      else if (type == double_type_node
157390075Sobrien	       || type == java_double_type_node)
157490075Sobrien	write_char ('d');
157590075Sobrien      else if (type == long_double_type_node)
157690075Sobrien	write_char ('e');
157790075Sobrien      else
157890075Sobrien	abort ();
157990075Sobrien      break;
158090075Sobrien
158190075Sobrien    default:
158290075Sobrien      abort ();
158390075Sobrien    }
158490075Sobrien}
158590075Sobrien
158690075Sobrien/* Non-terminal <function-type>.  NODE is a FUNCTION_TYPE or
158790075Sobrien   METHOD_TYPE.  The return type is mangled before the parameter
158890075Sobrien   types.
158990075Sobrien
159090075Sobrien     <function-type> ::= F [Y] <bare-function-type> E   */
159190075Sobrien
159290075Sobrienstatic void
159390075Sobrienwrite_function_type (type)
159490075Sobrien     tree type;
159590075Sobrien{
159690075Sobrien  MANGLE_TRACE_TREE ("function-type", type);
159790075Sobrien
159890075Sobrien  write_char ('F');
159990075Sobrien  /* We don't track whether or not a type is `extern "C"'.  Note that
160090075Sobrien     you can have an `extern "C"' function that does not have
160190075Sobrien     `extern "C"' type, and vice versa:
160290075Sobrien
160390075Sobrien       extern "C" typedef void function_t();
160490075Sobrien       function_t f; // f has C++ linkage, but its type is
160590075Sobrien                     // `extern "C"'
160690075Sobrien
160790075Sobrien       typedef void function_t();
160890075Sobrien       extern "C" function_t f; // Vice versa.
160990075Sobrien
161090075Sobrien     See [dcl.link].  */
161190075Sobrien  write_bare_function_type (type, /*include_return_type_p=*/1,
161290075Sobrien			    /*decl=*/NULL);
161390075Sobrien  write_char ('E');
161490075Sobrien}
161590075Sobrien
161690075Sobrien/* Non-terminal <bare-function-type>.  TYPE is a FUNCTION_TYPE or
161790075Sobrien   METHOD_TYPE.  If INCLUDE_RETURN_TYPE is non-zero, the return value
161890075Sobrien   is mangled before the parameter types.  If non-NULL, DECL is
161990075Sobrien   FUNCTION_DECL for the function whose type is being emitted.
162090075Sobrien
162190075Sobrien     <bare-function-type> ::= </signature/ type>+  */
162290075Sobrien
162390075Sobrienstatic void
162490075Sobrienwrite_bare_function_type (type, include_return_type_p, decl)
162590075Sobrien     tree type;
162690075Sobrien     int include_return_type_p;
162790075Sobrien     tree decl;
162890075Sobrien{
162990075Sobrien  MANGLE_TRACE_TREE ("bare-function-type", type);
163090075Sobrien
163190075Sobrien  /* Mangle the return type, if requested.  */
163290075Sobrien  if (include_return_type_p)
163390075Sobrien    write_type (TREE_TYPE (type));
163490075Sobrien
163590075Sobrien  /* Now mangle the types of the arguments.  */
163690075Sobrien  write_method_parms (TYPE_ARG_TYPES (type),
163790075Sobrien		      TREE_CODE (type) == METHOD_TYPE,
163890075Sobrien		      decl);
163990075Sobrien}
164090075Sobrien
164190075Sobrien/* Write the mangled representation of a method parameter list of
164290075Sobrien   types given in PARM_TYPES.  If METHOD_P is non-zero, the function is
164390075Sobrien   considered a non-static method, and the this parameter is omitted.
164490075Sobrien   If non-NULL, DECL is the FUNCTION_DECL for the function whose
164590075Sobrien   parameters are being emitted.  */
164690075Sobrien
164790075Sobrienstatic void
164890075Sobrienwrite_method_parms (parm_types, method_p, decl)
164990075Sobrien     tree decl;
165090075Sobrien     tree parm_types;
165190075Sobrien     int method_p;
165290075Sobrien{
165390075Sobrien  tree first_parm_type;
165490075Sobrien  tree parm_decl = decl ? DECL_ARGUMENTS (decl) : NULL_TREE;
165590075Sobrien
165690075Sobrien  /* Assume this parameter type list is variable-length.  If it ends
165790075Sobrien     with a void type, then it's not.  */
165890075Sobrien  int varargs_p = 1;
165990075Sobrien
166090075Sobrien  /* If this is a member function, skip the first arg, which is the
166190075Sobrien     this pointer.
166290075Sobrien       "Member functions do not encode the type of their implicit this
166390075Sobrien       parameter."
166490075Sobrien
166590075Sobrien     Similarly, there's no need to mangle artificial parameters, like
166690075Sobrien     the VTT parameters for constructors and destructors.  */
166790075Sobrien  if (method_p)
166890075Sobrien    {
166990075Sobrien      parm_types = TREE_CHAIN (parm_types);
167090075Sobrien      parm_decl = parm_decl ? TREE_CHAIN (parm_decl) : NULL_TREE;
167190075Sobrien
167290075Sobrien      while (parm_decl && DECL_ARTIFICIAL (parm_decl))
167390075Sobrien	{
167490075Sobrien	  parm_types = TREE_CHAIN (parm_types);
167590075Sobrien	  parm_decl = TREE_CHAIN (parm_decl);
167690075Sobrien	}
167790075Sobrien    }
167890075Sobrien
167990075Sobrien  for (first_parm_type = parm_types;
168090075Sobrien       parm_types;
168190075Sobrien       parm_types = TREE_CHAIN (parm_types))
168290075Sobrien    {
168390075Sobrien      tree parm = TREE_VALUE (parm_types);
168490075Sobrien      if (parm == void_type_node)
168590075Sobrien	{
168690075Sobrien	  /* "Empty parameter lists, whether declared as () or
168790075Sobrien	     conventionally as (void), are encoded with a void parameter
168890075Sobrien	     (v)."  */
168990075Sobrien	  if (parm_types == first_parm_type)
169090075Sobrien	    write_type (parm);
169190075Sobrien	  /* If the parm list is terminated with a void type, it's
169290075Sobrien	     fixed-length.  */
169390075Sobrien	  varargs_p = 0;
169490075Sobrien	  /* A void type better be the last one.  */
169590075Sobrien	  my_friendly_assert (TREE_CHAIN (parm_types) == NULL, 20000523);
169690075Sobrien	}
169790075Sobrien      else
169890075Sobrien	write_type (parm);
169990075Sobrien    }
170090075Sobrien
170190075Sobrien  if (varargs_p)
170290075Sobrien    /* <builtin-type> ::= z  # ellipsis  */
170390075Sobrien    write_char ('z');
170490075Sobrien}
170590075Sobrien
170690075Sobrien/* <class-enum-type> ::= <name>  */
170790075Sobrien
170890075Sobrienstatic void
170990075Sobrienwrite_class_enum_type (type)
171090075Sobrien     tree type;
171190075Sobrien{
171290075Sobrien  write_name (TYPE_NAME (type), /*ignore_local_scope=*/0);
171390075Sobrien}
171490075Sobrien
171590075Sobrien/* Non-terminal <template-args>.  ARGS is a TREE_VEC of template
171690075Sobrien   arguments.
171790075Sobrien
171890075Sobrien     <template-args> ::= I <template-arg>+ E  */
171990075Sobrien
172090075Sobrienstatic void
172190075Sobrienwrite_template_args (args)
172290075Sobrien     tree args;
172390075Sobrien{
172490075Sobrien  int i;
172590075Sobrien  int length = TREE_VEC_LENGTH (args);
172690075Sobrien
172790075Sobrien  MANGLE_TRACE_TREE ("template-args", args);
172890075Sobrien
172990075Sobrien  my_friendly_assert (length > 0, 20000422);
173090075Sobrien
173190075Sobrien  if (TREE_CODE (TREE_VEC_ELT (args, 0)) == TREE_VEC)
173290075Sobrien    {
173390075Sobrien      /* We have nested template args.  We want the innermost template
173490075Sobrien	 argument list.  */
173590075Sobrien      args = TREE_VEC_ELT (args, length - 1);
173690075Sobrien      length = TREE_VEC_LENGTH (args);
173790075Sobrien    }
173890075Sobrien
173990075Sobrien  write_char ('I');
174090075Sobrien  for (i = 0; i < length; ++i)
174190075Sobrien    write_template_arg (TREE_VEC_ELT (args, i));
174290075Sobrien  write_char ('E');
174390075Sobrien}
174490075Sobrien
174590075Sobrien/* <expression> ::= <unary operator-name> <expression>
174690075Sobrien		::= <binary operator-name> <expression> <expression>
174790075Sobrien		::= <expr-primary>
174890075Sobrien
174990075Sobrien   <expr-primary> ::= <template-param>
175090075Sobrien		  ::= L <type> <value number> E  # literal
175190075Sobrien		  ::= L <mangled-name> E         # external name  */
175290075Sobrien
175390075Sobrienstatic void
175490075Sobrienwrite_expression (expr)
175590075Sobrien     tree expr;
175690075Sobrien{
175790075Sobrien  enum tree_code code;
175890075Sobrien
175990075Sobrien  code = TREE_CODE (expr);
176090075Sobrien
176190075Sobrien  /* Handle pointers-to-members by making them look like expression
176290075Sobrien     nodes.  */
176390075Sobrien  if (code == PTRMEM_CST)
176490075Sobrien    {
176590075Sobrien      expr = build_nt (ADDR_EXPR,
176690075Sobrien		       build_nt (SCOPE_REF,
176790075Sobrien				 PTRMEM_CST_CLASS (expr),
176890075Sobrien				 PTRMEM_CST_MEMBER (expr)));
176990075Sobrien      code = TREE_CODE (expr);
177090075Sobrien    }
177190075Sobrien
177290075Sobrien  /* Handle template parameters. */
177390075Sobrien  if (code == TEMPLATE_TYPE_PARM
177490075Sobrien      || code == TEMPLATE_TEMPLATE_PARM
177590075Sobrien      || code == BOUND_TEMPLATE_TEMPLATE_PARM
177690075Sobrien      || code == TEMPLATE_PARM_INDEX)
177790075Sobrien    write_template_param (expr);
177890075Sobrien  /* Handle literals.  */
177990075Sobrien  else if (TREE_CODE_CLASS (code) == 'c')
178090075Sobrien    write_template_arg_literal (expr);
178190075Sobrien  else if (DECL_P (expr))
178290075Sobrien    {
178390075Sobrien      write_char ('L');
178490075Sobrien      write_mangled_name (expr);
178590075Sobrien      write_char ('E');
178690075Sobrien    }
178790075Sobrien  else
178890075Sobrien    {
178990075Sobrien      int i;
179090075Sobrien
179190075Sobrien      /* Skip NOP_EXPRs.  They can occur when (say) a pointer argument
179290075Sobrien	 is converted (via qualification conversions) to another
179390075Sobrien	 type.  */
179490075Sobrien      while (TREE_CODE (expr) == NOP_EXPR)
179590075Sobrien	{
179690075Sobrien	  expr = TREE_OPERAND (expr, 0);
179790075Sobrien	  code = TREE_CODE (expr);
179890075Sobrien	}
179990075Sobrien
180090075Sobrien      /* When we bind a variable or function to a non-type template
180190075Sobrien	 argument with reference type, we create an ADDR_EXPR to show
180290075Sobrien	 the fact that the entity's address has been taken.  But, we
180390075Sobrien	 don't actually want to output a mangling code for the `&'.  */
180490075Sobrien      if (TREE_CODE (expr) == ADDR_EXPR
180590075Sobrien	  && TREE_TYPE (expr)
180690075Sobrien	  && TREE_CODE (TREE_TYPE (expr)) == REFERENCE_TYPE)
180790075Sobrien	{
180890075Sobrien	  expr = TREE_OPERAND (expr, 0);
180990075Sobrien	  if (DECL_P (expr))
181090075Sobrien	    {
181190075Sobrien	      write_expression (expr);
181290075Sobrien	      return;
181390075Sobrien	    }
181490075Sobrien
181590075Sobrien	  code = TREE_CODE (expr);
181690075Sobrien	}
181790075Sobrien
181890075Sobrien      /* If it wasn't any of those, recursively expand the expression.  */
181990075Sobrien      write_string (operator_name_info[(int) code].mangled_name);
182090075Sobrien
182190075Sobrien      switch (code)
182290075Sobrien	{
182390075Sobrien	case CAST_EXPR:
182490075Sobrien	  write_type (TREE_TYPE (expr));
182590075Sobrien	  write_expression (TREE_VALUE (TREE_OPERAND (expr, 0)));
182690075Sobrien	  break;
182790075Sobrien
182890075Sobrien	case STATIC_CAST_EXPR:
182990075Sobrien	case CONST_CAST_EXPR:
183090075Sobrien	  write_type (TREE_TYPE (expr));
183190075Sobrien	  write_expression (TREE_OPERAND (expr, 0));
183290075Sobrien	  break;
183390075Sobrien
183490075Sobrien	/* Handle pointers-to-members specially.  */
183590075Sobrien	case SCOPE_REF:
183690075Sobrien	  write_type (TREE_OPERAND (expr, 0));
183790075Sobrien	  if (TREE_CODE (TREE_OPERAND (expr, 1)) == IDENTIFIER_NODE)
183890075Sobrien	    write_source_name (TREE_OPERAND (expr, 1));
183990075Sobrien	  else
184090075Sobrien	    write_encoding (TREE_OPERAND (expr, 1));
184190075Sobrien	  break;
184290075Sobrien
184390075Sobrien	default:
184490075Sobrien	  for (i = 0; i < TREE_CODE_LENGTH (code); ++i)
184590075Sobrien	    write_expression (TREE_OPERAND (expr, i));
184690075Sobrien	}
184790075Sobrien    }
184890075Sobrien}
184990075Sobrien
185090075Sobrien/* Literal subcase of non-terminal <template-arg>.
185190075Sobrien
185290075Sobrien     "Literal arguments, e.g. "A<42L>", are encoded with their type
185390075Sobrien     and value. Negative integer values are preceded with "n"; for
185490075Sobrien     example, "A<-42L>" becomes "1AILln42EE". The bool value false is
185590075Sobrien     encoded as 0, true as 1. If floating-point arguments are accepted
185690075Sobrien     as an extension, their values should be encoded using a
185790075Sobrien     fixed-length lowercase hexadecimal string corresponding to the
185890075Sobrien     internal representation (IEEE on IA-64), high-order bytes first,
185990075Sobrien     without leading zeroes. For example: "Lfbff000000E" is -1.0f."  */
186090075Sobrien
186190075Sobrienstatic void
186290075Sobrienwrite_template_arg_literal (value)
186390075Sobrien     tree value;
186490075Sobrien{
186590075Sobrien  tree type = TREE_TYPE (value);
186690075Sobrien  write_char ('L');
186790075Sobrien  write_type (type);
186890075Sobrien
186990075Sobrien  if (TREE_CODE (value) == CONST_DECL)
187090075Sobrien    write_integer_cst (DECL_INITIAL (value));
187190075Sobrien  else if (TREE_CODE (value) == INTEGER_CST)
187290075Sobrien    {
187390075Sobrien      if (same_type_p (type, boolean_type_node))
187490075Sobrien	{
187590075Sobrien	  if (value == boolean_false_node || integer_zerop (value))
187690075Sobrien	    write_unsigned_number (0);
187790075Sobrien	  else if (value == boolean_true_node)
187890075Sobrien	    write_unsigned_number (1);
187990075Sobrien	  else
188090075Sobrien	    abort ();
188190075Sobrien	}
188290075Sobrien      else
188390075Sobrien	write_integer_cst (value);
188490075Sobrien    }
188590075Sobrien  else if (TREE_CODE (value) == REAL_CST)
188690075Sobrien    {
188790075Sobrien#ifdef CROSS_COMPILE
188890075Sobrien      static int explained;
188990075Sobrien
189090075Sobrien      if (!explained)
189190075Sobrien	{
189290075Sobrien	  sorry ("real-valued template parameters when cross-compiling");
189390075Sobrien	  explained = 1;
189490075Sobrien	}
189590075Sobrien#else
189690075Sobrien      size_t i;
189790075Sobrien      for (i = 0; i < sizeof (TREE_REAL_CST (value)); ++i)
189890075Sobrien	write_number (((unsigned char *)
189990075Sobrien		       &TREE_REAL_CST (value))[i],
190090075Sobrien		      /*unsigned_p=*/1,
190190075Sobrien		      16);
190290075Sobrien#endif
190390075Sobrien    }
190490075Sobrien  else
190590075Sobrien    abort ();
190690075Sobrien
190790075Sobrien  write_char ('E');
190890075Sobrien}
190990075Sobrien
191090075Sobrien/* Non-terminal <tempalate-arg>.
191190075Sobrien
191290075Sobrien     <template-arg> ::= <type>                        # type
191390075Sobrien                    ::= L <type> </value/ number> E   # literal
191490075Sobrien                    ::= LZ <name> E                   # external name
191590075Sobrien                    ::= X <expression> E              # expression  */
191690075Sobrien
191790075Sobrienstatic void
191890075Sobrienwrite_template_arg (node)
191990075Sobrien     tree node;
192090075Sobrien{
192190075Sobrien  enum tree_code code = TREE_CODE (node);
192290075Sobrien
192390075Sobrien  MANGLE_TRACE_TREE ("template-arg", node);
192490075Sobrien
192590075Sobrien  /* A template template paramter's argument list contains TREE_LIST
192690075Sobrien     nodes of which the value field is the the actual argument.  */
192790075Sobrien  if (code == TREE_LIST)
192890075Sobrien    {
192990075Sobrien      node = TREE_VALUE (node);
193090075Sobrien      /* If it's a decl, deal with its type instead.  */
193190075Sobrien      if (DECL_P (node))
193290075Sobrien	{
193390075Sobrien	  node = TREE_TYPE (node);
193490075Sobrien	  code = TREE_CODE (node);
193590075Sobrien	}
193690075Sobrien    }
193790075Sobrien
193890075Sobrien  if (TYPE_P (node))
193990075Sobrien    write_type (node);
194090075Sobrien  else if (code == TEMPLATE_DECL)
194190075Sobrien    /* A template appearing as a template arg is a template template arg.  */
194290075Sobrien    write_template_template_arg (node);
194390075Sobrien  else if (DECL_P (node))
194490075Sobrien    {
194590075Sobrien      write_char ('L');
194690075Sobrien      write_char ('Z');
194790075Sobrien      write_encoding (node);
194890075Sobrien      write_char ('E');
194990075Sobrien    }
195090075Sobrien  else if (TREE_CODE_CLASS (code) == 'c' && code != PTRMEM_CST)
195190075Sobrien    write_template_arg_literal (node);
195290075Sobrien  else
195390075Sobrien    {
195490075Sobrien      /* Template arguments may be expressions.  */
195590075Sobrien      write_char ('X');
195690075Sobrien      write_expression (node);
195790075Sobrien      write_char ('E');
195890075Sobrien    }
195990075Sobrien}
196090075Sobrien
196190075Sobrien/*  <template-template-arg>
196290075Sobrien			::= <name>
196390075Sobrien			::= <substitution>  */
196490075Sobrien
196590075Sobrienvoid
196690075Sobrienwrite_template_template_arg (tree decl)
196790075Sobrien{
196890075Sobrien  MANGLE_TRACE_TREE ("template-template-arg", decl);
196990075Sobrien
197090075Sobrien  if (find_substitution (decl))
197190075Sobrien    return;
197290075Sobrien  write_name (decl, /*ignore_local_scope=*/0);
197390075Sobrien  add_substitution (decl);
197490075Sobrien}
197590075Sobrien
197690075Sobrien
197790075Sobrien/* Non-terminal <array-type>.  TYPE is an ARRAY_TYPE.
197890075Sobrien
197990075Sobrien     <array-type> ::= A [</dimension/ number>] _ </element/ type>
198090075Sobrien                  ::= A <expression> _ </element/ type>
198190075Sobrien
198290075Sobrien     "Array types encode the dimension (number of elements) and the
198390075Sobrien     element type. For variable length arrays, the dimension (but not
198490075Sobrien     the '_' separator) is omitted."  */
198590075Sobrien
198690075Sobrienstatic void
198790075Sobrienwrite_array_type (type)
198890075Sobrien  tree type;
198990075Sobrien{
199090075Sobrien  write_char ('A');
199190075Sobrien  if (TYPE_DOMAIN (type))
199290075Sobrien    {
199390075Sobrien      tree index_type;
199490075Sobrien      tree max;
199590075Sobrien
199690075Sobrien      index_type = TYPE_DOMAIN (type);
199790075Sobrien      /* The INDEX_TYPE gives the upper and lower bounds of the
199890075Sobrien	 array.  */
199990075Sobrien      max = TYPE_MAX_VALUE (index_type);
200090075Sobrien      if (TREE_CODE (max) == INTEGER_CST)
200190075Sobrien	{
200290075Sobrien	  /* The ABI specifies that we should mangle the number of
200390075Sobrien	     elements in the array, not the largest allowed index.  */
200490075Sobrien	  max = size_binop (PLUS_EXPR, max, size_one_node);
200590075Sobrien	  write_unsigned_number (tree_low_cst (max, 1));
200690075Sobrien	}
200790075Sobrien      else
200890075Sobrien	write_expression (TREE_OPERAND (max, 0));
200990075Sobrien    }
201090075Sobrien  write_char ('_');
201190075Sobrien  write_type (TREE_TYPE (type));
201290075Sobrien}
201390075Sobrien
201490075Sobrien/* Non-terminal <pointer-to-member-type> for pointer-to-member
201590075Sobrien   variables.  TYPE is a pointer-to-member POINTER_TYPE.
201690075Sobrien
201790075Sobrien     <pointer-to-member-type> ::= M </class/ type> </member/ type>  */
201890075Sobrien
201990075Sobrienstatic void
202090075Sobrienwrite_pointer_to_member_type (type)
202190075Sobrien     tree type;
202290075Sobrien{
202390075Sobrien  write_char ('M');
202490075Sobrien  /* For a pointer-to-function member, the class type may be
202590075Sobrien     cv-qualified, but that won't be reflected in
202690075Sobrien     TYPE_PTRMEM_CLASS_TYPE.  So, we go fishing around in
202790075Sobrien     TYPE_PTRMEM_POINTED_TO_TYPE instead.  */
202890075Sobrien  if (TYPE_PTRMEMFUNC_P (type))
202990075Sobrien    {
203090075Sobrien      tree fn_type;
203190075Sobrien      tree this_type;
203290075Sobrien
203390075Sobrien      fn_type = TYPE_PTRMEM_POINTED_TO_TYPE (type);
203490075Sobrien      /* The first parameter must be a POINTER_TYPE pointing to the
203590075Sobrien	 `this' parameter.  */
203690075Sobrien      this_type = TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (fn_type)));
203790075Sobrien      write_type (this_type);
203890075Sobrien    }
203990075Sobrien  /* For a pointer-to-data member, things are simpler.  */
204090075Sobrien  else
204190075Sobrien    write_type (TYPE_PTRMEM_CLASS_TYPE (type));
204290075Sobrien  write_type (TYPE_PTRMEM_POINTED_TO_TYPE (type));
204390075Sobrien}
204490075Sobrien
204590075Sobrien/* Non-terminal <template-param>.  PARM is a TEMPLATE_TYPE_PARM,
204690075Sobrien   TEMPLATE_TEMPLATE_PARM, BOUND_TEMPLATE_TEMPLATE_PARM or a
204790075Sobrien   TEMPLATE_PARM_INDEX.
204890075Sobrien
204990075Sobrien     <template-param> ::= T </parameter/ number> _  */
205090075Sobrien
205190075Sobrienstatic void
205290075Sobrienwrite_template_param (parm)
205390075Sobrien     tree parm;
205490075Sobrien{
205590075Sobrien  int parm_index;
205690075Sobrien
205790075Sobrien  MANGLE_TRACE_TREE ("template-parm", parm);
205890075Sobrien
205990075Sobrien  switch (TREE_CODE (parm))
206090075Sobrien    {
206190075Sobrien    case TEMPLATE_TYPE_PARM:
206290075Sobrien    case TEMPLATE_TEMPLATE_PARM:
206390075Sobrien    case BOUND_TEMPLATE_TEMPLATE_PARM:
206490075Sobrien      parm_index = TEMPLATE_TYPE_IDX (parm);
206590075Sobrien      break;
206690075Sobrien
206790075Sobrien    case TEMPLATE_PARM_INDEX:
206890075Sobrien      parm_index = TEMPLATE_PARM_IDX (parm);
206990075Sobrien      break;
207090075Sobrien
207190075Sobrien    default:
207290075Sobrien      abort ();
207390075Sobrien    }
207490075Sobrien
207590075Sobrien  write_char ('T');
207690075Sobrien  /* NUMBER as it appears in the mangling is (-1)-indexed, with the
207790075Sobrien     earliest template param denoted by `_'.  */
207890075Sobrien  if (parm_index > 0)
207990075Sobrien    write_unsigned_number (parm_index - 1);
208090075Sobrien  write_char ('_');
208190075Sobrien}
208290075Sobrien
208390075Sobrien/*  <template-template-param>
208490075Sobrien                        ::= <template-param>
208590075Sobrien			::= <substitution>  */
208690075Sobrien
208790075Sobrienstatic void
208890075Sobrienwrite_template_template_param (parm)
208990075Sobrien     tree parm;
209090075Sobrien{
209190075Sobrien  tree template = NULL_TREE;
209290075Sobrien
209390075Sobrien  /* PARM, a TEMPLATE_TEMPLATE_PARM, is an instantiation of the
209490075Sobrien     template template parameter.  The substitution candidate here is
209590075Sobrien     only the template.  */
209690075Sobrien  if (TREE_CODE (parm) == BOUND_TEMPLATE_TEMPLATE_PARM)
209790075Sobrien    {
209890075Sobrien      template
209990075Sobrien	= TI_TEMPLATE (TEMPLATE_TEMPLATE_PARM_TEMPLATE_INFO (parm));
210090075Sobrien      if (find_substitution (template))
210190075Sobrien	return;
210290075Sobrien    }
210390075Sobrien
210490075Sobrien  /* <template-param> encodes only the template parameter position,
210590075Sobrien     not its template arguments, which is fine here.  */
210690075Sobrien  write_template_param (parm);
210790075Sobrien  if (template)
210890075Sobrien    add_substitution (template);
210990075Sobrien}
211090075Sobrien
211190075Sobrien/* Non-terminal <substitution>.
211290075Sobrien
211390075Sobrien      <substitution> ::= S <seq-id> _
211490075Sobrien                     ::= S_  */
211590075Sobrien
211690075Sobrienstatic void
211790075Sobrienwrite_substitution (seq_id)
211890075Sobrien     int seq_id;
211990075Sobrien{
212090075Sobrien  MANGLE_TRACE ("substitution", "");
212190075Sobrien
212290075Sobrien  write_char ('S');
212390075Sobrien  if (seq_id > 0)
212490075Sobrien    write_number (seq_id - 1, /*unsigned=*/1, 36);
212590075Sobrien  write_char ('_');
212690075Sobrien}
212790075Sobrien
212890075Sobrien/* Start mangling a new name or type.  */
212990075Sobrien
213090075Sobrienstatic inline void
213190075Sobrienstart_mangling ()
213290075Sobrien{
213390075Sobrien  obstack_free (&G.name_obstack, obstack_base (&G.name_obstack));
213490075Sobrien}
213590075Sobrien
213690075Sobrien/* Done with mangling.  Return the generated mangled name.  */
213790075Sobrien
213890075Sobrienstatic inline const char *
213990075Sobrienfinish_mangling ()
214090075Sobrien{
214190075Sobrien  /* Clear all the substitutions.  */
214290075Sobrien  VARRAY_POP_ALL (G.substitutions);
214390075Sobrien
214490075Sobrien  /* Null-terminate the string.  */
214590075Sobrien  write_char ('\0');
214690075Sobrien
214790075Sobrien  return (const char *) obstack_base (&G.name_obstack);
214890075Sobrien}
214990075Sobrien
215090075Sobrien/* Initialize data structures for mangling.  */
215190075Sobrien
215290075Sobrienvoid
215390075Sobrieninit_mangle ()
215490075Sobrien{
215590075Sobrien  gcc_obstack_init (&G.name_obstack);
215690075Sobrien  VARRAY_TREE_INIT (G.substitutions, 1, "mangling substitutions");
215790075Sobrien
215890075Sobrien  /* Cache these identifiers for quick comparison when checking for
215990075Sobrien     standard substitutions.  */
216090075Sobrien  subst_identifiers[SUBID_ALLOCATOR] = get_identifier ("allocator");
216190075Sobrien  subst_identifiers[SUBID_BASIC_STRING] = get_identifier ("basic_string");
216290075Sobrien  subst_identifiers[SUBID_CHAR_TRAITS] = get_identifier ("char_traits");
216390075Sobrien  subst_identifiers[SUBID_BASIC_ISTREAM] = get_identifier ("basic_istream");
216490075Sobrien  subst_identifiers[SUBID_BASIC_OSTREAM] = get_identifier ("basic_ostream");
216590075Sobrien  subst_identifiers[SUBID_BASIC_IOSTREAM] = get_identifier ("basic_iostream");
216690075Sobrien}
216790075Sobrien
216890075Sobrien/* Generate the mangled name of DECL.  */
216990075Sobrien
217090075Sobrienstatic const char *
217190075Sobrienmangle_decl_string (decl)
217290075Sobrien     tree decl;
217390075Sobrien{
217490075Sobrien  const char *result;
217590075Sobrien
217690075Sobrien  start_mangling ();
217790075Sobrien
217890075Sobrien  if (TREE_CODE (decl) == TYPE_DECL)
217990075Sobrien    write_type (TREE_TYPE (decl));
218090075Sobrien  else if (/* The names of `extern "C"' functions are not mangled.  */
218190075Sobrien	   (DECL_EXTERN_C_FUNCTION_P (decl)
218290075Sobrien	    /* But overloaded operator names *are* mangled.  */
218390075Sobrien	    && !DECL_OVERLOADED_OPERATOR_P (decl))
218490075Sobrien	   /* The names of global variables aren't mangled either.  */
218590075Sobrien	   || (TREE_CODE (decl) == VAR_DECL
218690075Sobrien	       && CP_DECL_CONTEXT (decl) == global_namespace)
218790075Sobrien	   /* And neither are `extern "C"' variables.  */
218890075Sobrien	   || (TREE_CODE (decl) == VAR_DECL
218990075Sobrien	       && DECL_EXTERN_C_P (decl)))
219090075Sobrien    write_string (IDENTIFIER_POINTER (DECL_NAME (decl)));
219190075Sobrien  else
219290075Sobrien    {
219390075Sobrien      write_mangled_name (decl);
219490075Sobrien      if (DECL_LANG_SPECIFIC (decl)
219590075Sobrien	  && (DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P (decl)
219690075Sobrien	      || DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (decl)))
219790075Sobrien	/* We need a distinct mangled name for these entities, but
219890075Sobrien	   we should never actually output it.  So, we append some
219990075Sobrien	   characters the assembler won't like.  */
220090075Sobrien	write_string (" *INTERNAL* ");
220190075Sobrien    }
220290075Sobrien
220390075Sobrien  result = finish_mangling ();
220490075Sobrien  if (DEBUG_MANGLE)
220590075Sobrien    fprintf (stderr, "mangle_decl_string = '%s'\n\n", result);
220690075Sobrien  return result;
220790075Sobrien}
220890075Sobrien
220990075Sobrien/* Create an identifier for the external mangled name of DECL.  */
221090075Sobrien
221190075Sobrienvoid
221290075Sobrienmangle_decl (decl)
221390075Sobrien     tree decl;
221490075Sobrien{
221590075Sobrien  tree id = get_identifier (mangle_decl_string (decl));
221690075Sobrien
221790075Sobrien  SET_DECL_ASSEMBLER_NAME (decl, id);
221890075Sobrien}
221990075Sobrien
222090075Sobrien/* Generate the mangled representation of TYPE.  */
222190075Sobrien
222290075Sobrienconst char *
222390075Sobrienmangle_type_string (type)
222490075Sobrien     tree type;
222590075Sobrien{
222690075Sobrien  const char *result;
222790075Sobrien
222890075Sobrien  start_mangling ();
222990075Sobrien  write_type (type);
223090075Sobrien  result = finish_mangling ();
223190075Sobrien  if (DEBUG_MANGLE)
223290075Sobrien    fprintf (stderr, "mangle_type_string = '%s'\n\n", result);
223390075Sobrien  return result;
223490075Sobrien}
223590075Sobrien
223690075Sobrien/* Create an identifier for the mangled representation of TYPE.  */
223790075Sobrien
223890075Sobrientree
223990075Sobrienmangle_type (type)
224090075Sobrien     tree type;
224190075Sobrien{
224290075Sobrien  return get_identifier (mangle_type_string (type));
224390075Sobrien}
224490075Sobrien
224590075Sobrien/* Create an identifier for the mangled name of a special component
224690075Sobrien   for belonging to TYPE.  CODE is the ABI-specified code for this
224790075Sobrien   component.  */
224890075Sobrien
224990075Sobrienstatic tree
225090075Sobrienmangle_special_for_type (type, code)
225190075Sobrien     tree type;
225290075Sobrien     const char *code;
225390075Sobrien{
225490075Sobrien  const char *result;
225590075Sobrien
225690075Sobrien  /* We don't have an actual decl here for the special component, so
225790075Sobrien     we can't just process the <encoded-name>.  Instead, fake it.  */
225890075Sobrien  start_mangling ();
225990075Sobrien
226090075Sobrien  /* Start the mangling.  */
226190075Sobrien  write_string ("_Z");
226290075Sobrien  write_string (code);
226390075Sobrien
226490075Sobrien  /* Add the type.  */
226590075Sobrien  write_type (type);
226690075Sobrien  result = finish_mangling ();
226790075Sobrien
226890075Sobrien  if (DEBUG_MANGLE)
226990075Sobrien    fprintf (stderr, "mangle_special_for_type = %s\n\n", result);
227090075Sobrien
227190075Sobrien  return get_identifier (result);
227290075Sobrien}
227390075Sobrien
227490075Sobrien/* Create an identifier for the mangled representation of the typeinfo
227590075Sobrien   structure for TYPE.  */
227690075Sobrien
227790075Sobrientree
227890075Sobrienmangle_typeinfo_for_type (type)
227990075Sobrien     tree type;
228090075Sobrien{
228190075Sobrien  return mangle_special_for_type (type, "TI");
228290075Sobrien}
228390075Sobrien
228490075Sobrien/* Create an identifier for the mangled name of the NTBS containing
228590075Sobrien   the mangled name of TYPE.  */
228690075Sobrien
228790075Sobrientree
228890075Sobrienmangle_typeinfo_string_for_type (type)
228990075Sobrien     tree type;
229090075Sobrien{
229190075Sobrien  return mangle_special_for_type (type, "TS");
229290075Sobrien}
229390075Sobrien
229490075Sobrien/* Create an identifier for the mangled name of the vtable for TYPE.  */
229590075Sobrien
229690075Sobrientree
229790075Sobrienmangle_vtbl_for_type (type)
229890075Sobrien     tree type;
229990075Sobrien{
230090075Sobrien  return mangle_special_for_type (type, "TV");
230190075Sobrien}
230290075Sobrien
230390075Sobrien/* Returns an identifier for the mangled name of the VTT for TYPE.  */
230490075Sobrien
230590075Sobrientree
230690075Sobrienmangle_vtt_for_type (type)
230790075Sobrien     tree type;
230890075Sobrien{
230990075Sobrien  return mangle_special_for_type (type, "TT");
231090075Sobrien}
231190075Sobrien
231290075Sobrien/* Return an identifier for a construction vtable group.  TYPE is
231390075Sobrien   the most derived class in the hierarchy; BINFO is the base
231490075Sobrien   subobject for which this construction vtable group will be used.
231590075Sobrien
231690075Sobrien   This mangling isn't part of the ABI specification; in the ABI
231790075Sobrien   specification, the vtable group is dumped in the same COMDAT as the
231890075Sobrien   main vtable, and is referenced only from that vtable, so it doesn't
231990075Sobrien   need an external name.  For binary formats without COMDAT sections,
232090075Sobrien   though, we need external names for the vtable groups.
232190075Sobrien
232290075Sobrien   We use the production
232390075Sobrien
232490075Sobrien    <special-name> ::= CT <type> <offset number> _ <base type>  */
232590075Sobrien
232690075Sobrientree
232790075Sobrienmangle_ctor_vtbl_for_type (type, binfo)
232890075Sobrien     tree type;
232990075Sobrien     tree binfo;
233090075Sobrien{
233190075Sobrien  const char *result;
233290075Sobrien
233390075Sobrien  start_mangling ();
233490075Sobrien
233590075Sobrien  write_string ("_Z");
233690075Sobrien  write_string ("TC");
233790075Sobrien  write_type (type);
233890075Sobrien  write_integer_cst (BINFO_OFFSET (binfo));
233990075Sobrien  write_char ('_');
234090075Sobrien  write_type (BINFO_TYPE (binfo));
234190075Sobrien
234290075Sobrien  result = finish_mangling ();
234390075Sobrien  if (DEBUG_MANGLE)
234490075Sobrien    fprintf (stderr, "mangle_ctor_vtbl_for_type = %s\n\n", result);
234590075Sobrien  return get_identifier (result);
234690075Sobrien}
234790075Sobrien
234890075Sobrien/* Return an identifier for the mangled name of a thunk to FN_DECL.
234990075Sobrien   OFFSET is the initial adjustment to this used to find the vptr.  If
235090075Sobrien   VCALL_OFFSET is non-NULL, this is a virtual thunk, and it is the
235190075Sobrien   vtbl offset in bytes.
235290075Sobrien
235390075Sobrien    <special-name> ::= Th <offset number> _ <base encoding>
235490075Sobrien                   ::= Tv <offset number> _ <vcall offset number> _
235590075Sobrien		                                            <base encoding>
235690075Sobrien*/
235790075Sobrien
235890075Sobrientree
235990075Sobrienmangle_thunk (fn_decl, offset, vcall_offset)
236090075Sobrien     tree fn_decl;
236190075Sobrien     tree offset;
236290075Sobrien     tree vcall_offset;
236390075Sobrien{
236490075Sobrien  const char *result;
236590075Sobrien
236690075Sobrien  start_mangling ();
236790075Sobrien
236890075Sobrien  write_string ("_Z");
236990075Sobrien  /* The <special-name> for virtual thunks is Tv, for non-virtual
237090075Sobrien     thunks Th.  */
237190075Sobrien  write_char ('T');
237290075Sobrien  if (vcall_offset != 0)
237390075Sobrien    write_char ('v');
237490075Sobrien  else
237590075Sobrien    write_char ('h');
237690075Sobrien
237790075Sobrien  /* For either flavor, write the offset to this.  */
237890075Sobrien  write_integer_cst (offset);
237990075Sobrien  write_char ('_');
238090075Sobrien
238190075Sobrien  /* For a virtual thunk, add the vcall offset.  */
238290075Sobrien  if (vcall_offset)
238390075Sobrien    {
238490075Sobrien      /* Virtual thunk.  Write the vcall offset and base type name.  */
238590075Sobrien      write_integer_cst (vcall_offset);
238690075Sobrien      write_char ('_');
238790075Sobrien    }
238890075Sobrien
238990075Sobrien  /* Scoped name.  */
239090075Sobrien  write_encoding (fn_decl);
239190075Sobrien
239290075Sobrien  result = finish_mangling ();
239390075Sobrien  if (DEBUG_MANGLE)
239490075Sobrien    fprintf (stderr, "mangle_thunk = %s\n\n", result);
239590075Sobrien  return get_identifier (result);
239690075Sobrien}
239790075Sobrien
239890075Sobrien/* Return an identifier for the mangled unqualified name for a
239990075Sobrien   conversion operator to TYPE.  This mangling is not specified by the
240090075Sobrien   ABI spec; it is only used internally.  */
240190075Sobrien
240290075Sobrientree
240390075Sobrienmangle_conv_op_name_for_type (type)
240490075Sobrien     tree type;
240590075Sobrien{
240690075Sobrien  tree identifier;
240790075Sobrien
240890075Sobrien  /* Build the mangling for TYPE.  */
240990075Sobrien  const char *mangled_type = mangle_type_string (type);
241090075Sobrien  /* Allocate a temporary buffer for the complete name.  */
241190075Sobrien  char *op_name = concat ("operator ", mangled_type, NULL);
241290075Sobrien  /* Find or create an identifier.  */
241390075Sobrien  identifier = get_identifier (op_name);
241490075Sobrien  /* Done with the temporary buffer.  */
241590075Sobrien  free (op_name);
241690075Sobrien  /* Set bits on the identifier so we know later it's a conversion.  */
241790075Sobrien  IDENTIFIER_OPNAME_P (identifier) = 1;
241890075Sobrien  IDENTIFIER_TYPENAME_P (identifier) = 1;
241990075Sobrien  /* Hang TYPE off the identifier so it can be found easily later when
242090075Sobrien     performing conversions.  */
242190075Sobrien  TREE_TYPE (identifier) = type;
242290075Sobrien
242390075Sobrien  return identifier;
242490075Sobrien}
242590075Sobrien
242690075Sobrien/* Return an identifier for the name of an initialization guard
242790075Sobrien   variable for indicated VARIABLE.  */
242890075Sobrien
242990075Sobrientree
243090075Sobrienmangle_guard_variable (variable)
243190075Sobrien     tree variable;
243290075Sobrien{
243390075Sobrien  start_mangling ();
243490075Sobrien  write_string ("_ZGV");
243590075Sobrien  if (strncmp (IDENTIFIER_POINTER (DECL_NAME (variable)), "_ZGR", 4) == 0)
243690075Sobrien    /* The name of a guard variable for a reference temporary should refer
243790075Sobrien       to the reference, not the temporary.  */
243890075Sobrien    write_string (IDENTIFIER_POINTER (DECL_NAME (variable)) + 4);
243990075Sobrien  else
244090075Sobrien    write_name (variable, /*ignore_local_scope=*/0);
244190075Sobrien  return get_identifier (finish_mangling ());
244290075Sobrien}
244390075Sobrien
244490075Sobrien/* Return an identifier for the name of a temporary variable used to
244590075Sobrien   initialize a static reference.  This isn't part of the ABI, but we might
244690075Sobrien   as well call them something readable.  */
244790075Sobrien
244890075Sobrientree
244990075Sobrienmangle_ref_init_variable (variable)
245090075Sobrien     tree variable;
245190075Sobrien{
245290075Sobrien  start_mangling ();
245390075Sobrien  write_string ("_ZGR");
245490075Sobrien  write_name (variable, /*ignore_local_scope=*/0);
245590075Sobrien  return get_identifier (finish_mangling ());
245690075Sobrien}
245790075Sobrien
245890075Sobrien
245990075Sobrien/* Foreign language type mangling section.  */
246090075Sobrien
246190075Sobrien/* How to write the type codes for the integer Java type.  */
246290075Sobrien
246390075Sobrienstatic void
246490075Sobrienwrite_java_integer_type_codes (type)
246590075Sobrien     tree type;
246690075Sobrien{
246790075Sobrien  if (type == java_int_type_node)
246890075Sobrien    write_char ('i');
246990075Sobrien  else if (type == java_short_type_node)
247090075Sobrien    write_char ('s');
247190075Sobrien  else if (type == java_byte_type_node)
247290075Sobrien    write_char ('c');
247390075Sobrien  else if (type == java_char_type_node)
247490075Sobrien    write_char ('w');
247590075Sobrien  else if (type == java_long_type_node)
247690075Sobrien    write_char ('x');
247790075Sobrien  else if (type == java_boolean_type_node)
247890075Sobrien    write_char ('b');
247990075Sobrien  else
248090075Sobrien    abort ();
248190075Sobrien}
248290075Sobrien
2483