This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [Bug c++/19199] [3.3/3.4/4.0/4.1 Regression] Wrong warning aboutreturning a reference to a temporary


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
--


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]