The C++ standard says that [[fallthrough]]; at the end of a switch statement is ill-formed: <http://eel.is/c++draft/dcl.attr.fallthrough>
Currently we do check that the statement after a fallthrough statement is a labeled statement, but we didn't warn if a fallthrough statement is at the very end of a switch statement. This patch adds this warning. Bootstrapped/regtested on x86_64-linux, ok for trunk? 2018-08-23 Marek Polacek <pola...@redhat.com> PR c++/87068 * gimplify.c (expand_FALLTHROUGH_r): If IFN_FALLTHROUGH was found at the end of a seq, save its location to walk_stmt_info. (expand_FALLTHROUGH): Warn if IFN_FALLTHROUGH is at the end of a switch. * c-c++-common/Wimplicit-fallthrough-37.c: New test. diff --git gcc/gimplify.c gcc/gimplify.c index e35137aec2c..04c15016f18 100644 --- gcc/gimplify.c +++ gcc/gimplify.c @@ -2231,7 +2231,7 @@ maybe_warn_implicit_fallthrough (gimple_seq seq) static tree expand_FALLTHROUGH_r (gimple_stmt_iterator *gsi_p, bool *handled_ops_p, - struct walk_stmt_info *) + struct walk_stmt_info *wi) { gimple *stmt = gsi_stmt (*gsi_p); @@ -2250,11 +2250,14 @@ expand_FALLTHROUGH_r (gimple_stmt_iterator *gsi_p, bool *handled_ops_p, if (gimple_call_internal_p (stmt, IFN_FALLTHROUGH)) { gsi_remove (gsi_p, true); + location_t loc = gimple_location (stmt); if (gsi_end_p (*gsi_p)) - return integer_zero_node; + { + wi->info = &loc; + return integer_zero_node; + } bool found = false; - location_t loc = gimple_location (stmt); gimple_stmt_iterator gsi2 = *gsi_p; stmt = gsi_stmt (gsi2); @@ -2317,6 +2320,14 @@ expand_FALLTHROUGH (gimple_seq *seq_p) struct walk_stmt_info wi; memset (&wi, 0, sizeof (wi)); walk_gimple_seq_mod (seq_p, expand_FALLTHROUGH_r, NULL, &wi); + if (wi.callback_result == integer_zero_node) + { + /* We've found [[fallthrough]]; at the end of a switch, which the C++ + standard says is ill-formed; see [dcl.attr.fallthrough]. */ + location_t *loc = static_cast<location_t *>(wi.info); + warning_at (*loc, 0, "attribute %<fallthrough%> not preceding " + "a case label or default label"); + } } diff --git gcc/testsuite/c-c++-common/Wimplicit-fallthrough-37.c gcc/testsuite/c-c++-common/Wimplicit-fallthrough-37.c index e69de29bb2d..644003af47d 100644 --- gcc/testsuite/c-c++-common/Wimplicit-fallthrough-37.c +++ gcc/testsuite/c-c++-common/Wimplicit-fallthrough-37.c @@ -0,0 +1,13 @@ +/* PR c++/87068 */ +/* { dg-do compile } */ + +void +f (int n) +{ + switch (n) + { + case 4: + ++n; + __attribute__((fallthrough)); /* { dg-warning "not preceding" } */ + } +}