1 /* { dg-skip-if "requires frame pointers" { *-*-* } "-fomit-frame-pointer" "" } */
2 /* { dg-require-effective-target return_address } */
3
4 extern void exit (int);
5 extern void abort (void);
6 extern void *alloca (__SIZE_TYPE__);
7 char *dummy (void);
8
9 #define NOINLINE __attribute__((noinline)) __attribute__ ((noclone))
10
11 void *save_ret1[6];
12 void *test4a (char *);
13 void *test5a (char *);
14 void *test6a (char *);
15
test1(void)16 void NOINLINE *test1 (void)
17 {
18 void * temp;
19 temp = __builtin_return_address (0);
20 return temp;
21 }
22
test2(void)23 void NOINLINE *test2 (void)
24 {
25 void * temp;
26 dummy ();
27 temp = __builtin_return_address (0);
28 return temp;
29 }
30
test3(void)31 void NOINLINE *test3 (void)
32 {
33 void * temp;
34 temp = __builtin_return_address (0);
35 dummy ();
36 return temp;
37 }
38
test4(void)39 void NOINLINE *test4 (void)
40 {
41 char * save = (char*) alloca (4);
42
43 return test4a (save);
44 }
45
test4a(char * p)46 void *NOINLINE test4a (char * p)
47 {
48 void * temp;
49 temp = __builtin_return_address (1);
50 return temp;
51 }
52
test5(void)53 void NOINLINE *test5 (void)
54 {
55 char * save = (char*) alloca (4);
56
57 return test5a (save);
58 }
59
test5a(char * p)60 void NOINLINE *test5a (char * p)
61 {
62 void * temp;
63 dummy ();
64 temp = __builtin_return_address (1);
65 return temp;
66 }
67
test6(void)68 void NOINLINE *test6 (void)
69 {
70 char * save = (char*) alloca (4);
71
72 return test6a (save);
73 }
74
test6a(char * p)75 void NOINLINE *test6a (char * p)
76 {
77 void * temp;
78 temp = __builtin_return_address (1);
79 dummy ();
80 return temp;
81 }
82
83 void *(*func1[6])(void) = { test1, test2, test3, test4, test5, test6 };
84
call_func1(int i)85 char * NOINLINE call_func1 (int i)
86 {
87 save_ret1[i] = func1[i] ();
88 }
89
90 static void *ret_addr;
91 void *save_ret2[6];
92 void test10a (char *);
93 void test11a (char *);
94 void test12a (char *);
95
test7(void)96 void NOINLINE test7 (void)
97 {
98 ret_addr = __builtin_return_address (0);
99 return;
100 }
101
test8(void)102 void NOINLINE test8 (void)
103 {
104 dummy ();
105 ret_addr = __builtin_return_address (0);
106 return;
107 }
108
test9(void)109 void NOINLINE test9 (void)
110 {
111 ret_addr = __builtin_return_address (0);
112 dummy ();
113 return;
114 }
115
test10(void)116 void NOINLINE test10 (void)
117 {
118 char * save = (char*) alloca (4);
119
120 test10a (save);
121 }
122
test10a(char * p)123 void NOINLINE test10a (char * p)
124 {
125 ret_addr = __builtin_return_address (1);
126 return;
127 }
128
test11(void)129 void NOINLINE test11 (void)
130 {
131 char * save = (char*) alloca (4);
132
133 test11a (save);
134 }
135
test11a(char * p)136 void NOINLINE test11a (char * p)
137 {
138 dummy ();
139 ret_addr = __builtin_return_address (1);
140 return;
141 }
142
test12(void)143 void NOINLINE test12 (void)
144 {
145 char * save = (char*) alloca (4);
146
147 test12a (save);
148 }
149
test12a(char * p)150 void NOINLINE test12a (char * p)
151 {
152 ret_addr = __builtin_return_address (1);
153 dummy ();
154 return;
155 }
156
dummy(void)157 char * dummy (void)
158 {
159 char * save = (char*) alloca (4);
160
161 return save;
162 }
163
164 void (*func2[6])(void) = { test7, test8, test9, test10, test11, test12 };
165
call_func2(int i)166 void NOINLINE call_func2 (int i)
167 {
168 func2[i] ();
169 save_ret2[i] = ret_addr;
170 }
171
main(void)172 int main (void)
173 {
174 int i;
175
176 for (i = 0; i < 6; i++) {
177 call_func1(i);
178 }
179
180 if (save_ret1[0] != save_ret1[1]
181 || save_ret1[1] != save_ret1[2])
182 abort ();
183 if (save_ret1[3] != save_ret1[4]
184 || save_ret1[4] != save_ret1[5])
185 abort ();
186 if (save_ret1[3] && save_ret1[0] != save_ret1[3])
187 abort ();
188
189
190 for (i = 0; i < 6; i++) {
191 call_func2(i);
192 }
193
194 if (save_ret2[0] != save_ret2[1]
195 || save_ret2[1] != save_ret2[2])
196 abort ();
197 if (save_ret2[3] != save_ret2[4]
198 || save_ret2[4] != save_ret2[5])
199 abort ();
200 if (save_ret2[3] && save_ret2[0] != save_ret2[3])
201 abort ();
202
203 exit (0);
204 }
205