]> granicus.if.org Git - clang/commitdiff
Implementation of a "soft opt-in" option for -Wimplicit-fallthrough diagnostics:...
authorAlexander Kornienko <alexfh@google.com>
Sat, 2 Jun 2012 01:01:07 +0000 (01:01 +0000)
committerAlexander Kornienko <alexfh@google.com>
Sat, 2 Jun 2012 01:01:07 +0000 (01:01 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@157871 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Basic/DiagnosticGroups.td
include/clang/Basic/DiagnosticSemaKinds.td
lib/Sema/AnalysisBasedWarnings.cpp
test/SemaCXX/switch-implicit-fallthrough-per-method.cpp [new file with mode: 0644]

index 76f1e414956c1cfbad88f5e4a46c63ad384f4d0a..f48eee416a9266d48391247bd7278b5258034606 100644 (file)
@@ -209,7 +209,9 @@ def MethodDuplicate : DiagGroup<"duplicate-method-match">;
 def CoveredSwitchDefault : DiagGroup<"covered-switch-default">;
 def SwitchEnum     : DiagGroup<"switch-enum">;
 def Switch         : DiagGroup<"switch">;
-def ImplicitFallthrough  : DiagGroup<"implicit-fallthrough">;
+def ImplicitFallthroughPerMethod : DiagGroup<"implicit-fallthrough-per-method">;
+def ImplicitFallthrough  : DiagGroup<"implicit-fallthrough",
+                                     [ImplicitFallthroughPerMethod]>;
 def Trigraphs      : DiagGroup<"trigraphs">;
 
 def : DiagGroup<"type-limits">;
index 32576a3de66adff4031629f5f03ad42934dff6a7..d3d82380acc311d588f0ec5588dd3642e7e92f06 100644 (file)
@@ -5297,6 +5297,9 @@ def warn_missing_cases : Warning<
 def warn_unannotated_fallthrough : Warning<
   "unannotated fall-through between switch labels">,
   InGroup<ImplicitFallthrough>, DefaultIgnore;
+def warn_unannotated_fallthrough_per_method : Warning<
+  "unannotated fall-through between switch labels in partly annotated method">,
+  InGroup<ImplicitFallthroughPerMethod>, DefaultIgnore;
 def note_insert_fallthrough_fixit : Note<
   "insert '[[clang::fallthrough]];' to silence this warning">;
 def note_insert_break_fixit : Note<
index 8f16e70b154a1a4920d506a05938e04453a4f958..cea8a765c805a07f17ce76cf15c044761f5203f1 100644 (file)
@@ -814,13 +814,17 @@ namespace {
   };
 }
 
-static void DiagnoseSwitchLabelsFallthrough(Sema &S, AnalysisDeclContext &AC) {
+static void DiagnoseSwitchLabelsFallthrough(Sema &S, AnalysisDeclContext &AC,
+                                            bool PerMethod) {
   FallthroughMapper FM(S);
   FM.TraverseStmt(AC.getBody());
 
   if (!FM.foundSwitchStatements())
     return;
 
+  if (PerMethod && FM.getFallthroughStmts().empty())
+    return;
+
   CFG *Cfg = AC.getCFG();
 
   if (!Cfg)
@@ -838,7 +842,9 @@ static void DiagnoseSwitchLabelsFallthrough(Sema &S, AnalysisDeclContext &AC) {
     if (!FM.checkFallThroughIntoBlock(B, AnnotatedCnt))
       continue;
 
-    S.Diag(Label->getLocStart(), diag::warn_unannotated_fallthrough);
+    S.Diag(Label->getLocStart(),
+        PerMethod ? diag::warn_unannotated_fallthrough_per_method
+                  : diag::warn_unannotated_fallthrough);
 
     if (!AnnotatedCnt) {
       SourceLocation L = Label->getLocStart();
@@ -1324,9 +1330,14 @@ AnalysisBasedWarnings::IssueWarnings(sema::AnalysisBasedWarnings::Policy P,
     }
   }
 
-  if (Diags.getDiagnosticLevel(diag::warn_unannotated_fallthrough,
-                              D->getLocStart()) != DiagnosticsEngine::Ignored) {
-    DiagnoseSwitchLabelsFallthrough(S, AC);
+  bool FallThroughDiagFull =
+      Diags.getDiagnosticLevel(diag::warn_unannotated_fallthrough,
+                               D->getLocStart()) != DiagnosticsEngine::Ignored;
+  bool FallThroughDiagPerMethod =
+      Diags.getDiagnosticLevel(diag::warn_unannotated_fallthrough_per_method,
+                               D->getLocStart()) != DiagnosticsEngine::Ignored;
+  if (FallThroughDiagFull || FallThroughDiagPerMethod) {
+    DiagnoseSwitchLabelsFallthrough(S, AC, !FallThroughDiagFull);
   }
 
   // Collect statistics about the CFG if it was built.
diff --git a/test/SemaCXX/switch-implicit-fallthrough-per-method.cpp b/test/SemaCXX/switch-implicit-fallthrough-per-method.cpp
new file mode 100644 (file)
index 0000000..3ca8590
--- /dev/null
@@ -0,0 +1,39 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 -Wimplicit-fallthrough-per-method %s
+
+
+int fallthrough(int n) {
+  switch (n / 10) {
+    case 0:
+      n += 100;
+    case 1:  // expected-warning{{unannotated fall-through between switch labels in partly annotated method}} expected-note{{insert '[[clang::fallthrough]];' to silence this warning}} expected-note{{insert 'break;' to avoid fall-through}}
+      switch (n) {
+      case 111:
+        n += 111;
+        [[clang::fallthrough]];
+      case 112:
+        n += 112;
+      case 113:  // expected-warning{{unannotated fall-through between switch labels in partly annotated method}} expected-note{{insert '[[clang::fallthrough]];' to silence this warning}} expected-note{{insert 'break;' to avoid fall-through}}
+        n += 113;
+        break    ;
+      }
+  }
+  return n;
+}
+
+int fallthrough2(int n) {
+  switch (n / 10) {
+    case 0:
+      n += 100;
+    case 1:  // no warning, as we didn't "opt-in" for it in this method
+      switch (n) {
+      case 111:
+        n += 111;
+      case 112:  // no warning, as we didn't "opt-in" for it in this method
+        n += 112;
+      case 113:  // no warning, as we didn't "opt-in" for it in this method
+        n += 113;
+        break    ;
+      }
+  }
+  return n;
+}