diff --git a/clang/lib/Sema/AnalysisBasedWarnings.cpp b/clang/lib/Sema/AnalysisBasedWarnings.cpp
--- a/clang/lib/Sema/AnalysisBasedWarnings.cpp
+++ b/clang/lib/Sema/AnalysisBasedWarnings.cpp
@@ -1087,6 +1087,31 @@
       }
     }
 
+    // Does this CFGBlock only contain a single statement which is a return?
+    bool isEmptyCaseWithReturn(const CFGBlock *B) {
+      if (B->size() == 1 && B->succ_size() == 1)
+        if (Optional<clang::CFGStmt> CS = B->front().getAs<CFGStmt>())
+          if (const Stmt *S = CS->getStmt())
+            if (isa<ReturnStmt>(S))
+              return true;
+      return false;
+    }
+
+    bool shouldntWarnSucessors(const CFGBlock *B) {
+      return llvm::any_of(B->succs(),
+                          [this](const CFGBlock::AdjacentBlock &Succ) {
+                            if (const CFGBlock *S = Succ.getReachableBlock()) {
+                              if (S->size())
+                                return isEmptyCaseWithReturn(S);
+                              if (const Stmt *T = S->getTerminatorStmt())
+                                if (isa<BreakStmt>(T) || isa<GotoStmt>(T))
+                                  return true;
+                              return shouldntWarnSucessors(S);
+                            }
+                            return false;
+                          });
+    }
+
     bool checkFallThroughIntoBlock(const CFGBlock &B, int &AnnotatedCnt,
                                    bool IsTemplateInstantiation) {
       assert(!ReachableBlocks.empty() && "ReachableBlocks empty");
@@ -1149,6 +1174,9 @@
           continue; // Fallthrough annotation, good.
         }
 
+        if (shouldntWarnSucessors(P))
+          continue;
+
         if (!LastStmt) { // This block contains no executable statements.
           // Traverse its predecessors.
           std::copy(P->pred_begin(), P->pred_end(),
diff --git a/clang/test/SemaCXX/switch-implicit-fallthrough-blocks.cpp b/clang/test/SemaCXX/switch-implicit-fallthrough-blocks.cpp
--- a/clang/test/SemaCXX/switch-implicit-fallthrough-blocks.cpp
+++ b/clang/test/SemaCXX/switch-implicit-fallthrough-blocks.cpp
@@ -7,11 +7,17 @@
     case 0:
       x++;
       [[clang::fallthrough]]; // no diagnostics
+    case 2:
+      x++;
+    case 3: // no diagnostics
+      break;
     case 1:
       x++;
     default: // \
         expected-warning{{unannotated fall-through between switch labels}} \
+        expected-note{{insert '[[clang::fallthrough]];' to silence this warning}} \
         expected-note{{insert 'break;' to avoid fall-through}}
+      x++;
       break;
     }
   };
diff --git a/clang/test/SemaCXX/switch-implicit-fallthrough.cpp b/clang/test/SemaCXX/switch-implicit-fallthrough.cpp
--- a/clang/test/SemaCXX/switch-implicit-fallthrough.cpp
+++ b/clang/test/SemaCXX/switch-implicit-fallthrough.cpp
@@ -33,7 +33,7 @@
       }
     case 6:  // expected-warning{{unannotated fall-through between switch labels}} expected-note{{insert '[[clang::fallthrough]];' to silence this warning}} expected-note{{insert 'break;' to avoid fall-through}}
       n += 300;
-    case 66:  // expected-warning{{unannotated fall-through between switch labels}} expected-note{{insert 'break;' to avoid fall-through}}
+    case 66:
     case 67:
     case 68:
       break;
