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: 22ae60884dSStanislav Gatev DataflowAnalysisContextTest() 23ae60884dSStanislav Gatev : Context(std::make_unique<WatchedLiteralsSolver>()) {} 24ae60884dSStanislav Gatev 25ae60884dSStanislav Gatev DataflowAnalysisContext Context; 26ae60884dSStanislav Gatev }; 27ae60884dSStanislav Gatev 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 279*fa34210fSWei Yi Tee #if !defined(NDEBUG) && GTEST_HAS_DEATH_TEST 280*fa34210fSWei Yi Tee TEST_F(DataflowAnalysisContextTest, SubstituteFlowConditionsTrueUnchanged) { 281*fa34210fSWei Yi Tee auto &True = Context.getBoolLiteralValue(true); 282*fa34210fSWei Yi Tee auto &Other = Context.createAtomicBoolValue(); 283*fa34210fSWei Yi Tee 284*fa34210fSWei Yi Tee // FC = True 285*fa34210fSWei Yi Tee auto &FC = Context.makeFlowConditionToken(); 286*fa34210fSWei Yi Tee Context.addFlowConditionConstraint(FC, True); 287*fa34210fSWei Yi Tee 288*fa34210fSWei Yi Tee // `True` should never be substituted 289*fa34210fSWei Yi Tee EXPECT_DEATH(Context.buildAndSubstituteFlowCondition(FC, {{&True, &Other}}), 290*fa34210fSWei Yi Tee "Do not substitute true/false boolean literals"); 291*fa34210fSWei Yi Tee } 292*fa34210fSWei Yi Tee 293*fa34210fSWei Yi Tee TEST_F(DataflowAnalysisContextTest, SubstituteFlowConditionsFalseUnchanged) { 294*fa34210fSWei Yi Tee auto &False = Context.getBoolLiteralValue(false); 295*fa34210fSWei Yi Tee auto &Other = Context.createAtomicBoolValue(); 296*fa34210fSWei Yi Tee 297*fa34210fSWei Yi Tee // FC = False 298*fa34210fSWei Yi Tee auto &FC = Context.makeFlowConditionToken(); 299*fa34210fSWei Yi Tee Context.addFlowConditionConstraint(FC, False); 300*fa34210fSWei Yi Tee 301*fa34210fSWei Yi Tee // `False` should never be substituted 302*fa34210fSWei Yi Tee EXPECT_DEATH(Context.buildAndSubstituteFlowCondition(FC, {{&False, &Other}}), 303*fa34210fSWei Yi Tee "Do not substitute true/false boolean literals"); 304*fa34210fSWei Yi Tee } 305*fa34210fSWei Yi Tee #endif 306*fa34210fSWei Yi Tee 307bdfe556dSWei Yi Tee TEST_F(DataflowAnalysisContextTest, SubstituteFlowConditionsAtomicFC) { 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 316bdfe556dSWei Yi Tee // If X is true in FC, FC = X must be 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 321bdfe556dSWei Yi Tee // If X is false in FC, FC = X must be 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 327bdfe556dSWei Yi Tee TEST_F(DataflowAnalysisContextTest, SubstituteFlowConditionsNegatedFC) { 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 336bdfe556dSWei Yi Tee // If X is true in FC, FC = !X must be 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 341bdfe556dSWei Yi Tee // If X is false in FC, FC = !X must be 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 347bdfe556dSWei Yi Tee TEST_F(DataflowAnalysisContextTest, SubstituteFlowConditionsDisjunctiveFC) { 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 357bdfe556dSWei Yi Tee // If X is true in FC, FC = X || Y must be 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 362bdfe556dSWei Yi Tee // If X is false in FC, FC = X || Y is equivalent to evaluating 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 368bdfe556dSWei Yi Tee TEST_F(DataflowAnalysisContextTest, SubstituteFlowConditionsConjunctiveFC) { 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 378bdfe556dSWei Yi Tee // If X is true in FC, FC = X && Y is equivalent to evaluating 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 383bdfe556dSWei Yi Tee // If X is false in FC, FC = X && Y must be 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 389bdfe556dSWei Yi Tee TEST_F(DataflowAnalysisContextTest, SubstituteFlowConditionsForkedFC) { 390bdfe556dSWei Yi Tee auto &X = Context.createAtomicBoolValue(); 391bdfe556dSWei Yi Tee auto &Y = Context.createAtomicBoolValue(); 392bdfe556dSWei Yi Tee auto &Z = Context.createAtomicBoolValue(); 393bdfe556dSWei Yi Tee auto &True = Context.getBoolLiteralValue(true); 394bdfe556dSWei Yi Tee auto &False = Context.getBoolLiteralValue(false); 395bdfe556dSWei Yi Tee 396bdfe556dSWei Yi Tee // FC = X && Y 397bdfe556dSWei Yi Tee auto &FC = Context.makeFlowConditionToken(); 398bdfe556dSWei Yi Tee Context.addFlowConditionConstraint(FC, Context.getOrCreateConjunction(X, Y)); 399bdfe556dSWei Yi Tee // ForkedFC = FC && Z = X && Y && Z 400bdfe556dSWei Yi Tee auto &ForkedFC = Context.forkFlowCondition(FC); 401bdfe556dSWei Yi Tee Context.addFlowConditionConstraint(ForkedFC, Z); 402bdfe556dSWei Yi Tee 403bdfe556dSWei Yi Tee // If any of X,Y,Z is true in ForkedFC, ForkedFC = X && Y && Z is equivalent 404bdfe556dSWei Yi Tee // to evaluating the conjunction of the remaining values 405bdfe556dSWei Yi Tee auto &ForkedFCWithZTrue = 406bdfe556dSWei Yi Tee Context.buildAndSubstituteFlowCondition(ForkedFC, {{&Z, &True}}); 407bdfe556dSWei Yi Tee EXPECT_TRUE(Context.equivalentBoolValues( 408bdfe556dSWei Yi Tee ForkedFCWithZTrue, Context.getOrCreateConjunction(X, Y))); 409bdfe556dSWei Yi Tee auto &ForkedFCWithYAndZTrue = Context.buildAndSubstituteFlowCondition( 410bdfe556dSWei Yi Tee ForkedFC, {{&Y, &True}, {&Z, &True}}); 411bdfe556dSWei Yi Tee EXPECT_TRUE(Context.equivalentBoolValues(ForkedFCWithYAndZTrue, X)); 412bdfe556dSWei Yi Tee 413bdfe556dSWei Yi Tee // If any of X,Y,Z is false in ForkedFC, ForkedFC = X && Y && Z must be false 414bdfe556dSWei Yi Tee auto &ForkedFCWithXFalse = 415bdfe556dSWei Yi Tee Context.buildAndSubstituteFlowCondition(ForkedFC, {{&X, &False}}); 416bdfe556dSWei Yi Tee auto &ForkedFCWithYFalse = 417bdfe556dSWei Yi Tee Context.buildAndSubstituteFlowCondition(ForkedFC, {{&Y, &False}}); 418bdfe556dSWei Yi Tee auto &ForkedFCWithZFalse = 419bdfe556dSWei Yi Tee Context.buildAndSubstituteFlowCondition(ForkedFC, {{&Z, &False}}); 420bdfe556dSWei Yi Tee EXPECT_TRUE(Context.equivalentBoolValues(ForkedFCWithXFalse, False)); 421bdfe556dSWei Yi Tee EXPECT_TRUE(Context.equivalentBoolValues(ForkedFCWithYFalse, False)); 422bdfe556dSWei Yi Tee EXPECT_TRUE(Context.equivalentBoolValues(ForkedFCWithZFalse, False)); 423bdfe556dSWei Yi Tee } 424bdfe556dSWei Yi Tee 425bdfe556dSWei Yi Tee TEST_F(DataflowAnalysisContextTest, SubstituteFlowConditionsJoinedFC) { 426bdfe556dSWei Yi Tee auto &X = Context.createAtomicBoolValue(); 427bdfe556dSWei Yi Tee auto &Y = Context.createAtomicBoolValue(); 428bdfe556dSWei Yi Tee auto &Z = Context.createAtomicBoolValue(); 429bdfe556dSWei Yi Tee auto &True = Context.getBoolLiteralValue(true); 430bdfe556dSWei Yi Tee auto &False = Context.getBoolLiteralValue(false); 431bdfe556dSWei Yi Tee 432bdfe556dSWei Yi Tee // FC1 = X 433bdfe556dSWei Yi Tee auto &FC1 = Context.makeFlowConditionToken(); 434bdfe556dSWei Yi Tee Context.addFlowConditionConstraint(FC1, X); 435bdfe556dSWei Yi Tee // FC2 = Y 436bdfe556dSWei Yi Tee auto &FC2 = Context.makeFlowConditionToken(); 437bdfe556dSWei Yi Tee Context.addFlowConditionConstraint(FC2, Y); 438bdfe556dSWei Yi Tee // JoinedFC = (FC1 || FC2) && Z = (X || Y) && Z 439bdfe556dSWei Yi Tee auto &JoinedFC = Context.joinFlowConditions(FC1, FC2); 440bdfe556dSWei Yi Tee Context.addFlowConditionConstraint(JoinedFC, Z); 441bdfe556dSWei Yi Tee 442bdfe556dSWei Yi Tee // If any of X, Y is true in JoinedFC, JoinedFC = (X || Y) && Z is equivalent 443bdfe556dSWei Yi Tee // to evaluating the remaining Z 444bdfe556dSWei Yi Tee auto &JoinedFCWithXTrue = 445bdfe556dSWei Yi Tee Context.buildAndSubstituteFlowCondition(JoinedFC, {{&X, &True}}); 446bdfe556dSWei Yi Tee auto &JoinedFCWithYTrue = 447bdfe556dSWei Yi Tee Context.buildAndSubstituteFlowCondition(JoinedFC, {{&Y, &True}}); 448bdfe556dSWei Yi Tee EXPECT_TRUE(Context.equivalentBoolValues(JoinedFCWithXTrue, Z)); 449bdfe556dSWei Yi Tee EXPECT_TRUE(Context.equivalentBoolValues(JoinedFCWithYTrue, Z)); 450bdfe556dSWei Yi Tee 451bdfe556dSWei Yi Tee // If Z is true in JoinedFC, JoinedFC = (X || Y) && Z is equivalent to 452bdfe556dSWei Yi Tee // evaluating the remaining disjunction (X || Y) 453bdfe556dSWei Yi Tee auto &JoinedFCWithZTrue = 454bdfe556dSWei Yi Tee Context.buildAndSubstituteFlowCondition(JoinedFC, {{&Z, &True}}); 455bdfe556dSWei Yi Tee EXPECT_TRUE(Context.equivalentBoolValues( 456bdfe556dSWei Yi Tee JoinedFCWithZTrue, Context.getOrCreateDisjunction(X, Y))); 457bdfe556dSWei Yi Tee 458bdfe556dSWei Yi Tee // If any of X, Y is false in JoinedFC, JoinedFC = (X || Y) && Z is equivalent 459bdfe556dSWei Yi Tee // to evaluating the conjunction of the other value and Z 460bdfe556dSWei Yi Tee auto &JoinedFCWithXFalse = 461bdfe556dSWei Yi Tee Context.buildAndSubstituteFlowCondition(JoinedFC, {{&X, &False}}); 462bdfe556dSWei Yi Tee auto &JoinedFCWithYFalse = 463bdfe556dSWei Yi Tee Context.buildAndSubstituteFlowCondition(JoinedFC, {{&Y, &False}}); 464bdfe556dSWei Yi Tee EXPECT_TRUE(Context.equivalentBoolValues( 465bdfe556dSWei Yi Tee JoinedFCWithXFalse, Context.getOrCreateConjunction(Y, Z))); 466bdfe556dSWei Yi Tee EXPECT_TRUE(Context.equivalentBoolValues( 467bdfe556dSWei Yi Tee JoinedFCWithYFalse, Context.getOrCreateConjunction(X, Z))); 468bdfe556dSWei Yi Tee 469bdfe556dSWei Yi Tee // If Z is false in JoinedFC, JoinedFC = (X || Y) && Z must be false 470bdfe556dSWei Yi Tee auto &JoinedFCWithZFalse = 471bdfe556dSWei Yi Tee Context.buildAndSubstituteFlowCondition(JoinedFC, {{&Z, &False}}); 472bdfe556dSWei Yi Tee EXPECT_TRUE(Context.equivalentBoolValues(JoinedFCWithZFalse, False)); 473bdfe556dSWei Yi Tee } 474bdfe556dSWei Yi Tee 475ae60884dSStanislav Gatev } // namespace 476