aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2012-01-06 16:39:43 -0500
committerJason Merrill <jason@gcc.gnu.org>2012-01-06 16:39:43 -0500
commit4b6aaa996e0d8f5abac818315b6f77cb3596db98 (patch)
treea4fb9016edd51d789295648c2f9d497fc2a85eb3 /gcc/cp
parent49f2da1a16b6336cbc8f5273a3dc835625fbf23f (diff)
downloadgcc-4b6aaa996e0d8f5abac818315b6f77cb3596db98.zip
gcc-4b6aaa996e0d8f5abac818315b6f77cb3596db98.tar.gz
gcc-4b6aaa996e0d8f5abac818315b6f77cb3596db98.tar.bz2
re PR c++/6057 (expression mangling doesn't work for operator new)
PR c++/6057 PR c++/48051 PR c++/50855 PR c++/51322 gcc/cp/ * mangle.c (write_expression): Support NEW_EXPR, DELETE_EXPR, THROW_EXPR, CONSTRUCTOR, OVERLOAD. Fix PREINCREMENT_EXPR and PREDECREMENT_EXPR. (write_template_arg): Fix mangling of class-scope functions and argument packs. (mangle_decl): Update suggested -fabi-version argument. * operators.def: Add DOTSTAR_EXPR, REINTERPRET_CAST_EXPR, DYNAMIC_CAST_EXPR; correct CONST_CAST_EXPR, STATIC_CAST_EXPR. * tree.c (dependent_name): No longer static. * cp-tree.h: Declare it. * pt.c (unify): Defer handling of unconverted functions. include/ * demangle.h (enum demangle_component_type): Add DEMANGLE_COMPONENT_INITIALIZER_LIST, DEMANGLE_COMPONENT_NULLARY. libiberty/ * cp-demangle.c (d_dump): Handle DEMANGLE_COMPONENT_NULLARY and DEMANGLE_COMPONENT_INITIALIZER_LIST. (d_make_comp): Likewise. Allow null right arg for DEMANGLE_COMPONENT_TRINARY_ARG2. (cplus_demangle_operators): Adjust new/delete; add .*, :: and throw. (d_template_args, d_template_arg): Handle 'J' for argument packs. (d_exprlist): Add terminator parm. (d_expression, d_print_comp): Handle initializer lists, nullary expressions, prefix/suffix operators, and new. (d_print_subexpr): Avoid parens around DEMANGLE_COMPONENT_QUAL_NAME and DEMANGLE_COMPONENT_INITIALIZER_LIST. * testsuite/demangle-expected: Add tests. From-SVN: r182970
Diffstat (limited to 'gcc/cp')
-rw-r--r--gcc/cp/ChangeLog16
-rw-r--r--gcc/cp/cp-tree.h1
-rw-r--r--gcc/cp/mangle.c141
-rw-r--r--gcc/cp/operators.def7
-rw-r--r--gcc/cp/pt.c2
-rw-r--r--gcc/cp/tree.c2
6 files changed, 158 insertions, 11 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 01480e3..041722d 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,5 +1,21 @@
2012-01-06 Jason Merrill <jason@redhat.com>
+ PR c++/6057
+ PR c++/48051
+ PR c++/50855
+ PR c++/51322
+ * mangle.c (write_expression): Support NEW_EXPR, DELETE_EXPR,
+ THROW_EXPR, CONSTRUCTOR, OVERLOAD. Fix PREINCREMENT_EXPR and
+ PREDECREMENT_EXPR.
+ (write_template_arg): Fix mangling of class-scope functions and
+ argument packs.
+ (mangle_decl): Update suggested -fabi-version argument.
+ * operators.def: Add DOTSTAR_EXPR, REINTERPRET_CAST_EXPR,
+ DYNAMIC_CAST_EXPR; correct CONST_CAST_EXPR, STATIC_CAST_EXPR.
+ * tree.c (dependent_name): No longer static.
+ * cp-tree.h: Declare it.
+ * pt.c (unify): Defer handling of unconverted functions.
+
* mangle.c (mangle_decl): Don't generate mangling aliases
for maybe-in-charge [cd]tors.
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 6e62bd1..ccad644 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -5674,6 +5674,7 @@ extern tree hash_tree_cons (tree, tree, tree);
extern tree hash_tree_chain (tree, tree);
extern tree build_qualified_name (tree, tree, tree, bool);
extern int is_overloaded_fn (tree);
+extern tree dependent_name (tree);
extern tree get_fns (tree);
extern tree get_first_fn (tree);
extern tree ovl_cons (tree, tree);
diff --git a/gcc/cp/mangle.c b/gcc/cp/mangle.c
index e5c2895..f4efa67 100644
--- a/gcc/cp/mangle.c
+++ b/gcc/cp/mangle.c
@@ -2646,6 +2646,102 @@ write_expression (tree expr)
write_expression (TREE_OPERAND (expr, 0));
write_expression (TREE_OPERAND (expr, 2));
}
+ else if (code == NEW_EXPR || code == VEC_NEW_EXPR)
+ {
+ /* ::= [gs] nw <expression>* _ <type> E
+ ::= [gs] nw <expression>* _ <type> <initializer>
+ ::= [gs] na <expression>* _ <type> E
+ ::= [gs] na <expression>* _ <type> <initializer>
+ <initializer> ::= pi <expression>* E */
+ tree placement = TREE_OPERAND (expr, 0);
+ tree type = TREE_OPERAND (expr, 1);
+ tree nelts = TREE_OPERAND (expr, 2);
+ tree init = TREE_OPERAND (expr, 3);
+ tree t;
+
+ gcc_assert (code == NEW_EXPR);
+ if (TREE_OPERAND (expr, 2))
+ code = VEC_NEW_EXPR;
+
+ if (NEW_EXPR_USE_GLOBAL (expr))
+ write_string ("gs");
+
+ write_string (operator_name_info[(int) code].mangled_name);
+
+ for (t = placement; t; t = TREE_CHAIN (t))
+ write_expression (TREE_VALUE (t));
+
+ write_char ('_');
+
+ if (nelts)
+ {
+ tree domain;
+ ++processing_template_decl;
+ domain = compute_array_index_type (NULL_TREE, nelts,
+ tf_warning_or_error);
+ type = build_cplus_array_type (type, domain);
+ --processing_template_decl;
+ }
+ write_type (type);
+
+ if (init && TREE_CODE (init) == TREE_LIST
+ && TREE_CODE (TREE_VALUE (init)) == CONSTRUCTOR
+ && CONSTRUCTOR_IS_DIRECT_INIT (TREE_VALUE (init)))
+ write_expression (TREE_VALUE (init));
+ else
+ {
+ if (init)
+ write_string ("pi");
+ if (init && init != void_zero_node)
+ for (t = init; t; t = TREE_CHAIN (t))
+ write_expression (TREE_VALUE (t));
+ write_char ('E');
+ }
+ }
+ else if (code == DELETE_EXPR || code == VEC_DELETE_EXPR)
+ {
+ gcc_assert (code == DELETE_EXPR);
+ if (DELETE_EXPR_USE_VEC (expr))
+ code = VEC_DELETE_EXPR;
+
+ if (DELETE_EXPR_USE_GLOBAL (expr))
+ write_string ("gs");
+
+ write_string (operator_name_info[(int) code].mangled_name);
+
+ write_expression (TREE_OPERAND (expr, 0));
+ }
+ else if (code == THROW_EXPR)
+ {
+ tree op = TREE_OPERAND (expr, 0);
+ if (op)
+ {
+ write_string ("tw");
+ write_expression (op);
+ }
+ else
+ write_string ("tr");
+ }
+ else if (code == CONSTRUCTOR)
+ {
+ VEC(constructor_elt,gc)* elts = CONSTRUCTOR_ELTS (expr);
+ unsigned i; tree val;
+
+ if (BRACE_ENCLOSED_INITIALIZER_P (expr))
+ write_string ("il");
+ else
+ {
+ write_string ("tl");
+ write_type (TREE_TYPE (expr));
+ }
+ FOR_EACH_CONSTRUCTOR_VALUE (elts, i, val)
+ write_expression (val);
+ write_char ('E');
+ }
+ else if (dependent_name (expr))
+ {
+ write_unqualified_id (dependent_name (expr));
+ }
else
{
int i, len;
@@ -2688,6 +2784,16 @@ write_expression (tree expr)
/* If it wasn't any of those, recursively expand the expression. */
name = operator_name_info[(int) code].mangled_name;
+
+ /* We used to mangle const_cast and static_cast like a C cast. */
+ if (!abi_version_at_least (6)
+ && (code == CONST_CAST_EXPR
+ || code == STATIC_CAST_EXPR))
+ {
+ name = operator_name_info[CAST_EXPR].mangled_name;
+ G.need_abi_warning = 1;
+ }
+
if (name == NULL)
{
sorry ("mangling %C", code);
@@ -2734,16 +2840,21 @@ write_expression (tree expr)
}
break;
- /* FIXME these should have a distinct mangling. */
+ case DYNAMIC_CAST_EXPR:
+ case REINTERPRET_CAST_EXPR:
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;
+ case PREINCREMENT_EXPR:
+ case PREDECREMENT_EXPR:
+ if (abi_version_at_least (6))
+ write_char ('_');
+ else
+ G.need_abi_warning = 1;
+ /* Fall through. */
default:
/* In the middle-end, some expressions have more operands than
@@ -2855,12 +2966,28 @@ write_template_arg (tree node)
G.need_abi_warning = 1;
}
+ if (TREE_CODE (node) == BASELINK
+ && !type_unknown_p (node))
+ {
+ if (abi_version_at_least (6))
+ node = BASELINK_FUNCTIONS (node);
+ else
+ /* We wrongly wrapped a class-scope function in X/E. */
+ 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');
+ if (abi_version_at_least (6))
+ write_char ('J');
+ else
+ {
+ write_char ('I');
+ G.need_abi_warning = 1;
+ }
for (i = 0; i < length; ++i)
write_template_arg (TREE_VEC_ELT (args, i));
write_char ('E');
@@ -3208,8 +3335,8 @@ mangle_decl (const tree decl)
SET_IDENTIFIER_GLOBAL_VALUE (id, decl);
if (IDENTIFIER_GLOBAL_VALUE (id) != decl)
- inform (DECL_SOURCE_LOCATION (decl), "-fabi-version=4 (or =0) "
- "avoids this error with a change in vector mangling");
+ inform (DECL_SOURCE_LOCATION (decl), "-fabi-version=6 (or =0) "
+ "avoids this error with a change in mangling");
#ifdef ASM_OUTPUT_DEF
save_ver = flag_abi_version;
diff --git a/gcc/cp/operators.def b/gcc/cp/operators.def
index 20d811b..3dc7404 100644
--- a/gcc/cp/operators.def
+++ b/gcc/cp/operators.def
@@ -101,8 +101,10 @@ DEF_SIMPLE_OPERATOR ("__real__", REALPART_EXPR, "v18__real__", 1)
/* The cast operator. */
DEF_SIMPLE_OPERATOR ("", TYPE_EXPR, "cv", 1)
DEF_SIMPLE_OPERATOR ("", CAST_EXPR, "cv", 1)
-DEF_SIMPLE_OPERATOR ("", CONST_CAST_EXPR, "cv", 1)
-DEF_SIMPLE_OPERATOR ("", STATIC_CAST_EXPR, "cv", 1)
+DEF_SIMPLE_OPERATOR ("dynamic_cast", DYNAMIC_CAST_EXPR, "dc", 1)
+DEF_SIMPLE_OPERATOR ("reinterpret_cast", REINTERPRET_CAST_EXPR, "rc", 1)
+DEF_SIMPLE_OPERATOR ("const_cast", CONST_CAST_EXPR, "cc", 1)
+DEF_SIMPLE_OPERATOR ("static_cast", STATIC_CAST_EXPR, "sc", 1)
/* Binary operators. */
DEF_SIMPLE_OPERATOR ("+", PLUS_EXPR, "pl", 2)
@@ -125,6 +127,7 @@ DEF_SIMPLE_OPERATOR ("&&", TRUTH_ANDIF_EXPR, "aa", 2)
DEF_SIMPLE_OPERATOR ("||", TRUTH_ORIF_EXPR, "oo", 2)
DEF_SIMPLE_OPERATOR (",", COMPOUND_EXPR, "cm", 2)
DEF_SIMPLE_OPERATOR ("->*", MEMBER_REF, "pm", 2)
+DEF_SIMPLE_OPERATOR (".*", DOTSTAR_EXPR, "ds", 2)
DEF_SIMPLE_OPERATOR ("->", COMPONENT_REF, "pt", 2)
DEF_SIMPLE_OPERATOR ("[]", ARRAY_REF, "ix", 2)
DEF_SIMPLE_OPERATOR ("++", POSTINCREMENT_EXPR, "pp", 2)
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 77e3388..bc3dd97 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -16885,7 +16885,7 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict,
default:
/* An unresolved overload is a nondeduced context. */
- if (type_unknown_p (parm))
+ if (is_overloaded_fn (parm) || type_unknown_p (parm))
return unify_success (explain_p);
gcc_assert (EXPR_P (parm));
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index dea7632..8ef3e25 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -1457,7 +1457,7 @@ is_overloaded_fn (tree x)
(14.6.2), return the IDENTIFIER_NODE for that name. Otherwise, return
NULL_TREE. */
-static tree
+tree
dependent_name (tree x)
{
if (TREE_CODE (x) == IDENTIFIER_NODE)