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, 36ae60884dSStanislav Gatev GetOrCreateConjunctionValueReturnsSameExprGivenSameArgs) { 37ae60884dSStanislav Gatev auto &X = Context.createAtomicBoolValue(); 38ae60884dSStanislav Gatev auto &XAndX = Context.getOrCreateConjunctionValue(X, X); 39ae60884dSStanislav Gatev EXPECT_EQ(&XAndX, &X); 40ae60884dSStanislav Gatev } 41ae60884dSStanislav Gatev 42ae60884dSStanislav Gatev TEST_F(DataflowAnalysisContextTest, 43ae60884dSStanislav Gatev GetOrCreateConjunctionValueReturnsSameExprOnSubsequentCalls) { 44ae60884dSStanislav Gatev auto &X = Context.createAtomicBoolValue(); 45ae60884dSStanislav Gatev auto &Y = Context.createAtomicBoolValue(); 46ae60884dSStanislav Gatev auto &XAndY1 = Context.getOrCreateConjunctionValue(X, Y); 47ae60884dSStanislav Gatev auto &XAndY2 = Context.getOrCreateConjunctionValue(X, Y); 48ae60884dSStanislav Gatev EXPECT_EQ(&XAndY1, &XAndY2); 49ae60884dSStanislav Gatev 50ae60884dSStanislav Gatev auto &YAndX = Context.getOrCreateConjunctionValue(Y, X); 51ae60884dSStanislav Gatev EXPECT_EQ(&XAndY1, &YAndX); 52ae60884dSStanislav Gatev 53ae60884dSStanislav Gatev auto &Z = Context.createAtomicBoolValue(); 54ae60884dSStanislav Gatev auto &XAndZ = Context.getOrCreateConjunctionValue(X, Z); 55ae60884dSStanislav Gatev EXPECT_NE(&XAndY1, &XAndZ); 56ae60884dSStanislav Gatev } 57ae60884dSStanislav Gatev 58ae60884dSStanislav Gatev TEST_F(DataflowAnalysisContextTest, 59ae60884dSStanislav Gatev GetOrCreateDisjunctionValueReturnsSameExprGivenSameArgs) { 60ae60884dSStanislav Gatev auto &X = Context.createAtomicBoolValue(); 61ae60884dSStanislav Gatev auto &XOrX = Context.getOrCreateDisjunctionValue(X, X); 62ae60884dSStanislav Gatev EXPECT_EQ(&XOrX, &X); 63ae60884dSStanislav Gatev } 64ae60884dSStanislav Gatev 65ae60884dSStanislav Gatev TEST_F(DataflowAnalysisContextTest, 66ae60884dSStanislav Gatev GetOrCreateDisjunctionValueReturnsSameExprOnSubsequentCalls) { 67ae60884dSStanislav Gatev auto &X = Context.createAtomicBoolValue(); 68ae60884dSStanislav Gatev auto &Y = Context.createAtomicBoolValue(); 69ae60884dSStanislav Gatev auto &XOrY1 = Context.getOrCreateDisjunctionValue(X, Y); 70ae60884dSStanislav Gatev auto &XOrY2 = Context.getOrCreateDisjunctionValue(X, Y); 71ae60884dSStanislav Gatev EXPECT_EQ(&XOrY1, &XOrY2); 72ae60884dSStanislav Gatev 73ae60884dSStanislav Gatev auto &YOrX = Context.getOrCreateDisjunctionValue(Y, X); 74ae60884dSStanislav Gatev EXPECT_EQ(&XOrY1, &YOrX); 75ae60884dSStanislav Gatev 76ae60884dSStanislav Gatev auto &Z = Context.createAtomicBoolValue(); 77ae60884dSStanislav Gatev auto &XOrZ = Context.getOrCreateDisjunctionValue(X, Z); 78ae60884dSStanislav Gatev EXPECT_NE(&XOrY1, &XOrZ); 79ae60884dSStanislav Gatev } 80ae60884dSStanislav Gatev 81ae60884dSStanislav Gatev TEST_F(DataflowAnalysisContextTest, 82ae60884dSStanislav Gatev GetOrCreateNegationValueReturnsSameExprOnSubsequentCalls) { 83ae60884dSStanislav Gatev auto &X = Context.createAtomicBoolValue(); 84ae60884dSStanislav Gatev auto &NotX1 = Context.getOrCreateNegationValue(X); 85ae60884dSStanislav Gatev auto &NotX2 = Context.getOrCreateNegationValue(X); 86ae60884dSStanislav Gatev EXPECT_EQ(&NotX1, &NotX2); 87ae60884dSStanislav Gatev 88ae60884dSStanislav Gatev auto &Y = Context.createAtomicBoolValue(); 89ae60884dSStanislav Gatev auto &NotY = Context.getOrCreateNegationValue(Y); 90ae60884dSStanislav Gatev EXPECT_NE(&NotX1, &NotY); 91ae60884dSStanislav Gatev } 92ae60884dSStanislav Gatev 93*955a05a2SStanislav Gatev TEST_F(DataflowAnalysisContextTest, EmptyFlowCondition) { 94*955a05a2SStanislav Gatev auto &FC = Context.makeFlowConditionToken(); 95*955a05a2SStanislav Gatev auto &C = Context.createAtomicBoolValue(); 96*955a05a2SStanislav Gatev EXPECT_FALSE(Context.flowConditionImplies(FC, C)); 97*955a05a2SStanislav Gatev } 98*955a05a2SStanislav Gatev 99*955a05a2SStanislav Gatev TEST_F(DataflowAnalysisContextTest, AddFlowConditionConstraint) { 100*955a05a2SStanislav Gatev auto &FC = Context.makeFlowConditionToken(); 101*955a05a2SStanislav Gatev auto &C = Context.createAtomicBoolValue(); 102*955a05a2SStanislav Gatev Context.addFlowConditionConstraint(FC, C); 103*955a05a2SStanislav Gatev EXPECT_TRUE(Context.flowConditionImplies(FC, C)); 104*955a05a2SStanislav Gatev } 105*955a05a2SStanislav Gatev 106*955a05a2SStanislav Gatev TEST_F(DataflowAnalysisContextTest, ForkFlowCondition) { 107*955a05a2SStanislav Gatev auto &FC1 = Context.makeFlowConditionToken(); 108*955a05a2SStanislav Gatev auto &C1 = Context.createAtomicBoolValue(); 109*955a05a2SStanislav Gatev Context.addFlowConditionConstraint(FC1, C1); 110*955a05a2SStanislav Gatev 111*955a05a2SStanislav Gatev // Forked flow condition inherits the constraints of its parent flow 112*955a05a2SStanislav Gatev // condition. 113*955a05a2SStanislav Gatev auto &FC2 = Context.forkFlowCondition(FC1); 114*955a05a2SStanislav Gatev EXPECT_TRUE(Context.flowConditionImplies(FC2, C1)); 115*955a05a2SStanislav Gatev 116*955a05a2SStanislav Gatev // Adding a new constraint to the forked flow condition does not affect its 117*955a05a2SStanislav Gatev // parent flow condition. 118*955a05a2SStanislav Gatev auto &C2 = Context.createAtomicBoolValue(); 119*955a05a2SStanislav Gatev Context.addFlowConditionConstraint(FC2, C2); 120*955a05a2SStanislav Gatev EXPECT_TRUE(Context.flowConditionImplies(FC2, C2)); 121*955a05a2SStanislav Gatev EXPECT_FALSE(Context.flowConditionImplies(FC1, C2)); 122*955a05a2SStanislav Gatev } 123*955a05a2SStanislav Gatev 124*955a05a2SStanislav Gatev TEST_F(DataflowAnalysisContextTest, JoinFlowConditions) { 125*955a05a2SStanislav Gatev auto &C1 = Context.createAtomicBoolValue(); 126*955a05a2SStanislav Gatev auto &C2 = Context.createAtomicBoolValue(); 127*955a05a2SStanislav Gatev auto &C3 = Context.createAtomicBoolValue(); 128*955a05a2SStanislav Gatev 129*955a05a2SStanislav Gatev auto &FC1 = Context.makeFlowConditionToken(); 130*955a05a2SStanislav Gatev Context.addFlowConditionConstraint(FC1, C1); 131*955a05a2SStanislav Gatev Context.addFlowConditionConstraint(FC1, C3); 132*955a05a2SStanislav Gatev 133*955a05a2SStanislav Gatev auto &FC2 = Context.makeFlowConditionToken(); 134*955a05a2SStanislav Gatev Context.addFlowConditionConstraint(FC2, C2); 135*955a05a2SStanislav Gatev Context.addFlowConditionConstraint(FC2, C3); 136*955a05a2SStanislav Gatev 137*955a05a2SStanislav Gatev auto &FC3 = Context.joinFlowConditions(FC1, FC2); 138*955a05a2SStanislav Gatev EXPECT_FALSE(Context.flowConditionImplies(FC3, C1)); 139*955a05a2SStanislav Gatev EXPECT_FALSE(Context.flowConditionImplies(FC3, C2)); 140*955a05a2SStanislav Gatev EXPECT_TRUE(Context.flowConditionImplies(FC3, C3)); 141*955a05a2SStanislav Gatev } 142*955a05a2SStanislav Gatev 143ae60884dSStanislav Gatev } // namespace 144