1 //===- unittests/StaticAnalyzer/StoreTest.cpp -----------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "Reusables.h" 10 11 #include "clang/Tooling/Tooling.h" 12 #include "gtest/gtest.h" 13 14 namespace clang { 15 namespace ento { 16 namespace { 17 18 // Test that we can put a value into an int-type variable and load it 19 // back from that variable. Test what happens if default bindings are used. 20 class VariableBindConsumer : public ExprEngineConsumer { 21 void performTest(const Decl *D) { 22 StoreManager &StMgr = Eng.getStoreManager(); 23 SValBuilder &SVB = Eng.getSValBuilder(); 24 MemRegionManager &MRMgr = StMgr.getRegionManager(); 25 const ASTContext &ACtx = Eng.getContext(); 26 27 const auto *VDX0 = findDeclByName<VarDecl>(D, "x0"); 28 const auto *VDY0 = findDeclByName<VarDecl>(D, "y0"); 29 const auto *VDZ0 = findDeclByName<VarDecl>(D, "z0"); 30 const auto *VDX1 = findDeclByName<VarDecl>(D, "x1"); 31 const auto *VDY1 = findDeclByName<VarDecl>(D, "y1"); 32 assert(VDX0 && VDY0 && VDZ0 && VDX1 && VDY1); 33 34 const StackFrameContext *SFC = 35 Eng.getAnalysisDeclContextManager().getStackFrame(D); 36 37 Loc LX0 = loc::MemRegionVal(MRMgr.getVarRegion(VDX0, SFC)); 38 Loc LY0 = loc::MemRegionVal(MRMgr.getVarRegion(VDY0, SFC)); 39 Loc LZ0 = loc::MemRegionVal(MRMgr.getVarRegion(VDZ0, SFC)); 40 Loc LX1 = loc::MemRegionVal(MRMgr.getVarRegion(VDX1, SFC)); 41 Loc LY1 = loc::MemRegionVal(MRMgr.getVarRegion(VDY1, SFC)); 42 43 Store StInit = StMgr.getInitialStore(SFC).getStore(); 44 SVal Zero = SVB.makeZeroVal(ACtx.IntTy); 45 SVal One = SVB.makeIntVal(1, ACtx.IntTy); 46 SVal NarrowZero = SVB.makeZeroVal(ACtx.CharTy); 47 48 // Bind(Zero) 49 Store StX0 = 50 StMgr.Bind(StInit, LX0, Zero).getStore(); 51 ASSERT_EQ(Zero, StMgr.getBinding(StX0, LX0, ACtx.IntTy)); 52 53 // BindDefaultInitial(Zero) 54 Store StY0 = 55 StMgr.BindDefaultInitial(StInit, LY0.getAsRegion(), Zero).getStore(); 56 ASSERT_EQ(Zero, StMgr.getBinding(StY0, LY0, ACtx.IntTy)); 57 ASSERT_EQ(Zero, *StMgr.getDefaultBinding(StY0, LY0.getAsRegion())); 58 59 // BindDefaultZero() 60 Store StZ0 = 61 StMgr.BindDefaultZero(StInit, LZ0.getAsRegion()).getStore(); 62 // BindDefaultZero wipes the region with '0 S8b', not with out Zero. 63 // Direct load, however, does give us back the object of the type 64 // that we specify for loading. 65 ASSERT_EQ(Zero, StMgr.getBinding(StZ0, LZ0, ACtx.IntTy)); 66 ASSERT_EQ(NarrowZero, *StMgr.getDefaultBinding(StZ0, LZ0.getAsRegion())); 67 68 // Bind(One) 69 Store StX1 = 70 StMgr.Bind(StInit, LX1, One).getStore(); 71 ASSERT_EQ(One, StMgr.getBinding(StX1, LX1, ACtx.IntTy)); 72 73 // BindDefaultInitial(One) 74 Store StY1 = 75 StMgr.BindDefaultInitial(StInit, LY1.getAsRegion(), One).getStore(); 76 ASSERT_EQ(One, StMgr.getBinding(StY1, LY1, ACtx.IntTy)); 77 ASSERT_EQ(One, *StMgr.getDefaultBinding(StY1, LY1.getAsRegion())); 78 } 79 80 public: 81 VariableBindConsumer(CompilerInstance &C) : ExprEngineConsumer(C) {} 82 83 bool HandleTopLevelDecl(DeclGroupRef DG) override { 84 for (const auto *D : DG) 85 performTest(D); 86 return true; 87 } 88 }; 89 90 class VariableBindAction : public ASTFrontendAction { 91 public: 92 std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &Compiler, 93 StringRef File) override { 94 return std::make_unique<VariableBindConsumer>(Compiler); 95 } 96 }; 97 98 TEST(Store, VariableBind) { 99 EXPECT_TRUE(tooling::runToolOnCode( 100 new VariableBindAction, "void foo() { int x0, y0, z0, x1, y1; }")); 101 } 102 103 } // namespace 104 } // namespace ento 105 } // namespace clang 106