From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 24781 invoked by alias); 3 Mar 2005 07:51:14 -0000 Mailing-List: contact gcc-bugs-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Archive: List-Post: List-Help: Sender: gcc-bugs-owner@gcc.gnu.org Received: (qmail 24617 invoked by alias); 3 Mar 2005 07:51:06 -0000 Date: Thu, 03 Mar 2005 07:51:00 -0000 Message-ID: <20050303075106.24616.qmail@sourceware.org> From: "aoliva at redhat dot com" To: gcc-bugs@gcc.gnu.org In-Reply-To: <20050302093824.20280.caolanm@redhat.com> References: <20050302093824.20280.caolanm@redhat.com> Reply-To: gcc-bugzilla@gcc.gnu.org Subject: [Bug c++/20280] [4.0/4.1 regression] ICE in create_tmp_var, at gimplify.c:368 X-Bugzilla-Reason: CC X-SW-Source: 2005-03/txt/msg00344.txt.bz2 List-Id: ------- Additional Comments From aoliva at gcc dot gnu dot org 2005-03-03 07:51 ------- Subject: [PR c++/20280] hoist indirect_ref out of addressable cond_exprs When passing an lvalue cond_expr to a function taking a reference that binds directly to either operand of ?:, we'd fail gimplification when the type of the expressions was addressable, because, once again, create_tmp_var would reject addressable types. The solution I came up with was to hoist the indirect_ref out of the cond_expr at the time it was created, such that we create a tmp_var with a reference to the result of the cond_expr, and when we take the address of the cond_expr to pass its result by reference, it cancels out with the indirect_ref, so it works beautifully. I went ahead and verified that I didn't break bit-field lvalues in conditional expressions (my first attempt did), but I was surprised to find out that the calls to h() pass. I understand why they do (we create a temporary and bind to that), but I'm not sure this is correct behavior. Opinions? I'm bootstrapping this on x86_64-linux-gnu, along with the patch for PR c++/20103; it's also passed C++ regression testing. Ok to install if bootstrap and all-languages regression testing passes? Index: gcc/cp/ChangeLog from Alexandre Oliva PR c++/20280 * call.c (build_conditional_expr): Hoist indirect_ref out of cond_expr if the result is an addressable lvalue. Index: gcc/cp/call.c =================================================================== RCS file: /cvs/gcc/gcc/gcc/cp/call.c,v retrieving revision 1.531 diff -u -p -r1.531 call.c --- gcc/cp/call.c 24 Feb 2005 21:55:10 -0000 1.531 +++ gcc/cp/call.c 3 Mar 2005 07:42:24 -0000 @@ -3111,6 +3111,7 @@ build_conditional_expr (tree arg1, tree tree result = NULL_TREE; tree result_type = NULL_TREE; bool lvalue_p = true; + bool indirect_p = false; struct z_candidate *candidates = 0; struct z_candidate *cand; void *p; @@ -3292,7 +3293,15 @@ build_conditional_expr (tree arg1, tree && real_lvalue_p (arg3) && same_type_p (arg2_type, arg3_type)) { - result_type = arg2_type; + if (TREE_ADDRESSABLE (arg2_type) && TREE_ADDRESSABLE (arg3_type)) + { + indirect_p = true; + result_type = build_pointer_type (arg2_type); + arg2 = fold_if_not_in_template (build_address (arg2)); + arg3 = fold_if_not_in_template (build_address (arg3)); + } + else + result_type = arg2_type; goto valid_operands; } @@ -3458,6 +3467,14 @@ build_conditional_expr (tree arg1, tree /* We can't use result_type below, as fold might have returned a throw_expr. */ + if (indirect_p) + { + if (TREE_CODE (TREE_TYPE (result)) == POINTER_TYPE) + result = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (result)), result); + else + gcc_assert (TREE_CODE (result) == THROW_EXPR); + } + /* Expand both sides into the same slot, hopefully the target of the ?: expression. We used to check for TARGET_EXPRs here, but now we sometimes wrap them in NOP_EXPRs so the test would fail. */ Index: gcc/testsuite/ChangeLog from Alexandre Oliva * g++.dg/tree-ssa/pr20103.C: New. Index: gcc/testsuite/g++.dg/tree-ssa/pr20280.C =================================================================== RCS file: gcc/testsuite/g++.dg/tree-ssa/pr20280.C diff -N gcc/testsuite/g++.dg/tree-ssa/pr20280.C --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ gcc/testsuite/g++.dg/tree-ssa/pr20280.C 3 Mar 2005 07:42:38 -0000 @@ -0,0 +1,62 @@ +// 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 + +// 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" } + + // Hmm... I don't think these should be accepted. The conditional + // expressions are lvalues for sure, and 8.5.3/5 exempts lvalues + // that are bit-fields, but not lvalues that are conditional + // expressions involving bit-fields. + 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" } +} -- Alexandre Oliva http://www.ic.unicamp.br/~oliva/ Red Hat Compiler Engineer aoliva@{redhat.com, gcc.gnu.org} Free Software Evangelist oliva@{lsd.ic.unicamp.br, gnu.org} -- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=20280