This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
C++: constant folding in a conditional expr
- To: gcc-patches at gcc dot gnu dot org
- Subject: C++: constant folding in a conditional expr
- From: Andrew Haley <aph at cambridge dot redhat dot com>
- Date: Wed, 28 Mar 2001 20:14:17 +0100 (BST)
This test case fails if BROKEN is #defined:
class Foo
{
public:
static const unsigned ACONST = 0;
static const unsigned BCONST = 1;
void SetData(bool p);
private:
unsigned _data;
};
void Foo::SetData(bool p)
{
#ifdef BROKEN
_data = p ? ACONST : BCONST;
#else
if (p)
_data = ACONST;
else
_data = BCONST;
#endif
}
105527.o: In function `Foo::SetData(bool)':
105527.o(.text+0xd): undefined reference to `Foo::ACONST '
105527.o(.text+0x17): undefined reference to `Foo::BCONST '
This seems to be because build_conditional_expr treats
p ? ACONST : BCONST
as an lvalue and so doesn't subsitute the initializers for the const
members. Of course, the static const members ACONST and BCONST are
never output, so we get a link error.
I've written a patch that doesn't treat the conditional expr as an
lvalue if either arm is read only, and that seems to fix the problem,
but is it the right fix?
Andrew.
Index: call.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/call.c,v
retrieving revision 1.265
diff -p -2 -c -r1.265 call.c
*** call.c 2001/03/23 01:49:10 1.265
--- call.c 2001/03/28 19:13:00
*************** build_conditional_expr (arg1, arg2, arg3
*** 3002,3006 ****
If the second and third operands are lvalues and have the same
type, the result is of that type and is an lvalue. */
! if (real_lvalue_p (arg2) && real_lvalue_p (arg3) &&
same_type_p (arg2_type, arg3_type))
{
--- 3002,3007 ----
If the second and third operands are lvalues and have the same
type, the result is of that type and is an lvalue. */
! if (! TREE_READONLY (arg2) && ! TREE_READONLY (arg3) &&
! real_lvalue_p (arg2) && real_lvalue_p (arg3) &&
same_type_p (arg2_type, arg3_type))
{