diff options
author | Jason Merrill <jason@redhat.com> | 2010-02-03 15:42:48 -0500 |
---|---|---|
committer | Jason Merrill <jason@gcc.gnu.org> | 2010-02-03 15:42:48 -0500 |
commit | f000c6a763acc0ba0184c5634f2feb3ea883992c (patch) | |
tree | 85f758f12214e67f5aac6efe669abcdc7aa570c7 /gcc | |
parent | abfe01cec91fae69bb05700bf6a53f41a64fd15c (diff) | |
download | gcc-f000c6a763acc0ba0184c5634f2feb3ea883992c.zip gcc-f000c6a763acc0ba0184c5634f2feb3ea883992c.tar.gz gcc-f000c6a763acc0ba0184c5634f2feb3ea883992c.tar.bz2 |
re PR c++/4926 (C++ ABI needs clarification on mangling of complex expressions)
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.
From-SVN: r156482
Diffstat (limited to 'gcc')
-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 |
5 files changed, 128 insertions, 54 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()); +} |