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>
|
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.
|
||||||
|
|
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> */
|
<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
|
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
|
||||||
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)
|
||||||
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)
|
||||||
{
|
{
|
||||||
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,10 +2576,7 @@ 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_expression (fn);
|
||||||
write_source_name (fn);
|
|
||||||
else
|
|
||||||
write_expression (fn);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < call_expr_nargs (expr); ++i)
|
for (i = 0; i < call_expr_nargs (expr); ++i)
|
||||||
|
|
|
@ -1,5 +1,10 @@
|
||||||
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.
|
||||||
|
|
||||||
|
|
|
@ -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>
|
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)
|
||||||
|
|
||||||
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)
|
||||||
{
|
{
|
||||||
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])
|
||||||
--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.
|
||||||
#
|
#
|
||||||
|
|
Loading…
Reference in New Issue