> Am 12.04.2024 um 09:50 schrieb Jakub Jelinek <ja...@redhat.com>:
>
> Hi!
>
> The tree-cfg.cc verifier only diagnoses returns_twice calls preceded
> by non-label/debug stmts if it is in a bb with abnormal predecessor.
> The following testcase shows that if a user lies in the attributes
> (a function which never returns can't be pure, and can't return
> twice when it doesn't ever return at all), when we figure it out,
> we can remove the abnormal edges to the "returns_twice" call and perhaps
> whole .ABNORMAL_DISPATCHER etc.
> edge_before_returns_twice_call then ICEs because it can't find such
> an edge.
>
> The following patch limits the special handling to calls in bbs where
> the verifier requires that.
>
> Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?
Ok
Richard
> 2024-04-12 Jakub Jelinek <ja...@redhat.com>
>
> PR sanitizer/114687
> * gimple-iterator.cc (gsi_safe_insert_before): Only use
> edge_before_returns_twice_call if bb_has_abnormal_pred.
> (gsi_safe_insert_seq_before): Likewise.
> * gimple-lower-bitint.cc (bitint_large_huge::lower_call): Only
> push to m_returns_twice_calls if bb_has_abnormal_pred.
>
> * gcc.dg/asan/pr114687.c: New test.
>
> --- gcc/gimple-iterator.cc.jj 2024-03-14 09:57:09.024966285 +0100
> +++ gcc/gimple-iterator.cc 2024-04-11 17:05:06.267081433 +0200
> @@ -1049,7 +1049,8 @@ gsi_safe_insert_before (gimple_stmt_iter
> gimple *stmt = gsi_stmt (*iter);
> if (stmt
> && is_gimple_call (stmt)
> - && (gimple_call_flags (stmt) & ECF_RETURNS_TWICE) != 0)
> + && (gimple_call_flags (stmt) & ECF_RETURNS_TWICE) != 0
> + && bb_has_abnormal_pred (gsi_bb (*iter)))
> {
> edge e = edge_before_returns_twice_call (gsi_bb (*iter));
> basic_block new_bb = gsi_insert_on_edge_immediate (e, g);
> @@ -1072,7 +1073,8 @@ gsi_safe_insert_seq_before (gimple_stmt_
> gimple *stmt = gsi_stmt (*iter);
> if (stmt
> && is_gimple_call (stmt)
> - && (gimple_call_flags (stmt) & ECF_RETURNS_TWICE) != 0)
> + && (gimple_call_flags (stmt) & ECF_RETURNS_TWICE) != 0
> + && bb_has_abnormal_pred (gsi_bb (*iter)))
> {
> edge e = edge_before_returns_twice_call (gsi_bb (*iter));
> gimple *f = gimple_seq_first_stmt (seq);
> --- gcc/gimple-lower-bitint.cc.jj 2024-04-09 09:28:21.261123664 +0200
> +++ gcc/gimple-lower-bitint.cc 2024-04-11 17:06:58.033548199 +0200
> @@ -5320,7 +5320,7 @@ bitint_large_huge::lower_call (tree obj,
> arg = make_ssa_name (TREE_TYPE (arg));
> gimple *g = gimple_build_assign (arg, v);
> gsi_insert_before (&gsi, g, GSI_SAME_STMT);
> - if (returns_twice)
> + if (returns_twice && bb_has_abnormal_pred (gimple_bb (stmt)))
> {
> m_returns_twice_calls.safe_push (stmt);
> returns_twice = false;
> --- gcc/testsuite/gcc.dg/asan/pr114687.c.jj 2024-04-11 17:09:54.518127165
> +0200
> +++ gcc/testsuite/gcc.dg/asan/pr114687.c 2024-04-11 17:09:22.699563654
> +0200
> @@ -0,0 +1,22 @@
> +/* PR sanitizer/114687 */
> +/* { dg-do compile } */
> +
> +int a;
> +int foo (int);
> +
> +__attribute__((pure, returns_twice)) int
> +bar (void)
> +{
> + a = 1;
> + while (a)
> + a = 2;
> + return a;
> +}
> +
> +int
> +baz (void)
> +{
> + int d = bar ();
> + foo (d);
> + return 0;
> +}
>
> Jakub
>