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, 36*00e9d534SWei Yi Tee GetOrCreateConjunctionReturnsSameExprGivenSameArgs) { 37ae60884dSStanislav Gatev auto &X = Context.createAtomicBoolValue(); 38*00e9d534SWei Yi Tee auto &XAndX = Context.getOrCreateConjunction(X, X); 39ae60884dSStanislav Gatev EXPECT_EQ(&XAndX, &X); 40ae60884dSStanislav Gatev } 41ae60884dSStanislav Gatev 42ae60884dSStanislav Gatev TEST_F(DataflowAnalysisContextTest, 43*00e9d534SWei Yi Tee GetOrCreateConjunctionReturnsSameExprOnSubsequentCalls) { 44ae60884dSStanislav Gatev auto &X = Context.createAtomicBoolValue(); 45ae60884dSStanislav Gatev auto &Y = Context.createAtomicBoolValue(); 46*00e9d534SWei Yi Tee auto &XAndY1 = Context.getOrCreateConjunction(X, Y); 47*00e9d534SWei Yi Tee auto &XAndY2 = Context.getOrCreateConjunction(X, Y); 48ae60884dSStanislav Gatev EXPECT_EQ(&XAndY1, &XAndY2); 49ae60884dSStanislav Gatev 50*00e9d534SWei Yi Tee auto &YAndX = Context.getOrCreateConjunction(Y, X); 51ae60884dSStanislav Gatev EXPECT_EQ(&XAndY1, &YAndX); 52ae60884dSStanislav Gatev 53ae60884dSStanislav Gatev auto &Z = Context.createAtomicBoolValue(); 54*00e9d534SWei Yi Tee auto &XAndZ = Context.getOrCreateConjunction(X, Z); 55ae60884dSStanislav Gatev EXPECT_NE(&XAndY1, &XAndZ); 56ae60884dSStanislav Gatev } 57ae60884dSStanislav Gatev 58ae60884dSStanislav Gatev TEST_F(DataflowAnalysisContextTest, 59*00e9d534SWei Yi Tee GetOrCreateDisjunctionReturnsSameExprGivenSameArgs) { 60ae60884dSStanislav Gatev auto &X = Context.createAtomicBoolValue(); 61*00e9d534SWei Yi Tee auto &XOrX = Context.getOrCreateDisjunction(X, X); 62ae60884dSStanislav Gatev EXPECT_EQ(&XOrX, &X); 63ae60884dSStanislav Gatev } 64ae60884dSStanislav Gatev 65ae60884dSStanislav Gatev TEST_F(DataflowAnalysisContextTest, 66*00e9d534SWei Yi Tee GetOrCreateDisjunctionReturnsSameExprOnSubsequentCalls) { 67ae60884dSStanislav Gatev auto &X = Context.createAtomicBoolValue(); 68ae60884dSStanislav Gatev auto &Y = Context.createAtomicBoolValue(); 69*00e9d534SWei Yi Tee auto &XOrY1 = Context.getOrCreateDisjunction(X, Y); 70*00e9d534SWei Yi Tee auto &XOrY2 = Context.getOrCreateDisjunction(X, Y); 71ae60884dSStanislav Gatev EXPECT_EQ(&XOrY1, &XOrY2); 72ae60884dSStanislav Gatev 73*00e9d534SWei Yi Tee auto &YOrX = Context.getOrCreateDisjunction(Y, X); 74ae60884dSStanislav Gatev EXPECT_EQ(&XOrY1, &YOrX); 75ae60884dSStanislav Gatev 76ae60884dSStanislav Gatev auto &Z = Context.createAtomicBoolValue(); 77*00e9d534SWei Yi Tee auto &XOrZ = Context.getOrCreateDisjunction(X, Z); 78ae60884dSStanislav Gatev EXPECT_NE(&XOrY1, &XOrZ); 79ae60884dSStanislav Gatev } 80ae60884dSStanislav Gatev 81ae60884dSStanislav Gatev TEST_F(DataflowAnalysisContextTest, 82*00e9d534SWei Yi Tee GetOrCreateNegationReturnsSameExprOnSubsequentCalls) { 83ae60884dSStanislav Gatev auto &X = Context.createAtomicBoolValue(); 84*00e9d534SWei Yi Tee auto &NotX1 = Context.getOrCreateNegation(X); 85*00e9d534SWei Yi Tee auto &NotX2 = Context.getOrCreateNegation(X); 86ae60884dSStanislav Gatev EXPECT_EQ(&NotX1, &NotX2); 87ae60884dSStanislav Gatev 88ae60884dSStanislav Gatev auto &Y = Context.createAtomicBoolValue(); 89*00e9d534SWei Yi Tee auto &NotY = Context.getOrCreateNegation(Y); 90ae60884dSStanislav Gatev EXPECT_NE(&NotX1, &NotY); 91ae60884dSStanislav Gatev } 92ae60884dSStanislav Gatev 93*00e9d534SWei Yi Tee TEST_F(DataflowAnalysisContextTest, 94*00e9d534SWei Yi Tee GetOrCreateImplicationReturnsTrueGivenSameArgs) { 95*00e9d534SWei Yi Tee auto &X = Context.createAtomicBoolValue(); 96*00e9d534SWei Yi Tee auto &XImpliesX = Context.getOrCreateImplication(X, X); 97*00e9d534SWei Yi Tee EXPECT_EQ(&XImpliesX, &Context.getBoolLiteralValue(true)); 98*00e9d534SWei Yi Tee } 99*00e9d534SWei Yi Tee 100*00e9d534SWei Yi Tee TEST_F(DataflowAnalysisContextTest, 101*00e9d534SWei Yi Tee GetOrCreateImplicationReturnsSameExprOnSubsequentCalls) { 102*00e9d534SWei Yi Tee auto &X = Context.createAtomicBoolValue(); 103*00e9d534SWei Yi Tee auto &Y = Context.createAtomicBoolValue(); 104*00e9d534SWei Yi Tee auto &XImpliesY1 = Context.getOrCreateImplication(X, Y); 105*00e9d534SWei Yi Tee auto &XImpliesY2 = Context.getOrCreateImplication(X, Y); 106*00e9d534SWei Yi Tee EXPECT_EQ(&XImpliesY1, &XImpliesY2); 107*00e9d534SWei Yi Tee 108*00e9d534SWei Yi Tee auto &YImpliesX = Context.getOrCreateImplication(Y, X); 109*00e9d534SWei Yi Tee EXPECT_NE(&XImpliesY1, &YImpliesX); 110*00e9d534SWei Yi Tee 111*00e9d534SWei Yi Tee auto &Z = Context.createAtomicBoolValue(); 112*00e9d534SWei Yi Tee auto &XImpliesZ = Context.getOrCreateImplication(X, Z); 113*00e9d534SWei Yi Tee EXPECT_NE(&XImpliesY1, &XImpliesZ); 114*00e9d534SWei Yi Tee } 115*00e9d534SWei Yi Tee 116*00e9d534SWei Yi Tee TEST_F(DataflowAnalysisContextTest, GetOrCreateIffReturnsTrueGivenSameArgs) { 117*00e9d534SWei Yi Tee auto &X = Context.createAtomicBoolValue(); 118*00e9d534SWei Yi Tee auto &XIffX = Context.getOrCreateIff(X, X); 119*00e9d534SWei Yi Tee EXPECT_EQ(&XIffX, &Context.getBoolLiteralValue(true)); 120*00e9d534SWei Yi Tee } 121*00e9d534SWei Yi Tee 122*00e9d534SWei Yi Tee TEST_F(DataflowAnalysisContextTest, 123*00e9d534SWei Yi Tee GetOrCreateIffReturnsSameExprOnSubsequentCalls) { 124*00e9d534SWei Yi Tee auto &X = Context.createAtomicBoolValue(); 125*00e9d534SWei Yi Tee auto &Y = Context.createAtomicBoolValue(); 126*00e9d534SWei Yi Tee auto &XIffY1 = Context.getOrCreateIff(X, Y); 127*00e9d534SWei Yi Tee auto &XIffY2 = Context.getOrCreateIff(X, Y); 128*00e9d534SWei Yi Tee EXPECT_EQ(&XIffY1, &XIffY2); 129*00e9d534SWei Yi Tee 130*00e9d534SWei Yi Tee auto &YIffX = Context.getOrCreateIff(Y, X); 131*00e9d534SWei Yi Tee EXPECT_EQ(&XIffY1, &YIffX); 132*00e9d534SWei Yi Tee 133*00e9d534SWei Yi Tee auto &Z = Context.createAtomicBoolValue(); 134*00e9d534SWei Yi Tee auto &XIffZ = Context.getOrCreateIff(X, Z); 135*00e9d534SWei Yi Tee EXPECT_NE(&XIffY1, &XIffZ); 136*00e9d534SWei Yi Tee } 137*00e9d534SWei 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( 212*00e9d534SWei Yi Tee FC5, Context.getOrCreateDisjunction(C1, Context.getOrCreateNegation(C1))); 21358abe36aSEric Li EXPECT_TRUE(Context.flowConditionIsTautology(FC5)); 21458abe36aSEric Li } 21558abe36aSEric Li 216ae60884dSStanislav Gatev } // namespace 217