65 lines
1.1 KiB
C
65 lines
1.1 KiB
C
/* { dg-options "-O2 -fno-inline-functions" } */
|
|
/* { dg-do run } */
|
|
|
|
/* Gimplification problem exposed by zsh. All the side-effects in
|
|
function arguments and in the called expression should happen
|
|
before the actual function call. */
|
|
extern void abort (void);
|
|
int A;
|
|
|
|
typedef void (*fnptr) (void);
|
|
fnptr *F;
|
|
|
|
void
|
|
foo (int x)
|
|
{
|
|
if (A == x)
|
|
abort ();
|
|
}
|
|
|
|
void
|
|
bar (int x, int y)
|
|
{
|
|
if (x == 5 || y != 3)
|
|
abort ();
|
|
}
|
|
|
|
void
|
|
boz (void)
|
|
{
|
|
abort ();
|
|
}
|
|
|
|
void
|
|
baz (void)
|
|
{
|
|
if (*F != boz)
|
|
abort ();
|
|
}
|
|
|
|
fnptr B[2] = { baz, boz };
|
|
|
|
main ()
|
|
{
|
|
int b, c;
|
|
|
|
/* The gimplifier was emitting A++ after the call to foo. */
|
|
A = 5;
|
|
foo (A++);
|
|
|
|
/* The increment to 'b' and 'c' must happen before the call. However,
|
|
the first argument to bar() must be the original value of 'b', while
|
|
the second argument must be the new value of 'c'. */
|
|
b = 4;
|
|
c = 2;
|
|
bar (b++, ++c);
|
|
|
|
/* This call via function pointer *F should go to baz, but F should
|
|
be incremented before the actual call (i.e., right before the
|
|
call F should be pointing to boz). */
|
|
F = &B[0];
|
|
(*F++) ();
|
|
|
|
return 0;
|
|
}
|