Handle member initializer in C++ ctor.
[clang.git] / lib / Checker / GRCXXExprEngine.cpp
blob072c21e721873c6a48d8c4d99eb98967dd57a82c
1 //===- GRCXXExprEngine.cpp - C++ expr evaluation engine ---------*- C++ -*-===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
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;
20 namespace {
21 class CallExprWLItem {
22 public:
23 CallExpr::const_arg_iterator I;
24 ExplodedNode *N;
26 CallExprWLItem(const CallExpr::const_arg_iterator &i, ExplodedNode *n)
27 : I(i), N(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();
42 WorkList.pop_back();
44 if (Item.I == AE) {
45 Dst.insert(Item.N);
46 continue;
49 // Evaluate the argument.
50 ExplodedNodeSet Tmp;
51 const unsigned ParamIdx = Item.I - AI;
52 const bool VisitAsLvalue = FnType && ParamIdx < FnType->getNumArgs()
53 ? FnType->getArgType(ParamIdx)->isReferenceType()
54 : false;
56 if (VisitAsLvalue)
57 VisitLValue(*Item.I, Item.N, Tmp);
58 else
59 Visit(*Item.I, Item.N, Tmp);
61 ++(Item.I);
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) {
76 ExplodedNodeSet Tmp;
77 Visit(Ex, Pred, Tmp);
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);
85 const MemRegion *R =
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,
96 ExplodedNode *Pred,
97 ExplodedNodeSet &Dst) {
98 if (!Dest)
99 Dest = ValMgr.getRegionManager().getCXXObjectRegion(E,
100 Pred->getLocationContext());
102 if (E->isElidable()) {
103 VisitAggExpr(E->getArg(0), Dest, Pred, Dst);
104 return;
107 const CXXConstructorDecl *CD = E->getConstructor();
108 assert(CD);
110 if (!(CD->isThisDeclarationADefinition() && AMgr.shouldInlineCall()))
111 // FIXME: invalidate the object.
112 return;
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(),
125 SFC);
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
132 // by 'Dest'.
133 state = state->bindLoc(loc::MemRegionVal(ThisR), loc::MemRegionVal(Dest));
134 ExplodedNode *N = Builder->generateNode(Loc, state, Pred);
135 if (N)
136 Dst.Add(N);
140 void GRExprEngine::VisitCXXMemberCallExpr(const CXXMemberCallExpr *MCE,
141 ExplodedNode *Pred,
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());
155 if (!ME)
156 return;
157 Expr *ObjArgExpr = ME->getBase();
158 for (ExplodedNodeSet::iterator I = ArgsEvaluated.begin(),
159 E = ArgsEvaluated.end(); I != E; ++I) {
160 if (ME->isArrow())
161 Visit(ObjArgExpr, *I, AllArgsEvaluated);
162 else
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);
177 return;
180 ExplodedNodeSet SetupThis;
181 const StackFrameContext *SFC = AMgr.getStackFrame(MD,
182 Pred->getLocationContext(),
183 MCE,
184 Builder->getBlock(),
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
197 // the arguments.
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.
208 return;
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();
224 if (CD)
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);
237 } else {
238 if (CNE->hasInitializer()) {
239 SVal V = state->getSVal(*CNE->constructor_arg_begin());
240 state = state->bindLoc(loc::MemRegionVal(EleReg), V);
241 } else {
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.
267 const MemRegion *R =
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));