1*7c3d14c8STreehugger Robot // RUN: %clangxx_asan -O1 %s -o %t
2*7c3d14c8STreehugger Robot // RUN: not %run %t 0 2>&1 | FileCheck %s --check-prefix=CHECK0
3*7c3d14c8STreehugger Robot // RUN: not %run %t 1 2>&1 | FileCheck %s --check-prefix=CHECK1
4*7c3d14c8STreehugger Robot // RUN: not %run %t 2 2>&1 | FileCheck %s --check-prefix=CHECK2
5*7c3d14c8STreehugger Robot // RUN: not %run %t 3 2>&1 | FileCheck %s --check-prefix=CHECK3
6*7c3d14c8STreehugger Robot
7*7c3d14c8STreehugger Robot #define NOINLINE __attribute__((noinline))
break_optimization(void * arg)8*7c3d14c8STreehugger Robot inline void break_optimization(void *arg) {
9*7c3d14c8STreehugger Robot __asm__ __volatile__("" : : "r" (arg) : "memory");
10*7c3d14c8STreehugger Robot }
11*7c3d14c8STreehugger Robot
Frame0(int frame,char * a,char * b,char * c)12*7c3d14c8STreehugger Robot NOINLINE static void Frame0(int frame, char *a, char *b, char *c) {
13*7c3d14c8STreehugger Robot char s[4] = {0};
14*7c3d14c8STreehugger Robot char *d = s;
15*7c3d14c8STreehugger Robot break_optimization(&d);
16*7c3d14c8STreehugger Robot switch (frame) {
17*7c3d14c8STreehugger Robot case 3: a[5]++; break;
18*7c3d14c8STreehugger Robot case 2: b[5]++; break;
19*7c3d14c8STreehugger Robot case 1: c[5]++; break;
20*7c3d14c8STreehugger Robot case 0: d[5]++; break;
21*7c3d14c8STreehugger Robot }
22*7c3d14c8STreehugger Robot }
Frame1(int frame,char * a,char * b)23*7c3d14c8STreehugger Robot NOINLINE static void Frame1(int frame, char *a, char *b) {
24*7c3d14c8STreehugger Robot char c[4] = {0}; Frame0(frame, a, b, c);
25*7c3d14c8STreehugger Robot break_optimization(0);
26*7c3d14c8STreehugger Robot }
Frame2(int frame,char * a)27*7c3d14c8STreehugger Robot NOINLINE static void Frame2(int frame, char *a) {
28*7c3d14c8STreehugger Robot char b[4] = {0}; Frame1(frame, a, b);
29*7c3d14c8STreehugger Robot break_optimization(0);
30*7c3d14c8STreehugger Robot }
Frame3(int frame)31*7c3d14c8STreehugger Robot NOINLINE static void Frame3(int frame) {
32*7c3d14c8STreehugger Robot char a[4] = {0}; Frame2(frame, a);
33*7c3d14c8STreehugger Robot break_optimization(0);
34*7c3d14c8STreehugger Robot }
35*7c3d14c8STreehugger Robot
main(int argc,char ** argv)36*7c3d14c8STreehugger Robot int main(int argc, char **argv) {
37*7c3d14c8STreehugger Robot if (argc != 2) return 1;
38*7c3d14c8STreehugger Robot Frame3(argv[1][0] - '0');
39*7c3d14c8STreehugger Robot }
40*7c3d14c8STreehugger Robot
41*7c3d14c8STreehugger Robot // CHECK0: AddressSanitizer: stack-buffer-overflow
42*7c3d14c8STreehugger Robot // CHECK0: #0{{.*}}Frame0
43*7c3d14c8STreehugger Robot // CHECK0: #1{{.*}}Frame1
44*7c3d14c8STreehugger Robot // CHECK0: #2{{.*}}Frame2
45*7c3d14c8STreehugger Robot // CHECK0: #3{{.*}}Frame3
46*7c3d14c8STreehugger Robot // CHECK0: is located in stack of thread T0 at offset
47*7c3d14c8STreehugger Robot // CHECK0-NEXT: #0{{.*}}Frame0
48*7c3d14c8STreehugger Robot //
49*7c3d14c8STreehugger Robot // CHECK1: AddressSanitizer: stack-buffer-overflow
50*7c3d14c8STreehugger Robot // CHECK1: is located in stack of thread T0 at offset
51*7c3d14c8STreehugger Robot // CHECK1-NEXT: #0{{.*}}Frame1
52*7c3d14c8STreehugger Robot //
53*7c3d14c8STreehugger Robot // CHECK2: AddressSanitizer: stack-buffer-overflow
54*7c3d14c8STreehugger Robot // CHECK2: is located in stack of thread T0 at offset
55*7c3d14c8STreehugger Robot // CHECK2-NEXT: #0{{.*}}Frame2
56*7c3d14c8STreehugger Robot //
57*7c3d14c8STreehugger Robot // CHECK3: AddressSanitizer: stack-buffer-overflow
58*7c3d14c8STreehugger Robot // CHECK3: is located in stack of thread T0 at offset
59*7c3d14c8STreehugger Robot // CHECK3-NEXT: #0{{.*}}Frame3
60