xref: /llvm-project/clang/unittests/Analysis/FlowSensitive/DataflowAnalysisContextTest.cpp (revision af1463d403182720ae0e3fab07634817dd0f41be)
1ae60884dSStanislav Gatev //===- unittests/Analysis/FlowSensitive/DataflowAnalysisContextTest.cpp ---===//
2ae60884dSStanislav Gatev //
3ae60884dSStanislav Gatev // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4ae60884dSStanislav Gatev // See https://llvm.org/LICENSE.txt for license information.
5ae60884dSStanislav Gatev // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6ae60884dSStanislav Gatev //
7ae60884dSStanislav Gatev //===----------------------------------------------------------------------===//
8ae60884dSStanislav Gatev 
9ae60884dSStanislav Gatev #include "clang/Analysis/FlowSensitive/DataflowAnalysisContext.h"
10ae60884dSStanislav Gatev #include "clang/Analysis/FlowSensitive/WatchedLiteralsSolver.h"
11ae60884dSStanislav Gatev #include "gmock/gmock.h"
12ae60884dSStanislav Gatev #include "gtest/gtest.h"
13ae60884dSStanislav Gatev #include <memory>
14ae60884dSStanislav Gatev 
15ae60884dSStanislav Gatev namespace {
16ae60884dSStanislav Gatev 
17ae60884dSStanislav Gatev using namespace clang;
18ae60884dSStanislav Gatev using namespace dataflow;
19ae60884dSStanislav Gatev 
20ae60884dSStanislav Gatev class DataflowAnalysisContextTest : public ::testing::Test {
21ae60884dSStanislav Gatev protected:
DataflowAnalysisContextTest()22ae60884dSStanislav Gatev   DataflowAnalysisContextTest()
23bf47c1edSSam McCall       : Context(std::make_unique<WatchedLiteralsSolver>()), A(Context.arena()) {
24bf47c1edSSam McCall   }
25ae60884dSStanislav Gatev 
26ae60884dSStanislav Gatev   DataflowAnalysisContext Context;
27bf47c1edSSam McCall   Arena &A;
28ae60884dSStanislav Gatev };
29ae60884dSStanislav Gatev 
TEST_F(DataflowAnalysisContextTest,DistinctTopsNotEquivalent)3039b9d4f1SYitzhak Mandelbaum TEST_F(DataflowAnalysisContextTest, DistinctTopsNotEquivalent) {
31fc9821a8SSam McCall   auto &X = A.makeTopValue();
32fc9821a8SSam McCall   auto &Y = A.makeTopValue();
33fc9821a8SSam McCall   EXPECT_FALSE(Context.equivalentFormulas(X.formula(), Y.formula()));
3439b9d4f1SYitzhak Mandelbaum }
3539b9d4f1SYitzhak Mandelbaum 
TEST_F(DataflowAnalysisContextTest,TautologicalFlowConditionImplies)36*af1463d4Smartinboehme TEST_F(DataflowAnalysisContextTest, TautologicalFlowConditionImplies) {
37fc9821a8SSam McCall   Atom FC = A.makeFlowConditionToken();
38*af1463d4Smartinboehme   EXPECT_TRUE(Context.flowConditionImplies(FC, A.makeLiteral(true)));
39*af1463d4Smartinboehme   EXPECT_FALSE(Context.flowConditionImplies(FC, A.makeLiteral(false)));
40*af1463d4Smartinboehme   EXPECT_FALSE(Context.flowConditionImplies(FC, A.makeAtomRef(A.makeAtom())));
41*af1463d4Smartinboehme }
42*af1463d4Smartinboehme 
TEST_F(DataflowAnalysisContextTest,TautologicalFlowConditionAllows)43*af1463d4Smartinboehme TEST_F(DataflowAnalysisContextTest, TautologicalFlowConditionAllows) {
44*af1463d4Smartinboehme   Atom FC = A.makeFlowConditionToken();
45*af1463d4Smartinboehme   EXPECT_TRUE(Context.flowConditionAllows(FC, A.makeLiteral(true)));
46*af1463d4Smartinboehme   EXPECT_FALSE(Context.flowConditionAllows(FC, A.makeLiteral(false)));
47*af1463d4Smartinboehme   EXPECT_TRUE(Context.flowConditionAllows(FC, A.makeAtomRef(A.makeAtom())));
48*af1463d4Smartinboehme }
49*af1463d4Smartinboehme 
TEST_F(DataflowAnalysisContextTest,ContradictoryFlowConditionImpliesAnything)50*af1463d4Smartinboehme TEST_F(DataflowAnalysisContextTest, ContradictoryFlowConditionImpliesAnything) {
51*af1463d4Smartinboehme   Atom FC = A.makeFlowConditionToken();
52*af1463d4Smartinboehme   Context.addFlowConditionConstraint(FC, A.makeLiteral(false));
53*af1463d4Smartinboehme   EXPECT_TRUE(Context.flowConditionImplies(FC, A.makeLiteral(true)));
54*af1463d4Smartinboehme   EXPECT_TRUE(Context.flowConditionImplies(FC, A.makeLiteral(false)));
55*af1463d4Smartinboehme   EXPECT_TRUE(Context.flowConditionImplies(FC, A.makeAtomRef(A.makeAtom())));
56*af1463d4Smartinboehme }
57*af1463d4Smartinboehme 
TEST_F(DataflowAnalysisContextTest,ContradictoryFlowConditionAllowsNothing)58*af1463d4Smartinboehme TEST_F(DataflowAnalysisContextTest, ContradictoryFlowConditionAllowsNothing) {
59*af1463d4Smartinboehme   Atom FC = A.makeFlowConditionToken();
60*af1463d4Smartinboehme   Context.addFlowConditionConstraint(FC, A.makeLiteral(false));
61*af1463d4Smartinboehme   EXPECT_FALSE(Context.flowConditionAllows(FC, A.makeLiteral(true)));
62*af1463d4Smartinboehme   EXPECT_FALSE(Context.flowConditionAllows(FC, A.makeLiteral(false)));
63*af1463d4Smartinboehme   EXPECT_FALSE(Context.flowConditionAllows(FC, A.makeAtomRef(A.makeAtom())));
64955a05a2SStanislav Gatev }
65955a05a2SStanislav Gatev 
TEST_F(DataflowAnalysisContextTest,AddFlowConditionConstraint)66955a05a2SStanislav Gatev TEST_F(DataflowAnalysisContextTest, AddFlowConditionConstraint) {
67fc9821a8SSam McCall   Atom FC = A.makeFlowConditionToken();
68fc9821a8SSam McCall   auto &C = A.makeAtomRef(A.makeAtom());
69955a05a2SStanislav Gatev   Context.addFlowConditionConstraint(FC, C);
70955a05a2SStanislav Gatev   EXPECT_TRUE(Context.flowConditionImplies(FC, C));
71955a05a2SStanislav Gatev }
72955a05a2SStanislav Gatev 
TEST_F(DataflowAnalysisContextTest,AddInvariant)7321ab252fSSam McCall TEST_F(DataflowAnalysisContextTest, AddInvariant) {
7421ab252fSSam McCall   Atom FC = A.makeFlowConditionToken();
7521ab252fSSam McCall   auto &C = A.makeAtomRef(A.makeAtom());
7621ab252fSSam McCall   Context.addInvariant(C);
7721ab252fSSam McCall   EXPECT_TRUE(Context.flowConditionImplies(FC, C));
7821ab252fSSam McCall }
7921ab252fSSam McCall 
TEST_F(DataflowAnalysisContextTest,InvariantAndFCConstraintInteract)8021ab252fSSam McCall TEST_F(DataflowAnalysisContextTest, InvariantAndFCConstraintInteract) {
8121ab252fSSam McCall   Atom FC = A.makeFlowConditionToken();
8221ab252fSSam McCall   auto &C = A.makeAtomRef(A.makeAtom());
8321ab252fSSam McCall   auto &D = A.makeAtomRef(A.makeAtom());
8421ab252fSSam McCall   Context.addInvariant(A.makeImplies(C, D));
8521ab252fSSam McCall   Context.addFlowConditionConstraint(FC, C);
8621ab252fSSam McCall   EXPECT_TRUE(Context.flowConditionImplies(FC, D));
8721ab252fSSam McCall }
8821ab252fSSam McCall 
TEST_F(DataflowAnalysisContextTest,ForkFlowCondition)89955a05a2SStanislav Gatev TEST_F(DataflowAnalysisContextTest, ForkFlowCondition) {
90fc9821a8SSam McCall   Atom FC1 = A.makeFlowConditionToken();
91fc9821a8SSam McCall   auto &C1 = A.makeAtomRef(A.makeAtom());
92955a05a2SStanislav Gatev   Context.addFlowConditionConstraint(FC1, C1);
93955a05a2SStanislav Gatev 
94955a05a2SStanislav Gatev   // Forked flow condition inherits the constraints of its parent flow
95955a05a2SStanislav Gatev   // condition.
96fc9821a8SSam McCall   Atom FC2 = Context.forkFlowCondition(FC1);
97955a05a2SStanislav Gatev   EXPECT_TRUE(Context.flowConditionImplies(FC2, C1));
98955a05a2SStanislav Gatev 
99955a05a2SStanislav Gatev   // Adding a new constraint to the forked flow condition does not affect its
100955a05a2SStanislav Gatev   // parent flow condition.
101fc9821a8SSam McCall   auto &C2 = A.makeAtomRef(A.makeAtom());
102955a05a2SStanislav Gatev   Context.addFlowConditionConstraint(FC2, C2);
103955a05a2SStanislav Gatev   EXPECT_TRUE(Context.flowConditionImplies(FC2, C2));
104955a05a2SStanislav Gatev   EXPECT_FALSE(Context.flowConditionImplies(FC1, C2));
105955a05a2SStanislav Gatev }
106955a05a2SStanislav Gatev 
TEST_F(DataflowAnalysisContextTest,JoinFlowConditions)107955a05a2SStanislav Gatev TEST_F(DataflowAnalysisContextTest, JoinFlowConditions) {
108fc9821a8SSam McCall   auto &C1 = A.makeAtomRef(A.makeAtom());
109fc9821a8SSam McCall   auto &C2 = A.makeAtomRef(A.makeAtom());
110fc9821a8SSam McCall   auto &C3 = A.makeAtomRef(A.makeAtom());
111955a05a2SStanislav Gatev 
112fc9821a8SSam McCall   Atom FC1 = A.makeFlowConditionToken();
113955a05a2SStanislav Gatev   Context.addFlowConditionConstraint(FC1, C1);
114955a05a2SStanislav Gatev   Context.addFlowConditionConstraint(FC1, C3);
115955a05a2SStanislav Gatev 
116fc9821a8SSam McCall   Atom FC2 = A.makeFlowConditionToken();
117955a05a2SStanislav Gatev   Context.addFlowConditionConstraint(FC2, C2);
118955a05a2SStanislav Gatev   Context.addFlowConditionConstraint(FC2, C3);
119955a05a2SStanislav Gatev 
120fc9821a8SSam McCall   Atom FC3 = Context.joinFlowConditions(FC1, FC2);
121955a05a2SStanislav Gatev   EXPECT_FALSE(Context.flowConditionImplies(FC3, C1));
122955a05a2SStanislav Gatev   EXPECT_FALSE(Context.flowConditionImplies(FC3, C2));
123955a05a2SStanislav Gatev   EXPECT_TRUE(Context.flowConditionImplies(FC3, C3));
124955a05a2SStanislav Gatev }
125955a05a2SStanislav Gatev 
TEST_F(DataflowAnalysisContextTest,EquivBoolVals)1260f65a3e6SWei Yi Tee TEST_F(DataflowAnalysisContextTest, EquivBoolVals) {
127fc9821a8SSam McCall   auto &X = A.makeAtomRef(A.makeAtom());
128fc9821a8SSam McCall   auto &Y = A.makeAtomRef(A.makeAtom());
129fc9821a8SSam McCall   auto &Z = A.makeAtomRef(A.makeAtom());
130bf47c1edSSam McCall   auto &True = A.makeLiteral(true);
131bf47c1edSSam McCall   auto &False = A.makeLiteral(false);
1320f65a3e6SWei Yi Tee 
1330f65a3e6SWei Yi Tee   // X == X
134fc9821a8SSam McCall   EXPECT_TRUE(Context.equivalentFormulas(X, X));
1350f65a3e6SWei Yi Tee   // X != Y
136fc9821a8SSam McCall   EXPECT_FALSE(Context.equivalentFormulas(X, Y));
1370f65a3e6SWei Yi Tee 
1380f65a3e6SWei Yi Tee   // !X != X
139fc9821a8SSam McCall   EXPECT_FALSE(Context.equivalentFormulas(A.makeNot(X), X));
1400f65a3e6SWei Yi Tee   // !(!X) = X
141fc9821a8SSam McCall   EXPECT_TRUE(Context.equivalentFormulas(A.makeNot(A.makeNot(X)), X));
1420f65a3e6SWei Yi Tee 
1430f65a3e6SWei Yi Tee   // (X || X) == X
144fc9821a8SSam McCall   EXPECT_TRUE(Context.equivalentFormulas(A.makeOr(X, X), X));
1450f65a3e6SWei Yi Tee   // (X || Y) != X
146fc9821a8SSam McCall   EXPECT_FALSE(Context.equivalentFormulas(A.makeOr(X, Y), X));
1470f65a3e6SWei Yi Tee   // (X || True) == True
148fc9821a8SSam McCall   EXPECT_TRUE(Context.equivalentFormulas(A.makeOr(X, True), True));
1490f65a3e6SWei Yi Tee   // (X || False) == X
150fc9821a8SSam McCall   EXPECT_TRUE(Context.equivalentFormulas(A.makeOr(X, False), X));
1510f65a3e6SWei Yi Tee 
1520f65a3e6SWei Yi Tee   // (X && X) == X
153fc9821a8SSam McCall   EXPECT_TRUE(Context.equivalentFormulas(A.makeAnd(X, X), X));
1540f65a3e6SWei Yi Tee   // (X && Y) != X
155fc9821a8SSam McCall   EXPECT_FALSE(Context.equivalentFormulas(A.makeAnd(X, Y), X));
1560f65a3e6SWei Yi Tee   // (X && True) == X
157fc9821a8SSam McCall   EXPECT_TRUE(Context.equivalentFormulas(A.makeAnd(X, True), X));
1580f65a3e6SWei Yi Tee   // (X && False) == False
159fc9821a8SSam McCall   EXPECT_TRUE(Context.equivalentFormulas(A.makeAnd(X, False), False));
1600f65a3e6SWei Yi Tee 
1610f65a3e6SWei Yi Tee   // (X || Y) == (Y || X)
162fc9821a8SSam McCall   EXPECT_TRUE(Context.equivalentFormulas(A.makeOr(X, Y), A.makeOr(Y, X)));
1630f65a3e6SWei Yi Tee   // (X && Y) == (Y && X)
164fc9821a8SSam McCall   EXPECT_TRUE(Context.equivalentFormulas(A.makeAnd(X, Y), A.makeAnd(Y, X)));
1650f65a3e6SWei Yi Tee 
1660f65a3e6SWei Yi Tee   // ((X || Y) || Z) == (X || (Y || Z))
167fc9821a8SSam McCall   EXPECT_TRUE(Context.equivalentFormulas(A.makeOr(A.makeOr(X, Y), Z),
168bf47c1edSSam McCall                                          A.makeOr(X, A.makeOr(Y, Z))));
1690f65a3e6SWei Yi Tee   // ((X && Y) && Z) == (X && (Y && Z))
170fc9821a8SSam McCall   EXPECT_TRUE(Context.equivalentFormulas(A.makeAnd(A.makeAnd(X, Y), Z),
171bf47c1edSSam McCall                                          A.makeAnd(X, A.makeAnd(Y, Z))));
172bdfe556dSWei Yi Tee }
173bdfe556dSWei Yi Tee 
174ae60884dSStanislav Gatev } // namespace
175