diff options
author | Martin Sebor <msebor@redhat.com> | 2019-07-09 04:15:42 +0000 |
---|---|---|
committer | Martin Sebor <msebor@gcc.gnu.org> | 2019-07-08 22:15:42 -0600 |
commit | aac9480da1ffd037ceb21790fe341b3ec23283d9 (patch) | |
tree | 4951dd2f7b63d615f0746cec0cc0235637d4b588 /gcc/testsuite/gcc.c-torture | |
parent | 7d64aec499687f593a1bab4ae7cac843bc1d47af (diff) | |
download | gcc-aac9480da1ffd037ceb21790fe341b3ec23283d9.zip gcc-aac9480da1ffd037ceb21790fe341b3ec23283d9.tar.gz gcc-aac9480da1ffd037ceb21790fe341b3ec23283d9.tar.bz2 |
PR middle-end/71924 - missing -Wreturn-local-addr returning alloca result
PR middle-end/71924 - missing -Wreturn-local-addr returning alloca result
PR middle-end/90549 - missing -Wreturn-local-addr maybe returning an address of a local array plus offset
gcc/ChangeLog:
PR middle-end/71924
PR middle-end/90549
* gimple-ssa-isolate-paths.c (isolate_path): Add attribute. Update
comment.
(args_loc_t): New type.
(args_loc_t, locmap_t): same.
(diag_returned_locals): New function.
(is_addr_local): Same.
(handle_return_addr_local_phi_arg, warn_return_addr_local): Same.
(find_implicit_erroneous_behavior): Call warn_return_addr_local_phi_arg.
(find_explicit_erroneous_behavior): Call warn_return_addr_local.
gcc/testsuite/ChangeLog:
PR middle-end/71924
PR middle-end/90549
* gcc.c-torture/execute/return-addr.c: New test.
* gcc.dg/Wreturn-local-addr-2.c: New test.
* gcc.dg/Wreturn-local-addr-4.c: New test.
* gcc.dg/Wreturn-local-addr-5.c: New test.
* gcc.dg/Wreturn-local-addr-6.c: New test.
* gcc.dg/Wreturn-local-addr-7.c: New test.
* gcc.dg/Wreturn-local-addr-8.c: New test.
* gcc.dg/Wreturn-local-addr-9.c: New test.
* gcc.dg/Wreturn-local-addr-10.c: New test.
* gcc.dg/Walloca-4.c: Handle expected warnings.
* gcc.dg/pr41551.c: Same.
* gcc.dg/pr59523.c: Same.
* gcc.dg/tree-ssa/pr88775-2.c: Same.
* gcc.dg/tree-ssa/alias-37.c: Same.
* gcc.dg/winline-7.c: Same.
From-SVN: r273261
Diffstat (limited to 'gcc/testsuite/gcc.c-torture')
-rw-r--r-- | gcc/testsuite/gcc.c-torture/execute/return-addr.c | 122 |
1 files changed, 122 insertions, 0 deletions
diff --git a/gcc/testsuite/gcc.c-torture/execute/return-addr.c b/gcc/testsuite/gcc.c-torture/execute/return-addr.c new file mode 100644 index 0000000..7981818 --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/execute/return-addr.c @@ -0,0 +1,122 @@ +/* Test to verify that a function that returns either the address + of a local variable or a non-local via a MAX_EXPR or MIN_EXPR + doesn't return null when the result of the expression is + the latter. */ + +#define NOIPA __attribute__ ((noclone, noinline, noipa)) + +#define A(expr) \ + ((expr) \ + ? (void)0 \ + : (__builtin_printf ("assertion failed on line %i: %s\n", \ + __LINE__, #expr), \ + __builtin_abort ())) + + +typedef __UINTPTR_TYPE__ uintptr_t; + +/* Return a bigger value than P. The address still points (just + past) the local variable pointed to by P so the caller does + return the address of a local variable but that's hidden from + GCC by the attribute and the point of the test is to verify + that the address in the return statement in the caller isn't + replaced by null when GCC cannot prove the address doesn't + reference a non-local variable. */ + +NOIPA char* get_max_2 (char *p) +{ + return p + 1; +} + +NOIPA char* get_max_3 (char *p, char *q) +{ + return p < q ? q + 1 : p + 1; +} + +/* Analogous to the above. The expressions are undefined because + they form an address prior to the beginning of the object but + it's hidden from GCC by the attributes. */ + +NOIPA char* get_min_2 (char *p) +{ + return p - 1; +} + +NOIPA char* get_min_3 (char *p, char *q) +{ + return p < q ? p - 1 : q - 1; +} + + +NOIPA void* test_max_2 (void) +{ + char c; + + char *p = get_max_2 (&c); + + void *q = p > &c ? p : &c; /* MAX_EXPR */ + return q; +} + +NOIPA void* test_max_3 (void) +{ + char c; + char d; + + char *p = get_max_3 (&c, &d); + + void *q = p < &c ? &c < &d ? &d : &c : p; + return q; +} + +NOIPA void* test_min_2 (void) +{ + char c; + + char *p = get_min_2 (&c); + + void *q = p < &c ? p : &c; /* MIN_EXPR" */ + return q; +} + +NOIPA void* test_min_3 (void) +{ + char c; + char d; + + char *p = get_min_3 (&c, &d); + + void *q = p > &c ? &c > &d ? &d : &c : p; + return q; +} + +NOIPA void* test_min_3_phi (int i) +{ + char a, b; + + char *p0 = &a; + char *p1 = &b; + char *p2 = get_min_3 (&a, &b); + char *p3 = get_min_3 (&a, &b); + + char *p4 = p2 < p0 ? p2 : p0; + char *p5 = p3 < p1 ? p3 : p1; + + __builtin_printf ("%p %p %p %p\n", p2, p3, p4, p5); + + if (i == 1) + return p4; + else + return p5; +} + +int main () +{ + A (0 != test_max_2 ()); + A (0 != test_max_3 ()); + + A (0 != test_min_2 ()); + A (0 != test_min_3 ()); + + A (0 != test_min_3_phi (0)); +} |