diff options
-rw-r--r-- | gcc/cp/ChangeLog | 8 | ||||
-rw-r--r-- | gcc/cp/mangle.c | 121 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/abi/mangle35.C | 13 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/abi/mangle37.C | 35 | ||||
-rw-r--r-- | libiberty/ChangeLog | 2 | ||||
-rw-r--r-- | libiberty/cp-demangle.c | 23 | ||||
-rw-r--r-- | libiberty/testsuite/demangle-expected | 5 |
8 files changed, 154 insertions, 58 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index c3b1bdc..5ae5ac6 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,5 +1,13 @@ 2010-02-03 Jason Merrill <jason@redhat.com> + PR c++/4926 + PR c++/38600 + * mangle.c (write_unqualified_id): Split out from write_expression. + (write_unqualified_name): Call it. + (write_member_name): Likewise. + (write_expression): Support TEMPLATE_ID_EXPR. + Disambiguate operator names. + PR c++/12909 * mangle.c (write_type) [VECTOR_TYPE]: Change mangling with -fabi-version=4. diff --git a/gcc/cp/mangle.c b/gcc/cp/mangle.c index 37293f1..ca15dab 100644 --- a/gcc/cp/mangle.c +++ b/gcc/cp/mangle.c @@ -1117,10 +1117,55 @@ write_template_prefix (const tree node) <local-source-name> ::= L <source-name> <discriminator> */ static void +write_unqualified_id (tree identifier) +{ + if (IDENTIFIER_TYPENAME_P (identifier)) + write_conversion_operator_name (TREE_TYPE (identifier)); + else if (IDENTIFIER_OPNAME_P (identifier)) + { + 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 == identifier) + { + /* 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 + == identifier) + { + mangled_name + = assignment_operator_name_info[i].mangled_name; + break; + } + write_string (mangled_name); + } + else + write_source_name (identifier); +} + +static void write_unqualified_name (const tree decl) { MANGLE_TRACE_TREE ("unqualified-name", decl); + if (TREE_CODE (decl) == IDENTIFIER_NODE) + { + write_unqualified_id (decl); + return; + } + if (DECL_NAME (decl) == NULL_TREE) { gcc_assert (DECL_ASSEMBLER_NAME_SET_P (decl)); @@ -2312,7 +2357,7 @@ static void write_member_name (tree member) { if (TREE_CODE (member) == IDENTIFIER_NODE) - write_source_name (member); + write_unqualified_id (member); else if (DECL_P (member)) write_unqualified_name (member); else if (TREE_CODE (member) == TEMPLATE_ID_EXPR) @@ -2435,57 +2480,9 @@ write_expression (tree expr) 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); + write_member_name (member); } } else if (TREE_CODE (expr) == INDIRECT_REF @@ -2494,6 +2491,25 @@ write_expression (tree expr) { write_expression (TREE_OPERAND (expr, 0)); } + else if (TREE_CODE (expr) == IDENTIFIER_NODE) + { + /* An operator name appearing as a dependent name needs to be + specially marked to disambiguate between a use of the operator + name and a use of the operator in an expression. */ + if (IDENTIFIER_OPNAME_P (expr)) + write_string ("on"); + write_unqualified_id (expr); + } + else if (TREE_CODE (expr) == TEMPLATE_ID_EXPR) + { + tree fn = TREE_OPERAND (expr, 0); + if (is_overloaded_fn (fn)) + fn = DECL_NAME (get_first_fn (fn)); + if (IDENTIFIER_OPNAME_P (fn)) + write_string ("on"); + write_unqualified_id (fn); + write_template_args (TREE_OPERAND (expr, 1)); + } else { int i, len; @@ -2560,10 +2576,7 @@ write_expression (tree expr) && 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); + write_expression (fn); } for (i = 0; i < call_expr_nargs (expr); ++i) diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 0c849b9..b3fef29 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,5 +1,10 @@ 2010-02-03 Jason Merrill <jason@redhat.com> + PR c++/4926 + PR c++/38600 + * g++.dg/abi/mangle35.C: New. + * g++.dg/abi/mangle37.C: New. + PR c++/12909 * g++.dg/abi/mangle36.C: New. diff --git a/gcc/testsuite/g++.dg/abi/mangle35.C b/gcc/testsuite/g++.dg/abi/mangle35.C new file mode 100644 index 0000000..78d9933 --- /dev/null +++ b/gcc/testsuite/g++.dg/abi/mangle35.C @@ -0,0 +1,13 @@ +// PR c++/38600 +// { dg-final { scan-assembler "_Z3barIiE1AIX3fooIT_EEEv" } } + +template<void (*)()> struct A {}; + +template<typename> void foo(); + +template<typename T> A<foo<T> > bar(); + +void baz() +{ + bar<int>(); +} diff --git a/gcc/testsuite/g++.dg/abi/mangle37.C b/gcc/testsuite/g++.dg/abi/mangle37.C new file mode 100644 index 0000000..7270861 --- /dev/null +++ b/gcc/testsuite/g++.dg/abi/mangle37.C @@ -0,0 +1,35 @@ +// Testcase for mangling of expressions involving operator names. +// { dg-options -std=c++0x } +// { dg-final { scan-assembler "_Z1fI1AEDTclonplfp_fp_EET_" } } +// { dg-final { scan-assembler "_Z1gI1AEDTclonplIT_Efp_fp_EES1_" } } +// { dg-final { scan-assembler "_Z1hI1AEDTcldtfp_miEET_" } } +// { dg-final { scan-assembler "_Z1iI1AEDTcldtfp_srT_miEES1_" } } +// { dg-final { scan-assembler "_Z1jI1AEDTcldtfp_cvPT_EES1_" } } + +struct A { + void operator-(); + template <class T> + operator T(); +}; +template <class T> +T operator+(T,T); + +template <class T> +auto f (T t) -> decltype(operator+(t,t)); +template <class T> +auto g (T t) -> decltype(operator+<T>(t,t)); +template <class T> +auto h (T t) -> decltype(t.operator-()); +template <class T> +auto i (T t) -> decltype(t.T::operator-()); +template <class T> +auto j (T t) -> decltype(t.operator T*()); + +int main() +{ + f(A()); + g(A()); + h(A()); + i(A()); + j(A()); +} diff --git a/libiberty/ChangeLog b/libiberty/ChangeLog index d4a43ec..20c88d7 100644 --- a/libiberty/ChangeLog +++ b/libiberty/ChangeLog @@ -1,5 +1,7 @@ 2010-02-03 Jason Merrill <jason@redhat.com> + * cp-demangle.c (d_expression): Handle dependent operator name. + PR c++/12909 * cp-demangle.c (d_number_component, d_vector_type): New. (cplus_demangle_type, d_print_comp, d_print_mod): Handle vectors. diff --git a/libiberty/cp-demangle.c b/libiberty/cp-demangle.c index 75706b3..b1319cf 100644 --- a/libiberty/cp-demangle.c +++ b/libiberty/cp-demangle.c @@ -2722,11 +2722,18 @@ d_expression (struct d_info *di) return d_make_function_param (di, index); } - else if (IS_DIGIT (peek)) + else if (IS_DIGIT (peek) + || (peek == 'o' && d_peek_next_char (di) == 'n')) { /* We can get an unqualified name as an expression in the case of - a dependent member access, i.e. decltype(T().i). */ - struct demangle_component *name = d_unqualified_name (di); + a dependent function call, i.e. decltype(f(t)). */ + struct demangle_component *name; + + if (peek == 'o') + /* operator-function-id, i.e. operator+(t). */ + d_advance (di, 2); + + name = d_unqualified_name (di); if (name == NULL) return NULL; if (d_peek_char (di) == 'I') @@ -2784,10 +2791,18 @@ d_expression (struct d_info *di) { struct demangle_component *left; struct demangle_component *right; + const char *code = op->u.s_operator.op->code; left = d_expression (di); - if (!strcmp (op->u.s_operator.op->code, "cl")) + if (!strcmp (code, "cl")) right = d_exprlist (di); + else if (!strcmp (code, "dt") || !strcmp (code, "pt")) + { + right = d_unqualified_name (di); + if (d_peek_char (di) == 'I') + right = d_make_comp (di, DEMANGLE_COMPONENT_TEMPLATE, + right, d_template_args (di)); + } else right = d_expression (di); diff --git a/libiberty/testsuite/demangle-expected b/libiberty/testsuite/demangle-expected index 3662f16..0f85ddc 100644 --- a/libiberty/testsuite/demangle-expected +++ b/libiberty/testsuite/demangle-expected @@ -3932,6 +3932,11 @@ f(float vector[32]) --format=gnu-v3 _Z1fIfLi4EEvDv_T0__T_ void f<float, 4>(float vector[4]) +_Z1fI1AEDTclonplfp_fp_EET_ +decltype ((operator+)({parm#1}, {parm#1})) f<A>(A) +--format=gnu-v3 +_Z1hI1AEDTcldtfp_miEET_ +decltype (({parm#1}.(operator-))()) h<A>(A) # # Ada (GNAT) tests. # |