/* Name mangling for the 3.0 C++ ABI.
- Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005
+ Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2007
Free Software Foundation, Inc.
- Written by Alex Samuel <sameul@codesourcery.com>
+ 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 2, or (at your option)
+ 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
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 COPYING. If not, write to the Free
- Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
- 02110-1301, USA. */
+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
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
-
-*/
+ mangle_thunk: thunk function or entry */
#include "config.h"
#include "system.h"
{
gcc_assert (!partially_mangled_name);
partially_mangled_name_len = obstack_object_size (mangle_obstack);
- partially_mangled_name = xmalloc (partially_mangled_name_len);
+ partially_mangled_name = XNEWVEC (char, partially_mangled_name_len);
memcpy (partially_mangled_name, obstack_base (mangle_obstack),
partially_mangled_name_len);
obstack_free (mangle_obstack, obstack_finish (mangle_obstack));
}
}
else if (TREE_CODE (decl) == VAR_DECL
- /* The names of global variables aren't mangled. */
+ /* 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)))
<unqualified-name> ::= <operator-name>
::= <special-name>
- ::= <source-name> */
+ ::= <source-name>
+ ::= <local-source-name>
+
+ <local-source-name> ::= L <source-name> <discriminator> */
static void
write_unqualified_name (const tree decl)
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));
}
for (; i != limit; i += dir)
{
- sprintf (buffer, "%08lx", target_real[i]);
+ sprintf (buffer, "%08lx", (unsigned long) target_real[i]);
write_chars (buffer, 8);
}
}
::= 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_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 switch (TREE_CODE (type))
- {
- case VOID_TYPE:
- case BOOLEAN_TYPE:
- case INTEGER_TYPE: /* Includes wchar_t. */
- case REAL_TYPE:
- {
+ else
+ {
/* Handle any target-specific fundamental types. */
const char *target_mangling
- = targetm.mangle_fundamental_type (type);
+ = targetm.mangle_type (type_orig);
if (target_mangling)
{
return;
}
- /* 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:
- 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;
-
- default:
- gcc_unreachable ();
+ switch (TREE_CODE (type))
+ {
+ case VOID_TYPE:
+ case BOOLEAN_TYPE:
+ case INTEGER_TYPE: /* Includes wchar_t. */
+ case REAL_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 ("U10__variadic");
+ 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');
+ write_expression (DECLTYPE_TYPE_EXPR (type));
+ write_char ('E');
+ break;
+
+ case TYPEOF_TYPE:
+ sorry ("mangling typeof, use decltype instead");
+ break;
+
+ default:
+ gcc_unreachable ();
+ }
}
}
break;
case INTEGER_TYPE:
- /* If this is size_t, get the underlying int type. */
- if (TYPE_IS_SIZETYPE (type))
- type = TYPE_DOMAIN (type);
-
/* TYPE may still be wchar_t, since that isn't in
integer_type_nodes. */
if (type == wchar_type_node)
is mangled before the parameter types. If non-NULL, DECL is
FUNCTION_DECL for the function whose type is being emitted.
- <bare-function-type> ::= </signature/ type>+ */
+ 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)
+ if (include_return_type_p || java_method_p)
write_type (TREE_TYPE (type));
/* Now mangle the types of the arguments. */
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)
break;
default:
- for (i = 0; i < TREE_CODE_LENGTH (code); ++i)
+ for (i = 0; i < TREE_OPERAND_LENGTH (expr); ++i)
{
tree operand = TREE_OPERAND (expr, i);
/* As a GNU extension, the middle operand of a
G.need_abi_warning = 1;
}
- if (TYPE_P (node))
+ if (ARGUMENT_PACK_P (node))
+ {
+ /* Expand the template argument pack. */
+ tree args = ARGUMENT_PACK_ARGS (node);
+ int i, length = TREE_VEC_LENGTH (args);
+ for (i = 0; i < length; ++i)
+ write_template_arg (TREE_VEC_ELT (args, i));
+ }
+ 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. */
finish_mangling (const bool warn)
{
if (warn_abi && warn && G.need_abi_warning)
- warning (0, "the mangled name of %qD will change in a future "
+ warning (OPT_Wabi, "the mangled name of %qD will change in a future "
"version of GCC",
G.entity);
void
mangle_decl (const tree decl)
{
- SET_DECL_ASSEMBLER_NAME (decl,
- get_identifier_nocopy (mangle_decl_string (decl)));
+ tree id = get_identifier_nocopy (mangle_decl_string (decl));
+ id = targetm.mangle_decl_assembler_name (decl, id);
+ SET_DECL_ASSEMBLER_NAME (decl, id);
}
/* Generate the mangled representation of TYPE. */
<special-name> ::= T <call-offset> <base encoding>
::= Tc <this_adjust call-offset> <result_adjust call-offset>
- <base encoding>
-*/
+ <base encoding> */
tree
mangle_thunk (tree fn_decl, const int this_adjusting, tree fixed_offset,
static hashval_t
hash_type (const void *val)
{
- return (hashval_t) TYPE_UID (TREE_TYPE ((tree) 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 ((tree) val1) == (tree) val2;
+ return TREE_TYPE ((const_tree) val1) == (const_tree) val2;
}
/* Return an identifier for the mangled unqualified name for a
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);