/* Name mangling for the 3.0 C++ ABI.
- Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009
- Free Software Foundation, Inc.
+ Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009, 2010,
+ 2011 Free Software Foundation, Inc.
Written by Alex Samuel <samuel@codesourcery.com>
This file is part of GCC.
#include "tm_p.h"
#include "cp-tree.h"
#include "obstack.h"
-#include "toplev.h"
#include "flags.h"
#include "target.h"
#include "cgraph.h"
/* The entity that is being mangled. */
tree GTY ((skip)) entity;
+ /* How many parameter scopes we are inside. */
+ int parm_depth;
+
/* True if the mangling will be different in a future version of the
ABI. */
bool need_abi_warning;
static tree
decl_mangling_context (tree decl)
{
+ tree tcontext = targetm.cxx.decl_mangling_context (decl);
+
+ if (tcontext != NULL_TREE)
+ return tcontext;
+
if (TREE_CODE (decl) == TYPE_DECL
&& LAMBDA_TYPE_P (TREE_TYPE (decl)))
{
static void
write_unscoped_name (const tree decl)
{
- tree context = CP_DECL_CONTEXT (decl);
+ tree context = decl_mangling_context (decl);
MANGLE_TRACE_TREE ("unscoped-name", decl);
else
{
/* No, just use <prefix> */
- write_prefix (DECL_CONTEXT (decl));
+ write_prefix (CP_DECL_CONTEXT (decl));
write_unqualified_name (decl);
}
write_char ('E');
/* <prefix> ::= <prefix> <unqualified-name>
::= <template-param>
::= <template-prefix> <template-args>
+ ::= <decltype>
::= # empty
::= <substitution> */
MANGLE_TRACE_TREE ("prefix", node);
+ if (TREE_CODE (node) == DECLTYPE_TYPE)
+ {
+ write_type (node);
+ return;
+ }
+
if (find_substitution (node))
return;
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');
+ if (TREE_CODE (type) == POINTER_TYPE)
+ write_char ('P');
+ else if (TYPE_REF_IS_RVALUE (type))
+ write_char ('O');
else
write_char ('R');
- write_type (TREE_TYPE (type));
+ {
+ tree target = TREE_TYPE (type);
+ /* Attribute const/noreturn are not reflected in mangling.
+ We strip them here rather than at a lower level because
+ a typedef or template argument can have function type
+ with function-cv-quals (that use the same representation),
+ but you can't have a pointer/reference to such a type. */
+ if (abi_version_at_least (5)
+ && TREE_CODE (target) == FUNCTION_TYPE)
+ target = build_qualified_type (target, TYPE_UNQUALIFIED);
+ write_type (target);
+ }
break;
case TEMPLATE_TYPE_PARM:
case DECLTYPE_TYPE:
/* These shouldn't make it into mangling. */
gcc_assert (!DECLTYPE_FOR_LAMBDA_CAPTURE (type)
- && !DECLTYPE_FOR_LAMBDA_RETURN (type));
+ && !DECLTYPE_FOR_LAMBDA_PROXY (type));
+
+ /* In ABI <5, we stripped decltype of a plain decl. */
+ if (!abi_version_at_least (5)
+ && DECLTYPE_TYPE_ID_EXPR_OR_MEMBER_ACCESS_P (type))
+ {
+ tree expr = DECLTYPE_TYPE_EXPR (type);
+ tree etype = NULL_TREE;
+ switch (TREE_CODE (expr))
+ {
+ case VAR_DECL:
+ case PARM_DECL:
+ case RESULT_DECL:
+ case FUNCTION_DECL:
+ case CONST_DECL:
+ case TEMPLATE_PARM_INDEX:
+ etype = TREE_TYPE (expr);
+ break;
+
+ default:
+ break;
+ }
+
+ if (etype && !type_uses_auto (etype))
+ {
+ G.need_abi_warning = 1;
+ write_type (etype);
+ return;
+ }
+ }
write_char ('D');
if (DECLTYPE_TYPE_ID_EXPR_OR_MEMBER_ACCESS_P (type))
sorry ("mangling typeof, use decltype instead");
break;
+ case UNDERLYING_TYPE:
+ sorry ("mangling __underlying_type");
+ break;
+
case LANG_TYPE:
/* fall through. */
array. */
cp_cv_quals quals = TYPE_QUALS (type);
- /* Attribute const/noreturn are not reflected in mangling. */
- if (abi_version_at_least (5)
- && (TREE_CODE (type) == FUNCTION_TYPE
- || TREE_CODE (type) == METHOD_TYPE))
- return 0;
-
if (quals & TYPE_QUAL_RESTRICT)
{
write_char ('r');
{
/* The first parameter must be a POINTER_TYPE pointing to the
`this' parameter. */
- tree this_type = TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (type)));
+ tree this_type = class_of_this_parm (type);
write_CV_qualifiers_for_type (this_type);
}
write_type (TREE_TYPE (type));
/* Now mangle the types of the arguments. */
+ ++G.parm_depth;
write_method_parms (TYPE_ARG_TYPES (type),
TREE_CODE (type) == METHOD_TYPE,
decl);
+ --G.parm_depth;
}
/* Write the mangled representation of a method parameter list of
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 && DECL_ARTIFICIAL (expr))
+ {
+ gcc_assert (!strcmp ("this", IDENTIFIER_POINTER (DECL_NAME (expr))));
+ write_string ("fpT");
+ }
else if (code == PARM_DECL)
{
/* A function parameter used in a late-specified return type. */
int index = DECL_PARM_INDEX (expr);
+ int level = DECL_PARM_LEVEL (expr);
+ int delta = G.parm_depth - level + 1;
gcc_assert (index >= 1);
- write_string ("fp");
+ write_char ('f');
+ if (delta != 0)
+ {
+ if (abi_version_at_least (5))
+ {
+ /* Let L be the number of function prototype scopes from the
+ innermost one (in which the parameter reference occurs) up
+ to (and including) the one containing the declaration of
+ the referenced parameter. If the parameter declaration
+ clause of the innermost function prototype scope has been
+ completely seen, it is not counted (in that case -- which
+ is perhaps the most common -- L can be zero). */
+ write_char ('L');
+ write_unsigned_number (delta - 1);
+ }
+ else
+ G.need_abi_warning = true;
+ }
+ write_char ('p');
write_compact_number (index - 1);
}
else if (DECL_P (expr))
write_unqualified_id (fn);
write_template_args (TREE_OPERAND (expr, 1));
}
+ else if (TREE_CODE (expr) == MODOP_EXPR)
+ {
+ enum tree_code subop = TREE_CODE (TREE_OPERAND (expr, 1));
+ const char *name = (assignment_operator_name_info[(int) subop]
+ .mangled_name);
+ write_string (name);
+ write_expression (TREE_OPERAND (expr, 0));
+ write_expression (TREE_OPERAND (expr, 2));
+ }
else
{
int i, len;
default:
/* In the middle-end, some expressions have more operands than
they do in templates (and mangling). */
- switch (code)
- {
- case PREINCREMENT_EXPR:
- case PREDECREMENT_EXPR:
- case POSTINCREMENT_EXPR:
- case POSTDECREMENT_EXPR:
- len = 1;
- break;
-
- case ARRAY_REF:
- len = 2;
- break;
-
- default:
- len = TREE_OPERAND_LENGTH (expr);
- break;
- }
+ len = cp_tree_operand_length (expr);
for (i = 0; i < len; ++i)
{
write_char ('L');
write_type (TREE_TYPE (value));
- switch (TREE_CODE (value))
- {
- case CONST_DECL:
- write_integer_cst (DECL_INITIAL (value));
- break;
+ /* Write a null member pointer value as (type)0, regardless of its
+ real representation. */
+ if (null_member_pointer_value_p (value))
+ write_integer_cst (integer_zero_node);
+ else
+ 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 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;
+ case REAL_CST:
+ write_real_cst (value);
+ break;
- default:
- gcc_unreachable ();
- }
+ case STRING_CST:
+ sorry ("string literal in function template signature");
+ break;
+
+ default:
+ gcc_unreachable ();
+ }
write_char ('E');
}
/* 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))
+ || (abi_version_at_least (2) && code == CONST_DECL)
+ || null_member_pointer_value_p (node))
write_template_arg_literal (node);
else if (DECL_P (node))
{
tree saved_fn = NULL_TREE;
bool template_p = false;
+ /* We shouldn't be trying to mangle an uninstantiated template. */
+ gcc_assert (!type_dependent_expression_p (decl));
+
if (DECL_LANG_SPECIFIC (decl) && DECL_USE_TEMPLATE (decl))
{
struct tinst_level *tl = current_instantiation ();
- if (!tl || tl->decl != decl)
+ if ((!tl || tl->decl != decl)
+ && push_tinst_level (decl))
{
template_p = true;
saved_fn = current_function_decl;
- push_tinst_level (decl);
current_function_decl = NULL_TREE;
}
}
if (vague_linkage_p (decl))
DECL_WEAK (alias) = 1;
if (TREE_CODE (decl) == FUNCTION_DECL)
- cgraph_same_body_alias (alias, decl);
+ cgraph_same_body_alias (cgraph_get_create_node (decl), alias, decl);
else
varpool_extra_name_alias (alias, decl);
#endif