[clang] [clang][dataflow] Don't crash when BlockToState is called from unreachable path (PR #65732)
Kinuko Yasuda via cfe-commits
cfe-commits at lists.llvm.org
Fri Sep 8 06:20:21 PDT 2023
https://github.com/kinu updated https://github.com/llvm/llvm-project/pull/65732:
>From bc119f4bb478431bf85cda47dbc2a25faa59e85f Mon Sep 17 00:00:00 2001
From: Kinuko Yasuda <kinuko at chromium.org>
Date: Fri, 8 Sep 2023 09:03:35 +0000
Subject: [PATCH 1/2] [clang][dataflow] Don't crash when BlockToState doesn't
have unreached block
When we call `getEnvironment`, `BlockToState[BlockId]` for the block can return
null even if CFCtx.isBlockReachable(B) returns true if it is called from a
particular block that is marked unreachable to the block.
(An example is in `EvaluateBlockWithUnreachablePreds` in TransferTest.cpp)
---
clang/lib/Analysis/FlowSensitive/Transfer.cpp | 15 +++++++++++++-
.../Analysis/FlowSensitive/TransferTest.cpp | 20 +++++++++++++++++++
2 files changed, 34 insertions(+), 1 deletion(-)
diff --git a/clang/lib/Analysis/FlowSensitive/Transfer.cpp b/clang/lib/Analysis/FlowSensitive/Transfer.cpp
index 67d8be392ae6053..b46c947c691b9b9 100644
--- a/clang/lib/Analysis/FlowSensitive/Transfer.cpp
+++ b/clang/lib/Analysis/FlowSensitive/Transfer.cpp
@@ -43,7 +43,20 @@ const Environment *StmtToEnvMap::getEnvironment(const Stmt &S) const {
if (!CFCtx.isBlockReachable(*BlockIt->getSecond()))
return nullptr;
const auto &State = BlockToState[BlockIt->getSecond()->getBlockID()];
- assert(State);
+ if (!(State)) {
+ LLVM_DEBUG({
+ // State can be null when this block is unreachable from the block that
+ // called this method.
+ bool hasUnreachableEdgeFromPred = false;
+ for (auto B : BlockIt->getSecond()->preds())
+ if (!B) {
+ hasUnreachableEdgeFromPred = true;
+ break;
+ }
+ assert(hasUnreachableEdgeFromPred);
+ });
+ return nullptr;
+ }
return &State->Env;
}
diff --git a/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp b/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
index 177970ac52a67eb..1fa800044c288d4 100644
--- a/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
+++ b/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
@@ -5853,4 +5853,24 @@ TEST(TransferTest, AnonymousStructWithReferenceField) {
});
}
+TEST(TransferTest, EvaluateBlockWithUnreachablePreds) {
+ // This is a crash repro.
+ // `false` block may not have been processed when we try to evalute the `||`
+ // after visiting `true`, because it is not necessary (and therefore the edge
+ // is marked unreachable). Trying to get the analysis state via
+ // `getEnvironment` for the subexpression should still not crash.
+ std::string Code = R"(
+ int cast(int i) {
+ if ((i < 0 && true) || false) {
+ return 0;
+ }
+ return 0;
+ }
+ )";
+ runDataflow(
+ Code,
+ [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
+ ASTContext &ASTCtx) {});
+}
+
} // namespace
>From 144cdf860b19f867e8c61c9478713adbe719967b Mon Sep 17 00:00:00 2001
From: Kinuko Yasuda <kinuko at chromium.org>
Date: Fri, 8 Sep 2023 13:11:49 +0000
Subject: [PATCH 2/2] comment change to see if it triggers build
---
clang/unittests/Analysis/FlowSensitive/TransferTest.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp b/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
index 1fa800044c288d4..ec07555d7f33b3b 100644
--- a/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
+++ b/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
@@ -5858,7 +5858,7 @@ TEST(TransferTest, EvaluateBlockWithUnreachablePreds) {
// `false` block may not have been processed when we try to evalute the `||`
// after visiting `true`, because it is not necessary (and therefore the edge
// is marked unreachable). Trying to get the analysis state via
- // `getEnvironment` for the subexpression should still not crash.
+ // `getEnvironment` for the subexpression still should not crash.
std::string Code = R"(
int cast(int i) {
if ((i < 0 && true) || false) {
More information about the cfe-commits
mailing list