PATCH for c++/87068, missing diagnostic with fallthrough statement

Marek Polacek polacek@redhat.com
Thu Aug 23 20:38:00 GMT 2018


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  <polacek@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" } */
+    }
+}



More information about the Gcc-patches mailing list