Skip to content

Commit 8323209

Browse files
committed
[clang][dataflow] Extend flow condition in the body of a for loop
Extend flow condition in the body of a for loop. Differential Revision: https://reviews.llvm.org/D128060
1 parent 362814d commit 8323209

File tree

2 files changed

+93
-0
lines changed

2 files changed

+93
-0
lines changed

clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,12 @@ class TerminatorVisitor : public ConstStmtVisitor<TerminatorVisitor> {
8989
extendFlowCondition(*Cond);
9090
}
9191

92+
void VisitForStmt(const ForStmt *S) {
93+
auto *Cond = S->getCond();
94+
assert(Cond != nullptr);
95+
extendFlowCondition(*Cond);
96+
}
97+
9298
void VisitBinaryOperator(const BinaryOperator *S) {
9399
assert(S->getOpcode() == BO_LAnd || S->getOpcode() == BO_LOr);
94100
auto *LHS = S->getLHS();

clang/unittests/Analysis/FlowSensitive/TransferTest.cpp

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3588,4 +3588,91 @@ TEST_F(TransferTest, BinaryOperatorComma) {
35883588
});
35893589
}
35903590

3591+
TEST_F(TransferTest, IfStmtBranchExtendsFlowCondition) {
3592+
std::string Code = R"(
3593+
void target(bool Foo) {
3594+
if (Foo) {
3595+
(void)0;
3596+
// [[if_then]]
3597+
} else {
3598+
(void)0;
3599+
// [[if_else]]
3600+
}
3601+
}
3602+
)";
3603+
runDataflow(
3604+
Code, [](llvm::ArrayRef<
3605+
std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
3606+
Results,
3607+
ASTContext &ASTCtx) {
3608+
ASSERT_THAT(Results,
3609+
ElementsAre(Pair("if_else", _), Pair("if_then", _)));
3610+
const Environment &ThenEnv = Results[1].second.Env;
3611+
const Environment &ElseEnv = Results[0].second.Env;
3612+
3613+
const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3614+
ASSERT_THAT(FooDecl, NotNull());
3615+
3616+
BoolValue &ThenFooVal =
3617+
*cast<BoolValue>(ThenEnv.getValue(*FooDecl, SkipPast::None));
3618+
EXPECT_TRUE(ThenEnv.flowConditionImplies(ThenFooVal));
3619+
3620+
BoolValue &ElseFooVal =
3621+
*cast<BoolValue>(ElseEnv.getValue(*FooDecl, SkipPast::None));
3622+
EXPECT_TRUE(ElseEnv.flowConditionImplies(ElseEnv.makeNot(ElseFooVal)));
3623+
});
3624+
}
3625+
3626+
TEST_F(TransferTest, WhileStmtBranchExtendsFlowCondition) {
3627+
std::string Code = R"(
3628+
void target(bool Foo) {
3629+
while (Foo) {
3630+
(void)0;
3631+
// [[while_branch]]
3632+
}
3633+
}
3634+
)";
3635+
runDataflow(Code,
3636+
[](llvm::ArrayRef<
3637+
std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
3638+
Results,
3639+
ASTContext &ASTCtx) {
3640+
ASSERT_THAT(Results, ElementsAre(Pair("while_branch", _)));
3641+
const Environment &Env = Results[0].second.Env;
3642+
3643+
const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3644+
ASSERT_THAT(FooDecl, NotNull());
3645+
3646+
BoolValue &FooVal =
3647+
*cast<BoolValue>(Env.getValue(*FooDecl, SkipPast::None));
3648+
EXPECT_TRUE(Env.flowConditionImplies(FooVal));
3649+
});
3650+
}
3651+
3652+
TEST_F(TransferTest, ForStmtBranchExtendsFlowCondition) {
3653+
std::string Code = R"(
3654+
void target(bool Foo) {
3655+
for (; Foo;) {
3656+
(void)0;
3657+
// [[for_branch]]
3658+
}
3659+
}
3660+
)";
3661+
runDataflow(Code,
3662+
[](llvm::ArrayRef<
3663+
std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
3664+
Results,
3665+
ASTContext &ASTCtx) {
3666+
ASSERT_THAT(Results, ElementsAre(Pair("for_branch", _)));
3667+
const Environment &Env = Results[0].second.Env;
3668+
3669+
const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3670+
ASSERT_THAT(FooDecl, NotNull());
3671+
3672+
BoolValue &FooVal =
3673+
*cast<BoolValue>(Env.getValue(*FooDecl, SkipPast::None));
3674+
EXPECT_TRUE(Env.flowConditionImplies(FooVal));
3675+
});
3676+
}
3677+
35913678
} // namespace

0 commit comments

Comments
 (0)