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.
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);
18 /* Make sure the warning doesn't assume every call has a DECL. */
20 int nowarn_pfi_v (void)
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)
41 #pragma GCC diagnostic pop
43 int nowarn_fi_v (void)
46 return nowarn_fi_v ();
51 int warn_if_i (int i
) // { dg-warning "-Winfinite-recursion" }
54 return warn_if_i (--i
); // { dg-message "recursive call" }
56 return warn_if_i (-i
); // { dg-message "recursive call" }
58 return warn_if_i (7); // { dg-message "recursive call" }
62 int nowarn_if_i (int i
)
65 return nowarn_if_i (--i
);
67 return nowarn_if_i (-i
);
72 int nowarn_switch (int i
, int a
[])
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);
84 int warn_switch (int i
, int a
[]) // { dg-warning "-Winfinite-recursion" }
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)
104 int warn_call_noret_r (void) // { dg-warning "-Winfinite-recursion" }
106 warn_call_noret_r (); // { dg-message "recursive call" }
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" }
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
)
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
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" }
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
168 int nowarn_call_longjmp_r (int n
)
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" }
179 __builtin_longjmp (jmpbuf
, 1);
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
195 int nowarn_call_siglongjmp_r (int n
)
198 siglongjmp (sigjmpbuf
, 1);
199 return n
+ nowarn_call_siglongjmp_r (n
- 1);
203 int nowarn_while_do_call_r (int n
)
207 z
+= nowarn_while_do_call_r (n
--);
211 int warn_do_while_call_r (int n
) // { dg-warning "-Winfinite-recursion" }
215 z
+= warn_do_while_call_r (n
); // { dg-message "recursive call" }
221 /* Verify warnings for a naive replacement of a built-in fucntion. */
223 void* malloc (size_t n
) // { dg-warning "-Winfinite-recursion" }
226 (size_t*)__builtin_malloc (n
+ sizeof n
); // { dg-message "recursive call" }
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 ();