This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
C++ PATCH: Fix decl_constant_value for COND_EXPRs
- From: Mark Mitchell <mark at codesourcery dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Thu, 28 Aug 2003 19:48:18 -0700
- Subject: C++ PATCH: Fix decl_constant_value for COND_EXPRs
- Reply-to: mark at codesourcery dot com
This patch implements Jason's suggestion that decl_constant_value
handle COND_EXPR specially; build_conditional_expr doesn't know
whether it's building an lvalue or an rvalue, sadly. I've added a
test for the bug that I introduced, as well.
(One might also note that the back end could perform the
decl_constant_value operation when using a VAR_DECL in an rvalue
context...)
Tested on i686-pc-linux-gnu, applied on the mainline
--
Mark Mitchell
CodeSourcery, LLC
mark@codesourcery.com
2003-08-28 Mark Mitchell <mark@codesourcery.com>
* init.c (decl_constant_value): Deal with COND_EXPR specially.
* call.c (build_conditional_expr): Revert previous patch.
2003-08-28 Mark Mitchell <mark@codesourcery.com>
* g++.dg/expr/cond3.C: New test.
Index: cp/call.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/call.c,v
retrieving revision 1.426
diff -c -5 -p -r1.426 call.c
*** cp/call.c 28 Aug 2003 07:14:26 -0000 1.426
--- cp/call.c 29 Aug 2003 02:47:10 -0000
*************** build_conditional_expr (tree arg1, tree
*** 3356,3367 ****
error ("operands to ?: have different types");
return error_mark_node;
}
valid_operands:
- arg2 = decl_constant_value (arg2);
- arg3 = decl_constant_value (arg3);
result = fold (build (COND_EXPR, result_type, arg1, arg2, arg3));
/* We can't use result_type below, as fold might have returned a
throw_expr. */
/* Expand both sides into the same slot, hopefully the target of the
--- 3356,3365 ----
Index: cp/init.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/init.c,v
retrieving revision 1.340
diff -c -5 -p -r1.340 init.c
*** cp/init.c 19 Aug 2003 12:54:59 -0000 1.340
--- cp/init.c 29 Aug 2003 02:47:10 -0000
*************** build_offset_ref (tree type, tree name,
*** 1585,1594 ****
--- 1585,1612 ----
constant, then return that value. */
tree
decl_constant_value (tree decl)
{
+ /* When we build a COND_EXPR, we don't know whether it will be used
+ as an lvalue or as an rvalue. If it is an lvalue, it's not safe
+ to replace the second and third operands with their
+ initializers. So, we do that here. */
+ if (TREE_CODE (decl) == COND_EXPR)
+ {
+ tree d1;
+ tree d2;
+
+ d1 = decl_constant_value (TREE_OPERAND (decl, 1));
+ d2 = decl_constant_value (TREE_OPERAND (decl, 2));
+
+ if (d1 != TREE_OPERAND (decl, 1) || d2 != TREE_OPERAND (decl, 2))
+ return build (COND_EXPR,
+ TREE_TYPE (decl),
+ TREE_OPERAND (decl, 0), d1, d2);
+ }
+
if (TREE_READONLY_DECL_P (decl)
&& ! TREE_THIS_VOLATILE (decl)
&& DECL_INITIAL (decl)
&& DECL_INITIAL (decl) != error_mark_node
/* This is invalid if initial value is not constant.
Index: testsuite/g++.dg/expr/cond3.C
===================================================================
RCS file: testsuite/g++.dg/expr/cond3.C
diff -N testsuite/g++.dg/expr/cond3.C
*** /dev/null 1 Jan 1970 00:00:00 -0000
--- testsuite/g++.dg/expr/cond3.C 29 Aug 2003 02:47:11 -0000
***************
*** 0 ****
--- 1,6 ----
+ const int i = 7;
+ const int j = 3;
+
+ void f(bool b) {
+ &(b ? i : j);
+ }