This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH?] PR optimization/5079: Help with C++ conversion functions
- From: Roger Sayle <roger at eyesopen dot com>
- To: gcc-patches at gcc dot gnu dot org
- Cc: Jason Merrill <jason at redhat dot com>
- Date: Sun, 6 Jul 2003 11:23:31 -0600 (MDT)
- Subject: [PATCH?] PR optimization/5079: Help with C++ conversion functions
I need some help finding my way around the twisty turny maze of conversion
functions available to the C++ front-end. The patch below resolves
PR optimization/5079, which I discovered by browsing bugzilla's most
frequently reported bugs list, but unfortunately it introduces a new
testsuite regression...
Consider the three functions below:
class Foo {
public:
static const int erf = 0;
static const int foo = 1;
};
int one()
{
return Foo::foo;
}
int two()
{
return Foo::foo + Foo:erf;
}
int three(int x)
{
return x ? Foo::erf : Foo::foo;
}
With current mainline g++ functions "one" and "two" inline the initialized
static constants, but "three" doesn't. [I appreciate this C++ example
may be ill-formed C++, but it serves to demonstrate the inconsistency.]
The difference appears to be that in the first two cases, the g++
front-end calls "convert" on the "var" which ends up replacing the
const variable with its initializer. In the third, build_conditional_expr
doesn't call convert on its second and third operands, and hence the
variable reference is never replaced with its initializer.
The "proof of concept" patch below calls generic "convert" at the
appropriate places in g++'s build_conditional_expr, and indeed allows
function "three" above to be optimized by the compiler. The problem
is that I'm fairly certain that "convert" is probably not the appropriate
function to use; perhaps cp_convert, or ocp_convert, or maybe even
perform_implicit_conversion. In short, I'm lost. Just to confirm how
lost, the patch below survives a complete "make bootstrap" on
i686-pc-linux-gnu, all languages except treelang, but with a single
testsuite regression: g++.old-deja/g++.other/array5.C, which reads:
extern int a1[];
extern int a2[];
int foo(int p)
{
int x = (p ? a1 : a2)[1];
return x;
}
which with my patch fails with the error message:
array5.C:8: error: conversion from `int[]' to non-scalar type
`int[]' requested
Clearly, "convert" is not the precise function that's required. Could
anyone who understands C++'s type system tell me the appropriate function?
If there isn't a conversion that will replace the initializer without
the above error, should I test for scalar types? Is this approach the
correct solution?
Many thanks in advance,
2003-07-06 Roger Sayle <roger@eyesopen.com>
PR optimization/5079
* call.c (build_conditional_expr): Call convert on operands of a
conditional expression once the result type has been determined.
Index: call.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/call.c,v
retrieving revision 1.400
diff -c -3 -p -r1.400 call.c
*** call.c 5 Jul 2003 03:02:02 -0000 1.400
--- call.c 6 Jul 2003 14:09:13 -0000
*************** build_conditional_expr (tree arg1, tree
*** 3299,3304 ****
--- 3299,3308 ----
return error_mark_node;
}
+ if (! VOID_TYPE_P (arg2_type))
+ arg2 = convert (result_type, arg2);
+ if (! VOID_TYPE_P (arg3_type))
+ arg3 = convert (result_type, arg3);
lvalue_p = false;
goto valid_operands;
}
*************** build_conditional_expr (tree arg1, tree
*** 3356,3361 ****
--- 3360,3367 ----
same_type_p (arg2_type, arg3_type))
{
result_type = arg2_type;
+ arg2 = convert (result_type, arg2);
+ arg3 = convert (result_type, arg3);
goto valid_operands;
}
*************** build_conditional_expr (tree arg1, tree
*** 3449,3455 ****
--The second and third operands have the same type; the result is of
that type. */
if (same_type_p (arg2_type, arg3_type))
! result_type = arg2_type;
/* [expr.cond]
--The second and third operands have arithmetic or enumeration
--- 3455,3465 ----
--The second and third operands have the same type; the result is of
that type. */
if (same_type_p (arg2_type, arg3_type))
! {
! result_type = arg2_type;
! arg2 = convert (result_type, arg2);
! arg3 = convert (result_type, arg3);
! }
/* [expr.cond]
--The second and third operands have arithmetic or enumeration
Roger
--
Roger Sayle, E-mail: roger@eyesopen.com
OpenEye Scientific Software, WWW: http://www.eyesopen.com/
Suite 1107, 3600 Cerrillos Road, Tel: (+1) 505-473-7385
Santa Fe, New Mexico, 87507. Fax: (+1) 505-473-0833