diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -167,6 +167,9 @@ ````. - Clang constexpr evaluator now provides a more concise diagnostic when calling function pointer that is known to be null. +- Clang now avoids duplicate warnings on unreachable ``[[fallthrough]];`` statements + previously issued from ``-Wunreachable-code`` and ``-Wunreachable-code-fallthrough`` + by prioritizing ``-Wunreachable-code-fallthrough``. Bug Fixes in This Version ------------------------- diff --git a/clang/include/clang/Analysis/Analyses/ReachableCode.h b/clang/include/clang/Analysis/Analyses/ReachableCode.h --- a/clang/include/clang/Analysis/Analyses/ReachableCode.h +++ b/clang/include/clang/Analysis/Analyses/ReachableCode.h @@ -48,11 +48,9 @@ virtual void anchor(); public: virtual ~Callback() {} - virtual void HandleUnreachable(UnreachableKind UK, - SourceLocation L, - SourceRange ConditionVal, - SourceRange R1, - SourceRange R2) = 0; + virtual void HandleUnreachable(UnreachableKind UK, SourceLocation L, + SourceRange ConditionVal, SourceRange R1, + SourceRange R2, bool HasFallThroughAttr) = 0; }; /// ScanReachableFromBlock - Mark all blocks reachable from Start. diff --git a/clang/lib/Analysis/ReachableCode.cpp b/clang/lib/Analysis/ReachableCode.cpp --- a/clang/lib/Analysis/ReachableCode.cpp +++ b/clang/lib/Analysis/ReachableCode.cpp @@ -12,6 +12,7 @@ //===----------------------------------------------------------------------===// #include "clang/Analysis/Analyses/ReachableCode.h" +#include "clang/AST/Attr.h" #include "clang/AST/Expr.h" #include "clang/AST/ExprCXX.h" #include "clang/AST/ExprObjC.h" @@ -629,6 +630,10 @@ UK = reachable_code::UK_Return; } + const auto *AS = dyn_cast(S); + bool HasFallThroughAttr = + AS && hasSpecificAttr(AS->getAttrs()); + SourceRange SilenceableCondVal; if (UK == reachable_code::UK_Other) { @@ -645,8 +650,9 @@ R2 = Inc->getSourceRange(); } - CB.HandleUnreachable(reachable_code::UK_Loop_Increment, - Loc, SourceRange(), SourceRange(Loc, Loc), R2); + CB.HandleUnreachable(reachable_code::UK_Loop_Increment, Loc, + SourceRange(), SourceRange(Loc, Loc), R2, + HasFallThroughAttr); return; } @@ -665,7 +671,7 @@ SourceRange R1, R2; SourceLocation Loc = GetUnreachableLoc(S, R1, R2); - CB.HandleUnreachable(UK, Loc, SilenceableCondVal, R1, R2); + CB.HandleUnreachable(UK, Loc, SilenceableCondVal, R1, R2, HasFallThroughAttr); } //===----------------------------------------------------------------------===// 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 @@ -66,11 +66,17 @@ public: UnreachableCodeHandler(Sema &s) : S(s) {} - void HandleUnreachable(reachable_code::UnreachableKind UK, - SourceLocation L, - SourceRange SilenceableCondVal, - SourceRange R1, - SourceRange R2) override { + void HandleUnreachable(reachable_code::UnreachableKind UK, SourceLocation L, + SourceRange SilenceableCondVal, SourceRange R1, + SourceRange R2, bool HasFallThroughAttr) override { + // If the diagnosed code is `[[fallthrough]];` and + // `-Wunreachable-code-fallthrough` is enabled, suppress `code will never + // be executed` warning to avoid generating diagnostic twice + if (HasFallThroughAttr && + !S.getDiagnostics().isIgnored(diag::warn_unreachable_fallthrough_attr, + SourceLocation())) + return; + // Avoid reporting multiple unreachable code diagnostics that are // triggered by the same conditional value. if (PreviousSilenceableCondVal.isValid() && diff --git a/clang/test/Sema/warn-unreachable-fallthrough.c b/clang/test/Sema/warn-unreachable-fallthrough.c new file mode 100644 --- /dev/null +++ b/clang/test/Sema/warn-unreachable-fallthrough.c @@ -0,0 +1,13 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c2x -Wunreachable-code-fallthrough %s +// RUN: %clang_cc1 -fsyntax-only -verify -std=c2x -Wunreachable-code %s +// RUN: %clang_cc1 -fsyntax-only -verify=code -std=c2x -Wunreachable-code -Wno-unreachable-code-fallthrough %s +// RUN: %clang_cc1 -fsyntax-only -verify -std=c2x -Wno-unreachable-code -Wunreachable-code-fallthrough %s + +int n; +void f(void){ + switch (n){ + [[fallthrough]]; // expected-warning{{fallthrough annotation in unreachable code}} + // code-warning@-1{{never be executed}} + case 1:; + } +}