blob: a49989b5fda547fee205573b308747554c6050c2 [file] [log] [blame]
Zhongxing Xucb7464a2010-04-19 12:51:02 +00001//===- 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.
11//
12//===----------------------------------------------------------------------===//
13
14#include "clang/Checker/PathSensitive/AnalysisManager.h"
15#include "clang/Checker/PathSensitive/GRExprEngine.h"
16#include "clang/AST/DeclCXX.h"
17
18using namespace clang;
19
Zhongxing Xu03509ae2010-07-20 06:22:24 +000020void GRExprEngine::EvalArguments(ConstExprIterator AI, ConstExprIterator AE,
Zhongxing Xub17b1b32010-04-20 03:37:34 +000021 const FunctionProtoType *FnType,
22 ExplodedNode *Pred, ExplodedNodeSet &Dst) {
23 llvm::SmallVector<CallExprWLItem, 20> WorkList;
24 WorkList.reserve(AE - AI);
25 WorkList.push_back(CallExprWLItem(AI, Pred));
26
27 while (!WorkList.empty()) {
28 CallExprWLItem Item = WorkList.back();
29 WorkList.pop_back();
30
31 if (Item.I == AE) {
32 Dst.insert(Item.N);
33 continue;
34 }
35
36 ExplodedNodeSet Tmp;
37 const unsigned ParamIdx = Item.I - AI;
38 bool VisitAsLvalue = FnType? FnType->getArgType(ParamIdx)->isReferenceType()
39 : false;
40 if (VisitAsLvalue)
41 VisitLValue(*Item.I, Item.N, Tmp);
42 else
43 Visit(*Item.I, Item.N, Tmp);
44
45 ++(Item.I);
46 for (ExplodedNodeSet::iterator NI=Tmp.begin(), NE=Tmp.end(); NI != NE; ++NI)
47 WorkList.push_back(CallExprWLItem(Item.I, *NI));
48 }
49}
50
Zhongxing Xucb7464a2010-04-19 12:51:02 +000051const CXXThisRegion *GRExprEngine::getCXXThisRegion(const CXXMethodDecl *D,
52 const StackFrameContext *SFC) {
53 Type *T = D->getParent()->getTypeForDecl();
54 QualType PT = getContext().getPointerType(QualType(T,0));
55 return ValMgr.getRegionManager().getCXXThisRegion(PT, SFC);
56}
57
Zhongxing Xu03509ae2010-07-20 06:22:24 +000058void GRExprEngine::CreateCXXTemporaryObject(const Expr *Ex, ExplodedNode *Pred,
Zhongxing Xucb7464a2010-04-19 12:51:02 +000059 ExplodedNodeSet &Dst) {
60 ExplodedNodeSet Tmp;
61 Visit(Ex, Pred, Tmp);
62 for (ExplodedNodeSet::iterator I = Tmp.begin(), E = Tmp.end(); I != E; ++I) {
63 const GRState *state = GetState(*I);
64
65 // Bind the temporary object to the value of the expression. Then bind
66 // the expression to the location of the object.
67 SVal V = state->getSVal(Ex);
68
69 const MemRegion *R =
70 ValMgr.getRegionManager().getCXXObjectRegion(Ex,
71 Pred->getLocationContext());
72
73 state = state->bindLoc(loc::MemRegionVal(R), V);
74 MakeNode(Dst, Ex, Pred, state->BindExpr(Ex, loc::MemRegionVal(R)));
75 }
76}
77
78void GRExprEngine::VisitCXXConstructExpr(const CXXConstructExpr *E, SVal Dest,
79 ExplodedNode *Pred,
80 ExplodedNodeSet &Dst) {
81 if (E->isElidable()) {
82 VisitAggExpr(E->getArg(0), Dest, Pred, Dst);
83 return;
84 }
85
86 const CXXConstructorDecl *CD = E->getConstructor();
87 assert(CD);
88
Zhongxing Xu7b99d122010-05-06 02:59:29 +000089 if (!(CD->isThisDeclarationADefinition() && AMgr.shouldInlineCall()))
Zhongxing Xucb7464a2010-04-19 12:51:02 +000090 // FIXME: invalidate the object.
91 return;
92
93
94 // Evaluate other arguments.
Zhongxing Xucb7464a2010-04-19 12:51:02 +000095 ExplodedNodeSet ArgsEvaluated;
Zhongxing Xu107ccd12010-04-20 05:40:40 +000096 const FunctionProtoType *FnType = CD->getType()->getAs<FunctionProtoType>();
Zhongxing Xu03509ae2010-07-20 06:22:24 +000097 EvalArguments(E->arg_begin(), E->arg_end(), FnType, Pred, ArgsEvaluated);
Zhongxing Xucb7464a2010-04-19 12:51:02 +000098 // The callee stack frame context used to create the 'this' parameter region.
99 const StackFrameContext *SFC = AMgr.getStackFrame(CD,
100 Pred->getLocationContext(),
101 E, Builder->getBlock(), Builder->getIndex());
102
103 const CXXThisRegion *ThisR = getCXXThisRegion(E->getConstructor(), SFC);
104
Zhongxing Xuc6238d22010-07-19 01:31:21 +0000105 CallEnter Loc(E, SFC->getAnalysisContext(), Pred->getLocationContext());
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000106 for (ExplodedNodeSet::iterator NI = ArgsEvaluated.begin(),
107 NE = ArgsEvaluated.end(); NI != NE; ++NI) {
108 const GRState *state = GetState(*NI);
Zhongxing Xu3bf185b2010-08-24 04:26:55 +0000109 // Setup 'this' region, so that the ctor is evaluated on the object pointed
110 // by 'Dest'.
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000111 state = state->bindLoc(loc::MemRegionVal(ThisR), Dest);
112 ExplodedNode *N = Builder->generateNode(Loc, state, Pred);
113 if (N)
114 Dst.Add(N);
115 }
116}
117
118void GRExprEngine::VisitCXXMemberCallExpr(const CXXMemberCallExpr *MCE,
119 ExplodedNode *Pred,
120 ExplodedNodeSet &Dst) {
121 // Get the method type.
122 const FunctionProtoType *FnType =
123 MCE->getCallee()->getType()->getAs<FunctionProtoType>();
124 assert(FnType && "Method type not available");
125
126 // Evaluate explicit arguments with a worklist.
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000127 ExplodedNodeSet ArgsEvaluated;
Zhongxing Xu03509ae2010-07-20 06:22:24 +0000128 EvalArguments(MCE->arg_begin(), MCE->arg_end(), FnType, Pred, ArgsEvaluated);
Zhongxing Xu107ccd12010-04-20 05:40:40 +0000129
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000130 // Evaluate the implicit object argument.
131 ExplodedNodeSet AllArgsEvaluated;
132 const MemberExpr *ME = dyn_cast<MemberExpr>(MCE->getCallee()->IgnoreParens());
133 if (!ME)
134 return;
135 Expr *ObjArgExpr = ME->getBase();
136 for (ExplodedNodeSet::iterator I = ArgsEvaluated.begin(),
137 E = ArgsEvaluated.end(); I != E; ++I) {
138 if (ME->isArrow())
139 Visit(ObjArgExpr, *I, AllArgsEvaluated);
140 else
141 VisitLValue(ObjArgExpr, *I, AllArgsEvaluated);
142 }
143
144 const CXXMethodDecl *MD = cast<CXXMethodDecl>(ME->getMemberDecl());
145 assert(MD && "not a CXXMethodDecl?");
146
Zhongxing Xu7b99d122010-05-06 02:59:29 +0000147 if (!(MD->isThisDeclarationADefinition() && AMgr.shouldInlineCall()))
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000148 // FIXME: conservative method call evaluation.
149 return;
150
151 const StackFrameContext *SFC = AMgr.getStackFrame(MD,
152 Pred->getLocationContext(),
153 MCE,
154 Builder->getBlock(),
155 Builder->getIndex());
156 const CXXThisRegion *ThisR = getCXXThisRegion(MD, SFC);
Zhongxing Xuc6238d22010-07-19 01:31:21 +0000157 CallEnter Loc(MCE, SFC->getAnalysisContext(), Pred->getLocationContext());
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000158 for (ExplodedNodeSet::iterator I = AllArgsEvaluated.begin(),
159 E = AllArgsEvaluated.end(); I != E; ++I) {
160 // Set up 'this' region.
161 const GRState *state = GetState(*I);
162 state = state->bindLoc(loc::MemRegionVal(ThisR),state->getSVal(ObjArgExpr));
163 ExplodedNode *N = Builder->generateNode(Loc, state, *I);
164 if (N)
165 Dst.Add(N);
166 }
167}
168
Zhongxing Xu03509ae2010-07-20 06:22:24 +0000169void GRExprEngine::VisitCXXNewExpr(const CXXNewExpr *CNE, ExplodedNode *Pred,
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000170 ExplodedNodeSet &Dst) {
171 if (CNE->isArray()) {
172 // FIXME: allocating an array has not been handled.
173 return;
174 }
175
176 unsigned Count = Builder->getCurrentBlockCount();
Zhongxing Xu03509ae2010-07-20 06:22:24 +0000177 DefinedOrUnknownSVal SymVal = getValueManager().getConjuredSymbolVal(NULL,CNE,
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000178 CNE->getType(), Count);
179 const MemRegion *NewReg = cast<loc::MemRegionVal>(SymVal).getRegion();
180
181 QualType ObjTy = CNE->getType()->getAs<PointerType>()->getPointeeType();
182
183 const ElementRegion *EleReg =
184 getStoreManager().GetElementZeroRegion(NewReg, ObjTy);
185
Zhongxing Xub17b1b32010-04-20 03:37:34 +0000186 // Evaluate constructor arguments.
187 const FunctionProtoType *FnType = NULL;
188 const CXXConstructorDecl *CD = CNE->getConstructor();
189 if (CD)
190 FnType = CD->getType()->getAs<FunctionProtoType>();
191 ExplodedNodeSet ArgsEvaluated;
192 EvalArguments(CNE->constructor_arg_begin(), CNE->constructor_arg_end(),
193 FnType, Pred, ArgsEvaluated);
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000194
Zhongxing Xub17b1b32010-04-20 03:37:34 +0000195 // Initialize the object region and bind the 'new' expression.
196 for (ExplodedNodeSet::iterator I = ArgsEvaluated.begin(),
197 E = ArgsEvaluated.end(); I != E; ++I) {
198 const GRState *state = GetState(*I);
199
200 if (ObjTy->isRecordType()) {
Jordy Roseff59efd2010-08-03 20:44:35 +0000201 state = state->InvalidateRegion(EleReg, CNE, Count);
Zhongxing Xub17b1b32010-04-20 03:37:34 +0000202 } else {
203 if (CNE->hasInitializer()) {
204 SVal V = state->getSVal(*CNE->constructor_arg_begin());
205 state = state->bindLoc(loc::MemRegionVal(EleReg), V);
206 } else {
207 // Explicitly set to undefined, because currently we retrieve symbolic
208 // value from symbolic region.
209 state = state->bindLoc(loc::MemRegionVal(EleReg), UndefinedVal());
210 }
211 }
212 state = state->BindExpr(CNE, loc::MemRegionVal(EleReg));
Zhongxing Xu978b9352010-04-21 02:20:10 +0000213 MakeNode(Dst, CNE, *I, state);
Zhongxing Xub17b1b32010-04-20 03:37:34 +0000214 }
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000215}
216
Zhongxing Xu03509ae2010-07-20 06:22:24 +0000217void GRExprEngine::VisitCXXDeleteExpr(const CXXDeleteExpr *CDE,
218 ExplodedNode *Pred,ExplodedNodeSet &Dst) {
Zhongxing Xu6b851382010-04-21 02:17:31 +0000219 // Should do more checking.
220 ExplodedNodeSet ArgEvaluated;
221 Visit(CDE->getArgument(), Pred, ArgEvaluated);
222 for (ExplodedNodeSet::iterator I = ArgEvaluated.begin(),
223 E = ArgEvaluated.end(); I != E; ++I) {
224 const GRState *state = GetState(*I);
225 MakeNode(Dst, CDE, *I, state);
226 }
227}
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000228
Zhongxing Xu03509ae2010-07-20 06:22:24 +0000229void GRExprEngine::VisitCXXThisExpr(const CXXThisExpr *TE, ExplodedNode *Pred,
Zhongxing Xu6b851382010-04-21 02:17:31 +0000230 ExplodedNodeSet &Dst) {
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000231 // Get the this object region from StoreManager.
232 const MemRegion *R =
233 ValMgr.getRegionManager().getCXXThisRegion(
234 getContext().getCanonicalType(TE->getType()),
235 Pred->getLocationContext());
236
237 const GRState *state = GetState(Pred);
238 SVal V = state->getSVal(loc::MemRegionVal(R));
239 MakeNode(Dst, TE, Pred, state->BindExpr(TE, V));
240}