https://gcc.gnu.org/bugzilla/show_bug.cgi?id=103597
--- Comment #5 from Jakub Jelinek <jakub at gcc dot gnu.org> --- Completely untested patch to set the flag when a label is only known reachable through fallthrough from previous instructions, never jumped to, as the only goto to it is on a non-executable branch of GIMPLE_COND with constant condition. --- gcc/tree.h.jj 2021-11-29 14:24:14.121633747 +0100 +++ gcc/tree.h 2021-12-07 19:26:06.645324657 +0100 @@ -787,6 +787,12 @@ extern void omp_clause_range_check_faile #define SWITCH_BREAK_LABEL_P(NODE) \ (LABEL_DECL_CHECK (NODE)->base.protected_flag) +/* Set on label that is known not to be jumped to, it can be only + reached by falling through from previous statements. + This is used to implement -Wimplicit-fallthrough. */ +#define UNUSED_LABEL_P(NODE) \ + (LABEL_DECL_CHECK (NODE)->base.default_def_flag) + /* Nonzero means this expression is volatile in the C sense: its address should be of type `volatile WHATEVER *'. In other words, the declared item is volatile qualified. --- gcc/gimplify.c.jj 2021-12-02 19:41:52.620552908 +0100 +++ gcc/gimplify.c 2021-12-07 19:49:43.964134745 +0100 @@ -4387,9 +4387,19 @@ gimplify_cond_expr (tree *expr_p, gimple if (TREE_OPERAND (expr, 1) == NULL_TREE && !have_else_clause_p && TREE_OPERAND (expr, 2) != NULL_TREE) - label_cont = label_true; + { + /* For if (0) {} else { code; } tell -Wimplicit-fallthrough + handling that label_cont == label_true can be only reached + through fallthrough from { code; }. */ + if (integer_zerop (COND_EXPR_COND (expr))) + UNUSED_LABEL_P (label_true) = 1; + label_cont = label_true; + } else { + bool then_side_effects + = (TREE_OPERAND (expr, 1) + && TREE_SIDE_EFFECTS (TREE_OPERAND (expr, 1))); gimplify_seq_add_stmt (&seq, gimple_build_label (label_true)); have_then_clause_p = gimplify_stmt (&TREE_OPERAND (expr, 1), &seq); /* For if (...) { code; } else {} or @@ -4403,6 +4413,16 @@ gimplify_cond_expr (tree *expr_p, gimple gimple *g; label_cont = create_artificial_label (UNKNOWN_LOCATION); + /* For if (0) { non-side-effect-code } else { code } + tell -Wimplicit-fallthrough handling that label_cont can + be only reached through fallthrough from { code }. */ + if (integer_zerop (COND_EXPR_COND (expr))) + { + UNUSED_LABEL_P (label_true) = 1; + if (!then_side_effects) + UNUSED_LABEL_P (label_cont) = 1; + } + g = gimple_build_goto (label_cont); /* GIMPLE_COND's are very low level; they have embedded @@ -4419,6 +4439,13 @@ gimplify_cond_expr (tree *expr_p, gimple } if (!have_else_clause_p) { + /* For if (1) { code } or if (1) { code } else { non-side-effect-code } + tell -Wimplicit-fallthrough handling that label_false can be only + reached through fallthrough from { code }. */ + if (integer_nonzerop (COND_EXPR_COND (expr)) + && (TREE_OPERAND (expr, 2) == NULL_TREE + || !TREE_SIDE_EFFECTS (TREE_OPERAND (expr, 2)))) + UNUSED_LABEL_P (label_false) = 1; gimplify_seq_add_stmt (&seq, gimple_build_label (label_false)); have_else_clause_p = gimplify_stmt (&TREE_OPERAND (expr, 2), &seq); }