From: Alexander Kornienko Date: Sat, 2 Jun 2012 01:01:07 +0000 (+0000) Subject: Implementation of a "soft opt-in" option for -Wimplicit-fallthrough diagnostics:... X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=1973634e445d4f1abdeedc2809f2d281929253b6;p=clang Implementation of a "soft opt-in" option for -Wimplicit-fallthrough diagnostics: -Wimplicit-fallthrough-per-method git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@157871 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Basic/DiagnosticGroups.td b/include/clang/Basic/DiagnosticGroups.td index 76f1e41495..f48eee416a 100644 --- a/include/clang/Basic/DiagnosticGroups.td +++ b/include/clang/Basic/DiagnosticGroups.td @@ -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">; diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 32576a3de6..d3d82380ac 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -5297,6 +5297,9 @@ def warn_missing_cases : Warning< def warn_unannotated_fallthrough : Warning< "unannotated fall-through between switch labels">, InGroup, DefaultIgnore; +def warn_unannotated_fallthrough_per_method : Warning< + "unannotated fall-through between switch labels in partly annotated method">, + InGroup, DefaultIgnore; def note_insert_fallthrough_fixit : Note< "insert '[[clang::fallthrough]];' to silence this warning">; def note_insert_break_fixit : Note< diff --git a/lib/Sema/AnalysisBasedWarnings.cpp b/lib/Sema/AnalysisBasedWarnings.cpp index 8f16e70b15..cea8a765c8 100644 --- a/lib/Sema/AnalysisBasedWarnings.cpp +++ b/lib/Sema/AnalysisBasedWarnings.cpp @@ -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 index 0000000000..3ca8590d39 --- /dev/null +++ b/test/SemaCXX/switch-implicit-fallthrough-per-method.cpp @@ -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; +}