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