Require target lra in gcc.dg/pr108095.c
[official-gcc.git] / gcc / testsuite / gcc.dg / Winfinite-recursion-2.c
blob23483122a6b053a42cddeb18ab6da6b147925f5b
1 /* PR middle-end/88232 - Please implement -Winfinite-recursion
2 Exercise warning with optimization. Same as -Winfinite-recursion.c
3 plus mutually recursive calls that depend on inlining.
4 { dg-do compile }
5 { dg-options "-O2 -Wall -Winfinite-recursion" } */
7 #define NORETURN __attribute__ ((noreturn))
9 typedef __SIZE_TYPE__ size_t;
11 extern void abort (void);
12 extern void exit (int);
14 extern int ei;
15 int (*pfi_v)(void);
18 /* Make sure the warning doesn't assume every call has a DECL. */
20 int nowarn_pfi_v (void)
22 return pfi_v ();
26 int warn_fi_v (void) // { dg-warning "-Winfinite-recursion" }
28 return warn_fi_v (); // { dg-message "recursive call" }
31 /* Verify #pragma suppression works. */
33 #pragma GCC diagnostic push
34 #pragma GCC diagnostic ignored "-Winfinite-recursion"
36 int suppress_warn_fi_v (void)
38 return warn_fi_v ();
41 #pragma GCC diagnostic pop
43 int nowarn_fi_v (void)
45 if (ei++ == 0)
46 return nowarn_fi_v ();
47 return 0;
51 int warn_if_i (int i) // { dg-warning "-Winfinite-recursion" }
53 if (i > 0)
54 return warn_if_i (--i); // { dg-message "recursive call" }
55 else if (i < 0)
56 return warn_if_i (-i); // { dg-message "recursive call" }
57 else
58 return warn_if_i (7); // { dg-message "recursive call" }
62 int nowarn_if_i (int i)
64 if (i > 0)
65 return nowarn_if_i (--i);
66 else if (i < 0)
67 return nowarn_if_i (-i);
68 else
69 return -1;
72 int nowarn_switch (int i, int a[])
74 switch (i)
76 case 0: return nowarn_switch (a[3], a + 1);
77 case 1: return nowarn_switch (a[5], a + 2);
78 case 2: return nowarn_switch (a[7], a + 3);
79 case 3: return nowarn_switch (a[9], a + 4);
81 return 77;
84 int warn_switch (int i, int a[]) // { dg-warning "-Winfinite-recursion" }
86 switch (i)
88 case 0: return warn_switch (a[3], a + 1);
89 case 1: return warn_switch (a[5], a + 2);
90 case 2: return warn_switch (a[7], a + 3);
91 case 3: return warn_switch (a[9], a + 4);
92 default: return warn_switch (a[1], a + 5);
96 NORETURN void fnoreturn (void);
98 /* Verify there's no warning for a function that doesn't return. */
99 int nowarn_call_noret (void)
101 fnoreturn ();
104 int warn_call_noret_r (void) // { dg-warning "-Winfinite-recursion" }
106 warn_call_noret_r (); // { dg-message "recursive call" }
107 fnoreturn ();
110 /* Verify a warning even though the abort() call would prevent the infinite
111 recursion. There's no good way to tell the two cases apart and letting
112 a simple abort prevent the warning would make it ineffective in cases
113 where it's the result of assert() expansion and not meant to actually
114 prevent recursion. */
117 warn_noret_call_abort_r (char *s, int n) // { dg-warning "-Winfinite-recursion" }
119 if (!s)
120 abort ();
122 if (n > 7)
123 abort ();
125 return n + warn_noret_call_abort_r (s, n - 1); // { dg-message "recursive call" }
128 /* Verify that a warning is not issued for an apparently infinitely
129 recursive function like the one above where the recursion would be
130 prevented by a call to a noreturn function if the recursive function
131 is itself declared noreturn. */
133 NORETURN void nowarn_noret_call_abort_r (int n)
135 if (n > 7)
136 abort ();
138 nowarn_noret_call_abort_r (n - 1);
141 int warn_call_abort_r (int n) // { dg-warning "-Winfinite-recursion" }
143 n += warn_call_abort_r (n - 1); // { dg-message "recursive call" }
144 if (n > 7) // unreachable
145 abort ();
146 return n;
150 /* And again with exit() for good measure. */
152 int warn_call_exit_r (int n) // { dg-warning "-Winfinite-recursion" }
154 n += warn_call_exit_r (n - 1); // { dg-message "recursive call" }
155 if (n > 7)
156 exit (0);
157 return n;
160 struct __jmp_buf_tag { };
161 typedef struct __jmp_buf_tag jmp_buf[1];
163 extern jmp_buf jmpbuf;
165 /* A call to longjmp() breaks infinite recursion. Verify it suppresses
166 the warning. */
168 int nowarn_call_longjmp_r (int n)
170 if (n > 7)
171 __builtin_longjmp (jmpbuf, 1);
172 return n + nowarn_call_longjmp_r (n - 1);
175 int warn_call_longjmp_r (int n) // { dg-warning "-Winfinite-recursion" }
177 n += warn_call_longjmp_r (n - 1); // { dg-message "recursive call" }
178 if (n > 7)
179 __builtin_longjmp (jmpbuf, 1);
180 return n;
184 struct __sigjmp_buf_tag { };
185 typedef struct __sigjmp_buf_tag sigjmp_buf[1];
187 extern sigjmp_buf sigjmpbuf;
189 /* GCC has no __builtin_siglongjmp(). */
190 extern void siglongjmp (sigjmp_buf, int);
192 /* A call to longjmp() breaks infinite recursion. Verify it suppresses
193 the warning. */
195 int nowarn_call_siglongjmp_r (int n)
197 if (n > 7)
198 siglongjmp (sigjmpbuf, 1);
199 return n + nowarn_call_siglongjmp_r (n - 1);
203 int nowarn_while_do_call_r (int n)
205 int z = 0;
206 while (n)
207 z += nowarn_while_do_call_r (n--);
208 return z;
211 int warn_do_while_call_r (int n) // { dg-warning "-Winfinite-recursion" }
213 int z = 0;
215 z += warn_do_while_call_r (n); // { dg-message "recursive call" }
216 while (--n);
217 return z;
221 /* Verify warnings for a naive replacement of a built-in fucntion. */
223 void* malloc (size_t n) // { dg-warning "-Winfinite-recursion" }
225 size_t *p =
226 (size_t*)__builtin_malloc (n + sizeof n); // { dg-message "recursive call" }
227 *p = n;
228 return p + 1;
232 int nowarn_fact (int n)
234 return n ? n * nowarn_fact (n - 1) : 1;
238 static int fi_v (void);
240 /* It would seem preferable to issue the warning for the extern function
241 but as it happens it's the static function that's inlined into a recursive
242 call to itself and warn_call_fi_v() expands to a call to it. */
244 int warn_call_fi_v (void) // { dg-warning "-Winfinite-recursion" "" { xfail *-*-* } }
246 return fi_v (); // { dg-message "recursive call" }
249 static int fi_v (void) // { dg-warning "-Winfinite-recursion" }
251 return warn_call_fi_v ();