--- /dev/null
+/* { dg-options "-O2 -Wmissing-noreturn -fgnu89-inline" } */
+/* { dg-additional-options "-mno-mmx" { target { { i?86-*-* x86_64-*-* } && ia32 } } } */
+/* { dg-do compile } */
+
+extern void abort (void);
+
+double
+foo (int arg)
+{
+ if (arg != 116)
+ abort();
+ return arg + 1;
+}
+
+__attribute__((noreturn))
+double
+bar (int arg)
+{
+ foo (arg);
+ __builtin_return (__builtin_apply ((void (*) ()) foo, /* { dg-warning "'noreturn' function does return" } */
+ __builtin_apply_args (), 16));
+}
+
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-fdump-tree-einline" } */
+
+/* PR ipa/119599 */
+/* inlining a noreturn function which returns
+ can cause an ICE when dealing finding an unreachable block.
+ We should get a __builtin_unreachable after the inliing. */
+
+
+void baz (void);
+
+static inline __attribute__((always_inline, noreturn)) void
+bar (void)
+{
+ static volatile int t = 0;
+ if (t == 0)
+ baz ();
+} /* { dg-warning "function does return" } */
+
+void
+foo (void)
+{
+ bar ();
+}
+
+/* After inlining, we should have call to __builtin_unreachable now. */
+/* { dg-final { scan-tree-dump "__builtin_unreachable " "einline" } } */
(e = ei_safe_edge (ei)); )
{
last = *gsi_last_bb (e->src);
- if ((gimple_code (last) == GIMPLE_RETURN
- || gimple_call_builtin_p (last, BUILT_IN_RETURN))
- && location == UNKNOWN_LOCATION
- && ((location = LOCATION_LOCUS (gimple_location (last)))
- != UNKNOWN_LOCATION)
- && !optimize)
- break;
- /* When optimizing, replace return stmts in noreturn functions
+ /* Warn about __builtin_return .*/
+ if (gimple_call_builtin_p (last, BUILT_IN_RETURN)
+ && location == UNKNOWN_LOCATION)
+ {
+ location = LOCATION_LOCUS (gimple_location (last));
+ ei_next (&ei);
+ }
+ /* Replace return stmts in noreturn functions
with __builtin_unreachable () call. */
- if (optimize && gimple_code (last) == GIMPLE_RETURN)
+ else if (gimple_code (last) == GIMPLE_RETURN)
{
location_t loc = gimple_location (last);
+ if (location == UNKNOWN_LOCATION)
+ location = LOCATION_LOCUS (loc);
gimple *new_stmt = gimple_build_builtin_unreachable (loc);
gimple_stmt_iterator gsi = gsi_for_stmt (last);
gsi_replace (&gsi, new_stmt, true);