mirror of git://gcc.gnu.org/git/gcc.git
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
This commit is contained in:
parent
abfe01cec9
commit
f000c6a763
|
@ -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.
|
||||
|
|
121
gcc/cp/mangle.c
121
gcc/cp/mangle.c
|
@ -1116,11 +1116,56 @@ 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)
|
||||
|
|
|
@ -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.
|
||||
|
||||
|
|
|
@ -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>();
|
||||
}
|
|
@ -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());
|
||||
}
|
|
@ -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.
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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.
|
||||
#
|
||||
|
|
Loading…
Reference in New Issue