diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 73a76d029afb928449d1eba97348c57bdfa19700..0e07e956f8234d2a5521544f5de5b2c23df856ef 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2004-09-09 Hans-Peter Nilsson <hp@axis.com> + + PR target/17377 + * gcc.c-torture/execute/pr17377.c: New test. + 2004-09-09 Joseph S. Myers <jsm@polyomino.org.uk> PR c/8420 diff --git a/gcc/testsuite/gcc.c-torture/execute/pr17377.c b/gcc/testsuite/gcc.c-torture/execute/pr17377.c new file mode 100644 index 0000000000000000000000000000000000000000..0be6f0a849e92cc60b64fb71b2f24c2c8f03a9be --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/execute/pr17377.c @@ -0,0 +1,59 @@ +/* PR target/17377 + Bug in code emitted by "return" pattern on CRIS: missing pop of + forced return address on stack. */ +int calls = 0; + +void *f (int) __attribute__ ((__noinline__)); +void * +f (int i) +{ + /* The code does a little brittle song and dance to trig the "return" + pattern instead of the function epilogue. This must still be a + leaf function for the bug to be exposed. */ + + if (calls++ == 0) + return __builtin_return_address (0); + + switch (i) + { + case 1: + return f; + case 0: + return __builtin_return_address (0); + } + return 0; +} + +int x; + +void *y (int i) __attribute__ ((__noinline__)); +void * +y (int i) +{ + x = 0; + + /* This must not be a sibling call: the return address must appear + constant for different calls to this function. Postincrementing x + catches otherwise unidentified multiple returns (e.g. through the + return-address register and then this epilogue popping the address + stored on stack in "f"). */ + return (char *) f (i) + x++; +} + +int +main (void) +{ + void *v = y (4); + if (y (1) != f + /* Can't reasonably check the validity of the return address + above, but it's not that important: the test-case will probably + crash on the first call to f with the bug present, or it will + run wild including returning early (in y or here), so we also + try and check the number of calls. */ + || y (0) != v + || y (3) != 0 + || y (-1) != 0 + || calls != 5) + abort (); + exit (0); +}