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()
23ae60884dSStanislav Gatev : Context(std::make_unique<WatchedLiteralsSolver>()) {}
24ae60884dSStanislav Gatev
25ae60884dSStanislav Gatev DataflowAnalysisContext Context;
26ae60884dSStanislav Gatev };
27ae60884dSStanislav Gatev
TEST_F(DataflowAnalysisContextTest,CreateAtomicBoolValueReturnsDistinctValues)28ae60884dSStanislav Gatev TEST_F(DataflowAnalysisContextTest,
29ae60884dSStanislav Gatev CreateAtomicBoolValueReturnsDistinctValues) {
30ae60884dSStanislav Gatev auto &X = Context.createAtomicBoolValue();
31ae60884dSStanislav Gatev auto &Y = Context.createAtomicBoolValue();
32ae60884dSStanislav Gatev EXPECT_NE(&X, &Y);
33ae60884dSStanislav Gatev }
34ae60884dSStanislav Gatev
TEST_F(DataflowAnalysisContextTest,GetOrCreateConjunctionReturnsSameExprGivenSameArgs)35ae60884dSStanislav Gatev TEST_F(DataflowAnalysisContextTest,
3600e9d534SWei Yi Tee GetOrCreateConjunctionReturnsSameExprGivenSameArgs) {
37ae60884dSStanislav Gatev auto &X = Context.createAtomicBoolValue();
3800e9d534SWei Yi Tee auto &XAndX = Context.getOrCreateConjunction(X, X);
39ae60884dSStanislav Gatev EXPECT_EQ(&XAndX, &X);
40ae60884dSStanislav Gatev }
41ae60884dSStanislav Gatev
TEST_F(DataflowAnalysisContextTest,GetOrCreateConjunctionReturnsSameExprOnSubsequentCalls)42ae60884dSStanislav Gatev TEST_F(DataflowAnalysisContextTest,
4300e9d534SWei Yi Tee GetOrCreateConjunctionReturnsSameExprOnSubsequentCalls) {
44ae60884dSStanislav Gatev auto &X = Context.createAtomicBoolValue();
45ae60884dSStanislav Gatev auto &Y = Context.createAtomicBoolValue();
4600e9d534SWei Yi Tee auto &XAndY1 = Context.getOrCreateConjunction(X, Y);
4700e9d534SWei Yi Tee auto &XAndY2 = Context.getOrCreateConjunction(X, Y);
48ae60884dSStanislav Gatev EXPECT_EQ(&XAndY1, &XAndY2);
49ae60884dSStanislav Gatev
5000e9d534SWei Yi Tee auto &YAndX = Context.getOrCreateConjunction(Y, X);
51ae60884dSStanislav Gatev EXPECT_EQ(&XAndY1, &YAndX);
52ae60884dSStanislav Gatev
53ae60884dSStanislav Gatev auto &Z = Context.createAtomicBoolValue();
5400e9d534SWei Yi Tee auto &XAndZ = Context.getOrCreateConjunction(X, Z);
55ae60884dSStanislav Gatev EXPECT_NE(&XAndY1, &XAndZ);
56ae60884dSStanislav Gatev }
57ae60884dSStanislav Gatev
TEST_F(DataflowAnalysisContextTest,GetOrCreateDisjunctionReturnsSameExprGivenSameArgs)58ae60884dSStanislav Gatev TEST_F(DataflowAnalysisContextTest,
5900e9d534SWei Yi Tee GetOrCreateDisjunctionReturnsSameExprGivenSameArgs) {
60ae60884dSStanislav Gatev auto &X = Context.createAtomicBoolValue();
6100e9d534SWei Yi Tee auto &XOrX = Context.getOrCreateDisjunction(X, X);
62ae60884dSStanislav Gatev EXPECT_EQ(&XOrX, &X);
63ae60884dSStanislav Gatev }
64ae60884dSStanislav Gatev
TEST_F(DataflowAnalysisContextTest,GetOrCreateDisjunctionReturnsSameExprOnSubsequentCalls)65ae60884dSStanislav Gatev TEST_F(DataflowAnalysisContextTest,
6600e9d534SWei Yi Tee GetOrCreateDisjunctionReturnsSameExprOnSubsequentCalls) {
67ae60884dSStanislav Gatev auto &X = Context.createAtomicBoolValue();
68ae60884dSStanislav Gatev auto &Y = Context.createAtomicBoolValue();
6900e9d534SWei Yi Tee auto &XOrY1 = Context.getOrCreateDisjunction(X, Y);
7000e9d534SWei Yi Tee auto &XOrY2 = Context.getOrCreateDisjunction(X, Y);
71ae60884dSStanislav Gatev EXPECT_EQ(&XOrY1, &XOrY2);
72ae60884dSStanislav Gatev
7300e9d534SWei Yi Tee auto &YOrX = Context.getOrCreateDisjunction(Y, X);
74ae60884dSStanislav Gatev EXPECT_EQ(&XOrY1, &YOrX);
75ae60884dSStanislav Gatev
76ae60884dSStanislav Gatev auto &Z = Context.createAtomicBoolValue();
7700e9d534SWei Yi Tee auto &XOrZ = Context.getOrCreateDisjunction(X, Z);
78ae60884dSStanislav Gatev EXPECT_NE(&XOrY1, &XOrZ);
79ae60884dSStanislav Gatev }
80ae60884dSStanislav Gatev
TEST_F(DataflowAnalysisContextTest,GetOrCreateNegationReturnsSameExprOnSubsequentCalls)81ae60884dSStanislav Gatev TEST_F(DataflowAnalysisContextTest,
8200e9d534SWei Yi Tee GetOrCreateNegationReturnsSameExprOnSubsequentCalls) {
83ae60884dSStanislav Gatev auto &X = Context.createAtomicBoolValue();
8400e9d534SWei Yi Tee auto &NotX1 = Context.getOrCreateNegation(X);
8500e9d534SWei Yi Tee auto &NotX2 = Context.getOrCreateNegation(X);
86ae60884dSStanislav Gatev EXPECT_EQ(&NotX1, &NotX2);
87ae60884dSStanislav Gatev
88ae60884dSStanislav Gatev auto &Y = Context.createAtomicBoolValue();
8900e9d534SWei Yi Tee auto &NotY = Context.getOrCreateNegation(Y);
90ae60884dSStanislav Gatev EXPECT_NE(&NotX1, &NotY);
91ae60884dSStanislav Gatev }
92ae60884dSStanislav Gatev
TEST_F(DataflowAnalysisContextTest,GetOrCreateImplicationReturnsTrueGivenSameArgs)9300e9d534SWei Yi Tee TEST_F(DataflowAnalysisContextTest,
9400e9d534SWei Yi Tee GetOrCreateImplicationReturnsTrueGivenSameArgs) {
9500e9d534SWei Yi Tee auto &X = Context.createAtomicBoolValue();
9600e9d534SWei Yi Tee auto &XImpliesX = Context.getOrCreateImplication(X, X);
9700e9d534SWei Yi Tee EXPECT_EQ(&XImpliesX, &Context.getBoolLiteralValue(true));
9800e9d534SWei Yi Tee }
9900e9d534SWei Yi Tee
TEST_F(DataflowAnalysisContextTest,GetOrCreateImplicationReturnsSameExprOnSubsequentCalls)10000e9d534SWei Yi Tee TEST_F(DataflowAnalysisContextTest,
10100e9d534SWei Yi Tee GetOrCreateImplicationReturnsSameExprOnSubsequentCalls) {
10200e9d534SWei Yi Tee auto &X = Context.createAtomicBoolValue();
10300e9d534SWei Yi Tee auto &Y = Context.createAtomicBoolValue();
10400e9d534SWei Yi Tee auto &XImpliesY1 = Context.getOrCreateImplication(X, Y);
10500e9d534SWei Yi Tee auto &XImpliesY2 = Context.getOrCreateImplication(X, Y);
10600e9d534SWei Yi Tee EXPECT_EQ(&XImpliesY1, &XImpliesY2);
10700e9d534SWei Yi Tee
10800e9d534SWei Yi Tee auto &YImpliesX = Context.getOrCreateImplication(Y, X);
10900e9d534SWei Yi Tee EXPECT_NE(&XImpliesY1, &YImpliesX);
11000e9d534SWei Yi Tee
11100e9d534SWei Yi Tee auto &Z = Context.createAtomicBoolValue();
11200e9d534SWei Yi Tee auto &XImpliesZ = Context.getOrCreateImplication(X, Z);
11300e9d534SWei Yi Tee EXPECT_NE(&XImpliesY1, &XImpliesZ);
11400e9d534SWei Yi Tee }
11500e9d534SWei Yi Tee
TEST_F(DataflowAnalysisContextTest,GetOrCreateIffReturnsTrueGivenSameArgs)11600e9d534SWei Yi Tee TEST_F(DataflowAnalysisContextTest, GetOrCreateIffReturnsTrueGivenSameArgs) {
11700e9d534SWei Yi Tee auto &X = Context.createAtomicBoolValue();
11800e9d534SWei Yi Tee auto &XIffX = Context.getOrCreateIff(X, X);
11900e9d534SWei Yi Tee EXPECT_EQ(&XIffX, &Context.getBoolLiteralValue(true));
12000e9d534SWei Yi Tee }
12100e9d534SWei Yi Tee
TEST_F(DataflowAnalysisContextTest,GetOrCreateIffReturnsSameExprOnSubsequentCalls)12200e9d534SWei Yi Tee TEST_F(DataflowAnalysisContextTest,
12300e9d534SWei Yi Tee GetOrCreateIffReturnsSameExprOnSubsequentCalls) {
12400e9d534SWei Yi Tee auto &X = Context.createAtomicBoolValue();
12500e9d534SWei Yi Tee auto &Y = Context.createAtomicBoolValue();
12600e9d534SWei Yi Tee auto &XIffY1 = Context.getOrCreateIff(X, Y);
12700e9d534SWei Yi Tee auto &XIffY2 = Context.getOrCreateIff(X, Y);
12800e9d534SWei Yi Tee EXPECT_EQ(&XIffY1, &XIffY2);
12900e9d534SWei Yi Tee
13000e9d534SWei Yi Tee auto &YIffX = Context.getOrCreateIff(Y, X);
13100e9d534SWei Yi Tee EXPECT_EQ(&XIffY1, &YIffX);
13200e9d534SWei Yi Tee
13300e9d534SWei Yi Tee auto &Z = Context.createAtomicBoolValue();
13400e9d534SWei Yi Tee auto &XIffZ = Context.getOrCreateIff(X, Z);
13500e9d534SWei Yi Tee EXPECT_NE(&XIffY1, &XIffZ);
13600e9d534SWei Yi Tee }
13700e9d534SWei Yi Tee
TEST_F(DataflowAnalysisContextTest,EmptyFlowCondition)138955a05a2SStanislav Gatev TEST_F(DataflowAnalysisContextTest, EmptyFlowCondition) {
139955a05a2SStanislav Gatev auto &FC = Context.makeFlowConditionToken();
140955a05a2SStanislav Gatev auto &C = Context.createAtomicBoolValue();
141955a05a2SStanislav Gatev EXPECT_FALSE(Context.flowConditionImplies(FC, C));
142955a05a2SStanislav Gatev }
143955a05a2SStanislav Gatev
TEST_F(DataflowAnalysisContextTest,AddFlowConditionConstraint)144955a05a2SStanislav Gatev TEST_F(DataflowAnalysisContextTest, AddFlowConditionConstraint) {
145955a05a2SStanislav Gatev auto &FC = Context.makeFlowConditionToken();
146955a05a2SStanislav Gatev auto &C = Context.createAtomicBoolValue();
147955a05a2SStanislav Gatev Context.addFlowConditionConstraint(FC, C);
148955a05a2SStanislav Gatev EXPECT_TRUE(Context.flowConditionImplies(FC, C));
149955a05a2SStanislav Gatev }
150955a05a2SStanislav Gatev
TEST_F(DataflowAnalysisContextTest,ForkFlowCondition)151955a05a2SStanislav Gatev TEST_F(DataflowAnalysisContextTest, ForkFlowCondition) {
152955a05a2SStanislav Gatev auto &FC1 = Context.makeFlowConditionToken();
153955a05a2SStanislav Gatev auto &C1 = Context.createAtomicBoolValue();
154955a05a2SStanislav Gatev Context.addFlowConditionConstraint(FC1, C1);
155955a05a2SStanislav Gatev
156955a05a2SStanislav Gatev // Forked flow condition inherits the constraints of its parent flow
157955a05a2SStanislav Gatev // condition.
158955a05a2SStanislav Gatev auto &FC2 = Context.forkFlowCondition(FC1);
159955a05a2SStanislav Gatev EXPECT_TRUE(Context.flowConditionImplies(FC2, C1));
160955a05a2SStanislav Gatev
161955a05a2SStanislav Gatev // Adding a new constraint to the forked flow condition does not affect its
162955a05a2SStanislav Gatev // parent flow condition.
163955a05a2SStanislav Gatev auto &C2 = Context.createAtomicBoolValue();
164955a05a2SStanislav Gatev Context.addFlowConditionConstraint(FC2, C2);
165955a05a2SStanislav Gatev EXPECT_TRUE(Context.flowConditionImplies(FC2, C2));
166955a05a2SStanislav Gatev EXPECT_FALSE(Context.flowConditionImplies(FC1, C2));
167955a05a2SStanislav Gatev }
168955a05a2SStanislav Gatev
TEST_F(DataflowAnalysisContextTest,JoinFlowConditions)169955a05a2SStanislav Gatev TEST_F(DataflowAnalysisContextTest, JoinFlowConditions) {
170955a05a2SStanislav Gatev auto &C1 = Context.createAtomicBoolValue();
171955a05a2SStanislav Gatev auto &C2 = Context.createAtomicBoolValue();
172955a05a2SStanislav Gatev auto &C3 = Context.createAtomicBoolValue();
173955a05a2SStanislav Gatev
174955a05a2SStanislav Gatev auto &FC1 = Context.makeFlowConditionToken();
175955a05a2SStanislav Gatev Context.addFlowConditionConstraint(FC1, C1);
176955a05a2SStanislav Gatev Context.addFlowConditionConstraint(FC1, C3);
177955a05a2SStanislav Gatev
178955a05a2SStanislav Gatev auto &FC2 = Context.makeFlowConditionToken();
179955a05a2SStanislav Gatev Context.addFlowConditionConstraint(FC2, C2);
180955a05a2SStanislav Gatev Context.addFlowConditionConstraint(FC2, C3);
181955a05a2SStanislav Gatev
182955a05a2SStanislav Gatev auto &FC3 = Context.joinFlowConditions(FC1, FC2);
183955a05a2SStanislav Gatev EXPECT_FALSE(Context.flowConditionImplies(FC3, C1));
184955a05a2SStanislav Gatev EXPECT_FALSE(Context.flowConditionImplies(FC3, C2));
185955a05a2SStanislav Gatev EXPECT_TRUE(Context.flowConditionImplies(FC3, C3));
186955a05a2SStanislav Gatev }
187955a05a2SStanislav Gatev
TEST_F(DataflowAnalysisContextTest,FlowConditionTautologies)18858abe36aSEric Li TEST_F(DataflowAnalysisContextTest, FlowConditionTautologies) {
18958abe36aSEric Li // Fresh flow condition with empty/no constraints is always true.
19058abe36aSEric Li auto &FC1 = Context.makeFlowConditionToken();
19158abe36aSEric Li EXPECT_TRUE(Context.flowConditionIsTautology(FC1));
19258abe36aSEric Li
19358abe36aSEric Li // Literal `true` is always true.
19458abe36aSEric Li auto &FC2 = Context.makeFlowConditionToken();
19558abe36aSEric Li Context.addFlowConditionConstraint(FC2, Context.getBoolLiteralValue(true));
19658abe36aSEric Li EXPECT_TRUE(Context.flowConditionIsTautology(FC2));
19758abe36aSEric Li
19858abe36aSEric Li // Literal `false` is never true.
19958abe36aSEric Li auto &FC3 = Context.makeFlowConditionToken();
20058abe36aSEric Li Context.addFlowConditionConstraint(FC3, Context.getBoolLiteralValue(false));
20158abe36aSEric Li EXPECT_FALSE(Context.flowConditionIsTautology(FC3));
20258abe36aSEric Li
20358abe36aSEric Li // We can't prove that an arbitrary bool A is always true...
20458abe36aSEric Li auto &C1 = Context.createAtomicBoolValue();
20558abe36aSEric Li auto &FC4 = Context.makeFlowConditionToken();
20658abe36aSEric Li Context.addFlowConditionConstraint(FC4, C1);
20758abe36aSEric Li EXPECT_FALSE(Context.flowConditionIsTautology(FC4));
20858abe36aSEric Li
20958abe36aSEric Li // ... but we can prove A || !A is true.
21058abe36aSEric Li auto &FC5 = Context.makeFlowConditionToken();
21158abe36aSEric Li Context.addFlowConditionConstraint(
21200e9d534SWei Yi Tee FC5, Context.getOrCreateDisjunction(C1, Context.getOrCreateNegation(C1)));
21358abe36aSEric Li EXPECT_TRUE(Context.flowConditionIsTautology(FC5));
21458abe36aSEric Li }
21558abe36aSEric Li
TEST_F(DataflowAnalysisContextTest,EquivBoolVals)2160f65a3e6SWei Yi Tee TEST_F(DataflowAnalysisContextTest, EquivBoolVals) {
2170f65a3e6SWei Yi Tee auto &X = Context.createAtomicBoolValue();
2180f65a3e6SWei Yi Tee auto &Y = Context.createAtomicBoolValue();
2190f65a3e6SWei Yi Tee auto &Z = Context.createAtomicBoolValue();
2200f65a3e6SWei Yi Tee auto &True = Context.getBoolLiteralValue(true);
2210f65a3e6SWei Yi Tee auto &False = Context.getBoolLiteralValue(false);
2220f65a3e6SWei Yi Tee
2230f65a3e6SWei Yi Tee // X == X
2240f65a3e6SWei Yi Tee EXPECT_TRUE(Context.equivalentBoolValues(X, X));
2250f65a3e6SWei Yi Tee // X != Y
2260f65a3e6SWei Yi Tee EXPECT_FALSE(Context.equivalentBoolValues(X, Y));
2270f65a3e6SWei Yi Tee
2280f65a3e6SWei Yi Tee // !X != X
2290f65a3e6SWei Yi Tee EXPECT_FALSE(Context.equivalentBoolValues(Context.getOrCreateNegation(X), X));
2300f65a3e6SWei Yi Tee // !(!X) = X
2310f65a3e6SWei Yi Tee EXPECT_TRUE(Context.equivalentBoolValues(
2320f65a3e6SWei Yi Tee Context.getOrCreateNegation(Context.getOrCreateNegation(X)), X));
2330f65a3e6SWei Yi Tee
2340f65a3e6SWei Yi Tee // (X || X) == X
2350f65a3e6SWei Yi Tee EXPECT_TRUE(
2360f65a3e6SWei Yi Tee Context.equivalentBoolValues(Context.getOrCreateDisjunction(X, X), X));
2370f65a3e6SWei Yi Tee // (X || Y) != X
2380f65a3e6SWei Yi Tee EXPECT_FALSE(
2390f65a3e6SWei Yi Tee Context.equivalentBoolValues(Context.getOrCreateDisjunction(X, Y), X));
2400f65a3e6SWei Yi Tee // (X || True) == True
2410f65a3e6SWei Yi Tee EXPECT_TRUE(Context.equivalentBoolValues(
2420f65a3e6SWei Yi Tee Context.getOrCreateDisjunction(X, True), True));
2430f65a3e6SWei Yi Tee // (X || False) == X
2440f65a3e6SWei Yi Tee EXPECT_TRUE(Context.equivalentBoolValues(
2450f65a3e6SWei Yi Tee Context.getOrCreateDisjunction(X, False), X));
2460f65a3e6SWei Yi Tee
2470f65a3e6SWei Yi Tee // (X && X) == X
2480f65a3e6SWei Yi Tee EXPECT_TRUE(
2490f65a3e6SWei Yi Tee Context.equivalentBoolValues(Context.getOrCreateConjunction(X, X), X));
2500f65a3e6SWei Yi Tee // (X && Y) != X
2510f65a3e6SWei Yi Tee EXPECT_FALSE(
2520f65a3e6SWei Yi Tee Context.equivalentBoolValues(Context.getOrCreateConjunction(X, Y), X));
2530f65a3e6SWei Yi Tee // (X && True) == X
2540f65a3e6SWei Yi Tee EXPECT_TRUE(
2550f65a3e6SWei Yi Tee Context.equivalentBoolValues(Context.getOrCreateConjunction(X, True), X));
2560f65a3e6SWei Yi Tee // (X && False) == False
2570f65a3e6SWei Yi Tee EXPECT_TRUE(Context.equivalentBoolValues(
2580f65a3e6SWei Yi Tee Context.getOrCreateConjunction(X, False), False));
2590f65a3e6SWei Yi Tee
2600f65a3e6SWei Yi Tee // (X || Y) == (Y || X)
2610f65a3e6SWei Yi Tee EXPECT_TRUE(
2620f65a3e6SWei Yi Tee Context.equivalentBoolValues(Context.getOrCreateDisjunction(X, Y),
2630f65a3e6SWei Yi Tee Context.getOrCreateDisjunction(Y, X)));
2640f65a3e6SWei Yi Tee // (X && Y) == (Y && X)
2650f65a3e6SWei Yi Tee EXPECT_TRUE(
2660f65a3e6SWei Yi Tee Context.equivalentBoolValues(Context.getOrCreateConjunction(X, Y),
2670f65a3e6SWei Yi Tee Context.getOrCreateConjunction(Y, X)));
2680f65a3e6SWei Yi Tee
2690f65a3e6SWei Yi Tee // ((X || Y) || Z) == (X || (Y || Z))
2700f65a3e6SWei Yi Tee EXPECT_TRUE(Context.equivalentBoolValues(
2710f65a3e6SWei Yi Tee Context.getOrCreateDisjunction(Context.getOrCreateDisjunction(X, Y), Z),
2720f65a3e6SWei Yi Tee Context.getOrCreateDisjunction(X, Context.getOrCreateDisjunction(Y, Z))));
2730f65a3e6SWei Yi Tee // ((X && Y) && Z) == (X && (Y && Z))
2740f65a3e6SWei Yi Tee EXPECT_TRUE(Context.equivalentBoolValues(
2750f65a3e6SWei Yi Tee Context.getOrCreateConjunction(Context.getOrCreateConjunction(X, Y), Z),
2760f65a3e6SWei Yi Tee Context.getOrCreateConjunction(X, Context.getOrCreateConjunction(Y, Z))));
2770f65a3e6SWei Yi Tee }
2780f65a3e6SWei Yi Tee
279fa34210fSWei Yi Tee #if !defined(NDEBUG) && GTEST_HAS_DEATH_TEST
TEST_F(DataflowAnalysisContextTest,SubstituteFlowConditionsTrueUnchanged)280fa34210fSWei Yi Tee TEST_F(DataflowAnalysisContextTest, SubstituteFlowConditionsTrueUnchanged) {
281fa34210fSWei Yi Tee auto &True = Context.getBoolLiteralValue(true);
282fa34210fSWei Yi Tee auto &Other = Context.createAtomicBoolValue();
283fa34210fSWei Yi Tee
284fa34210fSWei Yi Tee // FC = True
285fa34210fSWei Yi Tee auto &FC = Context.makeFlowConditionToken();
286fa34210fSWei Yi Tee Context.addFlowConditionConstraint(FC, True);
287fa34210fSWei Yi Tee
288fa34210fSWei Yi Tee // `True` should never be substituted
289fa34210fSWei Yi Tee EXPECT_DEATH(Context.buildAndSubstituteFlowCondition(FC, {{&True, &Other}}),
290fa34210fSWei Yi Tee "Do not substitute true/false boolean literals");
291fa34210fSWei Yi Tee }
292fa34210fSWei Yi Tee
TEST_F(DataflowAnalysisContextTest,SubstituteFlowConditionsFalseUnchanged)293fa34210fSWei Yi Tee TEST_F(DataflowAnalysisContextTest, SubstituteFlowConditionsFalseUnchanged) {
294fa34210fSWei Yi Tee auto &False = Context.getBoolLiteralValue(false);
295fa34210fSWei Yi Tee auto &Other = Context.createAtomicBoolValue();
296fa34210fSWei Yi Tee
297fa34210fSWei Yi Tee // FC = False
298fa34210fSWei Yi Tee auto &FC = Context.makeFlowConditionToken();
299fa34210fSWei Yi Tee Context.addFlowConditionConstraint(FC, False);
300fa34210fSWei Yi Tee
301fa34210fSWei Yi Tee // `False` should never be substituted
302fa34210fSWei Yi Tee EXPECT_DEATH(Context.buildAndSubstituteFlowCondition(FC, {{&False, &Other}}),
303fa34210fSWei Yi Tee "Do not substitute true/false boolean literals");
304fa34210fSWei Yi Tee }
305fa34210fSWei Yi Tee #endif
306fa34210fSWei Yi Tee
TEST_F(DataflowAnalysisContextTest,SubstituteFlowConditionContainingAtomic)307*b5e3dac3SDmitri Gribenko TEST_F(DataflowAnalysisContextTest, SubstituteFlowConditionContainingAtomic) {
308bdfe556dSWei Yi Tee auto &X = Context.createAtomicBoolValue();
309bdfe556dSWei Yi Tee auto &True = Context.getBoolLiteralValue(true);
310bdfe556dSWei Yi Tee auto &False = Context.getBoolLiteralValue(false);
311bdfe556dSWei Yi Tee
312bdfe556dSWei Yi Tee // FC = X
313bdfe556dSWei Yi Tee auto &FC = Context.makeFlowConditionToken();
314bdfe556dSWei Yi Tee Context.addFlowConditionConstraint(FC, X);
315bdfe556dSWei Yi Tee
316*b5e3dac3SDmitri Gribenko // If X is true, FC is true
317bdfe556dSWei Yi Tee auto &FCWithXTrue =
318bdfe556dSWei Yi Tee Context.buildAndSubstituteFlowCondition(FC, {{&X, &True}});
319bdfe556dSWei Yi Tee EXPECT_TRUE(Context.equivalentBoolValues(FCWithXTrue, True));
320bdfe556dSWei Yi Tee
321*b5e3dac3SDmitri Gribenko // If X is false, FC is false
322bdfe556dSWei Yi Tee auto &FC1WithXFalse =
323bdfe556dSWei Yi Tee Context.buildAndSubstituteFlowCondition(FC, {{&X, &False}});
324bdfe556dSWei Yi Tee EXPECT_TRUE(Context.equivalentBoolValues(FC1WithXFalse, False));
325bdfe556dSWei Yi Tee }
326bdfe556dSWei Yi Tee
TEST_F(DataflowAnalysisContextTest,SubstituteFlowConditionContainingNegation)327*b5e3dac3SDmitri Gribenko TEST_F(DataflowAnalysisContextTest, SubstituteFlowConditionContainingNegation) {
328bdfe556dSWei Yi Tee auto &X = Context.createAtomicBoolValue();
329bdfe556dSWei Yi Tee auto &True = Context.getBoolLiteralValue(true);
330bdfe556dSWei Yi Tee auto &False = Context.getBoolLiteralValue(false);
331bdfe556dSWei Yi Tee
332bdfe556dSWei Yi Tee // FC = !X
333bdfe556dSWei Yi Tee auto &FC = Context.makeFlowConditionToken();
334bdfe556dSWei Yi Tee Context.addFlowConditionConstraint(FC, Context.getOrCreateNegation(X));
335bdfe556dSWei Yi Tee
336*b5e3dac3SDmitri Gribenko // If X is true, FC is false
337bdfe556dSWei Yi Tee auto &FCWithXTrue =
338bdfe556dSWei Yi Tee Context.buildAndSubstituteFlowCondition(FC, {{&X, &True}});
339bdfe556dSWei Yi Tee EXPECT_TRUE(Context.equivalentBoolValues(FCWithXTrue, False));
340bdfe556dSWei Yi Tee
341*b5e3dac3SDmitri Gribenko // If X is false, FC is true
342bdfe556dSWei Yi Tee auto &FC1WithXFalse =
343bdfe556dSWei Yi Tee Context.buildAndSubstituteFlowCondition(FC, {{&X, &False}});
344bdfe556dSWei Yi Tee EXPECT_TRUE(Context.equivalentBoolValues(FC1WithXFalse, True));
345bdfe556dSWei Yi Tee }
346bdfe556dSWei Yi Tee
TEST_F(DataflowAnalysisContextTest,SubstituteFlowConditionContainingDisjunction)347*b5e3dac3SDmitri Gribenko TEST_F(DataflowAnalysisContextTest, SubstituteFlowConditionContainingDisjunction) {
348bdfe556dSWei Yi Tee auto &X = Context.createAtomicBoolValue();
349bdfe556dSWei Yi Tee auto &Y = Context.createAtomicBoolValue();
350bdfe556dSWei Yi Tee auto &True = Context.getBoolLiteralValue(true);
351bdfe556dSWei Yi Tee auto &False = Context.getBoolLiteralValue(false);
352bdfe556dSWei Yi Tee
353bdfe556dSWei Yi Tee // FC = X || Y
354bdfe556dSWei Yi Tee auto &FC = Context.makeFlowConditionToken();
355bdfe556dSWei Yi Tee Context.addFlowConditionConstraint(FC, Context.getOrCreateDisjunction(X, Y));
356bdfe556dSWei Yi Tee
357*b5e3dac3SDmitri Gribenko // If X is true, FC is true
358bdfe556dSWei Yi Tee auto &FCWithXTrue =
359bdfe556dSWei Yi Tee Context.buildAndSubstituteFlowCondition(FC, {{&X, &True}});
360bdfe556dSWei Yi Tee EXPECT_TRUE(Context.equivalentBoolValues(FCWithXTrue, True));
361bdfe556dSWei Yi Tee
362*b5e3dac3SDmitri Gribenko // If X is false, FC is equivalent to Y
363bdfe556dSWei Yi Tee auto &FC1WithXFalse =
364bdfe556dSWei Yi Tee Context.buildAndSubstituteFlowCondition(FC, {{&X, &False}});
365bdfe556dSWei Yi Tee EXPECT_TRUE(Context.equivalentBoolValues(FC1WithXFalse, Y));
366bdfe556dSWei Yi Tee }
367bdfe556dSWei Yi Tee
TEST_F(DataflowAnalysisContextTest,SubstituteFlowConditionContainingConjunction)368*b5e3dac3SDmitri Gribenko TEST_F(DataflowAnalysisContextTest, SubstituteFlowConditionContainingConjunction) {
369bdfe556dSWei Yi Tee auto &X = Context.createAtomicBoolValue();
370bdfe556dSWei Yi Tee auto &Y = Context.createAtomicBoolValue();
371bdfe556dSWei Yi Tee auto &True = Context.getBoolLiteralValue(true);
372bdfe556dSWei Yi Tee auto &False = Context.getBoolLiteralValue(false);
373bdfe556dSWei Yi Tee
374bdfe556dSWei Yi Tee // FC = X && Y
375bdfe556dSWei Yi Tee auto &FC = Context.makeFlowConditionToken();
376bdfe556dSWei Yi Tee Context.addFlowConditionConstraint(FC, Context.getOrCreateConjunction(X, Y));
377bdfe556dSWei Yi Tee
378*b5e3dac3SDmitri Gribenko // If X is true, FC is equivalent to Y
379bdfe556dSWei Yi Tee auto &FCWithXTrue =
380bdfe556dSWei Yi Tee Context.buildAndSubstituteFlowCondition(FC, {{&X, &True}});
381bdfe556dSWei Yi Tee EXPECT_TRUE(Context.equivalentBoolValues(FCWithXTrue, Y));
382bdfe556dSWei Yi Tee
383*b5e3dac3SDmitri Gribenko // If X is false, FC is false
384bdfe556dSWei Yi Tee auto &FCWithXFalse =
385bdfe556dSWei Yi Tee Context.buildAndSubstituteFlowCondition(FC, {{&X, &False}});
386bdfe556dSWei Yi Tee EXPECT_TRUE(Context.equivalentBoolValues(FCWithXFalse, False));
387bdfe556dSWei Yi Tee }
388bdfe556dSWei Yi Tee
TEST_F(DataflowAnalysisContextTest,SubstituteFlowConditionContainingImplication)389*b5e3dac3SDmitri Gribenko TEST_F(DataflowAnalysisContextTest, SubstituteFlowConditionContainingImplication) {
390*b5e3dac3SDmitri Gribenko auto &X = Context.createAtomicBoolValue();
391*b5e3dac3SDmitri Gribenko auto &Y = Context.createAtomicBoolValue();
392*b5e3dac3SDmitri Gribenko auto &True = Context.getBoolLiteralValue(true);
393*b5e3dac3SDmitri Gribenko auto &False = Context.getBoolLiteralValue(false);
394*b5e3dac3SDmitri Gribenko
395*b5e3dac3SDmitri Gribenko // FC = (X => Y)
396*b5e3dac3SDmitri Gribenko auto &FC = Context.makeFlowConditionToken();
397*b5e3dac3SDmitri Gribenko Context.addFlowConditionConstraint(FC, Context.getOrCreateImplication(X, Y));
398*b5e3dac3SDmitri Gribenko
399*b5e3dac3SDmitri Gribenko // If X is true, FC is equivalent to Y
400*b5e3dac3SDmitri Gribenko auto &FCWithXTrue =
401*b5e3dac3SDmitri Gribenko Context.buildAndSubstituteFlowCondition(FC, {{&X, &True}});
402*b5e3dac3SDmitri Gribenko EXPECT_TRUE(Context.equivalentBoolValues(FCWithXTrue, Y));
403*b5e3dac3SDmitri Gribenko
404*b5e3dac3SDmitri Gribenko // If X is false, FC is true
405*b5e3dac3SDmitri Gribenko auto &FC1WithXFalse =
406*b5e3dac3SDmitri Gribenko Context.buildAndSubstituteFlowCondition(FC, {{&X, &False}});
407*b5e3dac3SDmitri Gribenko EXPECT_TRUE(Context.equivalentBoolValues(FC1WithXFalse, True));
408*b5e3dac3SDmitri Gribenko
409*b5e3dac3SDmitri Gribenko // If Y is true, FC is true
410*b5e3dac3SDmitri Gribenko auto &FCWithYTrue =
411*b5e3dac3SDmitri Gribenko Context.buildAndSubstituteFlowCondition(FC, {{&Y, &True}});
412*b5e3dac3SDmitri Gribenko EXPECT_TRUE(Context.equivalentBoolValues(FCWithYTrue, True));
413*b5e3dac3SDmitri Gribenko
414*b5e3dac3SDmitri Gribenko // If Y is false, FC is equivalent to !X
415*b5e3dac3SDmitri Gribenko auto &FCWithYFalse =
416*b5e3dac3SDmitri Gribenko Context.buildAndSubstituteFlowCondition(FC, {{&Y, &False}});
417*b5e3dac3SDmitri Gribenko EXPECT_TRUE(Context.equivalentBoolValues(FCWithYFalse,
418*b5e3dac3SDmitri Gribenko Context.getOrCreateNegation(X)));
419*b5e3dac3SDmitri Gribenko }
420*b5e3dac3SDmitri Gribenko
TEST_F(DataflowAnalysisContextTest,SubstituteFlowConditionContainingBiconditional)421*b5e3dac3SDmitri Gribenko TEST_F(DataflowAnalysisContextTest, SubstituteFlowConditionContainingBiconditional) {
422*b5e3dac3SDmitri Gribenko auto &X = Context.createAtomicBoolValue();
423*b5e3dac3SDmitri Gribenko auto &Y = Context.createAtomicBoolValue();
424*b5e3dac3SDmitri Gribenko auto &True = Context.getBoolLiteralValue(true);
425*b5e3dac3SDmitri Gribenko auto &False = Context.getBoolLiteralValue(false);
426*b5e3dac3SDmitri Gribenko
427*b5e3dac3SDmitri Gribenko // FC = (X <=> Y)
428*b5e3dac3SDmitri Gribenko auto &FC = Context.makeFlowConditionToken();
429*b5e3dac3SDmitri Gribenko Context.addFlowConditionConstraint(FC, Context.getOrCreateIff(X, Y));
430*b5e3dac3SDmitri Gribenko
431*b5e3dac3SDmitri Gribenko // If X is true, FC is equivalent to Y
432*b5e3dac3SDmitri Gribenko auto &FCWithXTrue =
433*b5e3dac3SDmitri Gribenko Context.buildAndSubstituteFlowCondition(FC, {{&X, &True}});
434*b5e3dac3SDmitri Gribenko EXPECT_TRUE(Context.equivalentBoolValues(FCWithXTrue, Y));
435*b5e3dac3SDmitri Gribenko
436*b5e3dac3SDmitri Gribenko // If X is false, FC is equivalent to !Y
437*b5e3dac3SDmitri Gribenko auto &FC1WithXFalse =
438*b5e3dac3SDmitri Gribenko Context.buildAndSubstituteFlowCondition(FC, {{&X, &False}});
439*b5e3dac3SDmitri Gribenko EXPECT_TRUE(Context.equivalentBoolValues(FC1WithXFalse,
440*b5e3dac3SDmitri Gribenko Context.getOrCreateNegation(Y)));
441*b5e3dac3SDmitri Gribenko
442*b5e3dac3SDmitri Gribenko // If Y is true, FC is equivalent to X
443*b5e3dac3SDmitri Gribenko auto &FCWithYTrue =
444*b5e3dac3SDmitri Gribenko Context.buildAndSubstituteFlowCondition(FC, {{&Y, &True}});
445*b5e3dac3SDmitri Gribenko EXPECT_TRUE(Context.equivalentBoolValues(FCWithYTrue, X));
446*b5e3dac3SDmitri Gribenko
447*b5e3dac3SDmitri Gribenko // If Y is false, FC is equivalent to !X
448*b5e3dac3SDmitri Gribenko auto &FCWithYFalse =
449*b5e3dac3SDmitri Gribenko Context.buildAndSubstituteFlowCondition(FC, {{&Y, &False}});
450*b5e3dac3SDmitri Gribenko EXPECT_TRUE(Context.equivalentBoolValues(FCWithYFalse,
451*b5e3dac3SDmitri Gribenko Context.getOrCreateNegation(X)));
452*b5e3dac3SDmitri Gribenko }
453*b5e3dac3SDmitri Gribenko
TEST_F(DataflowAnalysisContextTest,SubstituteFlowConditionsForkedFC)454bdfe556dSWei Yi Tee TEST_F(DataflowAnalysisContextTest, SubstituteFlowConditionsForkedFC) {
455bdfe556dSWei Yi Tee auto &X = Context.createAtomicBoolValue();
456bdfe556dSWei Yi Tee auto &Y = Context.createAtomicBoolValue();
457bdfe556dSWei Yi Tee auto &Z = Context.createAtomicBoolValue();
458bdfe556dSWei Yi Tee auto &True = Context.getBoolLiteralValue(true);
459bdfe556dSWei Yi Tee auto &False = Context.getBoolLiteralValue(false);
460bdfe556dSWei Yi Tee
461bdfe556dSWei Yi Tee // FC = X && Y
462bdfe556dSWei Yi Tee auto &FC = Context.makeFlowConditionToken();
463bdfe556dSWei Yi Tee Context.addFlowConditionConstraint(FC, Context.getOrCreateConjunction(X, Y));
464bdfe556dSWei Yi Tee // ForkedFC = FC && Z = X && Y && Z
465bdfe556dSWei Yi Tee auto &ForkedFC = Context.forkFlowCondition(FC);
466bdfe556dSWei Yi Tee Context.addFlowConditionConstraint(ForkedFC, Z);
467bdfe556dSWei Yi Tee
468bdfe556dSWei Yi Tee // If any of X,Y,Z is true in ForkedFC, ForkedFC = X && Y && Z is equivalent
469bdfe556dSWei Yi Tee // to evaluating the conjunction of the remaining values
470bdfe556dSWei Yi Tee auto &ForkedFCWithZTrue =
471bdfe556dSWei Yi Tee Context.buildAndSubstituteFlowCondition(ForkedFC, {{&Z, &True}});
472bdfe556dSWei Yi Tee EXPECT_TRUE(Context.equivalentBoolValues(
473bdfe556dSWei Yi Tee ForkedFCWithZTrue, Context.getOrCreateConjunction(X, Y)));
474bdfe556dSWei Yi Tee auto &ForkedFCWithYAndZTrue = Context.buildAndSubstituteFlowCondition(
475bdfe556dSWei Yi Tee ForkedFC, {{&Y, &True}, {&Z, &True}});
476bdfe556dSWei Yi Tee EXPECT_TRUE(Context.equivalentBoolValues(ForkedFCWithYAndZTrue, X));
477bdfe556dSWei Yi Tee
478*b5e3dac3SDmitri Gribenko // If any of X,Y,Z is false, ForkedFC is false
479bdfe556dSWei Yi Tee auto &ForkedFCWithXFalse =
480bdfe556dSWei Yi Tee Context.buildAndSubstituteFlowCondition(ForkedFC, {{&X, &False}});
481bdfe556dSWei Yi Tee auto &ForkedFCWithYFalse =
482bdfe556dSWei Yi Tee Context.buildAndSubstituteFlowCondition(ForkedFC, {{&Y, &False}});
483bdfe556dSWei Yi Tee auto &ForkedFCWithZFalse =
484bdfe556dSWei Yi Tee Context.buildAndSubstituteFlowCondition(ForkedFC, {{&Z, &False}});
485bdfe556dSWei Yi Tee EXPECT_TRUE(Context.equivalentBoolValues(ForkedFCWithXFalse, False));
486bdfe556dSWei Yi Tee EXPECT_TRUE(Context.equivalentBoolValues(ForkedFCWithYFalse, False));
487bdfe556dSWei Yi Tee EXPECT_TRUE(Context.equivalentBoolValues(ForkedFCWithZFalse, False));
488bdfe556dSWei Yi Tee }
489bdfe556dSWei Yi Tee
TEST_F(DataflowAnalysisContextTest,SubstituteFlowConditionsJoinedFC)490bdfe556dSWei Yi Tee TEST_F(DataflowAnalysisContextTest, SubstituteFlowConditionsJoinedFC) {
491bdfe556dSWei Yi Tee auto &X = Context.createAtomicBoolValue();
492bdfe556dSWei Yi Tee auto &Y = Context.createAtomicBoolValue();
493bdfe556dSWei Yi Tee auto &Z = Context.createAtomicBoolValue();
494bdfe556dSWei Yi Tee auto &True = Context.getBoolLiteralValue(true);
495bdfe556dSWei Yi Tee auto &False = Context.getBoolLiteralValue(false);
496bdfe556dSWei Yi Tee
497bdfe556dSWei Yi Tee // FC1 = X
498bdfe556dSWei Yi Tee auto &FC1 = Context.makeFlowConditionToken();
499bdfe556dSWei Yi Tee Context.addFlowConditionConstraint(FC1, X);
500bdfe556dSWei Yi Tee // FC2 = Y
501bdfe556dSWei Yi Tee auto &FC2 = Context.makeFlowConditionToken();
502bdfe556dSWei Yi Tee Context.addFlowConditionConstraint(FC2, Y);
503bdfe556dSWei Yi Tee // JoinedFC = (FC1 || FC2) && Z = (X || Y) && Z
504bdfe556dSWei Yi Tee auto &JoinedFC = Context.joinFlowConditions(FC1, FC2);
505bdfe556dSWei Yi Tee Context.addFlowConditionConstraint(JoinedFC, Z);
506bdfe556dSWei Yi Tee
507*b5e3dac3SDmitri Gribenko // If any of X, Y is true, JoinedFC is equivalent to Z
508bdfe556dSWei Yi Tee auto &JoinedFCWithXTrue =
509bdfe556dSWei Yi Tee Context.buildAndSubstituteFlowCondition(JoinedFC, {{&X, &True}});
510bdfe556dSWei Yi Tee auto &JoinedFCWithYTrue =
511bdfe556dSWei Yi Tee Context.buildAndSubstituteFlowCondition(JoinedFC, {{&Y, &True}});
512bdfe556dSWei Yi Tee EXPECT_TRUE(Context.equivalentBoolValues(JoinedFCWithXTrue, Z));
513bdfe556dSWei Yi Tee EXPECT_TRUE(Context.equivalentBoolValues(JoinedFCWithYTrue, Z));
514bdfe556dSWei Yi Tee
515*b5e3dac3SDmitri Gribenko // If Z is true, JoinedFC is equivalent to (X || Y)
516bdfe556dSWei Yi Tee auto &JoinedFCWithZTrue =
517bdfe556dSWei Yi Tee Context.buildAndSubstituteFlowCondition(JoinedFC, {{&Z, &True}});
518bdfe556dSWei Yi Tee EXPECT_TRUE(Context.equivalentBoolValues(
519bdfe556dSWei Yi Tee JoinedFCWithZTrue, Context.getOrCreateDisjunction(X, Y)));
520bdfe556dSWei Yi Tee
521*b5e3dac3SDmitri Gribenko // If any of X, Y is false, JoinedFC is equivalent to the conjunction of the
522*b5e3dac3SDmitri Gribenko // other value and Z
523bdfe556dSWei Yi Tee auto &JoinedFCWithXFalse =
524bdfe556dSWei Yi Tee Context.buildAndSubstituteFlowCondition(JoinedFC, {{&X, &False}});
525bdfe556dSWei Yi Tee auto &JoinedFCWithYFalse =
526bdfe556dSWei Yi Tee Context.buildAndSubstituteFlowCondition(JoinedFC, {{&Y, &False}});
527bdfe556dSWei Yi Tee EXPECT_TRUE(Context.equivalentBoolValues(
528bdfe556dSWei Yi Tee JoinedFCWithXFalse, Context.getOrCreateConjunction(Y, Z)));
529bdfe556dSWei Yi Tee EXPECT_TRUE(Context.equivalentBoolValues(
530bdfe556dSWei Yi Tee JoinedFCWithYFalse, Context.getOrCreateConjunction(X, Z)));
531bdfe556dSWei Yi Tee
532*b5e3dac3SDmitri Gribenko // If Z is false, JoinedFC is false
533bdfe556dSWei Yi Tee auto &JoinedFCWithZFalse =
534bdfe556dSWei Yi Tee Context.buildAndSubstituteFlowCondition(JoinedFC, {{&Z, &False}});
535bdfe556dSWei Yi Tee EXPECT_TRUE(Context.equivalentBoolValues(JoinedFCWithZFalse, False));
536bdfe556dSWei Yi Tee }
537bdfe556dSWei Yi Tee
538ae60884dSStanislav Gatev } // namespace
539