[clang] [clang-tools-extra] Backport/pr 139068 (PR #229998)
via cfe-commits
cfe-commits at lists.llvm.org
Wed Oct 7 23:14:51 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang-tidy
Author: Magyarimiki
<details>
<summary>Changes</summary>
---
Patch is 20.30 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/229998.diff
11 Files Affected:
- (modified) clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp (+3)
- (modified) clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt (+1)
- (added) clang-tools-extra/clang-tidy/bugprone/DataflowDeadCodeCheck.cpp (+122)
- (added) clang-tools-extra/clang-tidy/bugprone/DataflowDeadCodeCheck.h (+37)
- (modified) clang-tools-extra/clangd/TidyProvider.cpp (+2)
- (added) clang-tools-extra/docs/clang-tidy/checks/bugprone/dataflow-dead-code.rst (+79)
- (modified) clang-tools-extra/docs/clang-tidy/checks/list.md (+1)
- (added) clang-tools-extra/test/clang-tidy/checkers/bugprone/dataflow-dead-code.cpp (+55)
- (added) clang/include/clang/Analysis/FlowSensitive/Models/DeadCodeModel.h (+68)
- (modified) clang/lib/Analysis/FlowSensitive/Models/CMakeLists.txt (+1)
- (added) clang/lib/Analysis/FlowSensitive/Models/DeadCodeModel.cpp (+103)
``````````diff
diff --git a/clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp b/clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp
index 3aa39d10ceb5d..5bb5fe880ba82 100644
--- a/clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp
+++ b/clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp
@@ -27,6 +27,7 @@
#include "DanglingHandleCheck.h"
#include "DefaultOperatorNewOnOveralignedTypeCheck.h"
#include "DerivedMethodShadowingBaseMethodCheck.h"
+#include "DataflowDeadCodeCheck.h"
#include "DynamicStaticInitializersCheck.h"
#include "EasilySwappableParametersCheck.h"
#include "EmptyCatchCheck.h"
@@ -156,6 +157,8 @@ class BugproneModule : public ClangTidyModule {
"bugprone-copy-constructor-mutates-argument");
CheckFactories.registerCheck<DanglingHandleCheck>(
"bugprone-dangling-handle");
+ CheckFactories.registerCheck<DataflowDeadCodeCheck>(
+ "bugprone-dataflow-dead-code");
CheckFactories.registerCheck<DefaultOperatorNewOnOveralignedTypeCheck>(
"bugprone-default-operator-new-on-overaligned-type");
CheckFactories.registerCheck<DerivedMethodShadowingBaseMethodCheck>(
diff --git a/clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt b/clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt
index 43e85b1407f21..0462d9daab4de 100644
--- a/clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt
+++ b/clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt
@@ -22,6 +22,7 @@ add_clang_library(clangTidyBugproneModule STATIC
CopyConstructorMutatesArgumentCheck.cpp
CrtpConstructorAccessibilityCheck.cpp
DanglingHandleCheck.cpp
+ DataflowDeadCodeCheck.cpp
DefaultOperatorNewOnOveralignedTypeCheck.cpp
DerivedMethodShadowingBaseMethodCheck.cpp
DynamicStaticInitializersCheck.cpp
diff --git a/clang-tools-extra/clang-tidy/bugprone/DataflowDeadCodeCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/DataflowDeadCodeCheck.cpp
new file mode 100644
index 0000000000000..2fe1519fa31d0
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/bugprone/DataflowDeadCodeCheck.cpp
@@ -0,0 +1,122 @@
+//===--- DataflowDeadCodeCheck.cpp - clang-tidy-------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "DataflowDeadCodeCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/DeclTemplate.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/ASTMatchers/ASTMatchers.h"
+#include "clang/Analysis/CFG.h"
+#include "clang/Analysis/FlowSensitive/DataflowAnalysisContext.h"
+#include "clang/Analysis/FlowSensitive/DataflowEnvironment.h"
+#include "clang/Analysis/FlowSensitive/DataflowLattice.h"
+#include "clang/Analysis/FlowSensitive/Models/DeadCodeModel.h"
+#include "clang/Analysis/FlowSensitive/NoopAnalysis.h"
+#include "clang/Analysis/FlowSensitive/WatchedLiteralsSolver.h"
+#include "clang/Basic/SourceLocation.h"
+#include "llvm/ADT/Any.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/Support/Error.h"
+#include <clang/Analysis/FlowSensitive/AdornedCFG.h>
+#include <memory>
+#include <vector>
+
+namespace clang::tidy::bugprone {
+
+using ast_matchers::MatchFinder;
+using dataflow::DeadCodeDiagnoser;
+using dataflow::DeadCodeModel;
+using dataflow::NoopAnalysis;
+using Diagnoser = DeadCodeDiagnoser;
+
+static constexpr llvm::StringLiteral FuncID("fun");
+
+struct ExpandedResult {
+ Diagnoser::DiagnosticEntry Entry;
+ std::optional<SourceLocation> DerefLoc;
+};
+
+using ResultType = Diagnoser::ResultType;
+
+static std::optional<ResultType> analyzeFunction(const FunctionDecl &FuncDecl) {
+ using dataflow::AdornedCFG;
+ using dataflow::DataflowAnalysisState;
+ using llvm::Expected;
+
+ ASTContext &ASTCtx = FuncDecl.getASTContext();
+
+ if (!FuncDecl.doesThisDeclarationHaveABody()) {
+ return std::nullopt;
+ }
+
+ Expected<AdornedCFG> Context =
+ AdornedCFG::build(FuncDecl, *FuncDecl.getBody(), ASTCtx);
+ if (!Context)
+ return std::nullopt;
+
+ dataflow::DataflowAnalysisContext AnalysisContext(
+ std::make_unique<dataflow::WatchedLiteralsSolver>());
+ dataflow::Environment Env(AnalysisContext, FuncDecl);
+ DeadCodeModel Analysis(ASTCtx);
+ Diagnoser Diagnoser;
+
+ ResultType Diagnostics;
+
+ if (llvm::Error E =
+ dataflow::diagnoseFunction<DeadCodeModel, Diagnoser::DiagnosticEntry>(
+ FuncDecl, ASTCtx, Diagnoser)
+ .moveInto(Diagnostics)) {
+ llvm::dbgs() << "Dataflow analysis failed: " << llvm::toString(std::move(E))
+ << ".\n";
+ return std::nullopt;
+ }
+
+ return Diagnostics;
+}
+
+void DataflowDeadCodeCheck::registerMatchers(MatchFinder *Finder) {
+ using namespace ast_matchers;
+ Finder->addMatcher(
+ decl(
+ anyOf(functionDecl(unless(isExpansionInSystemHeader()),
+ // FIXME: Remove the filter below when lambdas are
+ // well supported by the check.
+ unless(hasDeclContext(cxxRecordDecl(isLambda())))),
+ cxxConstructorDecl(
+ unless(hasDeclContext(cxxRecordDecl(isLambda()))))))
+ .bind(FuncID),
+ this);
+}
+
+void DataflowDeadCodeCheck::check(const MatchFinder::MatchResult &Result) {
+ if (Result.SourceManager->getDiagnostics().hasUncompilableErrorOccurred())
+ return;
+
+ const auto *FuncDecl = Result.Nodes.getNodeAs<FunctionDecl>(FuncID);
+ assert(FuncDecl && "invalid FuncDecl matcher");
+ if (FuncDecl->isTemplated())
+ return;
+
+ if (const auto Diagnostics = analyzeFunction(*FuncDecl)) {
+ for (const auto [Loc, Type] : *Diagnostics) {
+
+ switch (Type) {
+ case Diagnoser::DiagnosticType::AlwaysTrue:
+ diag(Loc, "dead code - branching condition is always true");
+ break;
+
+ case Diagnoser::DiagnosticType::AlwaysFalse:
+ diag(Loc, "dead code - branching condition is always false");
+ break;
+ }
+ }
+ }
+}
+
+} // namespace clang::tidy::bugprone
diff --git a/clang-tools-extra/clang-tidy/bugprone/DataflowDeadCodeCheck.h b/clang-tools-extra/clang-tidy/bugprone/DataflowDeadCodeCheck.h
new file mode 100644
index 0000000000000..06338550da9d5
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/bugprone/DataflowDeadCodeCheck.h
@@ -0,0 +1,37 @@
+//===--- DataflowDeadCodeCheck.h - clang-tidy ----------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_DEADCODECHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_DEADCODECHECK_H
+
+#include "../ClangTidyCheck.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+namespace clang::tidy::bugprone {
+
+/// Finds checks for pointer nullability after a pointer has already been
+/// dereferenced, using the data-flow framework.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/bugprone/null-check-after-dereference.html
+class DataflowDeadCodeCheck : public ClangTidyCheck {
+public:
+ DataflowDeadCodeCheck(StringRef Name, ClangTidyContext *Context)
+ : ClangTidyCheck(Name, Context) {}
+
+ // The data-flow framework does not support C because of AST differences.
+ bool isLanguageVersionSupported(const LangOptions &LangOpts) const override {
+ return LangOpts.CPlusPlus;
+ }
+ void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+ void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+};
+
+} // namespace clang::tidy::bugprone
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_DEADCODECHECK_H
\ No newline at end of file
diff --git a/clang-tools-extra/clangd/TidyProvider.cpp b/clang-tools-extra/clangd/TidyProvider.cpp
index aae7d6b126c5a..2d0d82c83cd81 100644
--- a/clang-tools-extra/clangd/TidyProvider.cpp
+++ b/clang-tools-extra/clangd/TidyProvider.cpp
@@ -221,6 +221,8 @@ TidyProvider disableUnusableChecks(llvm::ArrayRef<std::string> ExtraBadChecks) {
// Check uses dataflow analysis, which might hang/crash unexpectedly on
// incomplete code.
"-bugprone-unchecked-optional-access",
+ "-bugprone-dataflow-dead-code",
+ "-bugprone-unchecked-optional-access",
"-abseil-unchecked-statusor-access");
size_t Size = BadChecks.size();
diff --git a/clang-tools-extra/docs/clang-tidy/checks/bugprone/dataflow-dead-code.rst b/clang-tools-extra/docs/clang-tidy/checks/bugprone/dataflow-dead-code.rst
new file mode 100644
index 0000000000000..de6bf8bcd3e14
--- /dev/null
+++ b/clang-tools-extra/docs/clang-tidy/checks/bugprone/dataflow-dead-code.rst
@@ -0,0 +1,79 @@
+.. title:: clang-tidy - bugprone-dataflow-dead-code
+
+bugprone-dataflow-dead-code
+===========================
+
+*Note*: This check uses a flow-sensitive static analysis to produce its
+results. Therefore, it may be more resource intensive (RAM, CPU) than the
+average clang-tidy check.
+
+Finds instances of always-true and always-false conditions in branch statements.
+
+.. code-block:: c++
+
+ void f(bool a, bool b) {
+ if (a) {
+ return;
+ } else if (a == b) {
+ if (b) { // warning: dead code - branching condition is always false
+ return;
+ }
+ }
+ }
+
+Notes
+-----
+
+True and false literals
+-----------------------
+
+Since macro and template code commonly uses always-true and always-false loops,
+the literals ``true`` and ``false`` are excluded from being matched outright.
+Assertion statements are a common example.
+
+.. code-block:: c++
+
+ // common way to define asserts in libraries
+ #define assert(x) do {} while(false)
+
+ void f(int *param) {
+ assert(param); // no-warning, even though while(false) is always false
+ }
+
+C++ class support
+-----------------
+
+Support for C++ datastructures is limited due to framework limitations.
+Calling non-const member functions of a class do not invalidate member variable
+values.
+
+.. code-block:: c++
+
+ struct S {
+ bool a;
+ void change_a() { a = random_bool(); }
+ };
+
+ void f(S s) {
+ if (s.a) {
+ return;
+ }
+ s.change_a();
+ if (s.a) {} // false-positive: condition is always false
+ }
+
+Marking of unexpected values
+----------------------------
+
+Due to framework limitations, the check currently utilizes a mark-and-check
+approach. First it marks all loop condition values, then it checks whether the
+value is always true or not. This can lead to the same value showing as
+always-true in an unexpected place, or in an unexpected expression.
+
+.. code-block:: c++
+
+ void f(int a, int b) {
+ if (a == b) {
+ f(a == b); // unexpected-warning: condition is always true
+ }
+ }
diff --git a/clang-tools-extra/docs/clang-tidy/checks/list.md b/clang-tools-extra/docs/clang-tidy/checks/list.md
index a74a26e691053..2613b5bf63d54 100644
--- a/clang-tools-extra/docs/clang-tidy/checks/list.md
+++ b/clang-tools-extra/docs/clang-tidy/checks/list.md
@@ -97,6 +97,7 @@ readability/*
| {doc}`bugprone-copy-constructor-mutates-argument <bugprone/copy-constructor-mutates-argument>` | |
| {doc}`bugprone-crtp-constructor-accessibility <bugprone/crtp-constructor-accessibility>` | Yes |
| {doc}`bugprone-dangling-handle <bugprone/dangling-handle>` | |
+| {doc}`bugprone-dataflow-dead-code <bugprone/bugprone-dataflow-dead-code>` | |
| {doc}`bugprone-default-operator-new-on-overaligned-type <bugprone/default-operator-new-on-overaligned-type>` | |
| {doc}`bugprone-derived-method-shadowing-base-method <bugprone/derived-method-shadowing-base-method>` | |
| {doc}`bugprone-dynamic-static-initializers <bugprone/dynamic-static-initializers>` | |
diff --git a/clang-tools-extra/test/clang-tidy/checkers/bugprone/dataflow-dead-code.cpp b/clang-tools-extra/test/clang-tidy/checkers/bugprone/dataflow-dead-code.cpp
new file mode 100644
index 0000000000000..99db84c266d1d
--- /dev/null
+++ b/clang-tools-extra/test/clang-tidy/checkers/bugprone/dataflow-dead-code.cpp
@@ -0,0 +1,55 @@
+// RUN: %check_clang_tidy %s bugprone-dataflow-dead-code %t
+
+void simple_cases(bool a) {
+ if (a) {
+ if (a) {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: dead code - branching condition is always true
+ while (!a) {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: dead code - branching condition is always false
+ // fixme: false positive
+ // CHECK-MESSAGES: :[[@LINE-3]]:13: warning: dead code - branching condition is always true
+ }
+}
+
+void transitive(bool a, bool b) {
+ if (a) {
+ return;
+ } else if (a == b) {
+ // fixme: false positive
+ // CHECK-MESSAGES: :[[@LINE-2]]:14: warning: dead code - branching condition is always false
+ if (b) {
+ // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: dead code - branching condition is always false
+ return;
+ }
+ }
+}
+
+#define assert(x) do {} while(false)
+
+void assert_excluded(int *x) {
+ assert(x); // no-warning
+}
+
+extern bool random_bool();
+
+void empty_forloop_excluded() {
+ for (;;) { // no-warning
+ if (random_bool()) { // no-warning
+ return;
+ }
+ }
+}
+
+struct S {
+ bool a;
+ void change_a() { a = random_bool(); }
+};
+
+void false_positive_classes(S s) {
+ if (s.a) {
+ return;
+ }
+ s.change_a();
+ if (s.a) {} // fixme: false positive
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: dead code - branching condition is always false
+}
\ No newline at end of file
diff --git a/clang/include/clang/Analysis/FlowSensitive/Models/DeadCodeModel.h b/clang/include/clang/Analysis/FlowSensitive/Models/DeadCodeModel.h
new file mode 100644
index 0000000000000..a44ce3c7a779c
--- /dev/null
+++ b/clang/include/clang/Analysis/FlowSensitive/Models/DeadCodeModel.h
@@ -0,0 +1,68 @@
+//===-- DeadCodeModel.h -----------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef CLANG_ANALYSIS_FLOWSENSITIVE_MODELS_DEADCODEMODEL_H
+#define CLANG_ANALYSIS_FLOWSENSITIVE_MODELS_DEADCODEMODEL_H
+
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/Stmt.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/ASTMatchers/ASTMatchers.h"
+#include "clang/Analysis/CFG.h"
+#include "clang/Analysis/FlowSensitive/CFGMatchSwitch.h"
+#include "clang/Analysis/FlowSensitive/DataflowAnalysis.h"
+#include "clang/Analysis/FlowSensitive/DataflowEnvironment.h"
+#include "clang/Analysis/FlowSensitive/DataflowLattice.h"
+#include "clang/Analysis/FlowSensitive/MapLattice.h"
+#include "clang/Analysis/FlowSensitive/NoopLattice.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/Twine.h"
+
+namespace clang::dataflow {
+
+class DeadCodeModel : public DataflowAnalysis<DeadCodeModel, NoopLattice> {
+public:
+ explicit DeadCodeModel(ASTContext &Context)
+ : DataflowAnalysis<DeadCodeModel, NoopLattice>(Context) {}
+
+ static NoopLattice initialElement() { return {}; }
+
+ void transfer(const CFGElement &E, NoopLattice &State, Environment &Env) {}
+
+ void transferBranch(bool Branch, const Stmt *S, NoopLattice &State,
+ Environment &Env);
+};
+
+class DeadCodeDiagnoser {
+public:
+ /// Returns source locations for pointers that were checked when known to be
+ // null, and checked after already dereferenced, respectively.
+ enum class DiagnosticType { AlwaysTrue, AlwaysFalse };
+
+ struct DiagnosticEntry {
+ SourceLocation Location;
+ DiagnosticType Type;
+ };
+ using ResultType = llvm::SmallVector<DiagnosticEntry>;
+
+private:
+ CFGMatchSwitch<const Environment, ResultType> DiagnoseMatchSwitch;
+
+public:
+ DeadCodeDiagnoser();
+
+ ResultType operator()(const CFGElement &Elt, ASTContext &Ctx,
+ const TransferStateForDiagnostics<NoopLattice> &State);
+};
+
+} // namespace clang::dataflow
+
+#endif
\ No newline at end of file
diff --git a/clang/lib/Analysis/FlowSensitive/Models/CMakeLists.txt b/clang/lib/Analysis/FlowSensitive/Models/CMakeLists.txt
index 62c9473842779..b3a31440ec8e3 100644
--- a/clang/lib/Analysis/FlowSensitive/Models/CMakeLists.txt
+++ b/clang/lib/Analysis/FlowSensitive/Models/CMakeLists.txt
@@ -1,5 +1,6 @@
add_clang_library(clangAnalysisFlowSensitiveModels
ChromiumCheckModel.cpp
+ DeadCodeModel.cpp
UncheckedOptionalAccessModel.cpp
UncheckedStatusOrAccessModel.cpp
GtestModelHelpers.cpp
diff --git a/clang/lib/Analysis/FlowSensitive/Models/DeadCodeModel.cpp b/clang/lib/Analysis/FlowSensitive/Models/DeadCodeModel.cpp
new file mode 100644
index 0000000000000..530a9cc0b5385
--- /dev/null
+++ b/clang/lib/Analysis/FlowSensitive/Models/DeadCodeModel.cpp
@@ -0,0 +1,103 @@
+//===-- NullPointerAnalysisModel.cpp ----------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Analysis/FlowSensitive/Models/DeadCodeModel.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/Stmt.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/ASTMatchers/ASTMatchers.h"
+#include "clang/Analysis/CFG.h"
+#include "clang/Analysis/FlowSensitive/CFGMatchSwitch.h"
+#include "clang/Analysis/FlowSensitive/DataflowAnalysis.h"
+#include "clang/Analysis/FlowSensitive/DataflowEnvironment.h"
+#include "clang/Analysis/FlowSensitive/DataflowLattice.h"
+#include "clang/Analysis/FlowSensitive/MapLattice.h"
+#include "clang/Analysis/FlowSensitive/NoopLattice.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/Twine.h"
+
+namespace clang::dataflow {
+namespace {
+using namespace ast_matchers;
+using Diagnoser = DeadCodeDiagnoser;
+
+constexpr char kCond[] = "condition";
+
+auto conditionMatcher() {
+ return expr(allOf(hasType(booleanType()), unless(cxxBoolLiteral())))
+ .bind(kCond);
+}
+
+DeadCodeDiagnoser::ResultType
+diagnoseAnyDeadCondition(const Expr *S, const MatchFinder::MatchResult &Result,
+ const Environment &Env) {
+ const auto *Cond = Result.Nodes.getNodeAs<Expr>(kCond);
+ assert(Cond != nullptr);
+
+ Value *Val = Env.getValue(*Cond);
+ if (!Val || !Val->getProperty(kCond))
+ return {};
+
+ if (Env.allows(Env.getBoolLiteralValue(false).formula())) {
+ // We are already in a dead code section, bail early
+ return {};
+ }
+
+ if (BoolValue *CondValue = cast_or_null<BoolValue>(Env.getValue(*Cond))) {
+ if (Env.proves(CondValue->formula())) {
+ return {{Cond->getBeginLoc(), Diagnoser::DiagnosticType::AlwaysTrue}};
+ }
+
+ if (Env.proves(Env.arena().makeNot(CondValue->formula()))) {
+ return {{Cond->getBeginLoc(), Diagnoser::DiagnosticType::AlwaysFalse}};
+ }
+ }
+
+ return {};
+}
+
+DeadCodeDiagnoser::ResultType catchall(const Stmt *S,
+ const MatchFinder::MatchResult &Result,
+ const Environment &Env) {
+ S->dump();
+ return {};
+}
+
+auto buildDiagnoseMatchSwitch() {
+ return CFGMatchSwitchBuilder<const Environment, Diagnoser::ResultType>()
+ .CaseOfCFGStmt<Expr>(conditionMatcher(), diagnoseAnyDeadCondition)
+ .Build();
+}
+
+} // namespace
+
+void DeadCodeModel::transferBranch(bool Branch, const Stmt *S,
+ NoopLattice &State, Environment &Env) {
+ if (!S || !isa<Expr>(S))
+ return;
+
+ Value *Val = Env.getValue(*cast<Expr>(S));
+
+ if (!Val)
+ return;
+
+ Val->setProperty(kCond, Env.getBoolLiteralValue(true));
+}
+
+DeadCodeDiagnoser::DeadCodeDiagnoser()
+ : DiagnoseMatchSwitch(buildDiagn...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/229998
More information about the cfe-commits
mailing list