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