@@ -151,23 +151,23 @@
 #define MY_CASE2(X, Y, U, V) case X: Y; case U: V
 
 int fallthrough_macro1(int n) {
-  MY_SWITCH(n, 13, n *= 2, 14, break)  // expected-warning{{unannotated fall-through between switch labels}}
+  MY_SWITCH(n, 13, n *= 2, 14, break)
 
   switch (n + 1) {
     MY_CASE(33, n += 2);
-    MY_CASE(44, break);  // expected-warning{{unannotated fall-through between switch labels}}
-    MY_CASE(55, n += 3);
+    MY_CASE(44, n += 3); // expected-warning{{unannotated fall-through between switch labels}}
+    MY_CASE(55, break);
   }
 
   switch (n + 3) {
     MY_CASE(333, return 333);
-    MY_CASE2(444, n += 44, 4444, break);  // expected-warning{{unannotated fall-through between switch labels}}
+    MY_CASE2(444, n += 44, 4444, break);
     MY_CASE(555, n += 33);
   }
 
-  MY_SWITCH2(n + 4, MY_CASE(17, n *= 3), MY_CASE(19, break))  // expected-warning{{unannotated fall-through between switch labels}}
+  MY_SWITCH2(n + 4, MY_CASE(17, n *= 3), MY_CASE(19, break))
 
-  MY_SWITCH2(n + 5, MY_CASE(21, break), MY_CASE2(23, n *= 7, 25, break))  // expected-warning{{unannotated fall-through between switch labels}}
+  MY_SWITCH2(n + 5, MY_CASE(21, break), MY_CASE2(23, n *= 7, 25, break))
 
   return n;
 }
@@ -237,9 +237,15 @@
           [[clang::fallthrough]]; // no diagnostics
         case 1:
           x++;
+        case 2: // no diagnostics
+          break;
+        case 3:
+          x++;
         default: // \
             expected-warning{{unannotated fall-through between switch labels}} \
+            expected-note{{insert '[[clang::fallthrough]];' to silence this warning}} \
             expected-note{{insert 'break;' to avoid fall-through}}
+          x++;
           break;
       }
     }
@@ -257,9 +263,15 @@
       [[clang::fallthrough]]; // no diagnostics
     case 1:
       x++;
+    case 2: // no diagnostics
+      break;
+    case 3:
+      x++;
     default: // \
         expected-warning{{unannotated fall-through between switch labels}} \
+        expected-note{{insert '[[clang::fallthrough]];' to silence this warning}} \
         expected-note{{insert 'break;' to avoid fall-through}}
+      x++;
       break;
     }
   };
@@ -279,6 +291,106 @@
   }
 }
 
+void bar(void);
+
+// Should not warn.
+void test0(int x) {
+  switch (x) {
+  case 0:
+    bar();
+  default:
+    break;
+  }
+}
+
+// should not warn.
+void test1(int x) {
+  switch (x) {
+  case 0:
+    bar();
+  default:
+    return;
+  }
+}
+
+// should not warn.
+void test2(int x) {
+  switch (x) {
+  case 0:
+    bar();
+  default:
+    goto y;
+  }
+y:;
+}
+
+void test3(int x) {
+  switch (x) {
+  case 0:
+    bar();
+  default: // \
+      // expected-warning{{unannotated fall-through between switch labels}} \
+      // expected-note{{insert '[[clang::fallthrough]];' to silence this warning}} \
+      // expected-note{{insert 'break;' to avoid fall-through}}
+    bar();
+    break;
+  }
+}
+
+// Should not warn.
+int y;
+void test4(int x) {
+  switch (x) {
+  case 0:
+    if (y)
+      bar();
+  default:
+    break;
+  }
+}
+
+// Should not warn.
+void test5(int x) {
+  switch (x) {
+  case 0:
+    ++x;
+  case 1:
+  case 2:
+  case 3:
+    break;
+  }
+}
+
+// Should not warn.
+// TODO: GCC does not warn
+void test6(int x) {
+  switch (x) {
+  case 0:
+    bar();
+  default: // \
+      // expected-warning{{unannotated fall-through between switch labels}} \
+      // expected-note{{insert '[[clang::fallthrough]];' to silence this warning}} \
+      // expected-note{{insert 'break;' to avoid fall-through}}
+           ;
+  }
+  bar();
+  bar();
+}
+
+// Should warn.
+void test7(int x) {
+  switch (x) {
+  case 3:
+    ++x;
+  case 4: // \
+      // expected-warning{{unannotated fall-through between switch labels}} \
+      // expected-note{{insert '[[clang::fallthrough]];' to silence this warning}} \
+      // expected-note{{insert 'break;' to avoid fall-through}}
+    do {
+    } while (1);
+    break;
+  }
+}
 int fallthrough_placement_error(int n) {
   switch (n) {
       [[clang::fallthrough]]; // expected-warning{{fallthrough annotation in unreachable code}}