diff options
author | Jason Merrill <jason@redhat.com> | 2012-01-06 16:39:43 -0500 |
---|---|---|
committer | Jason Merrill <jason@gcc.gnu.org> | 2012-01-06 16:39:43 -0500 |
commit | 4b6aaa996e0d8f5abac818315b6f77cb3596db98 (patch) | |
tree | a4fb9016edd51d789295648c2f9d497fc2a85eb3 /gcc/cp | |
parent | 49f2da1a16b6336cbc8f5273a3dc835625fbf23f (diff) | |
download | gcc-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/ChangeLog | 16 | ||||
-rw-r--r-- | gcc/cp/cp-tree.h | 1 | ||||
-rw-r--r-- | gcc/cp/mangle.c | 141 | ||||
-rw-r--r-- | gcc/cp/operators.def | 7 | ||||
-rw-r--r-- | gcc/cp/pt.c | 2 | ||||
-rw-r--r-- | gcc/cp/tree.c | 2 |
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) |