On Mar 7, 2005, Roger Sayle <[EMAIL PROTECTED]> wrote: > For example, I believe that Alex's proposed solution to PR c++/19199 > isn't an appropriate fix. It's perfectly reasonable for fold to convert > a C++ COND_EXPR into a MIN_EXPR or MAX_EXPR, as according to the C++ > front-end all three of these tree nodes are valid lvalues.
But not if the values it places in the MIN_EXPR or MAX_EXPR operands aren't lvalues themselves, otherwise you're turning an lvalue into an rvalue. In the example of this testcase, the compare operands are <nop(int) <parm_decl>> (rvalues), whereas the cond_expr operands are <parm_decl> (lvalues), and the min_expr operands end up being <nop(int) <parm_decl>>. So the transformation is in error. It wouldn't be if we managed to first remove the extensions from the compare operands, and only then turn them into min/max_expr. Any reason to avoid comparing the enums directly, without wrapping them in conversions to int? > It also doesn't help with the problematic C++ extension: > (a >? b) = c; > which use MIN_EXPR/MAX_EXPR as a valid lvalue in C++ without any help > from "fold". As long as there isn't any conversion needed for the compare. > The first is to see if in the C++ parser provides enough information > such that it knows we're if parsing an lvalue or an rvalue. It doesn't, and it can't. Consider: ( void ) ( ( a ? b : c ) ) ( void ) ( ( a ? b : c ) = 0) ^ you're here how could you possibly tell one from the other without looking too far ahead? > In these cases, the C++ front-end can avoid calling "fold" on the > COND_EXPR its creating in build_conditional_expr. This only impacts > that C++ front-end and doesn't impact performance of C/fortran/java > code that may usefully take advantage of min/max. See that I've already suggested the solution for the other languages in which cond_expr is never an lvalue: make sure they turn the operands of the cond_expr into non-lvalues, even if this demands gratuitous non_lvalue_exprs or nops. > An improvement on this approach is for the C++ front-end never to create > COND_EXPR, MIN_EXPR or MAX_EXPR as the target of MODIFY_EXPRs, and lower > them itself upon creation. By forbidding them in "generic", support for > COND_EXPRs as lvalues can be removed from language-independent > gimplification, fold, non_lvalue, etc... greatly simplifying the compiler. This isn't a complete solution. MODIFY_EXPR is not the only situation in which lvalueness of a COND_EXPR is relevant. You may have to bind a reference to the result of a COND_EXPR. > Finally, the third approach would be to introduce new tree codes for > LCOND_EXPR, LMIN_EXPR and LMAX_EXPR that reflect the subtley different > semantics of these operators when uses as lvalues. Why bother? We already handle them all properly, except for this one case that mis-handles COND_EXPRs whose compares include extensions. We can fix that, and not lose performance by getting front-ends that can offer guarantees about non-lvalueness of COND_EXPRs to give this information to the middle end. > My final comment is that in the lowering of (a ? b : c) = d by using > a pointer temporary runs into the problems with bitfields "b" and "c", > and marking of objects addressable when they need not be. Yup. > runs into problems. A better approach it to use a temporary for "d". Yup, we have a transformation that does just that at some point. But again, it only operates on MODIFY_EXPRs, it can't help for the other important lvalue case, that of reference-binding. Hmm... Maybe we could generate the COND_EXPR without folding, and then, when we use it as an rvalue, we fold it; when it use it as an lvalue, we transform it in something else that is fold-resistant. I'm not sure I like this, but I suppose it's the only way to go if we don't want to enable COND_EXPR, MIN_EXPR and MAX_EXPR to be handled as lvalues in the middle end. -- Alexandre Oliva http://www.ic.unicamp.br/~oliva/ Red Hat Compiler Engineer [EMAIL PROTECTED], gcc.gnu.org} Free Software Evangelist [EMAIL PROTECTED], gnu.org}