1 //===- GRCXXExprEngine.cpp - C++ expr evaluation engine ---------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file defines the C++ expression evaluation engine.
12 //===----------------------------------------------------------------------===//
14 #include "clang/Checker/PathSensitive/AnalysisManager.h"
15 #include "clang/Checker/PathSensitive/GRExprEngine.h"
16 #include "clang/AST/DeclCXX.h"
18 using namespace clang
;
21 class CallExprWLItem
{
23 CallExpr::const_arg_iterator I
;
26 CallExprWLItem(const CallExpr::const_arg_iterator
&i
, ExplodedNode
*n
)
31 void GRExprEngine::EvalArguments(ConstExprIterator AI
, ConstExprIterator AE
,
32 const FunctionProtoType
*FnType
,
33 ExplodedNode
*Pred
, ExplodedNodeSet
&Dst
) {
36 llvm::SmallVector
<CallExprWLItem
, 20> WorkList
;
37 WorkList
.reserve(AE
- AI
);
38 WorkList
.push_back(CallExprWLItem(AI
, Pred
));
40 while (!WorkList
.empty()) {
41 CallExprWLItem Item
= WorkList
.back();
49 // Evaluate the argument.
51 const unsigned ParamIdx
= Item
.I
- AI
;
52 const bool VisitAsLvalue
= FnType
&& ParamIdx
< FnType
->getNumArgs()
53 ? FnType
->getArgType(ParamIdx
)->isReferenceType()
57 VisitLValue(*Item
.I
, Item
.N
, Tmp
);
59 Visit(*Item
.I
, Item
.N
, Tmp
);
62 for (ExplodedNodeSet::iterator NI
=Tmp
.begin(), NE
=Tmp
.end(); NI
!= NE
; ++NI
)
63 WorkList
.push_back(CallExprWLItem(Item
.I
, *NI
));
67 const CXXThisRegion
*GRExprEngine::getCXXThisRegion(const CXXRecordDecl
*D
,
68 const StackFrameContext
*SFC
) {
69 Type
*T
= D
->getTypeForDecl();
70 QualType PT
= getContext().getPointerType(QualType(T
, 0));
71 return ValMgr
.getRegionManager().getCXXThisRegion(PT
, SFC
);
74 void GRExprEngine::CreateCXXTemporaryObject(const Expr
*Ex
, ExplodedNode
*Pred
,
75 ExplodedNodeSet
&Dst
) {
78 for (ExplodedNodeSet::iterator I
= Tmp
.begin(), E
= Tmp
.end(); I
!= E
; ++I
) {
79 const GRState
*state
= GetState(*I
);
81 // Bind the temporary object to the value of the expression. Then bind
82 // the expression to the location of the object.
83 SVal V
= state
->getSVal(Ex
);
86 ValMgr
.getRegionManager().getCXXObjectRegion(Ex
,
87 Pred
->getLocationContext());
89 state
= state
->bindLoc(loc::MemRegionVal(R
), V
);
90 MakeNode(Dst
, Ex
, Pred
, state
->BindExpr(Ex
, loc::MemRegionVal(R
)));
94 void GRExprEngine::VisitCXXConstructExpr(const CXXConstructExpr
*E
,
95 const MemRegion
*Dest
,
97 ExplodedNodeSet
&Dst
) {
99 Dest
= ValMgr
.getRegionManager().getCXXObjectRegion(E
,
100 Pred
->getLocationContext());
102 if (E
->isElidable()) {
103 VisitAggExpr(E
->getArg(0), Dest
, Pred
, Dst
);
107 const CXXConstructorDecl
*CD
= E
->getConstructor();
110 if (!(CD
->isThisDeclarationADefinition() && AMgr
.shouldInlineCall()))
111 // FIXME: invalidate the object.
115 // Evaluate other arguments.
116 ExplodedNodeSet ArgsEvaluated
;
117 const FunctionProtoType
*FnType
= CD
->getType()->getAs
<FunctionProtoType
>();
118 EvalArguments(E
->arg_begin(), E
->arg_end(), FnType
, Pred
, ArgsEvaluated
);
119 // The callee stack frame context used to create the 'this' parameter region.
120 const StackFrameContext
*SFC
= AMgr
.getStackFrame(CD
,
121 Pred
->getLocationContext(),
122 E
, Builder
->getBlock(), Builder
->getIndex());
124 const CXXThisRegion
*ThisR
=getCXXThisRegion(E
->getConstructor()->getParent(),
127 CallEnter
Loc(E
, SFC
->getAnalysisContext(), Pred
->getLocationContext());
128 for (ExplodedNodeSet::iterator NI
= ArgsEvaluated
.begin(),
129 NE
= ArgsEvaluated
.end(); NI
!= NE
; ++NI
) {
130 const GRState
*state
= GetState(*NI
);
131 // Setup 'this' region, so that the ctor is evaluated on the object pointed
133 state
= state
->bindLoc(loc::MemRegionVal(ThisR
), loc::MemRegionVal(Dest
));
134 ExplodedNode
*N
= Builder
->generateNode(Loc
, state
, Pred
);
140 void GRExprEngine::VisitCXXMemberCallExpr(const CXXMemberCallExpr
*MCE
,
142 ExplodedNodeSet
&Dst
) {
143 // Get the method type.
144 const FunctionProtoType
*FnType
=
145 MCE
->getCallee()->getType()->getAs
<FunctionProtoType
>();
146 assert(FnType
&& "Method type not available");
148 // Evaluate explicit arguments with a worklist.
149 ExplodedNodeSet ArgsEvaluated
;
150 EvalArguments(MCE
->arg_begin(), MCE
->arg_end(), FnType
, Pred
, ArgsEvaluated
);
152 // Evaluate the implicit object argument.
153 ExplodedNodeSet AllArgsEvaluated
;
154 const MemberExpr
*ME
= dyn_cast
<MemberExpr
>(MCE
->getCallee()->IgnoreParens());
157 Expr
*ObjArgExpr
= ME
->getBase();
158 for (ExplodedNodeSet::iterator I
= ArgsEvaluated
.begin(),
159 E
= ArgsEvaluated
.end(); I
!= E
; ++I
) {
161 Visit(ObjArgExpr
, *I
, AllArgsEvaluated
);
163 VisitLValue(ObjArgExpr
, *I
, AllArgsEvaluated
);
166 // Allow checkers to pre-visit the member call.
167 ExplodedNodeSet PreVisitChecks
;
168 CheckerVisit(MCE
, PreVisitChecks
, AllArgsEvaluated
, PreVisitStmtCallback
);
170 // Now evaluate the call itself.
171 const CXXMethodDecl
*MD
= cast
<CXXMethodDecl
>(ME
->getMemberDecl());
172 assert(MD
&& "not a CXXMethodDecl?");
174 if (!(MD
->isThisDeclarationADefinition() && AMgr
.shouldInlineCall())) {
175 // FIXME: conservative method call evaluation.
176 CheckerVisit(MCE
, Dst
, PreVisitChecks
, PostVisitStmtCallback
);
180 ExplodedNodeSet SetupThis
;
181 const StackFrameContext
*SFC
= AMgr
.getStackFrame(MD
,
182 Pred
->getLocationContext(),
185 Builder
->getIndex());
186 const CXXThisRegion
*ThisR
= getCXXThisRegion(MD
->getParent(), SFC
);
187 CallEnter
Loc(MCE
, SFC
->getAnalysisContext(), Pred
->getLocationContext());
188 for (ExplodedNodeSet::iterator I
= PreVisitChecks
.begin(),
189 E
= PreVisitChecks
.end(); I
!= E
; ++I
) {
190 // Set up 'this' region.
191 const GRState
*state
= GetState(*I
);
192 state
= state
->bindLoc(loc::MemRegionVal(ThisR
),state
->getSVal(ObjArgExpr
));
193 SetupThis
.Add(Builder
->generateNode(Loc
, state
, *I
));
196 // FIXME: Perform the actual method call. Right now all we do is evaluate
199 // Perform post-visit.
200 CheckerVisit(MCE
, Dst
, /* FIXME: don't forget to update later */ SetupThis
,
201 PostVisitStmtCallback
);
204 void GRExprEngine::VisitCXXNewExpr(const CXXNewExpr
*CNE
, ExplodedNode
*Pred
,
205 ExplodedNodeSet
&Dst
) {
206 if (CNE
->isArray()) {
207 // FIXME: allocating an array has not been handled.
211 unsigned Count
= Builder
->getCurrentBlockCount();
212 DefinedOrUnknownSVal SymVal
= getValueManager().getConjuredSymbolVal(NULL
,CNE
,
213 CNE
->getType(), Count
);
214 const MemRegion
*NewReg
= cast
<loc::MemRegionVal
>(SymVal
).getRegion();
216 QualType ObjTy
= CNE
->getType()->getAs
<PointerType
>()->getPointeeType();
218 const ElementRegion
*EleReg
=
219 getStoreManager().GetElementZeroRegion(NewReg
, ObjTy
);
221 // Evaluate constructor arguments.
222 const FunctionProtoType
*FnType
= NULL
;
223 const CXXConstructorDecl
*CD
= CNE
->getConstructor();
225 FnType
= CD
->getType()->getAs
<FunctionProtoType
>();
226 ExplodedNodeSet ArgsEvaluated
;
227 EvalArguments(CNE
->constructor_arg_begin(), CNE
->constructor_arg_end(),
228 FnType
, Pred
, ArgsEvaluated
);
230 // Initialize the object region and bind the 'new' expression.
231 for (ExplodedNodeSet::iterator I
= ArgsEvaluated
.begin(),
232 E
= ArgsEvaluated
.end(); I
!= E
; ++I
) {
233 const GRState
*state
= GetState(*I
);
235 if (ObjTy
->isRecordType()) {
236 state
= state
->InvalidateRegion(EleReg
, CNE
, Count
);
238 if (CNE
->hasInitializer()) {
239 SVal V
= state
->getSVal(*CNE
->constructor_arg_begin());
240 state
= state
->bindLoc(loc::MemRegionVal(EleReg
), V
);
242 // Explicitly set to undefined, because currently we retrieve symbolic
243 // value from symbolic region.
244 state
= state
->bindLoc(loc::MemRegionVal(EleReg
), UndefinedVal());
247 state
= state
->BindExpr(CNE
, loc::MemRegionVal(EleReg
));
248 MakeNode(Dst
, CNE
, *I
, state
);
252 void GRExprEngine::VisitCXXDeleteExpr(const CXXDeleteExpr
*CDE
,
253 ExplodedNode
*Pred
,ExplodedNodeSet
&Dst
) {
254 // Should do more checking.
255 ExplodedNodeSet ArgEvaluated
;
256 Visit(CDE
->getArgument(), Pred
, ArgEvaluated
);
257 for (ExplodedNodeSet::iterator I
= ArgEvaluated
.begin(),
258 E
= ArgEvaluated
.end(); I
!= E
; ++I
) {
259 const GRState
*state
= GetState(*I
);
260 MakeNode(Dst
, CDE
, *I
, state
);
264 void GRExprEngine::VisitCXXThisExpr(const CXXThisExpr
*TE
, ExplodedNode
*Pred
,
265 ExplodedNodeSet
&Dst
) {
266 // Get the this object region from StoreManager.
268 ValMgr
.getRegionManager().getCXXThisRegion(
269 getContext().getCanonicalType(TE
->getType()),
270 Pred
->getLocationContext());
272 const GRState
*state
= GetState(Pred
);
273 SVal V
= state
->getSVal(loc::MemRegionVal(R
));
274 MakeNode(Dst
, TE
, Pred
, state
->BindExpr(TE
, V
));