From 9cbe0ef60f0154cbbefaa7d3092d65e4a4ab4d2a Mon Sep 17 00:00:00 2001 From: Paul Semel Date: Wed, 7 Feb 2024 13:06:40 +0000 Subject: [PATCH] [dataflow] CXXForRangeStmt should extend flow condition This is needed in order to correctly assume implicit iterator validity in the iterator checker. --- .../TypeErasedDataflowAnalysis.cpp | 9 +++++--- .../TypeErasedDataflowAnalysisTest.cpp | 21 +++++++++++++++++++ 2 files changed, 27 insertions(+), 3 deletions(-) diff --git a/clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp b/clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp index 4c88c46142d64..f02c65094113e 100644 --- a/clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp +++ b/clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp @@ -103,9 +103,12 @@ class TerminatorVisitor return {nullptr, false}; } - TerminatorVisitorRetTy VisitCXXForRangeStmt(const CXXForRangeStmt *) { - // Don't do anything special for CXXForRangeStmt, because the condition - // (being implicitly generated) isn't visible from the loop body. + TerminatorVisitorRetTy VisitCXXForRangeStmt(const CXXForRangeStmt *S) { + // Even though the condition isn't visible from the loop body, analysis + // might depend on the implicit implicit statements implied by the loop. + auto *Cond = S->getCond(); + if (Cond != nullptr) + return extendFlowCondition(*Cond); return {nullptr, false}; } diff --git a/clang/unittests/Analysis/FlowSensitive/TypeErasedDataflowAnalysisTest.cpp b/clang/unittests/Analysis/FlowSensitive/TypeErasedDataflowAnalysisTest.cpp index 3bca9cced8d6f..b940fb876710c 100644 --- a/clang/unittests/Analysis/FlowSensitive/TypeErasedDataflowAnalysisTest.cpp +++ b/clang/unittests/Analysis/FlowSensitive/TypeErasedDataflowAnalysisTest.cpp @@ -1710,4 +1710,25 @@ TEST_F(TopTest, ForRangeStmtConverges) { // analysis converged. }); } + +TEST_F(TopTest, ForRangeStmtHasFlowCondition) { + std::string Code = R"( + #include + void target(bool Foo) { + std::array t; + for (auto& i : t) { + (void)0; + /*[[p1]]*/ + } + } + )"; + runDataflow(Code, + [](const llvm::StringMap> &Results, + const AnalysisOutputs &AO) { + ASSERT_THAT(Results.keys(), UnorderedElementsAre("p1")); + const Environment &Env1 = getEnvironmentAtAnnotation(Results, "p1"); + ASSERT_TRUE(Env1.proves(Env1.arena().makeAtomRef(Env1.getFlowConditionToken()))); + }); +} + } // namespace