testsuite: Skip analyzer tests on AIX.
[official-gcc.git] / gcc / testsuite / c-c++-common / strub-defer-O3.c
blob40ee8edd1e0e68b886ae15c042bfb5e4682d3099
1 /* { dg-do run } */
2 /* { dg-options "-fstrub=strict -O3" } */
3 /* { dg-require-effective-target strub } */
5 /* Check that a strub function called by another strub function defers the
6 strubbing to its caller at -O3. */
8 #ifndef EXPECT_DEFERRAL
9 /* Other strub-defer*.c tests override this macro. */
10 # define EXPECT_DEFERRAL
11 #endif
13 const char test_string[] = "\x55\xde\xad\xbe\xef\xc0\x1d\xca\xfe\x55\xaa";
15 /* Pad before and after the string on the stack, so that it's not overwritten by
16 regular stack use. */
17 #define PAD 7
19 static inline __attribute__ ((__always_inline__, __strub__ ("callable")))
20 char *
21 leak_string (void)
23 /* We use this variable to avoid any stack red zone. Stack scrubbing covers
24 it, but __builtin_stack_address, that we take as a reference, doesn't, so
25 if e.g. callable() were to store the string in the red zone, we wouldn't
26 find it because it would be outside the range we searched. */
27 typedef void __attribute__ ((__strub__ ("callable"))) callable_t (char *);
28 callable_t *f = 0;
30 char s[2 * PAD + 1][sizeof (test_string)];
31 __builtin_strcpy (s[PAD], test_string);
32 asm ("" : "+m" (s), "+r" (f));
34 if (__builtin_expect (!f, 1))
35 return (char*)__builtin_stack_address ();
37 f (s[PAD]);
38 return 0;
41 static inline __attribute__ ((__always_inline__, __strub__ ("callable")))
42 int
43 look_for_string (char *e)
45 char *p = (char*)__builtin_stack_address ();
47 if (p == e)
48 __builtin_abort ();
50 if (p > e)
52 char *q = p;
53 p = e;
54 e = q;
57 for (char *re = e - sizeof (test_string); p < re; p++)
58 for (int i = 0; p[i] == test_string[i]; i++)
59 if (i == sizeof (test_string) - 1)
60 return i;
62 return 0;
65 static __attribute__ ((__strub__ ("at-calls"), __noinline__, __noclone__))
66 char *
67 at_calls ()
69 return leak_string ();
72 static __attribute__ ((__strub__ ("at-calls")))
73 char *
74 deferred_at_calls ()
76 char *ret;
77 int i = 1;
78 /* Since these test check stack contents above the top of the stack, an
79 unexpected asynchronous signal or interrupt might overwrite the bits we
80 expect to find and cause spurious fails. Tolerate one such overall
81 spurious fail by retrying. */
82 while (EXPECT_DEFERRAL !look_for_string ((ret = at_calls ())))
83 if (!i--) __builtin_abort ();
84 return ret;
87 static __attribute__ ((__strub__ ("internal")))
88 char *
89 deferred_internal ()
91 int i = 1;
92 char *ret;
93 while (EXPECT_DEFERRAL !look_for_string ((ret = at_calls ())))
94 if (!i--) __builtin_abort ();
95 return ret;
98 int main ()
100 int i = 1;
101 /* These calls should not be subject to spurious fails: whether or not some
102 asynchronous event overwrites the scrubbed stack space, the string won't
103 remain there. Unless the asynchronous event happens to write the string
104 where we look for it, but what are the odds? Anyway, it doesn't hurt to
105 retry, even if just for symmetry. */
106 while (look_for_string (deferred_at_calls ()))
107 if (!i--) __builtin_abort ();
108 while (look_for_string (deferred_internal ()))
109 if (!i--) __builtin_abort ();
110 __builtin_exit (0);