@@ -15,89 +15,139 @@ namespace clang {
1515namespace ento {
1616namespace {
1717
18+ class StoreTestConsumer : public ExprEngineConsumer {
19+ public:
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+
28+ private:
29+ virtual void performTest (const Decl *D) = 0;
30+ };
31+
32+ template <class ConsumerTy > class TestAction : public ASTFrontendAction {
33+ public:
34+ std::unique_ptr<ASTConsumer> CreateASTConsumer (CompilerInstance &Compiler,
35+ StringRef File) override {
36+ return std::make_unique<ConsumerTy>(Compiler);
37+ }
38+ };
39+
1840// Test that we can put a value into an int-type variable and load it
1941// 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 ();
42+ class 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 ();
2648
2749 const auto *VDX0 = findDeclByName<VarDecl>(D, " x0" );
2850 const auto *VDY0 = findDeclByName<VarDecl>(D, " y0" );
2951 const auto *VDZ0 = findDeclByName<VarDecl>(D, " z0" );
3052 const auto *VDX1 = findDeclByName<VarDecl>(D, " x1" );
3153 const auto *VDY1 = findDeclByName<VarDecl>(D, " y1" );
32- assert (VDX0 && VDY0 && VDZ0 && VDX1 && VDY1);
54+
55+ ASSERT_TRUE (VDX0 && VDY0 && VDZ0 && VDX1 && VDY1);
3356
3457 const StackFrameContext *SFC =
3558 Eng.getAnalysisDeclContextManager ().getStackFrame (D);
3659
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));
60+ Loc LX0 = loc::MemRegionVal (MRManager .getVarRegion (VDX0, SFC));
61+ Loc LY0 = loc::MemRegionVal (MRManager .getVarRegion (VDY0, SFC));
62+ Loc LZ0 = loc::MemRegionVal (MRManager .getVarRegion (VDZ0, SFC));
63+ Loc LX1 = loc::MemRegionVal (MRManager .getVarRegion (VDX1, SFC));
64+ Loc LY1 = loc::MemRegionVal (MRManager .getVarRegion (VDY1, SFC));
4265
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 );
66+ Store StInit = SManager .getInitialStore (SFC).getStore ();
67+ SVal Zero = Builder .makeZeroVal (ASTCtxt .IntTy );
68+ SVal One = Builder .makeIntVal (1 , ASTCtxt .IntTy );
69+ SVal NarrowZero = Builder .makeZeroVal (ASTCtxt .CharTy );
4770
4871 // Bind(Zero)
49- Store StX0 =
50- StMgr.Bind (StInit, LX0, Zero).getStore ();
51- ASSERT_EQ (Zero, StMgr.getBinding (StX0, LX0, ACtx.IntTy ));
72+ Store StX0 = SManager.Bind (StInit, LX0, Zero).getStore ();
73+ EXPECT_EQ (Zero, SManager.getBinding (StX0, LX0, ASTCtxt.IntTy ));
5274
5375 // BindDefaultInitial(Zero)
5476 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 ()));
77+ SManager .BindDefaultInitial (StInit, LY0.getAsRegion (), Zero).getStore ();
78+ EXPECT_EQ (Zero, SManager .getBinding (StY0, LY0, ASTCtxt .IntTy ));
79+ EXPECT_EQ (Zero, *SManager .getDefaultBinding (StY0, LY0.getAsRegion ()));
5880
5981 // BindDefaultZero()
60- Store StZ0 =
61- StMgr.BindDefaultZero (StInit, LZ0.getAsRegion ()).getStore ();
82+ Store StZ0 = SManager.BindDefaultZero (StInit, LZ0.getAsRegion ()).getStore ();
6283 // BindDefaultZero wipes the region with '0 S8b', not with out Zero.
6384 // Direct load, however, does give us back the object of the type
6485 // that we specify for loading.
65- ASSERT_EQ (Zero, StMgr .getBinding (StZ0, LZ0, ACtx .IntTy ));
66- ASSERT_EQ (NarrowZero, *StMgr .getDefaultBinding (StZ0, LZ0.getAsRegion ()));
86+ EXPECT_EQ (Zero, SManager .getBinding (StZ0, LZ0, ASTCtxt .IntTy ));
87+ EXPECT_EQ (NarrowZero, *SManager .getDefaultBinding (StZ0, LZ0.getAsRegion ()));
6788
6889 // Bind(One)
69- Store StX1 =
70- StMgr.Bind (StInit, LX1, One).getStore ();
71- ASSERT_EQ (One, StMgr.getBinding (StX1, LX1, ACtx.IntTy ));
90+ Store StX1 = SManager.Bind (StInit, LX1, One).getStore ();
91+ EXPECT_EQ (One, SManager.getBinding (StX1, LX1, ASTCtxt.IntTy ));
7292
7393 // BindDefaultInitial(One)
7494 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 ()));
95+ SManager .BindDefaultInitial (StInit, LY1.getAsRegion (), One).getStore ();
96+ EXPECT_EQ (One, SManager .getBinding (StY1, LY1, ASTCtxt .IntTy ));
97+ EXPECT_EQ (One, *SManager .getDefaultBinding (StY1, LY1.getAsRegion ()));
7898 }
7999
80100public:
81- VariableBindConsumer (CompilerInstance &C) : ExprEngineConsumer(C) {}
101+ using StoreTestConsumer::StoreTestConsumer;
102+ };
82103
83- bool HandleTopLevelDecl (DeclGroupRef DG) override {
84- for (const auto *D : DG)
85- performTest (D);
86- return true ;
104+ TEST (Store, VariableBind) {
105+ EXPECT_TRUE (tooling::runToolOnCode (
106+ std::make_unique<TestAction<VariableBindConsumer>>(),
107+ " void foo() { int x0, y0, z0, x1, y1; }" ));
108+ }
109+
110+ class LiteralCompoundConsumer : public StoreTestConsumer {
111+ void performTest (const Decl *D) override {
112+ StoreManager &SManager = Eng.getStoreManager ();
113+ SValBuilder &Builder = Eng.getSValBuilder ();
114+ MemRegionManager &MRManager = SManager.getRegionManager ();
115+ ASTContext &ASTCtxt = Eng.getContext ();
116+
117+ using namespace ast_matchers ;
118+
119+ const auto *CL = findNode<CompoundLiteralExpr>(D, compoundLiteralExpr ());
120+
121+ const StackFrameContext *SFC =
122+ Eng.getAnalysisDeclContextManager ().getStackFrame (D);
123+
124+ QualType Int = ASTCtxt.IntTy ;
125+
126+ // Get region for 'test'
127+ const SubRegion *CLRegion = MRManager.getCompoundLiteralRegion (CL, SFC);
128+
129+ // Get value for 'test[0]'
130+ NonLoc Zero = Builder.makeIntVal (0 , false );
131+ loc::MemRegionVal ZeroElement (
132+ MRManager.getElementRegion (ASTCtxt.IntTy , Zero, CLRegion, ASTCtxt));
133+
134+ Store StInit = SManager.getInitialStore (SFC).getStore ();
135+ // Let's bind constant 1 to 'test[0]'
136+ SVal One = Builder.makeIntVal (1 , Int);
137+ Store StX = SManager.Bind (StInit, ZeroElement, One).getStore ();
138+
139+ // And make sure that we can read this binding back as it was
140+ EXPECT_EQ (One, SManager.getBinding (StX, ZeroElement, Int));
87141 }
88- };
89142
90- class VariableBindAction : public ASTFrontendAction {
91143public:
92- std::unique_ptr<ASTConsumer> CreateASTConsumer (CompilerInstance &Compiler,
93- StringRef File) override {
94- return std::make_unique<VariableBindConsumer>(Compiler);
95- }
144+ using StoreTestConsumer::StoreTestConsumer;
96145};
97146
98- TEST (Store, VariableBind) {
99- EXPECT_TRUE (tooling::runToolOnCode (std::make_unique<VariableBindAction>(),
100- " void foo() { int x0, y0, z0, x1, y1; }" ));
147+ TEST (Store, LiteralCompound) {
148+ EXPECT_TRUE (tooling::runToolOnCode (
149+ std::make_unique<TestAction<LiteralCompoundConsumer>>(),
150+ " void foo() { int *test = (int[]){ 1, 2, 3 }; }" , " input.c" ));
101151}
102152
103153} // namespace
0 commit comments