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