diff options
author | aoliva <aoliva@138bc75d-0d04-0410-961f-82ee72b054a4> | 2005-03-14 20:02:05 +0000 |
---|---|---|
committer | aoliva <aoliva@138bc75d-0d04-0410-961f-82ee72b054a4> | 2005-03-14 20:02:05 +0000 |
commit | 03623d96836cf980f972e4ef8b9cb98aec14d4fd (patch) | |
tree | e0f63580eedb94d2efdb29726248cb05ff0f224d /gcc | |
parent | c42692ef59d8969f31256fec2929fbabfea84a10 (diff) | |
download | gcc-03623d96836cf980f972e4ef8b9cb98aec14d4fd.tar.gz |
gcc/ChangeLog:
PR c++/20280
* gimplify.c (gimplify_cond_expr): Add fallback argument. Use a
temporary variable of pointer type if an lvalues is required.
(gimplify_modify_expr_rhs): Request an rvalue from it.
(gimplify_expr): Pass fallback on.
gcc/testsuite/ChangeLog:
PR c++/20280
* g++.dg/tree-ssa/pr20280.C: New.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@96444 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 8 | ||||
-rw-r--r-- | gcc/gimplify.c | 37 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/tree-ssa/pr20280.C | 63 |
4 files changed, 107 insertions, 6 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 54c0d114859..910eb398c9f 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,11 @@ +2005-03-14 Alexandre Oliva <aoliva@redhat.com> + + PR c++/20280 + * gimplify.c (gimplify_cond_expr): Add fallback argument. Use a + temporary variable of pointer type if an lvalues is required. + (gimplify_modify_expr_rhs): Request an rvalue from it. + (gimplify_expr): Pass fallback on. + 2005-03-14 Kazu Hirata <kazu@cs.umass.edu> * cfgbuild.c: Update comments. diff --git a/gcc/gimplify.c b/gcc/gimplify.c index 9a6d3076f13..f16ff201694 100644 --- a/gcc/gimplify.c +++ b/gcc/gimplify.c @@ -2123,7 +2123,8 @@ gimple_boolify (tree expr) *EXPR_P should be stored. */ static enum gimplify_status -gimplify_cond_expr (tree *expr_p, tree *pre_p, tree *post_p, tree target) +gimplify_cond_expr (tree *expr_p, tree *pre_p, tree *post_p, tree target, + fallback_t fallback) { tree expr = *expr_p; tree tmp, tmp2, type; @@ -2137,18 +2138,40 @@ gimplify_cond_expr (tree *expr_p, tree *pre_p, tree *post_p, tree target) the arms. */ else if (! VOID_TYPE_P (type)) { + tree result; + if (target) { ret = gimplify_expr (&target, pre_p, post_p, is_gimple_min_lval, fb_lvalue); if (ret != GS_ERROR) ret = GS_OK; - tmp = target; + result = tmp = target; tmp2 = unshare_expr (target); } + else if ((fallback & fb_lvalue) == 0) + { + result = tmp2 = tmp = create_tmp_var (TREE_TYPE (expr), "iftmp"); + ret = GS_ALL_DONE; + } else { - tmp2 = tmp = create_tmp_var (TREE_TYPE (expr), "iftmp"); + tree type = build_pointer_type (TREE_TYPE (expr)); + + if (TREE_TYPE (TREE_OPERAND (expr, 1)) != void_type_node) + TREE_OPERAND (expr, 1) = + build_fold_addr_expr (TREE_OPERAND (expr, 1)); + + if (TREE_TYPE (TREE_OPERAND (expr, 2)) != void_type_node) + TREE_OPERAND (expr, 2) = + build_fold_addr_expr (TREE_OPERAND (expr, 2)); + + tmp2 = tmp = create_tmp_var (type, "iftmp"); + + expr = build (COND_EXPR, void_type_node, TREE_OPERAND (expr, 0), + TREE_OPERAND (expr, 1), TREE_OPERAND (expr, 2)); + + result = build_fold_indirect_ref (tmp); ret = GS_ALL_DONE; } @@ -2169,7 +2192,7 @@ gimplify_cond_expr (tree *expr_p, tree *pre_p, tree *post_p, tree target) /* Move the COND_EXPR to the prequeue. */ gimplify_and_add (expr, pre_p); - *expr_p = tmp; + *expr_p = result; return ret; } @@ -2907,7 +2930,8 @@ gimplify_modify_expr_rhs (tree *expr_p, tree *from_p, tree *to_p, tree *pre_p, if (!is_gimple_reg_type (TREE_TYPE (*from_p))) { *expr_p = *from_p; - return gimplify_cond_expr (expr_p, pre_p, post_p, *to_p); + return gimplify_cond_expr (expr_p, pre_p, post_p, *to_p, + fb_rvalue); } else ret = GS_UNHANDLED; @@ -3786,7 +3810,8 @@ gimplify_expr (tree *expr_p, tree *pre_p, tree *post_p, break; case COND_EXPR: - ret = gimplify_cond_expr (expr_p, pre_p, post_p, NULL_TREE); + ret = gimplify_cond_expr (expr_p, pre_p, post_p, NULL_TREE, + fallback); break; case CALL_EXPR: diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index ef6463180c6..4e18492dbab 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2005-03-14 Alexandre Oliva <aoliva@redhat.com> + + PR c++/20280 + * g++.dg/tree-ssa/pr20280.C: New. + 2005-03-14 Tobias Schl"uter <tobias.schlueter@physik.uni-muenchen.de> PR fortran/20467 diff --git a/gcc/testsuite/g++.dg/tree-ssa/pr20280.C b/gcc/testsuite/g++.dg/tree-ssa/pr20280.C new file mode 100644 index 00000000000..ec4dad70620 --- /dev/null +++ b/gcc/testsuite/g++.dg/tree-ssa/pr20280.C @@ -0,0 +1,63 @@ +// PR c++/20280 + +// { dg-do compile } + +// Gimplification of the COND_EXPR used to fail because it had an +// addressable type, and create_tmp_var rejected that. + +struct A +{ + ~A(); +}; + +struct B : A {}; + +A& foo(); + +void bar(bool b) +{ + (B&) (b ? foo() : foo()); +} + +// Make sure bit-fields and addressable types don't cause crashes. +// These were not in the original bug report. + +// Added by Alexandre Oliva <aoliva@redhat.com> + +// Copyright 2005 Free Software Foundation + +struct X +{ + long i : 32, j, k : 32; +}; + +void g(long&); +void h(const long&); + +void f(X &x, bool b) +{ + (b ? x.i : x.j) = 1; + (b ? x.j : x.k) = 2; + (b ? x.i : x.k) = 3; + + (void)(b ? x.i : x.j); + (void)(b ? x.i : x.k); + (void)(b ? x.j : x.k); + + g (b ? x.i : x.j); // { dg-error "cannot bind bitfield" } + g (b ? x.i : x.k); // { dg-error "cannot bind bitfield" } + g (b ? x.j : x.k); // { dg-error "cannot bind bitfield" } + + // It's not entirely clear whether these should be accepted. The + // conditional expressions are lvalues for sure, and 8.5.3/5 exempts + // lvalues for bit-fields, but it's not clear that conditional + // expressions that are lvalues and that have at least one possible + // result that is a bit-field lvalue meets this condition. + h (b ? x.i : x.j); + h (b ? x.i : x.k); + h (b ? x.j : x.k); + + (long &)(b ? x.i : x.j); // { dg-error "address of bit-field" } + (long &)(b ? x.i : x.k); // { dg-error "address of bit-field" } + (long &)(b ? x.j : x.k); // { dg-error "address of bit-field" } +} |