Commit f000c6a7 by Jason Merrill Committed by Jason Merrill

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
parent abfe01ce
2010-02-03 Jason Merrill <jason@redhat.com> 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 PR c++/12909
* mangle.c (write_type) [VECTOR_TYPE]: Change mangling with * mangle.c (write_type) [VECTOR_TYPE]: Change mangling with
-fabi-version=4. -fabi-version=4.
......
...@@ -1117,10 +1117,55 @@ write_template_prefix (const tree node) ...@@ -1117,10 +1117,55 @@ write_template_prefix (const tree node)
<local-source-name> ::= L <source-name> <discriminator> */ <local-source-name> ::= L <source-name> <discriminator> */
static void 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) write_unqualified_name (const tree decl)
{ {
MANGLE_TRACE_TREE ("unqualified-name", decl); MANGLE_TRACE_TREE ("unqualified-name", decl);
if (TREE_CODE (decl) == IDENTIFIER_NODE)
{
write_unqualified_id (decl);
return;
}
if (DECL_NAME (decl) == NULL_TREE) if (DECL_NAME (decl) == NULL_TREE)
{ {
gcc_assert (DECL_ASSEMBLER_NAME_SET_P (decl)); gcc_assert (DECL_ASSEMBLER_NAME_SET_P (decl));
...@@ -2312,7 +2357,7 @@ static void ...@@ -2312,7 +2357,7 @@ static void
write_member_name (tree member) write_member_name (tree member)
{ {
if (TREE_CODE (member) == IDENTIFIER_NODE) if (TREE_CODE (member) == IDENTIFIER_NODE)
write_source_name (member); write_unqualified_id (member);
else if (DECL_P (member)) else if (DECL_P (member))
write_unqualified_name (member); write_unqualified_name (member);
else if (TREE_CODE (member) == TEMPLATE_ID_EXPR) else if (TREE_CODE (member) == TEMPLATE_ID_EXPR)
...@@ -2435,57 +2480,9 @@ write_expression (tree expr) ...@@ -2435,57 +2480,9 @@ write_expression (tree expr)
write_expression (member); write_expression (member);
else else
{ {
tree template_args;
write_string ("sr"); write_string ("sr");
write_type (scope); write_type (scope);
/* If MEMBER is a template-id, separate the template write_member_name (member);
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);
} }
} }
else if (TREE_CODE (expr) == INDIRECT_REF else if (TREE_CODE (expr) == INDIRECT_REF
...@@ -2494,6 +2491,25 @@ write_expression (tree expr) ...@@ -2494,6 +2491,25 @@ write_expression (tree expr)
{ {
write_expression (TREE_OPERAND (expr, 0)); 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 else
{ {
int i, len; int i, len;
...@@ -2560,9 +2576,6 @@ write_expression (tree expr) ...@@ -2560,9 +2576,6 @@ write_expression (tree expr)
&& type_dependent_expression_p_push (expr)) && type_dependent_expression_p_push (expr))
fn = DECL_NAME (get_first_fn (fn)); fn = DECL_NAME (get_first_fn (fn));
if (TREE_CODE (fn) == IDENTIFIER_NODE)
write_source_name (fn);
else
write_expression (fn); write_expression (fn);
} }
......
2010-02-03 Jason Merrill <jason@redhat.com> 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 PR c++/12909
* g++.dg/abi/mangle36.C: New. * g++.dg/abi/mangle36.C: New.
......
// 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>();
}
// 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());
}
2010-02-03 Jason Merrill <jason@redhat.com> 2010-02-03 Jason Merrill <jason@redhat.com>
* cp-demangle.c (d_expression): Handle dependent operator name.
PR c++/12909 PR c++/12909
* cp-demangle.c (d_number_component, d_vector_type): New. * cp-demangle.c (d_number_component, d_vector_type): New.
(cplus_demangle_type, d_print_comp, d_print_mod): Handle vectors. (cplus_demangle_type, d_print_comp, d_print_mod): Handle vectors.
......
...@@ -2722,11 +2722,18 @@ d_expression (struct d_info *di) ...@@ -2722,11 +2722,18 @@ d_expression (struct d_info *di)
return d_make_function_param (di, index); 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 /* We can get an unqualified name as an expression in the case of
a dependent member access, i.e. decltype(T().i). */ a dependent function call, i.e. decltype(f(t)). */
struct demangle_component *name = d_unqualified_name (di); 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) if (name == NULL)
return NULL; return NULL;
if (d_peek_char (di) == 'I') if (d_peek_char (di) == 'I')
...@@ -2784,10 +2791,18 @@ d_expression (struct d_info *di) ...@@ -2784,10 +2791,18 @@ d_expression (struct d_info *di)
{ {
struct demangle_component *left; struct demangle_component *left;
struct demangle_component *right; struct demangle_component *right;
const char *code = op->u.s_operator.op->code;
left = d_expression (di); left = d_expression (di);
if (!strcmp (op->u.s_operator.op->code, "cl")) if (!strcmp (code, "cl"))
right = d_exprlist (di); 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 else
right = d_expression (di); right = d_expression (di);
......
...@@ -3932,6 +3932,11 @@ f(float vector[32]) ...@@ -3932,6 +3932,11 @@ f(float vector[32])
--format=gnu-v3 --format=gnu-v3
_Z1fIfLi4EEvDv_T0__T_ _Z1fIfLi4EEvDv_T0__T_
void f<float, 4>(float vector[4]) 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. # Ada (GNAT) tests.
# #
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment