--- gcc/c-family/c-lex.c.jj	2016-09-30 18:16:26.303336781 +0200
+++ gcc/c-family/c-lex.c	2016-09-30 18:26:14.650999215 +0200
@@ -598,7 +598,18 @@ c_lex_with_flags (tree *value, location_
 
     /* CPP_COMMENT will appear when compiling with -C and should be
        ignored.  */
-     case CPP_COMMENT:
+    case CPP_COMMENT:
+      if (tok->flags & PREV_FALLTHROUGH)
+	{
+	  do
+	    {
+	      tok = cpp_get_token_with_location (parse_in, loc);
+	      type = tok->type;
+	    }
+	  while (type == CPP_PADDING || type == CPP_COMMENT);
+	  add_flags = PREV_FALLTHROUGH;
+	  goto retry_after_at;
+	}
        goto retry;
 
     default:
--- gcc/doc/invoke.texi.jj	2016-09-30 18:16:26.308336719 +0200
+++ gcc/doc/invoke.texi	2016-09-30 18:26:33.288766793 +0200
@@ -4157,10 +4157,26 @@ C++17 provides a standard way to suppres
 warning using @code{[[fallthrough]];} instead of the GNU attribute.  In C++11
 or C++14 users can use @code{[[gnu::fallthrough]];}, which is a GNU extension.
 Instead of the these attributes, it is also possible to add a "falls through"
-comment to silence the warning.  GCC accepts a wide range of such comments,
-for example all of "Falls through.", "fallthru", "FALLS-THROUGH" work.  This
-comment needs to consist of two words merely, optionally followed by periods
-or whitespaces.
+comment to silence the warning.  The whole body of the C or C++ style comment
+should match one of the following regular expressions:
+
+@itemize @bullet
+
+@item @code{-fallthrough}
+
+@item @code{@@fallthrough@@}
+
+@item @code{[ \t]*FALL(S | |-)?THR(OUGH|U)\.?[ \t]*}
+
+@item @code{[ \t]*Fall((s | |-)[Tt]|t)hr(ough|u)\.?[ \t]*}
+
+@item @code{[ \t]*fall(s | |-)?thr(ough|u)\.?[ \t]*}
+
+@end itemize
+
+and the comment needs to be followed after optional whitespace and other comments
+by @code{case} or @code{default} keywords or by a user label that preceeds some
+@code{case} or @code{default} label.
 
 @smallexample
 @group
--- libcpp/lex.c.jj	2016-09-30 18:16:22.987378137 +0200
+++ libcpp/lex.c	2016-09-30 18:26:33.289766781 +0200
@@ -2060,7 +2060,7 @@ fallthrough_comment_p (cpp_reader *pfile
     }
   /* Whole comment contents (regex):
      [ \t]*FALL(S | |-)?THR(OUGH|U)\.?[ \t]*
-     [ \t]*Fall(s | |-)?[Tt]hr(ough|u)\.?[ \t]*
+     [ \t]*Fall((s | |-)[Tt]|t)hr(ough|u)\.?[ \t]*
      [ \t]*fall(s | |-)?thr(ough|u)\.?[ \t]*
    */
   else
@@ -2070,30 +2070,27 @@ fallthrough_comment_p (cpp_reader *pfile
       unsigned char f = *from;
       if (f != 'F' && f != 'f')
 	return false;
-      if ((size_t) (pfile->buffer->cur - from) < sizeof "fallthrough")
+      if ((size_t) (pfile->buffer->cur - from) < sizeof "fallthru" - 1)
 	return false;
       bool all_upper = false;
       if (f == 'F' && memcmp (from + 1, "ALL", sizeof "ALL" - 1) == 0)
 	all_upper = true;
       else if (memcmp (from + 1, "all", sizeof "all" - 1))
 	return false;
-      if (from[sizeof "fall" - 1] == (all_upper ? 'S' : 's')
-	  && from[sizeof "falls" - 1] == ' ')
-	from += sizeof "falls " - 1;
-      else if (from[sizeof "fall" - 1] == ' '
-	       || from[sizeof "fall" - 1] == '-')
-	from += sizeof "fall " - 1;
-      else if (from[sizeof "fall" - 1] != (all_upper ? 'T' : 't'))
+      from += sizeof "fall" - 1;
+      if (*from == (all_upper ? 'S' : 's') && from[1] == ' ')
+	from += 2;
+      else if (*from == ' ' || *from == '-')
+	from++;
+      else if (*from != (all_upper ? 'T' : 't'))
 	return false;
-      else
-	from += sizeof "fall" - 1;
       if ((f == 'f' || *from != 'T') && (all_upper || *from != 't'))
 	return false;
-      if ((size_t) (pfile->buffer->cur - from) < sizeof "thru")
+      if ((size_t) (pfile->buffer->cur - from) < sizeof "thru" - 1)
 	return false;
       if (memcmp (from + 1, all_upper ? "HRU" : "hru", sizeof "hru" - 1))
 	{
-	  if ((size_t) (pfile->buffer->cur - from) < sizeof "through")
+	  if ((size_t) (pfile->buffer->cur - from) < sizeof "through" - 1)
 	    return false;
 	  if (memcmp (from + 1, all_upper ? "HROUGH" : "hrough",
 		      sizeof "hrough" - 1))
@@ -2398,7 +2395,8 @@ _cpp_lex_direct (cpp_reader *pfile)
 {
   cppchar_t c;
   cpp_buffer *buffer;
-  const unsigned char *comment_start = NULL;
+  const unsigned char *comment_start;
+  bool fallthrough_comment = false;
   cpp_token *result = pfile->cur_token++;
 
  fresh_line:
@@ -2426,7 +2424,7 @@ _cpp_lex_direct (cpp_reader *pfile)
 	  return result;
 	}
       if (buffer != pfile->buffer)
-	comment_start = NULL;
+	fallthrough_comment = false;
       if (!pfile->keep_tokens)
 	{
 	  pfile->cur_run = &pfile->base_run;
@@ -2535,8 +2533,7 @@ _cpp_lex_direct (cpp_reader *pfile)
 	}
 
       /* Signal FALLTHROUGH comment followed by another token.  */
-      if (comment_start
-	  && fallthrough_comment_p (pfile, comment_start))
+      if (fallthrough_comment)
 	result->flags |= PREV_FALLTHROUGH;
       break;
 
@@ -2623,13 +2620,16 @@ _cpp_lex_direct (cpp_reader *pfile)
 	  break;
 	}
 
+      if (fallthrough_comment_p (pfile, comment_start))
+	fallthrough_comment = true;
+
       if (!pfile->state.save_comments)
 	{
 	  result->flags |= PREV_WHITE;
 	  goto update_tokens_line;
 	}
 
-      if (fallthrough_comment_p (pfile, comment_start))
+      if (fallthrough_comment)
 	result->flags |= PREV_FALLTHROUGH;
 
       /* Save the comment as a token in its own right.  */
--- gcc/testsuite/c-c++-common/Wimplicit-fallthrough-22.c.jj	2016-09-30 18:16:26.293336906 +0200
+++ gcc/testsuite/c-c++-common/Wimplicit-fallthrough-22.c	2016-09-30 18:26:33.289766781 +0200
@@ -0,0 +1,123 @@
+/* { dg-do compile } */
+/* { dg-options "-Wimplicit-fallthrough" } */
+
+void bar (int);
+
+void
+foo (int i)
+{
+  switch (i)
+    {
+    case 1:
+      bar (1);			/* { dg-bogus "this statement may \[laf]* through" } */
+      /* FALLTHROUGH */
+    case 2:
+      bar (2);
+      break;
+    case 3:
+      bar (3);			/* { dg-bogus "this statement may \[laf]* through" } */
+      /* FALLS THRU.  */
+      /* Some other comment.  */
+    case 4:
+      bar (4);
+      break;
+    case 7:
+      bar (7);			/* { dg-bogus "this statement may \[laf]* through" } */
+      /* Some comment.  */
+      /* fallthrough.  */
+      /* Some other comment.  */
+      /* And yet another.  */
+    case 8:
+      bar (8);
+      break;
+    case 15:
+      bar (15);			/* { dg-bogus "this statement may \[laf]* through" } */
+      /*-fallthrough*/
+    case 16:
+      bar (16);
+      break;
+    case 17:
+      bar (17);			/* { dg-bogus "this statement may \[laf]* through" } */
+      /*@fallthrough@*/
+    case 18:
+      bar (18);
+      break;
+    case 23:
+      bar (23);			/* { dg-bogus "this statement may \[laf]* through" } */
+      /*fallthru*/
+    case 24:
+      bar (24);
+      break;
+    case 31:
+      bar (31);			/* { dg-bogus "this statement may \[laf]* through" } */
+      /*Falls thru*/
+    case 32:
+      bar (32);
+      break;
+    case 33:
+      bar (33);			/* { dg-bogus "this statement may \[laf]* through" } */
+      /*Fall-through*/
+    case 34:
+      bar (34);
+      break;
+    default:
+      break;
+    }
+  switch (i)
+    {
+    case 1:
+      bar (1);			/* { dg-bogus "this statement may \[laf]* through" } */
+      // FALLTHROUGH
+    case 2:
+      bar (2);
+      break;
+    case 3:
+      bar (3);			/* { dg-bogus "this statement may \[laf]* through" } */
+      // FALLS THRU.  
+      // Some other comment.
+    case 4:
+      bar (4);
+      break;
+    case 7:
+      bar (7);			/* { dg-bogus "this statement may \[laf]* through" } */
+      // Some comment.
+      // fallthrough
+      // Some other comment.
+      // And yet another.
+    case 8:
+      bar (8);
+      break;
+    case 15:
+      bar (15);			/* { dg-bogus "this statement may \[laf]* through" } */
+      //-fallthrough
+    case 16:
+      bar (16);
+      break;
+    case 17:
+      bar (17);			/* { dg-bogus "this statement may \[laf]* through" } */
+      //@fallthrough@
+    case 18:
+      bar (18);
+      break;
+    case 23:
+      bar (23);			/* { dg-bogus "this statement may \[laf]* through" } */
+      //fallthru
+    case 24:
+      bar (24);
+      break;
+    case 31:
+      bar (31);			/* { dg-bogus "this statement may \[laf]* through" } */
+      //Falls thru
+    case 32:
+      bar (32);
+      break;
+    case 33:
+      bar (33);			/* { dg-bogus "this statement may \[laf]* through" } */
+      //Fall-through
+    case 34:
+      bar (34);
+      break;
+    default:
+      break;
+    }
+}
--- gcc/testsuite/c-c++-common/Wimplicit-fallthrough-23.c.jj	2016-09-30 18:16:26.298336844 +0200
+++ gcc/testsuite/c-c++-common/Wimplicit-fallthrough-23.c	2016-09-30 18:26:14.659999103 +0200
@@ -0,0 +1,4 @@
+/* { dg-do compile } */
+/* { dg-options "-Wimplicit-fallthrough -C" } */
+
+#include "Wimplicit-fallthrough-22.c"
