Hi Alex and Mark, On 7 Mar 2005, mark at codesourcery dot com wrote: > Yes, I understand. You still need to take it up with Roger, though.
My apologies to both of you for being curiously/annoyingly silent on this is issue. I've been getting up to speed on the internals of the C++ parser, in order to come up with a correct solution to this problem. 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. Hence it's not this transformation in fold that's in error. 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". In all fairness, though I suspect most of the middle-end is currently set-up to handle the implications of this. For example, in several places we perform transformations that assume MIN_EXPR and MAX_EXPR are commutative, but this is only true for lvalue MIN_EXPR and lvalue MAX_EXPR. For rvalue MIN_EXPR and rvalue MAX_EXPR, the semantics need to specify a reference to the first operand is returned for values comparing equal. I also suspect that the gimplification process may not be preserving the lvalue-ness during lowering. Simply disabling the COND_EXPR -> MIN_EXPR/MAX_EXPR transformation is also likely to be a serious performance penalty, especially on targets that support efficient sequences for "min" and "max". Clearly, it's always safe to only perform this when one side or other is an rvalue, but taking the maximum of two user defined variables, I would expect to be a fairly common instance. My current thinking of how best to solve this falls into one of three plans. 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. 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. If the parser can't be used to provide useful context, we could potentially postpone the calling of "fold" for C++ COND_EXPRs during parsing, but call "fold" on COND_EXPRs while lowering to gimple, where we'll always know whether we're expecting lvalues/rvalues. 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. 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. If these were then created by the C++ front-end when a lvalue is potentially required, it would provide a convenient mechanism for the middle-end to distinguish which transformations and implementation/lowering strategies are appplicable. 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. i.e. t = a ? &b : &c; *t = d; runs into problems. A better approach it to use a temporary for "d". i.e. t = d; if (a) b = t; else c = t; If C++ semantics don't allow for a new temporary (i.e. a SAVE_EXPR) in this case, then we can do far worse than to duplicate "d", i.e. if (a) b = d; else c = d; Sorry again for my hesitancy in replying, but I'm desparately trying to get up to speed on the options available to the C++ front-end before recommending the correct long term fix. Does anyone have opinions on each of the above approaches? [I predict the tree-ssa folks will argue we disallow COND_EXPRs as lvalues, and the C++ folks will argue that knowing whether an expression appears before "=" is difficult (requiring deep lookahead) at parse time.] "Stuck-in-the-middle"-end! Roger --