[clang] e363c59 - [clang][dataflow] Extend flow condition in the body of a do/while loop
Stanislav Gatev via cfe-commits
cfe-commits at lists.llvm.org
Mon Jun 20 10:31:08 PDT 2022
Author: Stanislav Gatev
Date: 2022-06-20T17:31:00Z
New Revision: e363c5963dc3ad5d9492d3f37055ad56a84411a5
URL: https://github.com/llvm/llvm-project/commit/e363c5963dc3ad5d9492d3f37055ad56a84411a5
DIFF: https://github.com/llvm/llvm-project/commit/e363c5963dc3ad5d9492d3f37055ad56a84411a5.diff
LOG: [clang][dataflow] Extend flow condition in the body of a do/while loop
Extend flow condition in the body of a do/while loop.
Differential Revision: https://reviews.llvm.org/D128183
Reviewed-by: gribozavr2, xazax.hun
Added:
Modified:
clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp
clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
Removed:
################################################################################
diff --git a/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp b/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
index 4759932a696f1..e8d3a4e6d4505 100644
--- a/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
+++ b/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
@@ -87,8 +87,13 @@ static Value *mergeDistinctValues(QualType Type, Value *Val1,
// have mutually exclusive conditions.
if (auto *Expr1 = dyn_cast<BoolValue>(Val1)) {
auto *Expr2 = cast<BoolValue>(Val2);
- return &Env1.makeOr(Env1.makeAnd(Env1.getFlowConditionToken(), *Expr1),
- Env1.makeAnd(Env2.getFlowConditionToken(), *Expr2));
+ auto &MergedVal = MergedEnv.makeAtomicBoolValue();
+ MergedEnv.addToFlowCondition(MergedEnv.makeOr(
+ MergedEnv.makeAnd(Env1.getFlowConditionToken(),
+ MergedEnv.makeIff(MergedVal, *Expr1)),
+ MergedEnv.makeAnd(Env2.getFlowConditionToken(),
+ MergedEnv.makeIff(MergedVal, *Expr2))));
+ return &MergedVal;
}
// FIXME: add unit tests that cover this statement.
diff --git a/clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp b/clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp
index a1ce2f6912574..68e897e035962 100644
--- a/clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp
+++ b/clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp
@@ -89,6 +89,12 @@ class TerminatorVisitor : public ConstStmtVisitor<TerminatorVisitor> {
extendFlowCondition(*Cond);
}
+ void VisitDoStmt(const DoStmt *S) {
+ auto *Cond = S->getCond();
+ assert(Cond != nullptr);
+ extendFlowCondition(*Cond);
+ }
+
void VisitForStmt(const ForStmt *S) {
auto *Cond = S->getCond();
assert(Cond != nullptr);
diff --git a/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp b/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
index 29a45a315074d..3a8e2ac8588a5 100644
--- a/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
+++ b/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
@@ -3628,25 +3628,81 @@ TEST_F(TransferTest, WhileStmtBranchExtendsFlowCondition) {
void target(bool Foo) {
while (Foo) {
(void)0;
- // [[while_branch]]
+ // [[loop_body]]
}
+ (void)0;
+ // [[after_loop]]
}
)";
- runDataflow(Code,
- [](llvm::ArrayRef<
- std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
- Results,
- ASTContext &ASTCtx) {
- ASSERT_THAT(Results, ElementsAre(Pair("while_branch", _)));
- const Environment &Env = Results[0].second.Env;
+ runDataflow(
+ Code, [](llvm::ArrayRef<
+ std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
+ Results,
+ ASTContext &ASTCtx) {
+ ASSERT_THAT(Results,
+ ElementsAre(Pair("after_loop", _), Pair("loop_body", _)));
+ const Environment &LoopBodyEnv = Results[1].second.Env;
+ const Environment &AfterLoopEnv = Results[0].second.Env;
- const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
- ASSERT_THAT(FooDecl, NotNull());
+ const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
+ ASSERT_THAT(FooDecl, NotNull());
- BoolValue &FooVal =
- *cast<BoolValue>(Env.getValue(*FooDecl, SkipPast::None));
- EXPECT_TRUE(Env.flowConditionImplies(FooVal));
- });
+ BoolValue &LoopBodyFooVal =
+ *cast<BoolValue>(LoopBodyEnv.getValue(*FooDecl, SkipPast::None));
+ EXPECT_TRUE(LoopBodyEnv.flowConditionImplies(LoopBodyFooVal));
+
+ BoolValue &AfterLoopFooVal =
+ *cast<BoolValue>(AfterLoopEnv.getValue(*FooDecl, SkipPast::None));
+ EXPECT_TRUE(AfterLoopEnv.flowConditionImplies(
+ AfterLoopEnv.makeNot(AfterLoopFooVal)));
+ });
+}
+
+TEST_F(TransferTest, DoWhileStmtBranchExtendsFlowCondition) {
+ std::string Code = R"(
+ void target(bool Foo) {
+ bool Bar = true;
+ do {
+ (void)0;
+ // [[loop_body]]
+ Bar = false;
+ } while (Foo);
+ (void)0;
+ // [[after_loop]]
+ }
+ )";
+ runDataflow(
+ Code, [](llvm::ArrayRef<
+ std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
+ Results,
+ ASTContext &ASTCtx) {
+ ASSERT_THAT(Results,
+ ElementsAre(Pair("after_loop", _), Pair("loop_body", _)));
+ const Environment &LoopBodyEnv = Results[1].second.Env;
+ const Environment &AfterLoopEnv = Results[0].second.Env;
+
+ const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
+ ASSERT_THAT(FooDecl, NotNull());
+
+ const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
+ ASSERT_THAT(BarDecl, NotNull());
+
+ BoolValue &LoopBodyFooVal =
+ *cast<BoolValue>(LoopBodyEnv.getValue(*FooDecl, SkipPast::None));
+ BoolValue &LoopBodyBarVal =
+ *cast<BoolValue>(LoopBodyEnv.getValue(*BarDecl, SkipPast::None));
+ EXPECT_TRUE(LoopBodyEnv.flowConditionImplies(
+ LoopBodyEnv.makeOr(LoopBodyBarVal, LoopBodyFooVal)));
+
+ BoolValue &AfterLoopFooVal =
+ *cast<BoolValue>(AfterLoopEnv.getValue(*FooDecl, SkipPast::None));
+ BoolValue &AfterLoopBarVal =
+ *cast<BoolValue>(AfterLoopEnv.getValue(*BarDecl, SkipPast::None));
+ EXPECT_TRUE(AfterLoopEnv.flowConditionImplies(
+ AfterLoopEnv.makeNot(AfterLoopFooVal)));
+ EXPECT_TRUE(AfterLoopEnv.flowConditionImplies(
+ AfterLoopEnv.makeNot(AfterLoopBarVal)));
+ });
}
TEST_F(TransferTest, ForStmtBranchExtendsFlowCondition) {
@@ -3654,25 +3710,34 @@ TEST_F(TransferTest, ForStmtBranchExtendsFlowCondition) {
void target(bool Foo) {
for (; Foo;) {
(void)0;
- // [[for_branch]]
+ // [[loop_body]]
}
+ (void)0;
+ // [[after_loop]]
}
)";
- runDataflow(Code,
- [](llvm::ArrayRef<
- std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
- Results,
- ASTContext &ASTCtx) {
- ASSERT_THAT(Results, ElementsAre(Pair("for_branch", _)));
- const Environment &Env = Results[0].second.Env;
+ runDataflow(
+ Code, [](llvm::ArrayRef<
+ std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
+ Results,
+ ASTContext &ASTCtx) {
+ ASSERT_THAT(Results,
+ ElementsAre(Pair("after_loop", _), Pair("loop_body", _)));
+ const Environment &LoopBodyEnv = Results[1].second.Env;
+ const Environment &AfterLoopEnv = Results[0].second.Env;
- const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
- ASSERT_THAT(FooDecl, NotNull());
+ const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
+ ASSERT_THAT(FooDecl, NotNull());
- BoolValue &FooVal =
- *cast<BoolValue>(Env.getValue(*FooDecl, SkipPast::None));
- EXPECT_TRUE(Env.flowConditionImplies(FooVal));
- });
+ BoolValue &LoopBodyFooVal =
+ *cast<BoolValue>(LoopBodyEnv.getValue(*FooDecl, SkipPast::None));
+ EXPECT_TRUE(LoopBodyEnv.flowConditionImplies(LoopBodyFooVal));
+
+ BoolValue &AfterLoopFooVal =
+ *cast<BoolValue>(AfterLoopEnv.getValue(*FooDecl, SkipPast::None));
+ EXPECT_TRUE(AfterLoopEnv.flowConditionImplies(
+ AfterLoopEnv.makeNot(AfterLoopFooVal)));
+ });
}
} // namespace
More information about the cfe-commits
mailing list