diff options
-rw-r--r-- | gcc/ChangeLog | 7 | ||||
-rw-r--r-- | gcc/gimplify.c | 3 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/torture/pr42363.c | 84 | ||||
-rw-r--r-- | gcc/tree-cfg.c | 8 |
5 files changed, 105 insertions, 2 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index b5c2407..2e66d7e 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,12 @@ 2010-01-09 Alexandre Oliva <aoliva@redhat.com> + PR middle-end/42363 + * gimplify.c (gimplify_modify_expr): Drop lhs on noreturn calls. + * tree-cfg.c (is_ctrl_altering_stmt): Don't compute flags twice. + (verify_gimple_call): Reject LHS in noreturn calls. + +2010-01-09 Alexandre Oliva <aoliva@redhat.com> + PR debug/42604 PR debug/42395 * tree-vect-loop-manip.c (adjust_info): New type. diff --git a/gcc/gimplify.c b/gcc/gimplify.c index a3c6834..e09cb3e 100644 --- a/gcc/gimplify.c +++ b/gcc/gimplify.c @@ -4407,7 +4407,8 @@ gimplify_modify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p, /* Since the RHS is a CALL_EXPR, we need to create a GIMPLE_CALL instead of a GIMPLE_ASSIGN. */ assign = gimple_build_call_from_tree (*from_p); - gimple_call_set_lhs (assign, *to_p); + if (!gimple_call_noreturn_p (assign)) + gimple_call_set_lhs (assign, *to_p); } else { diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 08c6bff..83535c0 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,5 +1,10 @@ 2010-01-09 Alexandre Oliva <aoliva@redhat.com> + PR middle-end/42363 + * gcc.dg/torture/pr42363.c: New. + +2010-01-09 Alexandre Oliva <aoliva@redhat.com> + PR debug/42604 PR debug/42395 * gcc.dg/vect/pr42604.c: New. diff --git a/gcc/testsuite/gcc.dg/torture/pr42363.c b/gcc/testsuite/gcc.dg/torture/pr42363.c new file mode 100644 index 0000000..9c9da13 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr42363.c @@ -0,0 +1,84 @@ +/* PR middle-end/pr42363, extended from the test for PR middle-end/37913. */ +/* { dg-do compile } */ +/* { dg-options "-g" } */ + +void foo (void) __attribute__ ((noreturn)); + +static int __attribute__ ((noreturn)) +bar (void) +{ + foo (); +} + +int +baz (void) +{ + int i = bar (); + return i + 1; +} + +int fooz (void) __attribute__ ((noreturn)); + +static int __attribute__ ((noreturn)) +bart (void) +{ + return fooz (); /* { dg-warning "noreturn" } */ +} + +int bazr (void) +{ + int i = bart (); + return i + 1; +} + +static inline int +bard (void) +{ + return fooz (); +} + +int bizr (void) +{ + int i, j; + + i = j = bard (); + + return i + 1; +} + +/* This might be regarded as pure and folded, rather than inlined. + It's pure evil. */ +static int __attribute__ ((pure, const, noreturn)) +barf (void) +{ +} /* { dg-warning "does return" } */ + +static int __attribute__ ((pure, const)) +bark (void) +{ + barf (); +} + +int buzr (void) +{ + int i, j; + + i = j = bark () + bark (); + + return i + 1; +} + +int buzt (void) +{ + int i, j; + + i = j = barf () + barf (); + + return i + 1; +} + +void bust (void) +{ + while (barf ()) + ; +} diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c index 36e518c..b6e9006 100644 --- a/gcc/tree-cfg.c +++ b/gcc/tree-cfg.c @@ -2230,7 +2230,7 @@ is_ctrl_altering_stmt (gimple t) return true; /* A call also alters control flow if it does not return. */ - if (gimple_call_flags (t) & ECF_NORETURN) + if (flags & ECF_NORETURN) return true; } break; @@ -2963,6 +2963,12 @@ verify_gimple_call (gimple stmt) return true; } + if (gimple_call_lhs (stmt) && gimple_call_noreturn_p (stmt)) + { + error ("LHS in noreturn call"); + return true; + } + fntype = TREE_TYPE (TREE_TYPE (fn)); if (gimple_call_lhs (stmt) && !useless_type_conversion_p (TREE_TYPE (gimple_call_lhs (stmt)), |