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
14namespace clang {
15namespace ento {
16namespace {
17
18class StoreTestConsumer : public ExprEngineConsumer {
19public:
20 StoreTestConsumer(CompilerInstance &C) : ExprEngineConsumer(C) {}
21
22 bool HandleTopLevelDecl(DeclGroupRef DG) override {
23 for (const auto *D : DG)
24 performTest(D);
25 return true;
26 }
27
28private:
29 virtual void performTest(const Decl *D) = 0;
30};
31
32template <class ConsumerTy> class TestAction : public ASTFrontendAction {
33public:
34 std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &Compiler,
35 StringRef File) override {
36 return std::make_unique<ConsumerTy>(Compiler);
37 }
38};
39
40// Test that we can put a value into an int-type variable and load it
41// back from that variable. Test what happens if default bindings are used.
42class VariableBindConsumer : public StoreTestConsumer {
43 void performTest(const Decl *D) override {
44 StoreManager &SManager = Eng.getStoreManager();
45 SValBuilder &Builder = Eng.getSValBuilder();
46 MemRegionManager &MRManager = SManager.getRegionManager();
47 const ASTContext &ASTCtxt = Eng.getContext();
48
49 const auto *VDX0 = findDeclByName<VarDecl>(Where: D, Name: "x0");
50 const auto *VDY0 = findDeclByName<VarDecl>(Where: D, Name: "y0");
51 const auto *VDZ0 = findDeclByName<VarDecl>(Where: D, Name: "z0");
52 const auto *VDX1 = findDeclByName<VarDecl>(Where: D, Name: "x1");
53 const auto *VDY1 = findDeclByName<VarDecl>(Where: D, Name: "y1");
54
55 ASSERT_TRUE(VDX0 && VDY0 && VDZ0 && VDX1 && VDY1);
56
57 const StackFrameContext *SFC =
58 Eng.getAnalysisDeclContextManager().getStackFrame(D);
59
60 Loc LX0 = loc::MemRegionVal(MRManager.getVarRegion(VD: VDX0, LC: SFC));
61 Loc LY0 = loc::MemRegionVal(MRManager.getVarRegion(VD: VDY0, LC: SFC));
62 Loc LZ0 = loc::MemRegionVal(MRManager.getVarRegion(VD: VDZ0, LC: SFC));
63 Loc LX1 = loc::MemRegionVal(MRManager.getVarRegion(VD: VDX1, LC: SFC));
64 Loc LY1 = loc::MemRegionVal(MRManager.getVarRegion(VD: VDY1, LC: SFC));
65
66 Store StInit = SManager.getInitialStore(InitLoc: SFC).getStore();
67 SVal Zero = Builder.makeZeroVal(type: ASTCtxt.IntTy);
68 SVal One = Builder.makeIntVal(1, ASTCtxt.IntTy);
69 SVal NarrowZero = Builder.makeZeroVal(type: ASTCtxt.CharTy);
70
71 // Bind(Zero)
72 Store StX0 = SManager.Bind(store: StInit, loc: LX0, val: Zero).ResultingStore.getStore();
73 EXPECT_EQ(Zero, SManager.getBinding(StX0, LX0, ASTCtxt.IntTy));
74
75 // BindDefaultInitial(Zero)
76 Store StY0 = SManager.BindDefaultInitial(store: StInit, R: LY0.getAsRegion(), V: Zero)
77 .ResultingStore.getStore();
78 EXPECT_EQ(Zero, SManager.getBinding(StY0, LY0, ASTCtxt.IntTy));
79 EXPECT_EQ(Zero, *SManager.getDefaultBinding(StY0, LY0.getAsRegion()));
80
81 // BindDefaultZero()
82 Store StZ0 = SManager.BindDefaultZero(store: StInit, R: LZ0.getAsRegion())
83 .ResultingStore.getStore();
84 // BindDefaultZero wipes the region with '0 S8b', not with out Zero.
85 // Direct load, however, does give us back the object of the type
86 // that we specify for loading.
87 EXPECT_EQ(Zero, SManager.getBinding(StZ0, LZ0, ASTCtxt.IntTy));
88 EXPECT_EQ(NarrowZero, *SManager.getDefaultBinding(StZ0, LZ0.getAsRegion()));
89
90 // Bind(One)
91 Store StX1 = SManager.Bind(store: StInit, loc: LX1, val: One).ResultingStore.getStore();
92 EXPECT_EQ(One, SManager.getBinding(StX1, LX1, ASTCtxt.IntTy));
93
94 // BindDefaultInitial(One)
95 Store StY1 = SManager.BindDefaultInitial(store: StInit, R: LY1.getAsRegion(), V: One)
96 .ResultingStore.getStore();
97 EXPECT_EQ(One, SManager.getBinding(StY1, LY1, ASTCtxt.IntTy));
98 EXPECT_EQ(One, *SManager.getDefaultBinding(StY1, LY1.getAsRegion()));
99 }
100
101public:
102 using StoreTestConsumer::StoreTestConsumer;
103};
104
105TEST(Store, VariableBind) {
106 EXPECT_TRUE(tooling::runToolOnCode(
107 std::make_unique<TestAction<VariableBindConsumer>>(),
108 "void foo() { int x0, y0, z0, x1, y1; }"));
109}
110
111class LiteralCompoundConsumer : public StoreTestConsumer {
112 void performTest(const Decl *D) override {
113 StoreManager &SManager = Eng.getStoreManager();
114 SValBuilder &Builder = Eng.getSValBuilder();
115 MemRegionManager &MRManager = SManager.getRegionManager();
116 ASTContext &ASTCtxt = Eng.getContext();
117
118 using namespace ast_matchers;
119
120 const auto *CL = findNode<CompoundLiteralExpr>(Where: D, What: compoundLiteralExpr());
121
122 const StackFrameContext *SFC =
123 Eng.getAnalysisDeclContextManager().getStackFrame(D);
124
125 QualType Int = ASTCtxt.IntTy;
126
127 // Get region for 'test'
128 const SubRegion *CLRegion = MRManager.getCompoundLiteralRegion(CL, LC: SFC);
129
130 // Get value for 'test[0]'
131 NonLoc Zero = Builder.makeIntVal(integer: 0, isUnsigned: false);
132 loc::MemRegionVal ZeroElement(
133 MRManager.getElementRegion(elementType: ASTCtxt.IntTy, Idx: Zero, superRegion: CLRegion, Ctx: ASTCtxt));
134
135 Store StInit = SManager.getInitialStore(InitLoc: SFC).getStore();
136 // Let's bind constant 1 to 'test[0]'
137 SVal One = Builder.makeIntVal(integer: 1, type: Int);
138 Store StX =
139 SManager.Bind(store: StInit, loc: ZeroElement, val: One).ResultingStore.getStore();
140
141 // And make sure that we can read this binding back as it was
142 EXPECT_EQ(One, SManager.getBinding(StX, ZeroElement, Int));
143 }
144
145public:
146 using StoreTestConsumer::StoreTestConsumer;
147};
148
149TEST(Store, LiteralCompound) {
150 EXPECT_TRUE(tooling::runToolOnCode(
151 std::make_unique<TestAction<LiteralCompoundConsumer>>(),
152 "void foo() { int *test = (int[]){ 1, 2, 3 }; }", "input.c"));
153}
154
155} // namespace
156} // namespace ento
157} // namespace clang
158

Provided by KDAB

Privacy Policy
Update your C++ knowledge – Modern C++11/14/17 Training
Find out more

source code of clang/unittests/StaticAnalyzer/StoreTest.cpp