Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1274)

Unified Diff: gcc/gcc/cp/mangle.c

Issue 3050029: [gcc] GCC 4.5.0=>4.5.1 (Closed) Base URL: ssh://git@gitrw.chromium.org:9222/nacl-toolchain.git
Patch Set: Created 10 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « gcc/gcc/cp/lex.c ('k') | gcc/gcc/cp/name-lookup.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: gcc/gcc/cp/mangle.c
diff --git a/gcc/gcc/cp/mangle.c b/gcc/gcc/cp/mangle.c
deleted file mode 100644
index f4d76d136574baa3fb27b79b91ae2c97d510b69c..0000000000000000000000000000000000000000
--- a/gcc/gcc/cp/mangle.c
+++ /dev/null
@@ -1,3111 +0,0 @@
-/* Name mangling for the 3.0 C++ ABI.
- Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009
- Free Software Foundation, Inc.
- Written by Alex Samuel <samuel@codesourcery.com>
-
- This file is part of GCC.
-
- GCC is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 3, or (at your option)
- any later version.
-
- GCC is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING3. If not see
-<http://www.gnu.org/licenses/>. */
-
-/* This file implements mangling of C++ names according to the IA64
- C++ ABI specification. A mangled name encodes a function or
- variable's name, scope, type, and/or template arguments into a text
- identifier. This identifier is used as the function's or
- variable's linkage name, to preserve compatibility between C++'s
- language features (templates, scoping, and overloading) and C
- linkers.
-
- Additionally, g++ uses mangled names internally. To support this,
- mangling of types is allowed, even though the mangled name of a
- type should not appear by itself as an exported name. Ditto for
- uninstantiated templates.
-
- The primary entry point for this module is mangle_decl, which
- returns an identifier containing the mangled name for a decl.
- Additional entry points are provided to build mangled names of
- particular constructs when the appropriate decl for that construct
- is not available. These are:
-
- mangle_typeinfo_for_type: typeinfo data
- mangle_typeinfo_string_for_type: typeinfo type name
- mangle_vtbl_for_type: virtual table data
- mangle_vtt_for_type: VTT data
- mangle_ctor_vtbl_for_type: `C-in-B' constructor virtual table data
- mangle_thunk: thunk function or entry */
-
-#include "config.h"
-#include "system.h"
-#include "coretypes.h"
-#include "tm.h"
-#include "tree.h"
-#include "tm_p.h"
-#include "cp-tree.h"
-#include "real.h"
-#include "obstack.h"
-#include "toplev.h"
-#include "varray.h"
-#include "flags.h"
-#include "target.h"
-
-/* Debugging support. */
-
-/* Define DEBUG_MANGLE to enable very verbose trace messages. */
-#ifndef DEBUG_MANGLE
-#define DEBUG_MANGLE 0
-#endif
-
-/* Macros for tracing the write_* functions. */
-#if DEBUG_MANGLE
-# define MANGLE_TRACE(FN, INPUT) \
- fprintf (stderr, " %-24s: %-24s\n", (FN), (INPUT))
-# define MANGLE_TRACE_TREE(FN, NODE) \
- fprintf (stderr, " %-24s: %-24s (%p)\n", \
- (FN), tree_code_name[TREE_CODE (NODE)], (void *) (NODE))
-#else
-# define MANGLE_TRACE(FN, INPUT)
-# define MANGLE_TRACE_TREE(FN, NODE)
-#endif
-
-/* Nonzero if NODE is a class template-id. We can't rely on
- CLASSTYPE_USE_TEMPLATE here because of tricky bugs in the parser
- that hard to distinguish A<T> from A, where A<T> is the type as
- instantiated outside of the template, and A is the type used
- without parameters inside the template. */
-#define CLASSTYPE_TEMPLATE_ID_P(NODE) \
- (TYPE_LANG_SPECIFIC (NODE) != NULL \
- && (TREE_CODE (NODE) == BOUND_TEMPLATE_TEMPLATE_PARM \
- || (CLASSTYPE_TEMPLATE_INFO (NODE) != NULL \
- && (PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (NODE))))))
-
-/* Things we only need one of. This module is not reentrant. */
-typedef struct globals GTY(())
-{
- /* An array of the current substitution candidates, in the order
- we've seen them. */
- VEC(tree,gc) *substitutions;
-
- /* The entity that is being mangled. */
- tree GTY ((skip)) entity;
-
- /* True if the mangling will be different in a future version of the
- ABI. */
- bool need_abi_warning;
-} globals;
-
-static GTY (()) globals G;
-
-/* The obstack on which we build mangled names. */
-static struct obstack *mangle_obstack;
-
-/* The obstack on which we build mangled names that are not going to
- be IDENTIFIER_NODEs. */
-static struct obstack name_obstack;
-
-/* The first object on the name_obstack; we use this to free memory
- allocated on the name_obstack. */
-static void *name_base;
-
-/* Indices into subst_identifiers. These are identifiers used in
- special substitution rules. */
-typedef enum
-{
- SUBID_ALLOCATOR,
- SUBID_BASIC_STRING,
- SUBID_CHAR_TRAITS,
- SUBID_BASIC_ISTREAM,
- SUBID_BASIC_OSTREAM,
- SUBID_BASIC_IOSTREAM,
- SUBID_MAX
-}
-substitution_identifier_index_t;
-
-/* For quick substitution checks, look up these common identifiers
- once only. */
-static GTY(()) tree subst_identifiers[SUBID_MAX];
-
-/* Single-letter codes for builtin integer types, defined in
- <builtin-type>. These are indexed by integer_type_kind values. */
-static const char
-integer_type_codes[itk_none] =
-{
- 'c', /* itk_char */
- 'a', /* itk_signed_char */
- 'h', /* itk_unsigned_char */
- 's', /* itk_short */
- 't', /* itk_unsigned_short */
- 'i', /* itk_int */
- 'j', /* itk_unsigned_int */
- 'l', /* itk_long */
- 'm', /* itk_unsigned_long */
- 'x', /* itk_long_long */
- 'y' /* itk_unsigned_long_long */
-};
-
-static int decl_is_template_id (const tree, tree* const);
-
-/* Functions for handling substitutions. */
-
-static inline tree canonicalize_for_substitution (tree);
-static void add_substitution (tree);
-static inline int is_std_substitution (const tree,
- const substitution_identifier_index_t);
-static inline int is_std_substitution_char (const tree,
- const substitution_identifier_index_t);
-static int find_substitution (tree);
-static void mangle_call_offset (const tree, const tree);
-
-/* Functions for emitting mangled representations of things. */
-
-static void write_mangled_name (const tree, bool);
-static void write_encoding (const tree);
-static void write_name (tree, const int);
-static void write_unscoped_name (const tree);
-static void write_unscoped_template_name (const tree);
-static void write_nested_name (const tree);
-static void write_prefix (const tree);
-static void write_template_prefix (const tree);
-static void write_unqualified_name (const tree);
-static void write_conversion_operator_name (const tree);
-static void write_source_name (tree);
-static int hwint_to_ascii (unsigned HOST_WIDE_INT, const unsigned int, char *,
- const unsigned int);
-static void write_number (unsigned HOST_WIDE_INT, const int,
- const unsigned int);
-static void write_integer_cst (const tree);
-static void write_real_cst (const tree);
-static void write_identifier (const char *);
-static void write_special_name_constructor (const tree);
-static void write_special_name_destructor (const tree);
-static void write_type (tree);
-static int write_CV_qualifiers_for_type (const tree);
-static void write_builtin_type (tree);
-static void write_function_type (const tree);
-static void write_bare_function_type (const tree, const int, const tree);
-static void write_method_parms (tree, const int, const tree);
-static void write_class_enum_type (const tree);
-static void write_template_args (tree);
-static void write_expression (tree);
-static void write_template_arg_literal (const tree);
-static void write_template_arg (tree);
-static void write_template_template_arg (const tree);
-static void write_array_type (const tree);
-static void write_pointer_to_member_type (const tree);
-static void write_template_param (const tree);
-static void write_template_template_param (const tree);
-static void write_substitution (const int);
-static int discriminator_for_local_entity (tree);
-static int discriminator_for_string_literal (tree, tree);
-static void write_discriminator (const int);
-static void write_local_name (const tree, const tree, const tree);
-static void dump_substitution_candidates (void);
-static tree mangle_decl_string (const tree);
-
-/* Control functions. */
-
-static inline void start_mangling (const tree);
-static inline const char *finish_mangling (const bool);
-static tree mangle_special_for_type (const tree, const char *);
-
-/* Foreign language functions. */
-
-static void write_java_integer_type_codes (const tree);
-
-/* Append a single character to the end of the mangled
- representation. */
-#define write_char(CHAR) \
- obstack_1grow (mangle_obstack, (CHAR))
-
-/* Append a sized buffer to the end of the mangled representation. */
-#define write_chars(CHAR, LEN) \
- obstack_grow (mangle_obstack, (CHAR), (LEN))
-
-/* Append a NUL-terminated string to the end of the mangled
- representation. */
-#define write_string(STRING) \
- obstack_grow (mangle_obstack, (STRING), strlen (STRING))
-
-/* Nonzero if NODE1 and NODE2 are both TREE_LIST nodes and have the
- same purpose (context, which may be a type) and value (template
- decl). See write_template_prefix for more information on what this
- is used for. */
-#define NESTED_TEMPLATE_MATCH(NODE1, NODE2) \
- (TREE_CODE (NODE1) == TREE_LIST \
- && TREE_CODE (NODE2) == TREE_LIST \
- && ((TYPE_P (TREE_PURPOSE (NODE1)) \
- && same_type_p (TREE_PURPOSE (NODE1), TREE_PURPOSE (NODE2))) \
- || TREE_PURPOSE (NODE1) == TREE_PURPOSE (NODE2)) \
- && TREE_VALUE (NODE1) == TREE_VALUE (NODE2))
-
-/* Write out an unsigned quantity in base 10. */
-#define write_unsigned_number(NUMBER) \
- write_number ((NUMBER), /*unsigned_p=*/1, 10)
-
-/* If DECL is a template instance, return nonzero and, if
- TEMPLATE_INFO is non-NULL, set *TEMPLATE_INFO to its template info.
- Otherwise return zero. */
-
-static int
-decl_is_template_id (const tree decl, tree* const template_info)
-{
- if (TREE_CODE (decl) == TYPE_DECL)
- {
- /* TYPE_DECLs are handled specially. Look at its type to decide
- if this is a template instantiation. */
- const tree type = TREE_TYPE (decl);
-
- if (CLASS_TYPE_P (type) && CLASSTYPE_TEMPLATE_ID_P (type))
- {
- if (template_info != NULL)
- /* For a templated TYPE_DECL, the template info is hanging
- off the type. */
- *template_info = TYPE_TEMPLATE_INFO (type);
- return 1;
- }
- }
- else
- {
- /* Check if this is a primary template. */
- if (DECL_LANG_SPECIFIC (decl) != NULL
- && DECL_USE_TEMPLATE (decl)
- && PRIMARY_TEMPLATE_P (DECL_TI_TEMPLATE (decl))
- && TREE_CODE (decl) != TEMPLATE_DECL)
- {
- if (template_info != NULL)
- /* For most templated decls, the template info is hanging
- off the decl. */
- *template_info = DECL_TEMPLATE_INFO (decl);
- return 1;
- }
- }
-
- /* It's not a template id. */
- return 0;
-}
-
-/* Produce debugging output of current substitution candidates. */
-
-static void
-dump_substitution_candidates (void)
-{
- unsigned i;
- tree el;
-
- fprintf (stderr, " ++ substitutions ");
- for (i = 0; VEC_iterate (tree, G.substitutions, i, el); ++i)
- {
- const char *name = "???";
-
- if (i > 0)
- fprintf (stderr, " ");
- if (DECL_P (el))
- name = IDENTIFIER_POINTER (DECL_NAME (el));
- else if (TREE_CODE (el) == TREE_LIST)
- name = IDENTIFIER_POINTER (DECL_NAME (TREE_VALUE (el)));
- else if (TYPE_NAME (el))
- name = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (el)));
- fprintf (stderr, " S%d_ = ", i - 1);
- if (TYPE_P (el) &&
- (CP_TYPE_RESTRICT_P (el)
- || CP_TYPE_VOLATILE_P (el)
- || CP_TYPE_CONST_P (el)))
- fprintf (stderr, "CV-");
- fprintf (stderr, "%s (%s at %p)\n",
- name, tree_code_name[TREE_CODE (el)], (void *) el);
- }
-}
-
-/* Both decls and types can be substitution candidates, but sometimes
- they refer to the same thing. For instance, a TYPE_DECL and
- RECORD_TYPE for the same class refer to the same thing, and should
- be treated accordingly in substitutions. This function returns a
- canonicalized tree node representing NODE that is used when adding
- and substitution candidates and finding matches. */
-
-static inline tree
-canonicalize_for_substitution (tree node)
-{
- /* For a TYPE_DECL, use the type instead. */
- if (TREE_CODE (node) == TYPE_DECL)
- node = TREE_TYPE (node);
- if (TYPE_P (node))
- node = canonical_type_variant (node);
-
- return node;
-}
-
-/* Add NODE as a substitution candidate. NODE must not already be on
- the list of candidates. */
-
-static void
-add_substitution (tree node)
-{
- tree c;
-
- if (DEBUG_MANGLE)
- fprintf (stderr, " ++ add_substitution (%s at %10p)\n",
- tree_code_name[TREE_CODE (node)], (void *) node);
-
- /* Get the canonicalized substitution candidate for NODE. */
- c = canonicalize_for_substitution (node);
- if (DEBUG_MANGLE && c != node)
- fprintf (stderr, " ++ using candidate (%s at %10p)\n",
- tree_code_name[TREE_CODE (node)], (void *) node);
- node = c;
-
-#if ENABLE_CHECKING
- /* Make sure NODE isn't already a candidate. */
- {
- int i;
- tree candidate;
-
- for (i = 0; VEC_iterate (tree, G.substitutions, i, candidate); i++)
- {
- gcc_assert (!(DECL_P (node) && node == candidate));
- gcc_assert (!(TYPE_P (node) && TYPE_P (candidate)
- && same_type_p (node, candidate)));
- }
- }
-#endif /* ENABLE_CHECKING */
-
- /* Put the decl onto the varray of substitution candidates. */
- VEC_safe_push (tree, gc, G.substitutions, node);
-
- if (DEBUG_MANGLE)
- dump_substitution_candidates ();
-}
-
-/* Helper function for find_substitution. Returns nonzero if NODE,
- which may be a decl or a CLASS_TYPE, is a template-id with template
- name of substitution_index[INDEX] in the ::std namespace. */
-
-static inline int
-is_std_substitution (const tree node,
- const substitution_identifier_index_t index)
-{
- tree type = NULL;
- tree decl = NULL;
-
- if (DECL_P (node))
- {
- type = TREE_TYPE (node);
- decl = node;
- }
- else if (CLASS_TYPE_P (node))
- {
- type = node;
- decl = TYPE_NAME (node);
- }
- else
- /* These are not the droids you're looking for. */
- return 0;
-
- return (DECL_NAMESPACE_STD_P (CP_DECL_CONTEXT (decl))
- && TYPE_LANG_SPECIFIC (type)
- && TYPE_TEMPLATE_INFO (type)
- && (DECL_NAME (TYPE_TI_TEMPLATE (type))
- == subst_identifiers[index]));
-}
-
-/* Helper function for find_substitution. Returns nonzero if NODE,
- which may be a decl or a CLASS_TYPE, is the template-id
- ::std::identifier<char>, where identifier is
- substitution_index[INDEX]. */
-
-static inline int
-is_std_substitution_char (const tree node,
- const substitution_identifier_index_t index)
-{
- tree args;
- /* Check NODE's name is ::std::identifier. */
- if (!is_std_substitution (node, index))
- return 0;
- /* Figure out its template args. */
- if (DECL_P (node))
- args = DECL_TI_ARGS (node);
- else if (CLASS_TYPE_P (node))
- args = CLASSTYPE_TI_ARGS (node);
- else
- /* Oops, not a template. */
- return 0;
- /* NODE's template arg list should be <char>. */
- return
- TREE_VEC_LENGTH (args) == 1
- && TREE_VEC_ELT (args, 0) == char_type_node;
-}
-
-/* Check whether a substitution should be used to represent NODE in
- the mangling.
-
- First, check standard special-case substitutions.
-
- <substitution> ::= St
- # ::std
-
- ::= Sa
- # ::std::allocator
-
- ::= Sb
- # ::std::basic_string
-
- ::= Ss
- # ::std::basic_string<char,
- ::std::char_traits<char>,
- ::std::allocator<char> >
-
- ::= Si
- # ::std::basic_istream<char, ::std::char_traits<char> >
-
- ::= So
- # ::std::basic_ostream<char, ::std::char_traits<char> >
-
- ::= Sd
- # ::std::basic_iostream<char, ::std::char_traits<char> >
-
- Then examine the stack of currently available substitution
- candidates for entities appearing earlier in the same mangling
-
- If a substitution is found, write its mangled representation and
- return nonzero. If none is found, just return zero. */
-
-static int
-find_substitution (tree node)
-{
- int i;
- const int size = VEC_length (tree, G.substitutions);
- tree decl;
- tree type;
-
- if (DEBUG_MANGLE)
- fprintf (stderr, " ++ find_substitution (%s at %p)\n",
- tree_code_name[TREE_CODE (node)], (void *) node);
-
- /* Obtain the canonicalized substitution representation for NODE.
- This is what we'll compare against. */
- node = canonicalize_for_substitution (node);
-
- /* Check for builtin substitutions. */
-
- decl = TYPE_P (node) ? TYPE_NAME (node) : node;
- type = TYPE_P (node) ? node : TREE_TYPE (node);
-
- /* Check for std::allocator. */
- if (decl
- && is_std_substitution (decl, SUBID_ALLOCATOR)
- && !CLASSTYPE_USE_TEMPLATE (TREE_TYPE (decl)))
- {
- write_string ("Sa");
- return 1;
- }
-
- /* Check for std::basic_string. */
- if (decl && is_std_substitution (decl, SUBID_BASIC_STRING))
- {
- if (TYPE_P (node))
- {
- /* If this is a type (i.e. a fully-qualified template-id),
- check for
- std::basic_string <char,
- std::char_traits<char>,
- std::allocator<char> > . */
- if (cp_type_quals (type) == TYPE_UNQUALIFIED
- && CLASSTYPE_USE_TEMPLATE (type))
- {
- tree args = CLASSTYPE_TI_ARGS (type);
- if (TREE_VEC_LENGTH (args) == 3
- && same_type_p (TREE_VEC_ELT (args, 0), char_type_node)
- && is_std_substitution_char (TREE_VEC_ELT (args, 1),
- SUBID_CHAR_TRAITS)
- && is_std_substitution_char (TREE_VEC_ELT (args, 2),
- SUBID_ALLOCATOR))
- {
- write_string ("Ss");
- return 1;
- }
- }
- }
- else
- /* Substitute for the template name only if this isn't a type. */
- {
- write_string ("Sb");
- return 1;
- }
- }
-
- /* Check for basic_{i,o,io}stream. */
- if (TYPE_P (node)
- && cp_type_quals (type) == TYPE_UNQUALIFIED
- && CLASS_TYPE_P (type)
- && CLASSTYPE_USE_TEMPLATE (type)
- && CLASSTYPE_TEMPLATE_INFO (type) != NULL)
- {
- /* First, check for the template
- args <char, std::char_traits<char> > . */
- tree args = CLASSTYPE_TI_ARGS (type);
- if (TREE_VEC_LENGTH (args) == 2
- && TYPE_P (TREE_VEC_ELT (args, 0))
- && same_type_p (TREE_VEC_ELT (args, 0), char_type_node)
- && is_std_substitution_char (TREE_VEC_ELT (args, 1),
- SUBID_CHAR_TRAITS))
- {
- /* Got them. Is this basic_istream? */
- if (is_std_substitution (decl, SUBID_BASIC_ISTREAM))
- {
- write_string ("Si");
- return 1;
- }
- /* Or basic_ostream? */
- else if (is_std_substitution (decl, SUBID_BASIC_OSTREAM))
- {
- write_string ("So");
- return 1;
- }
- /* Or basic_iostream? */
- else if (is_std_substitution (decl, SUBID_BASIC_IOSTREAM))
- {
- write_string ("Sd");
- return 1;
- }
- }
- }
-
- /* Check for namespace std. */
- if (decl && DECL_NAMESPACE_STD_P (decl))
- {
- write_string ("St");
- return 1;
- }
-
- /* Now check the list of available substitutions for this mangling
- operation. */
- for (i = 0; i < size; ++i)
- {
- tree candidate = VEC_index (tree, G.substitutions, i);
- /* NODE is a matched to a candidate if it's the same decl node or
- if it's the same type. */
- if (decl == candidate
- || (TYPE_P (candidate) && type && TYPE_P (type)
- && same_type_p (type, candidate))
- || NESTED_TEMPLATE_MATCH (node, candidate))
- {
- write_substitution (i);
- return 1;
- }
- }
-
- /* No substitution found. */
- return 0;
-}
-
-
-/* TOP_LEVEL is true, if this is being called at outermost level of
- mangling. It should be false when mangling a decl appearing in an
- expression within some other mangling.
-
- <mangled-name> ::= _Z <encoding> */
-
-static void
-write_mangled_name (const tree decl, bool top_level)
-{
- MANGLE_TRACE_TREE ("mangled-name", decl);
-
- if (/* The names of `extern "C"' functions are not mangled. */
- DECL_EXTERN_C_FUNCTION_P (decl)
- /* But overloaded operator names *are* mangled. */
- && !DECL_OVERLOADED_OPERATOR_P (decl))
- {
- unmangled_name:;
-
- if (top_level)
- write_string (IDENTIFIER_POINTER (DECL_NAME (decl)));
- else
- {
- /* The standard notes: "The <encoding> of an extern "C"
- function is treated like global-scope data, i.e. as its
- <source-name> without a type." We cannot write
- overloaded operators that way though, because it contains
- characters invalid in assembler. */
- if (abi_version_at_least (2))
- write_string ("_Z");
- else
- G.need_abi_warning = true;
- write_source_name (DECL_NAME (decl));
- }
- }
- else if (TREE_CODE (decl) == VAR_DECL
- /* The names of non-static global variables aren't mangled. */
- && DECL_EXTERNAL_LINKAGE_P (decl)
- && (CP_DECL_CONTEXT (decl) == global_namespace
- /* And neither are `extern "C"' variables. */
- || DECL_EXTERN_C_P (decl)))
- {
- if (top_level || abi_version_at_least (2))
- goto unmangled_name;
- else
- {
- G.need_abi_warning = true;
- goto mangled_name;
- }
- }
- else
- {
- mangled_name:;
- write_string ("_Z");
- write_encoding (decl);
- if (DECL_LANG_SPECIFIC (decl)
- && (DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P (decl)
- || DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (decl)))
- /* We need a distinct mangled name for these entities, but
- we should never actually output it. So, we append some
- characters the assembler won't like. */
- write_string (" *INTERNAL* ");
- }
-}
-
-/* <encoding> ::= <function name> <bare-function-type>
- ::= <data name> */
-
-static void
-write_encoding (const tree decl)
-{
- MANGLE_TRACE_TREE ("encoding", decl);
-
- if (DECL_LANG_SPECIFIC (decl) && DECL_EXTERN_C_FUNCTION_P (decl))
- {
- /* For overloaded operators write just the mangled name
- without arguments. */
- if (DECL_OVERLOADED_OPERATOR_P (decl))
- write_name (decl, /*ignore_local_scope=*/0);
- else
- write_source_name (DECL_NAME (decl));
- return;
- }
-
- write_name (decl, /*ignore_local_scope=*/0);
- if (TREE_CODE (decl) == FUNCTION_DECL)
- {
- tree fn_type;
- tree d;
-
- if (decl_is_template_id (decl, NULL))
- {
- fn_type = get_mostly_instantiated_function_type (decl);
- /* FN_TYPE will not have parameter types for in-charge or
- VTT parameters. Therefore, we pass NULL_TREE to
- write_bare_function_type -- otherwise, it will get
- confused about which artificial parameters to skip. */
- d = NULL_TREE;
- }
- else
- {
- fn_type = TREE_TYPE (decl);
- d = decl;
- }
-
- write_bare_function_type (fn_type,
- (!DECL_CONSTRUCTOR_P (decl)
- && !DECL_DESTRUCTOR_P (decl)
- && !DECL_CONV_FN_P (decl)
- && decl_is_template_id (decl, NULL)),
- d);
- }
-}
-
-/* <name> ::= <unscoped-name>
- ::= <unscoped-template-name> <template-args>
- ::= <nested-name>
- ::= <local-name>
-
- If IGNORE_LOCAL_SCOPE is nonzero, this production of <name> is
- called from <local-name>, which mangles the enclosing scope
- elsewhere and then uses this function to mangle just the part
- underneath the function scope. So don't use the <local-name>
- production, to avoid an infinite recursion. */
-
-static void
-write_name (tree decl, const int ignore_local_scope)
-{
- tree context;
-
- MANGLE_TRACE_TREE ("name", decl);
-
- if (TREE_CODE (decl) == TYPE_DECL)
- {
- /* In case this is a typedef, fish out the corresponding
- TYPE_DECL for the main variant. */
- decl = TYPE_NAME (TYPE_MAIN_VARIANT (TREE_TYPE (decl)));
- context = TYPE_CONTEXT (TYPE_MAIN_VARIANT (TREE_TYPE (decl)));
- }
- else
- context = (DECL_CONTEXT (decl) == NULL) ? NULL : CP_DECL_CONTEXT (decl);
-
- /* A decl in :: or ::std scope is treated specially. The former is
- mangled using <unscoped-name> or <unscoped-template-name>, the
- latter with a special substitution. Also, a name that is
- directly in a local function scope is also mangled with
- <unscoped-name> rather than a full <nested-name>. */
- if (context == NULL
- || context == global_namespace
- || DECL_NAMESPACE_STD_P (context)
- || (ignore_local_scope && TREE_CODE (context) == FUNCTION_DECL))
- {
- tree template_info;
- /* Is this a template instance? */
- if (decl_is_template_id (decl, &template_info))
- {
- /* Yes: use <unscoped-template-name>. */
- write_unscoped_template_name (TI_TEMPLATE (template_info));
- write_template_args (TI_ARGS (template_info));
- }
- else
- /* Everything else gets an <unqualified-name>. */
- write_unscoped_name (decl);
- }
- else
- {
- /* Handle local names, unless we asked not to (that is, invoked
- under <local-name>, to handle only the part of the name under
- the local scope). */
- if (!ignore_local_scope)
- {
- /* Scan up the list of scope context, looking for a
- function. If we find one, this entity is in local
- function scope. local_entity tracks context one scope
- level down, so it will contain the element that's
- directly in that function's scope, either decl or one of
- its enclosing scopes. */
- tree local_entity = decl;
- while (context != NULL && context != global_namespace)
- {
- /* Make sure we're always dealing with decls. */
- if (context != NULL && TYPE_P (context))
- context = TYPE_NAME (context);
- /* Is this a function? */
- if (TREE_CODE (context) == FUNCTION_DECL)
- {
- /* Yes, we have local scope. Use the <local-name>
- production for the innermost function scope. */
- write_local_name (context, local_entity, decl);
- return;
- }
- /* Up one scope level. */
- local_entity = context;
- context = CP_DECL_CONTEXT (context);
- }
-
- /* No local scope found? Fall through to <nested-name>. */
- }
-
- /* Other decls get a <nested-name> to encode their scope. */
- write_nested_name (decl);
- }
-}
-
-/* <unscoped-name> ::= <unqualified-name>
- ::= St <unqualified-name> # ::std:: */
-
-static void
-write_unscoped_name (const tree decl)
-{
- tree context = CP_DECL_CONTEXT (decl);
-
- MANGLE_TRACE_TREE ("unscoped-name", decl);
-
- /* Is DECL in ::std? */
- if (DECL_NAMESPACE_STD_P (context))
- {
- write_string ("St");
- write_unqualified_name (decl);
- }
- else
- {
- /* If not, it should be either in the global namespace, or directly
- in a local function scope. */
- gcc_assert (context == global_namespace
- || context == NULL
- || TREE_CODE (context) == FUNCTION_DECL);
-
- write_unqualified_name (decl);
- }
-}
-
-/* <unscoped-template-name> ::= <unscoped-name>
- ::= <substitution> */
-
-static void
-write_unscoped_template_name (const tree decl)
-{
- MANGLE_TRACE_TREE ("unscoped-template-name", decl);
-
- if (find_substitution (decl))
- return;
- write_unscoped_name (decl);
- add_substitution (decl);
-}
-
-/* Write the nested name, including CV-qualifiers, of DECL.
-
- <nested-name> ::= N [<CV-qualifiers>] <prefix> <unqualified-name> E
- ::= N [<CV-qualifiers>] <template-prefix> <template-args> E
-
- <CV-qualifiers> ::= [r] [V] [K] */
-
-static void
-write_nested_name (const tree decl)
-{
- tree template_info;
-
- MANGLE_TRACE_TREE ("nested-name", decl);
-
- write_char ('N');
-
- /* Write CV-qualifiers, if this is a member function. */
- if (TREE_CODE (decl) == FUNCTION_DECL
- && DECL_NONSTATIC_MEMBER_FUNCTION_P (decl))
- {
- if (DECL_VOLATILE_MEMFUNC_P (decl))
- write_char ('V');
- if (DECL_CONST_MEMFUNC_P (decl))
- write_char ('K');
- }
-
- /* Is this a template instance? */
- if (decl_is_template_id (decl, &template_info))
- {
- /* Yes, use <template-prefix>. */
- write_template_prefix (decl);
- write_template_args (TI_ARGS (template_info));
- }
- else if (TREE_CODE (TREE_TYPE (decl)) == TYPENAME_TYPE)
- {
- tree name = TYPENAME_TYPE_FULLNAME (TREE_TYPE (decl));
- if (TREE_CODE (name) == TEMPLATE_ID_EXPR)
- {
- write_template_prefix (decl);
- write_template_args (TREE_OPERAND (name, 1));
- }
- else
- {
- write_prefix (CP_DECL_CONTEXT (decl));
- write_unqualified_name (decl);
- }
- }
- else
- {
- /* No, just use <prefix> */
- write_prefix (DECL_CONTEXT (decl));
- write_unqualified_name (decl);
- }
- write_char ('E');
-}
-
-/* <prefix> ::= <prefix> <unqualified-name>
- ::= <template-param>
- ::= <template-prefix> <template-args>
- ::= # empty
- ::= <substitution> */
-
-static void
-write_prefix (const tree node)
-{
- tree decl;
- /* Non-NULL if NODE represents a template-id. */
- tree template_info = NULL;
-
- MANGLE_TRACE_TREE ("prefix", node);
-
- if (node == NULL
- || node == global_namespace)
- return;
-
- if (find_substitution (node))
- return;
-
- if (DECL_P (node))
- {
- /* If this is a function decl, that means we've hit function
- scope, so this prefix must be for a local name. In this
- case, we're under the <local-name> production, which encodes
- the enclosing function scope elsewhere. So don't continue
- here. */
- if (TREE_CODE (node) == FUNCTION_DECL)
- return;
-
- decl = node;
- decl_is_template_id (decl, &template_info);
- }
- else
- {
- /* Node is a type. */
- decl = TYPE_NAME (node);
- if (CLASSTYPE_TEMPLATE_ID_P (node))
- template_info = TYPE_TEMPLATE_INFO (node);
- }
-
- /* In G++ 3.2, the name of the template parameter was used. */
- if (TREE_CODE (node) == TEMPLATE_TYPE_PARM
- && !abi_version_at_least (2))
- G.need_abi_warning = true;
-
- if (TREE_CODE (node) == TEMPLATE_TYPE_PARM
- && abi_version_at_least (2))
- write_template_param (node);
- else if (template_info != NULL)
- /* Templated. */
- {
- write_template_prefix (decl);
- write_template_args (TI_ARGS (template_info));
- }
- else if (TREE_CODE (TREE_TYPE (decl)) == TYPENAME_TYPE)
- {
- tree name = TYPENAME_TYPE_FULLNAME (TREE_TYPE (decl));
- if (TREE_CODE (name) == TEMPLATE_ID_EXPR)
- {
- write_template_prefix (decl);
- write_template_args (TREE_OPERAND (name, 1));
- }
- else
- {
- write_prefix (CP_DECL_CONTEXT (decl));
- write_unqualified_name (decl);
- }
- }
- else
- /* Not templated. */
- {
- write_prefix (CP_DECL_CONTEXT (decl));
- write_unqualified_name (decl);
- }
-
- add_substitution (node);
-}
-
-/* <template-prefix> ::= <prefix> <template component>
- ::= <template-param>
- ::= <substitution> */
-
-static void
-write_template_prefix (const tree node)
-{
- tree decl = DECL_P (node) ? node : TYPE_NAME (node);
- tree type = DECL_P (node) ? TREE_TYPE (node) : node;
- tree context = CP_DECL_CONTEXT (decl);
- tree template_info;
- tree templ;
- tree substitution;
-
- MANGLE_TRACE_TREE ("template-prefix", node);
-
- /* Find the template decl. */
- if (decl_is_template_id (decl, &template_info))
- templ = TI_TEMPLATE (template_info);
- else if (TREE_CODE (type) == TYPENAME_TYPE)
- /* For a typename type, all we have is the name. */
- templ = DECL_NAME (decl);
- else
- {
- gcc_assert (CLASSTYPE_TEMPLATE_ID_P (type));
-
- templ = TYPE_TI_TEMPLATE (type);
- }
-
- /* For a member template, though, the template name for the
- innermost name must have all the outer template levels
- instantiated. For instance, consider
-
- template<typename T> struct Outer {
- template<typename U> struct Inner {};
- };
-
- The template name for `Inner' in `Outer<int>::Inner<float>' is
- `Outer<int>::Inner<U>'. In g++, we don't instantiate the template
- levels separately, so there's no TEMPLATE_DECL available for this
- (there's only `Outer<T>::Inner<U>').
-
- In order to get the substitutions right, we create a special
- TREE_LIST to represent the substitution candidate for a nested
- template. The TREE_PURPOSE is the template's context, fully
- instantiated, and the TREE_VALUE is the TEMPLATE_DECL for the inner
- template.
-
- So, for the example above, `Outer<int>::Inner' is represented as a
- substitution candidate by a TREE_LIST whose purpose is `Outer<int>'
- and whose value is `Outer<T>::Inner<U>'. */
- if (TYPE_P (context))
- substitution = build_tree_list (context, templ);
- else
- substitution = templ;
-
- if (find_substitution (substitution))
- return;
-
- /* In G++ 3.2, the name of the template template parameter was used. */
- if (TREE_TYPE (templ)
- && TREE_CODE (TREE_TYPE (templ)) == TEMPLATE_TEMPLATE_PARM
- && !abi_version_at_least (2))
- G.need_abi_warning = true;
-
- if (TREE_TYPE (templ)
- && TREE_CODE (TREE_TYPE (templ)) == TEMPLATE_TEMPLATE_PARM
- && abi_version_at_least (2))
- write_template_param (TREE_TYPE (templ));
- else
- {
- write_prefix (context);
- write_unqualified_name (decl);
- }
-
- add_substitution (substitution);
-}
-
-/* We don't need to handle thunks, vtables, or VTTs here. Those are
- mangled through special entry points.
-
- <unqualified-name> ::= <operator-name>
- ::= <special-name>
- ::= <source-name>
- ::= <local-source-name>
-
- <local-source-name> ::= L <source-name> <discriminator> */
-
-static void
-write_unqualified_name (const tree decl)
-{
- MANGLE_TRACE_TREE ("unqualified-name", decl);
-
- if (DECL_LANG_SPECIFIC (decl) != NULL && DECL_CONSTRUCTOR_P (decl))
- write_special_name_constructor (decl);
- else if (DECL_LANG_SPECIFIC (decl) != NULL && DECL_DESTRUCTOR_P (decl))
- write_special_name_destructor (decl);
- else if (DECL_NAME (decl) == NULL_TREE)
- {
- gcc_assert (DECL_ASSEMBLER_NAME_SET_P (decl));
- write_source_name (DECL_ASSEMBLER_NAME (decl));
- }
- else if (DECL_CONV_FN_P (decl))
- {
- /* Conversion operator. Handle it right here.
- <operator> ::= cv <type> */
- tree type;
- if (decl_is_template_id (decl, NULL))
- {
- tree fn_type;
- fn_type = get_mostly_instantiated_function_type (decl);
- type = TREE_TYPE (fn_type);
- }
- else
- type = DECL_CONV_FN_TYPE (decl);
- write_conversion_operator_name (type);
- }
- else if (DECL_OVERLOADED_OPERATOR_P (decl))
- {
- operator_name_info_t *oni;
- if (DECL_ASSIGNMENT_OPERATOR_P (decl))
- oni = assignment_operator_name_info;
- else
- oni = operator_name_info;
-
- write_string (oni[DECL_OVERLOADED_OPERATOR_P (decl)].mangled_name);
- }
- else if (VAR_OR_FUNCTION_DECL_P (decl) && ! TREE_PUBLIC (decl)
- && DECL_NAMESPACE_SCOPE_P (decl)
- && decl_linkage (decl) == lk_internal)
- {
- MANGLE_TRACE_TREE ("local-source-name", decl);
- write_char ('L');
- write_source_name (DECL_NAME (decl));
- /* The default discriminator is 1, and that's all we ever use,
- so there's no code to output one here. */
- }
- else
- write_source_name (DECL_NAME (decl));
-}
-
-/* Write the unqualified-name for a conversion operator to TYPE. */
-
-static void
-write_conversion_operator_name (const tree type)
-{
- write_string ("cv");
- write_type (type);
-}
-
-/* Non-terminal <source-name>. IDENTIFIER is an IDENTIFIER_NODE.
-
- <source-name> ::= </length/ number> <identifier> */
-
-static void
-write_source_name (tree identifier)
-{
- MANGLE_TRACE_TREE ("source-name", identifier);
-
- /* Never write the whole template-id name including the template
- arguments; we only want the template name. */
- if (IDENTIFIER_TEMPLATE (identifier))
- identifier = IDENTIFIER_TEMPLATE (identifier);
-
- write_unsigned_number (IDENTIFIER_LENGTH (identifier));
- write_identifier (IDENTIFIER_POINTER (identifier));
-}
-
-/* Convert NUMBER to ascii using base BASE and generating at least
- MIN_DIGITS characters. BUFFER points to the _end_ of the buffer
- into which to store the characters. Returns the number of
- characters generated (these will be layed out in advance of where
- BUFFER points). */
-
-static int
-hwint_to_ascii (unsigned HOST_WIDE_INT number, const unsigned int base,
- char *buffer, const unsigned int min_digits)
-{
- static const char base_digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
- unsigned digits = 0;
-
- while (number)
- {
- unsigned HOST_WIDE_INT d = number / base;
-
- *--buffer = base_digits[number - d * base];
- digits++;
- number = d;
- }
- while (digits < min_digits)
- {
- *--buffer = base_digits[0];
- digits++;
- }
- return digits;
-}
-
-/* Non-terminal <number>.
-
- <number> ::= [n] </decimal integer/> */
-
-static void
-write_number (unsigned HOST_WIDE_INT number, const int unsigned_p,
- const unsigned int base)
-{
- char buffer[sizeof (HOST_WIDE_INT) * 8];
- unsigned count = 0;
-
- if (!unsigned_p && (HOST_WIDE_INT) number < 0)
- {
- write_char ('n');
- number = -((HOST_WIDE_INT) number);
- }
- count = hwint_to_ascii (number, base, buffer + sizeof (buffer), 1);
- write_chars (buffer + sizeof (buffer) - count, count);
-}
-
-/* Write out an integral CST in decimal. Most numbers are small, and
- representable in a HOST_WIDE_INT. Occasionally we'll have numbers
- bigger than that, which we must deal with. */
-
-static inline void
-write_integer_cst (const tree cst)
-{
- int sign = tree_int_cst_sgn (cst);
-
- if (TREE_INT_CST_HIGH (cst) + (sign < 0))
- {
- /* A bignum. We do this in chunks, each of which fits in a
- HOST_WIDE_INT. */
- char buffer[sizeof (HOST_WIDE_INT) * 8 * 2];
- unsigned HOST_WIDE_INT chunk;
- unsigned chunk_digits;
- char *ptr = buffer + sizeof (buffer);
- unsigned count = 0;
- tree n, base, type;
- int done;
-
- /* HOST_WIDE_INT must be at least 32 bits, so 10^9 is
- representable. */
- chunk = 1000000000;
- chunk_digits = 9;
-
- if (sizeof (HOST_WIDE_INT) >= 8)
- {
- /* It is at least 64 bits, so 10^18 is representable. */
- chunk_digits = 18;
- chunk *= chunk;
- }
-
- type = c_common_signed_or_unsigned_type (1, TREE_TYPE (cst));
- base = build_int_cstu (type, chunk);
- n = build_int_cst_wide (type,
- TREE_INT_CST_LOW (cst), TREE_INT_CST_HIGH (cst));
-
- if (sign < 0)
- {
- write_char ('n');
- n = fold_build1 (NEGATE_EXPR, type, n);
- }
- do
- {
- tree d = fold_build2 (FLOOR_DIV_EXPR, type, n, base);
- tree tmp = fold_build2 (MULT_EXPR, type, d, base);
- unsigned c;
-
- done = integer_zerop (d);
- tmp = fold_build2 (MINUS_EXPR, type, n, tmp);
- c = hwint_to_ascii (TREE_INT_CST_LOW (tmp), 10, ptr,
- done ? 1 : chunk_digits);
- ptr -= c;
- count += c;
- n = d;
- }
- while (!done);
- write_chars (ptr, count);
- }
- else
- {
- /* A small num. */
- unsigned HOST_WIDE_INT low = TREE_INT_CST_LOW (cst);
-
- if (sign < 0)
- {
- write_char ('n');
- low = -low;
- }
- write_unsigned_number (low);
- }
-}
-
-/* Write out a floating-point literal.
-
- "Floating-point literals are encoded using the bit pattern of the
- target processor's internal representation of that number, as a
- fixed-length lowercase hexadecimal string, high-order bytes first
- (even if the target processor would store low-order bytes first).
- The "n" prefix is not used for floating-point literals; the sign
- bit is encoded with the rest of the number.
-
- Here are some examples, assuming the IEEE standard representation
- for floating point numbers. (Spaces are for readability, not
- part of the encoding.)
-
- 1.0f Lf 3f80 0000 E
- -1.0f Lf bf80 0000 E
- 1.17549435e-38f Lf 0080 0000 E
- 1.40129846e-45f Lf 0000 0001 E
- 0.0f Lf 0000 0000 E"
-
- Caller is responsible for the Lx and the E. */
-static void
-write_real_cst (const tree value)
-{
- if (abi_version_at_least (2))
- {
- long target_real[4]; /* largest supported float */
- char buffer[9]; /* eight hex digits in a 32-bit number */
- int i, limit, dir;
-
- tree type = TREE_TYPE (value);
- int words = GET_MODE_BITSIZE (TYPE_MODE (type)) / 32;
-
- real_to_target (target_real, &TREE_REAL_CST (value),
- TYPE_MODE (type));
-
- /* The value in target_real is in the target word order,
- so we must write it out backward if that happens to be
- little-endian. write_number cannot be used, it will
- produce uppercase. */
- if (FLOAT_WORDS_BIG_ENDIAN)
- i = 0, limit = words, dir = 1;
- else
- i = words - 1, limit = -1, dir = -1;
-
- for (; i != limit; i += dir)
- {
- sprintf (buffer, "%08lx", (unsigned long) target_real[i]);
- write_chars (buffer, 8);
- }
- }
- else
- {
- /* In G++ 3.3 and before the REAL_VALUE_TYPE was written out
- literally. Note that compatibility with 3.2 is impossible,
- because the old floating-point emulator used a different
- format for REAL_VALUE_TYPE. */
- size_t i;
- for (i = 0; i < sizeof (TREE_REAL_CST (value)); ++i)
- write_number (((unsigned char *) &TREE_REAL_CST (value))[i],
- /*unsigned_p*/ 1,
- /*base*/ 16);
- G.need_abi_warning = 1;
- }
-}
-
-/* Non-terminal <identifier>.
-
- <identifier> ::= </unqualified source code identifier> */
-
-static void
-write_identifier (const char *identifier)
-{
- MANGLE_TRACE ("identifier", identifier);
- write_string (identifier);
-}
-
-/* Handle constructor productions of non-terminal <special-name>.
- CTOR is a constructor FUNCTION_DECL.
-
- <special-name> ::= C1 # complete object constructor
- ::= C2 # base object constructor
- ::= C3 # complete object allocating constructor
-
- Currently, allocating constructors are never used.
-
- We also need to provide mangled names for the maybe-in-charge
- constructor, so we treat it here too. mangle_decl_string will
- append *INTERNAL* to that, to make sure we never emit it. */
-
-static void
-write_special_name_constructor (const tree ctor)
-{
- if (DECL_BASE_CONSTRUCTOR_P (ctor))
- write_string ("C2");
- else
- {
- gcc_assert (DECL_COMPLETE_CONSTRUCTOR_P (ctor)
- /* Even though we don't ever emit a definition of
- the old-style destructor, we still have to
- consider entities (like static variables) nested
- inside it. */
- || DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (ctor));
- write_string ("C1");
- }
-}
-
-/* Handle destructor productions of non-terminal <special-name>.
- DTOR is a destructor FUNCTION_DECL.
-
- <special-name> ::= D0 # deleting (in-charge) destructor
- ::= D1 # complete object (in-charge) destructor
- ::= D2 # base object (not-in-charge) destructor
-
- We also need to provide mangled names for the maybe-incharge
- destructor, so we treat it here too. mangle_decl_string will
- append *INTERNAL* to that, to make sure we never emit it. */
-
-static void
-write_special_name_destructor (const tree dtor)
-{
- if (DECL_DELETING_DESTRUCTOR_P (dtor))
- write_string ("D0");
- else if (DECL_BASE_DESTRUCTOR_P (dtor))
- write_string ("D2");
- else
- {
- gcc_assert (DECL_COMPLETE_DESTRUCTOR_P (dtor)
- /* Even though we don't ever emit a definition of
- the old-style destructor, we still have to
- consider entities (like static variables) nested
- inside it. */
- || DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P (dtor));
- write_string ("D1");
- }
-}
-
-/* Return the discriminator for ENTITY appearing inside
- FUNCTION. The discriminator is the lexical ordinal of VAR among
- entities with the same name in the same FUNCTION. */
-
-static int
-discriminator_for_local_entity (tree entity)
-{
- /* Assume this is the only local entity with this name. */
- int discriminator = 0;
-
- if (DECL_DISCRIMINATOR_P (entity) && DECL_LANG_SPECIFIC (entity))
- discriminator = DECL_DISCRIMINATOR (entity);
- else if (TREE_CODE (entity) == TYPE_DECL)
- {
- int ix;
-
- /* Scan the list of local classes. */
- entity = TREE_TYPE (entity);
- for (ix = 0; ; ix++)
- {
- tree type = VEC_index (tree, local_classes, ix);
- if (type == entity)
- break;
- if (TYPE_IDENTIFIER (type) == TYPE_IDENTIFIER (entity)
- && TYPE_CONTEXT (type) == TYPE_CONTEXT (entity))
- ++discriminator;
- }
- }
-
- return discriminator;
-}
-
-/* Return the discriminator for STRING, a string literal used inside
- FUNCTION. The discriminator is the lexical ordinal of STRING among
- string literals used in FUNCTION. */
-
-static int
-discriminator_for_string_literal (tree function ATTRIBUTE_UNUSED,
- tree string ATTRIBUTE_UNUSED)
-{
- /* For now, we don't discriminate amongst string literals. */
- return 0;
-}
-
-/* <discriminator> := _ <number>
-
- The discriminator is used only for the second and later occurrences
- of the same name within a single function. In this case <number> is
- n - 2, if this is the nth occurrence, in lexical order. */
-
-static void
-write_discriminator (const int discriminator)
-{
- /* If discriminator is zero, don't write anything. Otherwise... */
- if (discriminator > 0)
- {
- write_char ('_');
- write_unsigned_number (discriminator - 1);
- }
-}
-
-/* Mangle the name of a function-scope entity. FUNCTION is the
- FUNCTION_DECL for the enclosing function. ENTITY is the decl for
- the entity itself. LOCAL_ENTITY is the entity that's directly
- scoped in FUNCTION_DECL, either ENTITY itself or an enclosing scope
- of ENTITY.
-
- <local-name> := Z <function encoding> E <entity name> [<discriminator>]
- := Z <function encoding> E s [<discriminator>] */
-
-static void
-write_local_name (const tree function, const tree local_entity,
- const tree entity)
-{
- MANGLE_TRACE_TREE ("local-name", entity);
-
- write_char ('Z');
- write_encoding (function);
- write_char ('E');
- if (TREE_CODE (entity) == STRING_CST)
- {
- write_char ('s');
- write_discriminator (discriminator_for_string_literal (function,
- entity));
- }
- else
- {
- /* Now the <entity name>. Let write_name know its being called
- from <local-name>, so it doesn't try to process the enclosing
- function scope again. */
- write_name (entity, /*ignore_local_scope=*/1);
- write_discriminator (discriminator_for_local_entity (local_entity));
- }
-}
-
-/* Non-terminals <type> and <CV-qualifier>.
-
- <type> ::= <builtin-type>
- ::= <function-type>
- ::= <class-enum-type>
- ::= <array-type>
- ::= <pointer-to-member-type>
- ::= <template-param>
- ::= <substitution>
- ::= <CV-qualifier>
- ::= P <type> # pointer-to
- ::= R <type> # reference-to
- ::= C <type> # complex pair (C 2000)
- ::= G <type> # imaginary (C 2000) [not supported]
- ::= U <source-name> <type> # vendor extended type qualifier
-
- C++0x extensions
-
- <type> ::= RR <type> # rvalue reference-to
- <type> ::= Dt <expression> # decltype of an id-expression or
- # class member access
- <type> ::= DT <expression> # decltype of an expression
-
- TYPE is a type node. */
-
-static void
-write_type (tree type)
-{
- /* This gets set to nonzero if TYPE turns out to be a (possibly
- CV-qualified) builtin type. */
- int is_builtin_type = 0;
-
- MANGLE_TRACE_TREE ("type", type);
-
- if (type == error_mark_node)
- return;
-
- if (find_substitution (type))
- return;
-
- if (write_CV_qualifiers_for_type (type) > 0)
- /* If TYPE was CV-qualified, we just wrote the qualifiers; now
- mangle the unqualified type. The recursive call is needed here
- since both the qualified and unqualified types are substitution
- candidates. */
- write_type (TYPE_MAIN_VARIANT (type));
- else if (TREE_CODE (type) == ARRAY_TYPE)
- /* It is important not to use the TYPE_MAIN_VARIANT of TYPE here
- so that the cv-qualification of the element type is available
- in write_array_type. */
- write_array_type (type);
- else
- {
- tree type_orig = type;
-
- /* See through any typedefs. */
- type = TYPE_MAIN_VARIANT (type);
-
- if (TYPE_PTRMEM_P (type))
- write_pointer_to_member_type (type);
- else
- {
- /* Handle any target-specific fundamental types. */
- const char *target_mangling
- = targetm.mangle_type (type_orig);
-
- if (target_mangling)
- {
- write_string (target_mangling);
- /* Add substitutions for types other than fundamental
- types. */
- if (TREE_CODE (type) != VOID_TYPE
- && TREE_CODE (type) != INTEGER_TYPE
- && TREE_CODE (type) != REAL_TYPE
- && TREE_CODE (type) != BOOLEAN_TYPE)
- add_substitution (type);
- return;
- }
-
- switch (TREE_CODE (type))
- {
- case VOID_TYPE:
- case BOOLEAN_TYPE:
- case INTEGER_TYPE: /* Includes wchar_t. */
- case REAL_TYPE:
- case FIXED_POINT_TYPE:
- {
- /* If this is a typedef, TYPE may not be one of
- the standard builtin type nodes, but an alias of one. Use
- TYPE_MAIN_VARIANT to get to the underlying builtin type. */
- write_builtin_type (TYPE_MAIN_VARIANT (type));
- ++is_builtin_type;
- }
- break;
-
- case COMPLEX_TYPE:
- write_char ('C');
- write_type (TREE_TYPE (type));
- break;
-
- case FUNCTION_TYPE:
- case METHOD_TYPE:
- write_function_type (type);
- break;
-
- case UNION_TYPE:
- case RECORD_TYPE:
- case ENUMERAL_TYPE:
- /* A pointer-to-member function is represented as a special
- RECORD_TYPE, so check for this first. */
- if (TYPE_PTRMEMFUNC_P (type))
- write_pointer_to_member_type (type);
- else
- write_class_enum_type (type);
- break;
-
- case TYPENAME_TYPE:
- case UNBOUND_CLASS_TEMPLATE:
- /* We handle TYPENAME_TYPEs and UNBOUND_CLASS_TEMPLATEs like
- ordinary nested names. */
- write_nested_name (TYPE_STUB_DECL (type));
- break;
-
- case POINTER_TYPE:
- write_char ('P');
- write_type (TREE_TYPE (type));
- break;
-
- case REFERENCE_TYPE:
- if (TYPE_REF_IS_RVALUE (type))
- write_char('O');
- else
- write_char ('R');
- write_type (TREE_TYPE (type));
- break;
-
- case TEMPLATE_TYPE_PARM:
- case TEMPLATE_PARM_INDEX:
- write_template_param (type);
- break;
-
- case TEMPLATE_TEMPLATE_PARM:
- write_template_template_param (type);
- break;
-
- case BOUND_TEMPLATE_TEMPLATE_PARM:
- write_template_template_param (type);
- write_template_args
- (TI_ARGS (TEMPLATE_TEMPLATE_PARM_TEMPLATE_INFO (type)));
- break;
-
- case VECTOR_TYPE:
- write_string ("U8__vector");
- write_type (TREE_TYPE (type));
- break;
-
- case TYPE_PACK_EXPANSION:
- write_string ("Dp");
- write_type (PACK_EXPANSION_PATTERN (type));
- break;
-
- case DECLTYPE_TYPE:
- write_char ('D');
- if (DECLTYPE_TYPE_ID_EXPR_OR_MEMBER_ACCESS_P (type))
- write_char ('t');
- else
- write_char ('T');
- ++skip_evaluation;
- write_expression (DECLTYPE_TYPE_EXPR (type));
- --skip_evaluation;
- write_char ('E');
- break;
-
- case TYPEOF_TYPE:
- sorry ("mangling typeof, use decltype instead");
- break;
-
- default:
- gcc_unreachable ();
- }
- }
- }
-
- /* Types other than builtin types are substitution candidates. */
- if (!is_builtin_type)
- add_substitution (type);
-}
-
-/* Non-terminal <CV-qualifiers> for type nodes. Returns the number of
- CV-qualifiers written for TYPE.
-
- <CV-qualifiers> ::= [r] [V] [K] */
-
-static int
-write_CV_qualifiers_for_type (const tree type)
-{
- int num_qualifiers = 0;
-
- /* The order is specified by:
-
- "In cases where multiple order-insensitive qualifiers are
- present, they should be ordered 'K' (closest to the base type),
- 'V', 'r', and 'U' (farthest from the base type) ..."
-
- Note that we do not use cp_type_quals below; given "const
- int[3]", the "const" is emitted with the "int", not with the
- array. */
-
- if (TYPE_QUALS (type) & TYPE_QUAL_RESTRICT)
- {
- write_char ('r');
- ++num_qualifiers;
- }
- if (TYPE_QUALS (type) & TYPE_QUAL_VOLATILE)
- {
- write_char ('V');
- ++num_qualifiers;
- }
- if (TYPE_QUALS (type) & TYPE_QUAL_CONST)
- {
- write_char ('K');
- ++num_qualifiers;
- }
-
- return num_qualifiers;
-}
-
-/* Non-terminal <builtin-type>.
-
- <builtin-type> ::= v # void
- ::= b # bool
- ::= w # wchar_t
- ::= c # char
- ::= a # signed char
- ::= h # unsigned char
- ::= s # short
- ::= t # unsigned short
- ::= i # int
- ::= j # unsigned int
- ::= l # long
- ::= m # unsigned long
- ::= x # long long, __int64
- ::= y # unsigned long long, __int64
- ::= n # __int128
- ::= o # unsigned __int128
- ::= f # float
- ::= d # double
- ::= e # long double, __float80
- ::= g # __float128 [not supported]
- ::= u <source-name> # vendor extended type */
-
-static void
-write_builtin_type (tree type)
-{
- if (TYPE_CANONICAL (type))
- type = TYPE_CANONICAL (type);
-
- switch (TREE_CODE (type))
- {
- case VOID_TYPE:
- write_char ('v');
- break;
-
- case BOOLEAN_TYPE:
- write_char ('b');
- break;
-
- case INTEGER_TYPE:
- /* TYPE may still be wchar_t, char16_t, or char32_t, since that
- isn't in integer_type_nodes. */
- if (type == wchar_type_node)
- write_char ('w');
- else if (type == char16_type_node)
- write_string ("Ds");
- else if (type == char32_type_node)
- write_string ("Di");
- else if (TYPE_FOR_JAVA (type))
- write_java_integer_type_codes (type);
- else
- {
- size_t itk;
- /* Assume TYPE is one of the shared integer type nodes. Find
- it in the array of these nodes. */
- iagain:
- for (itk = 0; itk < itk_none; ++itk)
- if (type == integer_types[itk])
- {
- /* Print the corresponding single-letter code. */
- write_char (integer_type_codes[itk]);
- break;
- }
-
- if (itk == itk_none)
- {
- tree t = c_common_type_for_mode (TYPE_MODE (type),
- TYPE_UNSIGNED (type));
- if (type != t)
- {
- type = t;
- goto iagain;
- }
-
- if (TYPE_PRECISION (type) == 128)
- write_char (TYPE_UNSIGNED (type) ? 'o' : 'n');
- else
- {
- /* Allow for cases where TYPE is not one of the shared
- integer type nodes and write a "vendor extended builtin
- type" with a name the form intN or uintN, respectively.
- Situations like this can happen if you have an
- __attribute__((__mode__(__SI__))) type and use exotic
- switches like '-mint8' on AVR. Of course, this is
- undefined by the C++ ABI (and '-mint8' is not even
- Standard C conforming), but when using such special
- options you're pretty much in nowhere land anyway. */
- const char *prefix;
- char prec[11]; /* up to ten digits for an unsigned */
-
- prefix = TYPE_UNSIGNED (type) ? "uint" : "int";
- sprintf (prec, "%u", (unsigned) TYPE_PRECISION (type));
- write_char ('u'); /* "vendor extended builtin type" */
- write_unsigned_number (strlen (prefix) + strlen (prec));
- write_string (prefix);
- write_string (prec);
- }
- }
- }
- break;
-
- case REAL_TYPE:
- if (type == float_type_node
- || type == java_float_type_node)
- write_char ('f');
- else if (type == double_type_node
- || type == java_double_type_node)
- write_char ('d');
- else if (type == long_double_type_node)
- write_char ('e');
- else
- gcc_unreachable ();
- break;
-
- case FIXED_POINT_TYPE:
- write_string ("DF");
- if (GET_MODE_IBIT (TYPE_MODE (type)) > 0)
- write_unsigned_number (GET_MODE_IBIT (TYPE_MODE (type)));
- if (type == fract_type_node
- || type == sat_fract_type_node
- || type == accum_type_node
- || type == sat_accum_type_node)
- write_char ('i');
- else if (type == unsigned_fract_type_node
- || type == sat_unsigned_fract_type_node
- || type == unsigned_accum_type_node
- || type == sat_unsigned_accum_type_node)
- write_char ('j');
- else if (type == short_fract_type_node
- || type == sat_short_fract_type_node
- || type == short_accum_type_node
- || type == sat_short_accum_type_node)
- write_char ('s');
- else if (type == unsigned_short_fract_type_node
- || type == sat_unsigned_short_fract_type_node
- || type == unsigned_short_accum_type_node
- || type == sat_unsigned_short_accum_type_node)
- write_char ('t');
- else if (type == long_fract_type_node
- || type == sat_long_fract_type_node
- || type == long_accum_type_node
- || type == sat_long_accum_type_node)
- write_char ('l');
- else if (type == unsigned_long_fract_type_node
- || type == sat_unsigned_long_fract_type_node
- || type == unsigned_long_accum_type_node
- || type == sat_unsigned_long_accum_type_node)
- write_char ('m');
- else if (type == long_long_fract_type_node
- || type == sat_long_long_fract_type_node
- || type == long_long_accum_type_node
- || type == sat_long_long_accum_type_node)
- write_char ('x');
- else if (type == unsigned_long_long_fract_type_node
- || type == sat_unsigned_long_long_fract_type_node
- || type == unsigned_long_long_accum_type_node
- || type == sat_unsigned_long_long_accum_type_node)
- write_char ('y');
- else
- sorry ("mangling unknown fixed point type");
- write_unsigned_number (GET_MODE_FBIT (TYPE_MODE (type)));
- if (TYPE_SATURATING (type))
- write_char ('s');
- else
- write_char ('n');
- break;
-
- default:
- gcc_unreachable ();
- }
-}
-
-/* Non-terminal <function-type>. NODE is a FUNCTION_TYPE or
- METHOD_TYPE. The return type is mangled before the parameter
- types.
-
- <function-type> ::= F [Y] <bare-function-type> E */
-
-static void
-write_function_type (const tree type)
-{
- MANGLE_TRACE_TREE ("function-type", type);
-
- /* For a pointer to member function, the function type may have
- cv-qualifiers, indicating the quals for the artificial 'this'
- parameter. */
- if (TREE_CODE (type) == METHOD_TYPE)
- {
- /* The first parameter must be a POINTER_TYPE pointing to the
- `this' parameter. */
- tree this_type = TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (type)));
- write_CV_qualifiers_for_type (this_type);
- }
-
- write_char ('F');
- /* We don't track whether or not a type is `extern "C"'. Note that
- you can have an `extern "C"' function that does not have
- `extern "C"' type, and vice versa:
-
- extern "C" typedef void function_t();
- function_t f; // f has C++ linkage, but its type is
- // `extern "C"'
-
- typedef void function_t();
- extern "C" function_t f; // Vice versa.
-
- See [dcl.link]. */
- write_bare_function_type (type, /*include_return_type_p=*/1,
- /*decl=*/NULL);
- write_char ('E');
-}
-
-/* Non-terminal <bare-function-type>. TYPE is a FUNCTION_TYPE or
- METHOD_TYPE. If INCLUDE_RETURN_TYPE is nonzero, the return value
- is mangled before the parameter types. If non-NULL, DECL is
- FUNCTION_DECL for the function whose type is being emitted.
-
- If DECL is a member of a Java type, then a literal 'J'
- is output and the return type is mangled as if INCLUDE_RETURN_TYPE
- were nonzero.
-
- <bare-function-type> ::= [J]</signature/ type>+ */
-
-static void
-write_bare_function_type (const tree type, const int include_return_type_p,
- const tree decl)
-{
- int java_method_p;
-
- MANGLE_TRACE_TREE ("bare-function-type", type);
-
- /* Detect Java methods and emit special encoding. */
- if (decl != NULL
- && DECL_FUNCTION_MEMBER_P (decl)
- && TYPE_FOR_JAVA (DECL_CONTEXT (decl))
- && !DECL_CONSTRUCTOR_P (decl)
- && !DECL_DESTRUCTOR_P (decl)
- && !DECL_CONV_FN_P (decl))
- {
- java_method_p = 1;
- write_char ('J');
- }
- else
- {
- java_method_p = 0;
- }
-
- /* Mangle the return type, if requested. */
- if (include_return_type_p || java_method_p)
- write_type (TREE_TYPE (type));
-
- /* Now mangle the types of the arguments. */
- write_method_parms (TYPE_ARG_TYPES (type),
- TREE_CODE (type) == METHOD_TYPE,
- decl);
-}
-
-/* Write the mangled representation of a method parameter list of
- types given in PARM_TYPES. If METHOD_P is nonzero, the function is
- considered a non-static method, and the this parameter is omitted.
- If non-NULL, DECL is the FUNCTION_DECL for the function whose
- parameters are being emitted. */
-
-static void
-write_method_parms (tree parm_types, const int method_p, const tree decl)
-{
- tree first_parm_type;
- tree parm_decl = decl ? DECL_ARGUMENTS (decl) : NULL_TREE;
-
- /* Assume this parameter type list is variable-length. If it ends
- with a void type, then it's not. */
- int varargs_p = 1;
-
- /* If this is a member function, skip the first arg, which is the
- this pointer.
- "Member functions do not encode the type of their implicit this
- parameter."
-
- Similarly, there's no need to mangle artificial parameters, like
- the VTT parameters for constructors and destructors. */
- if (method_p)
- {
- parm_types = TREE_CHAIN (parm_types);
- parm_decl = parm_decl ? TREE_CHAIN (parm_decl) : NULL_TREE;
-
- while (parm_decl && DECL_ARTIFICIAL (parm_decl))
- {
- parm_types = TREE_CHAIN (parm_types);
- parm_decl = TREE_CHAIN (parm_decl);
- }
- }
-
- for (first_parm_type = parm_types;
- parm_types;
- parm_types = TREE_CHAIN (parm_types))
- {
- tree parm = TREE_VALUE (parm_types);
- if (parm == void_type_node)
- {
- /* "Empty parameter lists, whether declared as () or
- conventionally as (void), are encoded with a void parameter
- (v)." */
- if (parm_types == first_parm_type)
- write_type (parm);
- /* If the parm list is terminated with a void type, it's
- fixed-length. */
- varargs_p = 0;
- /* A void type better be the last one. */
- gcc_assert (TREE_CHAIN (parm_types) == NULL);
- }
- else
- write_type (parm);
- }
-
- if (varargs_p)
- /* <builtin-type> ::= z # ellipsis */
- write_char ('z');
-}
-
-/* <class-enum-type> ::= <name> */
-
-static void
-write_class_enum_type (const tree type)
-{
- write_name (TYPE_NAME (type), /*ignore_local_scope=*/0);
-}
-
-/* Non-terminal <template-args>. ARGS is a TREE_VEC of template
- arguments.
-
- <template-args> ::= I <template-arg>* E */
-
-static void
-write_template_args (tree args)
-{
- int i;
- int length = 0;
-
- MANGLE_TRACE_TREE ("template-args", args);
-
- write_char ('I');
-
- if (args)
- length = TREE_VEC_LENGTH (args);
-
- if (args && TREE_CODE (TREE_VEC_ELT (args, 0)) == TREE_VEC)
- {
- /* We have nested template args. We want the innermost template
- argument list. */
- args = TREE_VEC_ELT (args, length - 1);
- length = TREE_VEC_LENGTH (args);
- }
- for (i = 0; i < length; ++i)
- write_template_arg (TREE_VEC_ELT (args, i));
-
- write_char ('E');
-}
-
-/* Write out the
- <unqualified-name>
- <unqualified-name> <template-args>
- part of SCOPE_REF or COMPONENT_REF mangling. */
-
-static void
-write_member_name (tree member)
-{
- if (TREE_CODE (member) == IDENTIFIER_NODE)
- write_source_name (member);
- else if (DECL_P (member))
- write_unqualified_name (member);
- else if (TREE_CODE (member) == TEMPLATE_ID_EXPR)
- {
- tree name = TREE_OPERAND (member, 0);
- if (TREE_CODE (name) == OVERLOAD)
- name = OVL_FUNCTION (name);
- write_member_name (name);
- write_template_args (TREE_OPERAND (member, 1));
- }
- else
- write_expression (member);
-}
-
-/* <expression> ::= <unary operator-name> <expression>
- ::= <binary operator-name> <expression> <expression>
- ::= <expr-primary>
-
- <expr-primary> ::= <template-param>
- ::= L <type> <value number> E # literal
- ::= L <mangled-name> E # external name
- ::= st <type> # sizeof
- ::= sr <type> <unqualified-name> # dependent name
- ::= sr <type> <unqualified-name> <template-args> */
-
-static void
-write_expression (tree expr)
-{
- enum tree_code code = TREE_CODE (expr);
-
- /* Skip NOP_EXPRs. They can occur when (say) a pointer argument
- is converted (via qualification conversions) to another
- type. */
- while (TREE_CODE (expr) == NOP_EXPR
- || TREE_CODE (expr) == NON_LVALUE_EXPR)
- {
- expr = TREE_OPERAND (expr, 0);
- code = TREE_CODE (expr);
- }
-
- if (code == BASELINK)
- {
- expr = BASELINK_FUNCTIONS (expr);
- code = TREE_CODE (expr);
- }
-
- /* Handle pointers-to-members by making them look like expression
- nodes. */
- if (code == PTRMEM_CST)
- {
- expr = build_nt (ADDR_EXPR,
- build_qualified_name (/*type=*/NULL_TREE,
- PTRMEM_CST_CLASS (expr),
- PTRMEM_CST_MEMBER (expr),
- /*template_p=*/false));
- code = TREE_CODE (expr);
- }
-
- /* Handle template parameters. */
- if (code == TEMPLATE_TYPE_PARM
- || code == TEMPLATE_TEMPLATE_PARM
- || code == BOUND_TEMPLATE_TEMPLATE_PARM
- || code == TEMPLATE_PARM_INDEX)
- write_template_param (expr);
- /* Handle literals. */
- else if (TREE_CODE_CLASS (code) == tcc_constant
- || (abi_version_at_least (2) && code == CONST_DECL))
- write_template_arg_literal (expr);
- else if (code == PARM_DECL)
- {
- /* A function parameter used in a late-specified return type. */
- int index = parm_index (expr);
- write_string ("fp");
- if (index > 1)
- write_unsigned_number (index - 2);
- write_char ('_');
- }
- else if (DECL_P (expr))
- {
- /* G++ 3.2 incorrectly mangled non-type template arguments of
- enumeration type using their names. */
- if (code == CONST_DECL)
- G.need_abi_warning = 1;
- write_char ('L');
- write_mangled_name (expr, false);
- write_char ('E');
- }
- else if (TREE_CODE (expr) == SIZEOF_EXPR
- && TYPE_P (TREE_OPERAND (expr, 0)))
- {
- write_string ("st");
- write_type (TREE_OPERAND (expr, 0));
- }
- else if (TREE_CODE (expr) == ALIGNOF_EXPR
- && TYPE_P (TREE_OPERAND (expr, 0)))
- {
- write_string ("at");
- write_type (TREE_OPERAND (expr, 0));
- }
- else if (TREE_CODE (expr) == SCOPE_REF)
- {
- tree scope = TREE_OPERAND (expr, 0);
- tree member = TREE_OPERAND (expr, 1);
-
- if (!abi_version_at_least (2))
- {
- write_string ("sr");
- write_type (scope);
- /* G++ 3.2 incorrectly put out both the "sr" code and
- the nested name of the qualified name. */
- G.need_abi_warning = 1;
- write_encoding (member);
- }
-
- /* If the MEMBER is a real declaration, then the qualifying
- scope was not dependent. Ideally, we would not have a
- SCOPE_REF in those cases, but sometimes we do. If the second
- argument is a DECL, then the name must not have been
- dependent. */
- else if (DECL_P (member))
- write_expression (member);
- else
- {
- tree template_args;
-
- write_string ("sr");
- write_type (scope);
- /* If MEMBER is a template-id, separate the template
- from the arguments. */
- if (TREE_CODE (member) == TEMPLATE_ID_EXPR)
- {
- template_args = TREE_OPERAND (member, 1);
- member = TREE_OPERAND (member, 0);
- }
- else
- template_args = NULL_TREE;
- /* Write out the name of the MEMBER. */
- if (IDENTIFIER_TYPENAME_P (member))
- write_conversion_operator_name (TREE_TYPE (member));
- else if (IDENTIFIER_OPNAME_P (member))
- {
- int i;
- const char *mangled_name = NULL;
-
- /* Unfortunately, there is no easy way to go from the
- name of the operator back to the corresponding tree
- code. */
- for (i = 0; i < MAX_TREE_CODES; ++i)
- if (operator_name_info[i].identifier == member)
- {
- /* The ABI says that we prefer binary operator
- names to unary operator names. */
- if (operator_name_info[i].arity == 2)
- {
- mangled_name = operator_name_info[i].mangled_name;
- break;
- }
- else if (!mangled_name)
- mangled_name = operator_name_info[i].mangled_name;
- }
- else if (assignment_operator_name_info[i].identifier
- == member)
- {
- mangled_name
- = assignment_operator_name_info[i].mangled_name;
- break;
- }
- write_string (mangled_name);
- }
- else
- write_source_name (member);
- /* Write out the template arguments. */
- if (template_args)
- write_template_args (template_args);
- }
- }
- else if (TREE_CODE (expr) == INDIRECT_REF
- && TREE_TYPE (TREE_OPERAND (expr, 0))
- && TREE_CODE (TREE_TYPE (TREE_OPERAND (expr, 0))) == REFERENCE_TYPE)
- {
- write_expression (TREE_OPERAND (expr, 0));
- }
- else
- {
- int i;
- const char *name;
-
- /* When we bind a variable or function to a non-type template
- argument with reference type, we create an ADDR_EXPR to show
- the fact that the entity's address has been taken. But, we
- don't actually want to output a mangling code for the `&'. */
- if (TREE_CODE (expr) == ADDR_EXPR
- && TREE_TYPE (expr)
- && TREE_CODE (TREE_TYPE (expr)) == REFERENCE_TYPE)
- {
- expr = TREE_OPERAND (expr, 0);
- if (DECL_P (expr))
- {
- write_expression (expr);
- return;
- }
-
- code = TREE_CODE (expr);
- }
-
- if (code == COMPONENT_REF)
- {
- tree ob = TREE_OPERAND (expr, 0);
-
- if (TREE_CODE (ob) == ARROW_EXPR)
- {
- write_string (operator_name_info[(int)code].mangled_name);
- ob = TREE_OPERAND (ob, 0);
- }
- else
- write_string ("dt");
-
- write_expression (ob);
- write_member_name (TREE_OPERAND (expr, 1));
- return;
- }
-
- /* If it wasn't any of those, recursively expand the expression. */
- name = operator_name_info[(int) code].mangled_name;
- if (name == NULL)
- {
- sorry ("mangling %C", code);
- return;
- }
- else
- write_string (name);
-
- switch (code)
- {
- case CALL_EXPR:
- {
- tree fn = CALL_EXPR_FN (expr);
-
- if (TREE_CODE (fn) == ADDR_EXPR)
- fn = TREE_OPERAND (fn, 0);
-
- /* Mangle a dependent name as the name, not whatever happens to
- be the first function in the overload set. */
- if ((TREE_CODE (fn) == FUNCTION_DECL
- || TREE_CODE (fn) == OVERLOAD)
- && type_dependent_expression_p_push (expr))
- fn = DECL_NAME (get_first_fn (fn));
-
- if (TREE_CODE (fn) == IDENTIFIER_NODE)
- write_source_name (fn);
- else
- write_expression (fn);
- }
-
- for (i = 0; i < call_expr_nargs (expr); ++i)
- write_expression (CALL_EXPR_ARG (expr, i));
- write_char ('E');
- break;
-
- case CAST_EXPR:
- write_type (TREE_TYPE (expr));
- if (list_length (TREE_OPERAND (expr, 0)) == 1)
- write_expression (TREE_VALUE (TREE_OPERAND (expr, 0)));
- else
- {
- tree args = TREE_OPERAND (expr, 0);
- write_char ('_');
- for (; args; args = TREE_CHAIN (args))
- write_expression (TREE_VALUE (args));
- write_char ('E');
- }
- break;
-
- /* FIXME these should have a distinct mangling. */
- case STATIC_CAST_EXPR:
- case CONST_CAST_EXPR:
- write_type (TREE_TYPE (expr));
- write_expression (TREE_OPERAND (expr, 0));
- break;
-
- case NEW_EXPR:
- sorry ("mangling new-expression");
- break;
-
- default:
- for (i = 0; i < TREE_OPERAND_LENGTH (expr); ++i)
- {
- tree operand = TREE_OPERAND (expr, i);
- /* As a GNU extension, the middle operand of a
- conditional may be omitted. Since expression
- manglings are supposed to represent the input token
- stream, there's no good way to mangle such an
- expression without extending the C++ ABI. */
- if (code == COND_EXPR && i == 1 && !operand)
- {
- error ("omitted middle operand to %<?:%> operand "
- "cannot be mangled");
- continue;
- }
- write_expression (operand);
- }
- }
- }
-}
-
-/* Literal subcase of non-terminal <template-arg>.
-
- "Literal arguments, e.g. "A<42L>", are encoded with their type
- and value. Negative integer values are preceded with "n"; for
- example, "A<-42L>" becomes "1AILln42EE". The bool value false is
- encoded as 0, true as 1." */
-
-static void
-write_template_arg_literal (const tree value)
-{
- write_char ('L');
- write_type (TREE_TYPE (value));
-
- switch (TREE_CODE (value))
- {
- case CONST_DECL:
- write_integer_cst (DECL_INITIAL (value));
- break;
-
- case INTEGER_CST:
- gcc_assert (!same_type_p (TREE_TYPE (value), boolean_type_node)
- || integer_zerop (value) || integer_onep (value));
- write_integer_cst (value);
- break;
-
- case REAL_CST:
- write_real_cst (value);
- break;
-
- default:
- gcc_unreachable ();
- }
-
- write_char ('E');
-}
-
-/* Non-terminal <template-arg>.
-
- <template-arg> ::= <type> # type
- ::= L <type> </value/ number> E # literal
- ::= LZ <name> E # external name
- ::= X <expression> E # expression */
-
-static void
-write_template_arg (tree node)
-{
- enum tree_code code = TREE_CODE (node);
-
- MANGLE_TRACE_TREE ("template-arg", node);
-
- /* A template template parameter's argument list contains TREE_LIST
- nodes of which the value field is the actual argument. */
- if (code == TREE_LIST)
- {
- node = TREE_VALUE (node);
- /* If it's a decl, deal with its type instead. */
- if (DECL_P (node))
- {
- node = TREE_TYPE (node);
- code = TREE_CODE (node);
- }
- }
-
- if (TREE_CODE (node) == NOP_EXPR
- && TREE_CODE (TREE_TYPE (node)) == REFERENCE_TYPE)
- {
- /* Template parameters can be of reference type. To maintain
- internal consistency, such arguments use a conversion from
- address of object to reference type. */
- gcc_assert (TREE_CODE (TREE_OPERAND (node, 0)) == ADDR_EXPR);
- if (abi_version_at_least (2))
- node = TREE_OPERAND (TREE_OPERAND (node, 0), 0);
- else
- G.need_abi_warning = 1;
- }
-
- if (ARGUMENT_PACK_P (node))
- {
- /* Expand the template argument pack. */
- tree args = ARGUMENT_PACK_ARGS (node);
- int i, length = TREE_VEC_LENGTH (args);
- write_char ('I');
- for (i = 0; i < length; ++i)
- write_template_arg (TREE_VEC_ELT (args, i));
- write_char ('E');
- }
- else if (TYPE_P (node))
- write_type (node);
- else if (code == TEMPLATE_DECL)
- /* A template appearing as a template arg is a template template arg. */
- write_template_template_arg (node);
- else if ((TREE_CODE_CLASS (code) == tcc_constant && code != PTRMEM_CST)
- || (abi_version_at_least (2) && code == CONST_DECL))
- write_template_arg_literal (node);
- else if (DECL_P (node))
- {
- /* Until ABI version 2, non-type template arguments of
- enumeration type were mangled using their names. */
- if (code == CONST_DECL && !abi_version_at_least (2))
- G.need_abi_warning = 1;
- write_char ('L');
- /* Until ABI version 3, the underscore before the mangled name
- was incorrectly omitted. */
- if (!abi_version_at_least (3))
- {
- G.need_abi_warning = 1;
- write_char ('Z');
- }
- else
- write_string ("_Z");
- write_encoding (node);
- write_char ('E');
- }
- else
- {
- /* Template arguments may be expressions. */
- write_char ('X');
- write_expression (node);
- write_char ('E');
- }
-}
-
-/* <template-template-arg>
- ::= <name>
- ::= <substitution> */
-
-static void
-write_template_template_arg (const tree decl)
-{
- MANGLE_TRACE_TREE ("template-template-arg", decl);
-
- if (find_substitution (decl))
- return;
- write_name (decl, /*ignore_local_scope=*/0);
- add_substitution (decl);
-}
-
-
-/* Non-terminal <array-type>. TYPE is an ARRAY_TYPE.
-
- <array-type> ::= A [</dimension/ number>] _ </element/ type>
- ::= A <expression> _ </element/ type>
-
- "Array types encode the dimension (number of elements) and the
- element type. For variable length arrays, the dimension (but not
- the '_' separator) is omitted." */
-
-static void
-write_array_type (const tree type)
-{
- write_char ('A');
- if (TYPE_DOMAIN (type))
- {
- tree index_type;
- tree max;
-
- index_type = TYPE_DOMAIN (type);
- /* The INDEX_TYPE gives the upper and lower bounds of the
- array. */
- max = TYPE_MAX_VALUE (index_type);
- if (TREE_CODE (max) == INTEGER_CST)
- {
- /* The ABI specifies that we should mangle the number of
- elements in the array, not the largest allowed index. */
- max = size_binop (PLUS_EXPR, max, size_one_node);
- write_unsigned_number (tree_low_cst (max, 1));
- }
- else
- {
- max = TREE_OPERAND (max, 0);
- if (!abi_version_at_least (2))
- {
- /* value_dependent_expression_p presumes nothing is
- dependent when PROCESSING_TEMPLATE_DECL is zero. */
- ++processing_template_decl;
- if (!value_dependent_expression_p (max))
- G.need_abi_warning = 1;
- --processing_template_decl;
- }
- write_expression (max);
- }
-
- }
- write_char ('_');
- write_type (TREE_TYPE (type));
-}
-
-/* Non-terminal <pointer-to-member-type> for pointer-to-member
- variables. TYPE is a pointer-to-member POINTER_TYPE.
-
- <pointer-to-member-type> ::= M </class/ type> </member/ type> */
-
-static void
-write_pointer_to_member_type (const tree type)
-{
- write_char ('M');
- write_type (TYPE_PTRMEM_CLASS_TYPE (type));
- write_type (TYPE_PTRMEM_POINTED_TO_TYPE (type));
-}
-
-/* Non-terminal <template-param>. PARM is a TEMPLATE_TYPE_PARM,
- TEMPLATE_TEMPLATE_PARM, BOUND_TEMPLATE_TEMPLATE_PARM or a
- TEMPLATE_PARM_INDEX.
-
- <template-param> ::= T </parameter/ number> _ */
-
-static void
-write_template_param (const tree parm)
-{
- int parm_index;
- int parm_level;
- tree parm_type = NULL_TREE;
-
- MANGLE_TRACE_TREE ("template-parm", parm);
-
- switch (TREE_CODE (parm))
- {
- case TEMPLATE_TYPE_PARM:
- case TEMPLATE_TEMPLATE_PARM:
- case BOUND_TEMPLATE_TEMPLATE_PARM:
- parm_index = TEMPLATE_TYPE_IDX (parm);
- parm_level = TEMPLATE_TYPE_LEVEL (parm);
- break;
-
- case TEMPLATE_PARM_INDEX:
- parm_index = TEMPLATE_PARM_IDX (parm);
- parm_level = TEMPLATE_PARM_LEVEL (parm);
- parm_type = TREE_TYPE (TEMPLATE_PARM_DECL (parm));
- break;
-
- default:
- gcc_unreachable ();
- }
-
- write_char ('T');
- /* NUMBER as it appears in the mangling is (-1)-indexed, with the
- earliest template param denoted by `_'. */
- if (parm_index > 0)
- write_unsigned_number (parm_index - 1);
- write_char ('_');
-}
-
-/* <template-template-param>
- ::= <template-param>
- ::= <substitution> */
-
-static void
-write_template_template_param (const tree parm)
-{
- tree templ = NULL_TREE;
-
- /* PARM, a TEMPLATE_TEMPLATE_PARM, is an instantiation of the
- template template parameter. The substitution candidate here is
- only the template. */
- if (TREE_CODE (parm) == BOUND_TEMPLATE_TEMPLATE_PARM)
- {
- templ
- = TI_TEMPLATE (TEMPLATE_TEMPLATE_PARM_TEMPLATE_INFO (parm));
- if (find_substitution (templ))
- return;
- }
-
- /* <template-param> encodes only the template parameter position,
- not its template arguments, which is fine here. */
- write_template_param (parm);
- if (templ)
- add_substitution (templ);
-}
-
-/* Non-terminal <substitution>.
-
- <substitution> ::= S <seq-id> _
- ::= S_ */
-
-static void
-write_substitution (const int seq_id)
-{
- MANGLE_TRACE ("substitution", "");
-
- write_char ('S');
- if (seq_id > 0)
- write_number (seq_id - 1, /*unsigned=*/1, 36);
- write_char ('_');
-}
-
-/* Start mangling ENTITY. */
-
-static inline void
-start_mangling (const tree entity)
-{
- G.entity = entity;
- G.need_abi_warning = false;
- obstack_free (&name_obstack, name_base);
- mangle_obstack = &name_obstack;
- name_base = obstack_alloc (&name_obstack, 0);
-}
-
-/* Done with mangling. If WARN is true, and the name of G.entity will
- be mangled differently in a future version of the ABI, issue a
- warning. */
-
-static void
-finish_mangling_internal (const bool warn)
-{
- if (warn_abi && warn && G.need_abi_warning)
- warning (OPT_Wabi, "the mangled name of %qD will change in a future "
- "version of GCC",
- G.entity);
-
- /* Clear all the substitutions. */
- VEC_truncate (tree, G.substitutions, 0);
-
- /* Null-terminate the string. */
- write_char ('\0');
-}
-
-
-/* Like finish_mangling_internal, but return the mangled string. */
-
-static inline const char *
-finish_mangling (const bool warn)
-{
- finish_mangling_internal (warn);
- return (const char *) obstack_finish (mangle_obstack);
-}
-
-/* Like finish_mangling_internal, but return an identifier. */
-
-static tree
-finish_mangling_get_identifier (const bool warn)
-{
- finish_mangling_internal (warn);
- /* Don't obstack_finish here, and the next start_mangling will
- remove the identifier. */
- return get_identifier ((const char *) obstack_base (mangle_obstack));
-}
-
-/* Initialize data structures for mangling. */
-
-void
-init_mangle (void)
-{
- gcc_obstack_init (&name_obstack);
- name_base = obstack_alloc (&name_obstack, 0);
- G.substitutions = NULL;
-
- /* Cache these identifiers for quick comparison when checking for
- standard substitutions. */
- subst_identifiers[SUBID_ALLOCATOR] = get_identifier ("allocator");
- subst_identifiers[SUBID_BASIC_STRING] = get_identifier ("basic_string");
- subst_identifiers[SUBID_CHAR_TRAITS] = get_identifier ("char_traits");
- subst_identifiers[SUBID_BASIC_ISTREAM] = get_identifier ("basic_istream");
- subst_identifiers[SUBID_BASIC_OSTREAM] = get_identifier ("basic_ostream");
- subst_identifiers[SUBID_BASIC_IOSTREAM] = get_identifier ("basic_iostream");
-}
-
-/* Generate the mangled name of DECL. */
-
-static tree
-mangle_decl_string (const tree decl)
-{
- tree result;
-
- start_mangling (decl);
-
- if (TREE_CODE (decl) == TYPE_DECL)
- write_type (TREE_TYPE (decl));
- else
- write_mangled_name (decl, true);
-
- result = finish_mangling_get_identifier (/*warn=*/true);
- if (DEBUG_MANGLE)
- fprintf (stderr, "mangle_decl_string = '%s'\n\n",
- IDENTIFIER_POINTER (result));
- return result;
-}
-
-/* Create an identifier for the external mangled name of DECL. */
-
-void
-mangle_decl (const tree decl)
-{
- tree id = mangle_decl_string (decl);
- id = targetm.mangle_decl_assembler_name (decl, id);
- SET_DECL_ASSEMBLER_NAME (decl, id);
-}
-
-/* Generate the mangled representation of TYPE. */
-
-const char *
-mangle_type_string (const tree type)
-{
- const char *result;
-
- start_mangling (type);
- write_type (type);
- result = finish_mangling (/*warn=*/false);
- if (DEBUG_MANGLE)
- fprintf (stderr, "mangle_type_string = '%s'\n\n", result);
- return result;
-}
-
-/* Create an identifier for the mangled name of a special component
- for belonging to TYPE. CODE is the ABI-specified code for this
- component. */
-
-static tree
-mangle_special_for_type (const tree type, const char *code)
-{
- tree result;
-
- /* We don't have an actual decl here for the special component, so
- we can't just process the <encoded-name>. Instead, fake it. */
- start_mangling (type);
-
- /* Start the mangling. */
- write_string ("_Z");
- write_string (code);
-
- /* Add the type. */
- write_type (type);
- result = finish_mangling_get_identifier (/*warn=*/false);
-
- if (DEBUG_MANGLE)
- fprintf (stderr, "mangle_special_for_type = %s\n\n",
- IDENTIFIER_POINTER (result));
-
- return result;
-}
-
-/* Create an identifier for the mangled representation of the typeinfo
- structure for TYPE. */
-
-tree
-mangle_typeinfo_for_type (const tree type)
-{
- return mangle_special_for_type (type, "TI");
-}
-
-/* Create an identifier for the mangled name of the NTBS containing
- the mangled name of TYPE. */
-
-tree
-mangle_typeinfo_string_for_type (const tree type)
-{
- return mangle_special_for_type (type, "TS");
-}
-
-/* Create an identifier for the mangled name of the vtable for TYPE. */
-
-tree
-mangle_vtbl_for_type (const tree type)
-{
- return mangle_special_for_type (type, "TV");
-}
-
-/* Returns an identifier for the mangled name of the VTT for TYPE. */
-
-tree
-mangle_vtt_for_type (const tree type)
-{
- return mangle_special_for_type (type, "TT");
-}
-
-/* Return an identifier for a construction vtable group. TYPE is
- the most derived class in the hierarchy; BINFO is the base
- subobject for which this construction vtable group will be used.
-
- This mangling isn't part of the ABI specification; in the ABI
- specification, the vtable group is dumped in the same COMDAT as the
- main vtable, and is referenced only from that vtable, so it doesn't
- need an external name. For binary formats without COMDAT sections,
- though, we need external names for the vtable groups.
-
- We use the production
-
- <special-name> ::= CT <type> <offset number> _ <base type> */
-
-tree
-mangle_ctor_vtbl_for_type (const tree type, const tree binfo)
-{
- tree result;
-
- start_mangling (type);
-
- write_string ("_Z");
- write_string ("TC");
- write_type (type);
- write_integer_cst (BINFO_OFFSET (binfo));
- write_char ('_');
- write_type (BINFO_TYPE (binfo));
-
- result = finish_mangling_get_identifier (/*warn=*/false);
- if (DEBUG_MANGLE)
- fprintf (stderr, "mangle_ctor_vtbl_for_type = %s\n\n",
- IDENTIFIER_POINTER (result));
- return result;
-}
-
-/* Mangle a this pointer or result pointer adjustment.
-
- <call-offset> ::= h <fixed offset number> _
- ::= v <fixed offset number> _ <virtual offset number> _ */
-
-static void
-mangle_call_offset (const tree fixed_offset, const tree virtual_offset)
-{
- write_char (virtual_offset ? 'v' : 'h');
-
- /* For either flavor, write the fixed offset. */
- write_integer_cst (fixed_offset);
- write_char ('_');
-
- /* For a virtual thunk, add the virtual offset. */
- if (virtual_offset)
- {
- write_integer_cst (virtual_offset);
- write_char ('_');
- }
-}
-
-/* Return an identifier for the mangled name of a this-adjusting or
- covariant thunk to FN_DECL. FIXED_OFFSET is the initial adjustment
- to this used to find the vptr. If VIRTUAL_OFFSET is non-NULL, this
- is a virtual thunk, and it is the vtbl offset in
- bytes. THIS_ADJUSTING is nonzero for a this adjusting thunk and
- zero for a covariant thunk. Note, that FN_DECL might be a covariant
- thunk itself. A covariant thunk name always includes the adjustment
- for the this pointer, even if there is none.
-
- <special-name> ::= T <call-offset> <base encoding>
- ::= Tc <this_adjust call-offset> <result_adjust call-offset>
- <base encoding> */
-
-tree
-mangle_thunk (tree fn_decl, const int this_adjusting, tree fixed_offset,
- tree virtual_offset)
-{
- tree result;
-
- start_mangling (fn_decl);
-
- write_string ("_Z");
- write_char ('T');
-
- if (!this_adjusting)
- {
- /* Covariant thunk with no this adjustment */
- write_char ('c');
- mangle_call_offset (integer_zero_node, NULL_TREE);
- mangle_call_offset (fixed_offset, virtual_offset);
- }
- else if (!DECL_THUNK_P (fn_decl))
- /* Plain this adjusting thunk. */
- mangle_call_offset (fixed_offset, virtual_offset);
- else
- {
- /* This adjusting thunk to covariant thunk. */
- write_char ('c');
- mangle_call_offset (fixed_offset, virtual_offset);
- fixed_offset = ssize_int (THUNK_FIXED_OFFSET (fn_decl));
- virtual_offset = THUNK_VIRTUAL_OFFSET (fn_decl);
- if (virtual_offset)
- virtual_offset = BINFO_VPTR_FIELD (virtual_offset);
- mangle_call_offset (fixed_offset, virtual_offset);
- fn_decl = THUNK_TARGET (fn_decl);
- }
-
- /* Scoped name. */
- write_encoding (fn_decl);
-
- result = finish_mangling_get_identifier (/*warn=*/false);
- if (DEBUG_MANGLE)
- fprintf (stderr, "mangle_thunk = %s\n\n", IDENTIFIER_POINTER (result));
- return result;
-}
-
-/* This hash table maps TYPEs to the IDENTIFIER for a conversion
- operator to TYPE. The nodes are IDENTIFIERs whose TREE_TYPE is the
- TYPE. */
-
-static GTY ((param_is (union tree_node))) htab_t conv_type_names;
-
-/* Hash a node (VAL1) in the table. */
-
-static hashval_t
-hash_type (const void *val)
-{
- return (hashval_t) TYPE_UID (TREE_TYPE ((const_tree) val));
-}
-
-/* Compare VAL1 (a node in the table) with VAL2 (a TYPE). */
-
-static int
-compare_type (const void *val1, const void *val2)
-{
- return TREE_TYPE ((const_tree) val1) == (const_tree) val2;
-}
-
-/* Return an identifier for the mangled unqualified name for a
- conversion operator to TYPE. This mangling is not specified by the
- ABI spec; it is only used internally. */
-
-tree
-mangle_conv_op_name_for_type (const tree type)
-{
- void **slot;
- tree identifier;
-
- if (type == error_mark_node)
- return error_mark_node;
-
- if (conv_type_names == NULL)
- conv_type_names = htab_create_ggc (31, &hash_type, &compare_type, NULL);
-
- slot = htab_find_slot_with_hash (conv_type_names, type,
- (hashval_t) TYPE_UID (type), INSERT);
- identifier = (tree)*slot;
- if (!identifier)
- {
- char buffer[64];
-
- /* Create a unique name corresponding to TYPE. */
- sprintf (buffer, "operator %lu",
- (unsigned long) htab_elements (conv_type_names));
- identifier = get_identifier (buffer);
- *slot = identifier;
-
- /* Hang TYPE off the identifier so it can be found easily later
- when performing conversions. */
- TREE_TYPE (identifier) = type;
-
- /* Set bits on the identifier so we know later it's a conversion. */
- IDENTIFIER_OPNAME_P (identifier) = 1;
- IDENTIFIER_TYPENAME_P (identifier) = 1;
- }
-
- return identifier;
-}
-
-/* Return an identifier for the name of an initialization guard
- variable for indicated VARIABLE. */
-
-tree
-mangle_guard_variable (const tree variable)
-{
- start_mangling (variable);
- write_string ("_ZGV");
- if (strncmp (IDENTIFIER_POINTER (DECL_NAME (variable)), "_ZGR", 4) == 0)
- /* The name of a guard variable for a reference temporary should refer
- to the reference, not the temporary. */
- write_string (IDENTIFIER_POINTER (DECL_NAME (variable)) + 4);
- else
- write_name (variable, /*ignore_local_scope=*/0);
- return finish_mangling_get_identifier (/*warn=*/false);
-}
-
-/* Return an identifier for the name of a temporary variable used to
- initialize a static reference. This isn't part of the ABI, but we might
- as well call them something readable. */
-
-tree
-mangle_ref_init_variable (const tree variable)
-{
- start_mangling (variable);
- write_string ("_ZGR");
- write_name (variable, /*ignore_local_scope=*/0);
- return finish_mangling_get_identifier (/*warn=*/false);
-}
-
-
-/* Foreign language type mangling section. */
-
-/* How to write the type codes for the integer Java type. */
-
-static void
-write_java_integer_type_codes (const tree type)
-{
- if (type == java_int_type_node)
- write_char ('i');
- else if (type == java_short_type_node)
- write_char ('s');
- else if (type == java_byte_type_node)
- write_char ('c');
- else if (type == java_char_type_node)
- write_char ('w');
- else if (type == java_long_type_node)
- write_char ('x');
- else if (type == java_boolean_type_node)
- write_char ('b');
- else
- gcc_unreachable ();
-}
-
-#include "gt-cp-mangle.h"
« no previous file with comments | « gcc/gcc/cp/lex.c ('k') | gcc/gcc/cp/name-lookup.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698