This is the mail archive of the
gcc-bugs@gcc.gnu.org
mailing list for the GCC project.
Re: C++ tree inlining bug with dynamic arrays
- To: Mark Mitchell <mark at codesourcery dot com>
- Subject: Re: C++ tree inlining bug with dynamic arrays
- From: Jim Wilson <wilson at cygnus dot com>
- Date: Wed, 26 Jan 2000 12:58:35 -0800
- cc: gcc-bugs at gcc dot gnu dot org
The right thing to do in C++ is to change
T a[E];
(where `E' is an expression) into:
int temp = E;
T a[temp];
That is exactly what the SAVE_EXPR does. It creates an unnamed local
temporary variable that has no associated decl node, and this temp gets
set only once, at the point where it is first used.
BTW, the C9x standard says that "it is unspecified whether
side-effects are produced when the size expression is evaluated".
The use of SAVE_EXPRs for VLA isn't because of problems with side-effects; it
is because variables can change. If the user says
int a[E];
E = 10;
sizeof (a)
then it would be wrong to compute 4 * E as the size of a, because E changed
in between the declaration of A and the sizeof. To avoid this problem, we
use a SAVE_EXPR, which ensures that 4 * E gets computed only once, at the
point of the declaration.
I know of only one funny case that occurs because of side-effects. If you
use a VLA as a function parameter, then there is no reason to compute the
size (unless you use sizeof), and hence side-effects don't occur natually.
If you declare a local as a VLA, then we must compute the size so that we can
allocate space, and hence side-effects occur naturally. Since we use a
SAVE_EXPR, the side-effects occur only once, even if sizeof is used multiple
times. This produces an inconsistency. To avoid the inconsistency, we
added special code at the end of expand_function_start which passes every
parameter type size to expand_expr, to force the side-effects to occur once.
This special code makes this program print 11 instead of 10.
int
sub (int i, int a[i++])
{
return i;
}
main()
{
int i = 10;
int array[i];
printf ("%d\n", sub (i, array));
return 0;
}
Alternatively, we could fix the inconsistency by not performing the side-effect
for local variable VLAs, and then remove the code in expand_function_start.
At the time, this seemed harder to implement, and harder to justify. After all
if we called alloca instead of using a VLA, then we would have performed the
side-effect, so it seems a little silly not to perform the side-effect when
using a VLA.
In general, I've concluded that SAVE_EXPRs are
semi-evil. I presume that they were invented because in
statement-at-a-time mode it's tough to introduce new temporaries on
the fly.
So you want to replace the SAVE_EXPR nodes with explicit unnamed local const
temporary VAR_DECL/PARM_DECL nodes. That seems like a reasonable thing to try.
Adding extra fake PARM_DECL nodes might be a little tricky. Perhaps we can
put the VLA parameter type sizes into local variables.
Doing this with functions-as-trees should be easier than doing it with old
statement at a time stuff.
Jim