aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/cp/ChangeLog8
-rw-r--r--gcc/cp/mangle.c121
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/g++.dg/abi/mangle35.C13
-rw-r--r--gcc/testsuite/g++.dg/abi/mangle37.C35
-rw-r--r--libiberty/ChangeLog2
-rw-r--r--libiberty/cp-demangle.c23
-rw-r--r--libiberty/testsuite/demangle-expected5
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.
#