aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTakuya Shimizu <shimizu2486@gmail.com>2023-03-14 08:43:35 -0400
committerAaron Ballman <aaron@aaronballman.com>2023-03-14 08:43:35 -0400
commitde401ac2a4ab74392b8234aa3a517481a1e2762c (patch)
tree773cb628bf6d3bd940323cd9984fa6909c26277f
parenteb54254b6e09afd726feefbebd1a74a4bc028722 (diff)
downloadllvm-de401ac2a4ab74392b8234aa3a517481a1e2762c.zip
llvm-de401ac2a4ab74392b8234aa3a517481a1e2762c.tar.gz
llvm-de401ac2a4ab74392b8234aa3a517481a1e2762c.tar.bz2
[clang][Sema] Avoid duplicate diagnostics for unreachable fallthrough attribute
This patch checks whether -Wunreachable-code-fallthrough is enabled when clang encounters unreachable fallthrough attributes and, if so, suppresses code will never be executed warning to avoid duplicate warnings. Fixes https://github.com/llvm/llvm-project/issues/60416 Differential Revision: https://reviews.llvm.org/D145842
-rw-r--r--clang/docs/ReleaseNotes.rst3
-rw-r--r--clang/include/clang/Analysis/Analyses/ReachableCode.h8
-rw-r--r--clang/lib/Analysis/ReachableCode.cpp12
-rw-r--r--clang/lib/Sema/AnalysisBasedWarnings.cpp16
-rw-r--r--clang/test/Sema/warn-unreachable-fallthrough.c13
5 files changed, 39 insertions, 13 deletions
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index a8c6f2f7..b466dfc 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -167,6 +167,9 @@ Improvements to Clang's diagnostics
``<built-in>``.
- 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
index 514b945..f1b63f7 100644
--- a/clang/include/clang/Analysis/Analyses/ReachableCode.h
+++ b/clang/include/clang/Analysis/Analyses/ReachableCode.h
@@ -48,11 +48,9 @@ class Callback {
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
index 5cc63bb..1bf0d9a 100644
--- 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 @@ void DeadCodeScan::reportDeadCode(const CFGBlock *B,
UK = reachable_code::UK_Return;
}
+ const auto *AS = dyn_cast<AttributedStmt>(S);
+ bool HasFallThroughAttr =
+ AS && hasSpecificAttr<FallThroughAttr>(AS->getAttrs());
+
SourceRange SilenceableCondVal;
if (UK == reachable_code::UK_Other) {
@@ -645,8 +650,9 @@ void DeadCodeScan::reportDeadCode(const CFGBlock *B,
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 @@ void DeadCodeScan::reportDeadCode(const CFGBlock *B,
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
index 4367435..f5c48ed 100644
--- a/clang/lib/Sema/AnalysisBasedWarnings.cpp
+++ b/clang/lib/Sema/AnalysisBasedWarnings.cpp
@@ -66,11 +66,17 @@ namespace {
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
index 0000000..e048a9e
--- /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:;
+ }
+}