diff options
author | Utkarsh Saxena <usx@google.com> | 2025-08-03 21:45:36 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2025-08-03 21:45:36 +0200 |
commit | f9be391dd7cf04d83525cfccc954c80c6f05d15d (patch) | |
tree | ec1f6be932c58525f8370c468741949f6ef67326 | |
parent | bc0f696b1fbf85b16bc9493b3e0e7027eb32f638 (diff) | |
download | llvm-f9be391dd7cf04d83525cfccc954c80c6f05d15d.zip llvm-f9be391dd7cf04d83525cfccc954c80c6f05d15d.tar.gz llvm-f9be391dd7cf04d83525cfccc954c80c6f05d15d.tar.bz2 |
[LifetimeSafety] Handle pruned-edges (null blocks) in dataflow (#150670)
Fix a crash in the lifetime safety dataflow analysis when handling null CFG blocks.
Added a null check for adjacent blocks in the dataflow analysis algorithm to prevent dereferencing null pointers. This occurs when processing CFG blocks with unreachable successors or predecessors.
Original crash: https://compiler-explorer.com/z/qfzfqG5vM
Fixes https://github.com/llvm/llvm-project/issues/150095
-rw-r--r-- | clang/lib/Analysis/LifetimeSafety.cpp | 2 | ||||
-rw-r--r-- | clang/unittests/Analysis/LifetimeSafetyTest.cpp | 19 |
2 files changed, 21 insertions, 0 deletions
diff --git a/clang/lib/Analysis/LifetimeSafety.cpp b/clang/lib/Analysis/LifetimeSafety.cpp index 94b8197..f39998c 100644 --- a/clang/lib/Analysis/LifetimeSafety.cpp +++ b/clang/lib/Analysis/LifetimeSafety.cpp @@ -603,6 +603,8 @@ public: OutStates[B] = StateOut; Visited.set(B->getBlockID()); for (const CFGBlock *AdjacentB : isForward() ? B->succs() : B->preds()) { + if (!AdjacentB) + continue; Lattice OldInState = getInState(AdjacentB); Lattice NewInState = D.join(OldInState, StateOut); // Enqueue the adjacent block if its in-state has changed or if we have diff --git a/clang/unittests/Analysis/LifetimeSafetyTest.cpp b/clang/unittests/Analysis/LifetimeSafetyTest.cpp index a48dc45..7cd679e 100644 --- a/clang/unittests/Analysis/LifetimeSafetyTest.cpp +++ b/clang/unittests/Analysis/LifetimeSafetyTest.cpp @@ -512,6 +512,25 @@ TEST_F(LifetimeAnalysisTest, PointersAndExpirationInACycle) { EXPECT_THAT(LoansTo({"temp"}), AreExpiredAt("after_loop")); } +TEST_F(LifetimeAnalysisTest, InfiniteLoopPrunesEdges) { + SetupTest(R"( + void target(MyObj out) { + MyObj *p = &out; + POINT(before_loop); + + for (;;) { + POINT(begin); + MyObj in; + p = ∈ + POINT(end); + } + } + )"); + EXPECT_THAT(Origin("p"), HasLoansTo({"out"}, "before_loop")); + EXPECT_THAT(Origin("p"), HasLoansTo({"in", "out"}, "begin")); + EXPECT_THAT(Origin("p"), HasLoansTo({"in"}, "end")); +} + TEST_F(LifetimeAnalysisTest, NestedScopes) { SetupTest(R"( void target() { |