1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | #include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h" |
14 | #include "clang/Analysis/ConstructionContext.h" |
15 | #include "clang/AST/DeclCXX.h" |
16 | #include "clang/AST/StmtCXX.h" |
17 | #include "clang/AST/ParentMap.h" |
18 | #include "clang/Basic/PrettyStackTrace.h" |
19 | #include "clang/StaticAnalyzer/Core/CheckerManager.h" |
20 | #include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h" |
21 | #include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h" |
22 | |
23 | using namespace clang; |
24 | using namespace ento; |
25 | |
26 | void ExprEngine::CreateCXXTemporaryObject(const MaterializeTemporaryExpr *ME, |
27 | ExplodedNode *Pred, |
28 | ExplodedNodeSet &Dst) { |
29 | StmtNodeBuilder Bldr(Pred, Dst, *currBldrCtx); |
30 | const Expr *tempExpr = ME->GetTemporaryExpr()->IgnoreParens(); |
31 | ProgramStateRef state = Pred->getState(); |
32 | const LocationContext *LCtx = Pred->getLocationContext(); |
33 | |
34 | state = createTemporaryRegionIfNeeded(state, LCtx, tempExpr, ME); |
35 | Bldr.generateNode(ME, Pred, state); |
36 | } |
37 | |
38 | |
39 | |
40 | void ExprEngine::performTrivialCopy(NodeBuilder &Bldr, ExplodedNode *Pred, |
41 | const CallEvent &Call) { |
42 | SVal ThisVal; |
43 | bool AlwaysReturnsLValue; |
44 | const CXXRecordDecl *ThisRD = nullptr; |
45 | if (const CXXConstructorCall *Ctor = dyn_cast<CXXConstructorCall>(&Call)) { |
46 | getDecl()->isTrivial()", "/home/seafit/code_projects/clang_source/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp", 46, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert(Ctor->getDecl()->isTrivial()); |
47 | getDecl()->isCopyOrMoveConstructor()", "/home/seafit/code_projects/clang_source/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp", 47, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert(Ctor->getDecl()->isCopyOrMoveConstructor()); |
48 | ThisVal = Ctor->getCXXThisVal(); |
49 | ThisRD = Ctor->getDecl()->getParent(); |
50 | AlwaysReturnsLValue = false; |
51 | } else { |
52 | (Call.getDecl())->isTrivial()", "/home/seafit/code_projects/clang_source/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp", 52, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert(cast<CXXMethodDecl>(Call.getDecl())->isTrivial()); |
53 | (Call.getDecl())->getOverloadedOperator() == OO_Equal", "/home/seafit/code_projects/clang_source/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp", 54, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert(cast<CXXMethodDecl>(Call.getDecl())->getOverloadedOperator() == |
54 | (Call.getDecl())->getOverloadedOperator() == OO_Equal", "/home/seafit/code_projects/clang_source/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp", 54, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true"> OO_Equal); |
55 | ThisVal = cast<CXXInstanceCall>(Call).getCXXThisVal(); |
56 | ThisRD = cast<CXXMethodDecl>(Call.getDecl())->getParent(); |
57 | AlwaysReturnsLValue = true; |
58 | } |
59 | |
60 | assert(ThisRD); |
61 | if (ThisRD->isEmpty()) { |
62 | |
63 | |
64 | |
65 | return; |
66 | } |
67 | |
68 | const LocationContext *LCtx = Pred->getLocationContext(); |
69 | |
70 | ExplodedNodeSet Dst; |
71 | Bldr.takeNodes(Pred); |
72 | |
73 | SVal V = Call.getArgSVal(0); |
74 | |
75 | |
76 | |
77 | if (Optional<Loc> L = V.getAs<Loc>()) |
78 | V = Pred->getState()->getSVal(*L); |
79 | else |
80 | assert(V.isUnknownOrUndef()); |
81 | |
82 | const Expr *CallExpr = Call.getOriginExpr(); |
83 | evalBind(Dst, CallExpr, Pred, ThisVal, V, true); |
84 | |
85 | PostStmt PS(CallExpr, LCtx); |
86 | for (ExplodedNodeSet::iterator I = Dst.begin(), E = Dst.end(); |
87 | I != E; ++I) { |
88 | ProgramStateRef State = (*I)->getState(); |
89 | if (AlwaysReturnsLValue) |
90 | State = State->BindExpr(CallExpr, LCtx, ThisVal); |
91 | else |
92 | State = bindReturnValue(Call, LCtx, State); |
93 | Bldr.generateNode(PS, State, *I); |
94 | } |
95 | } |
96 | |
97 | |
98 | SVal ExprEngine::makeZeroElementRegion(ProgramStateRef State, SVal LValue, |
99 | QualType &Ty, bool &IsArray) { |
100 | SValBuilder &SVB = State->getStateManager().getSValBuilder(); |
101 | ASTContext &Ctx = SVB.getContext(); |
102 | |
103 | while (const ArrayType *AT = Ctx.getAsArrayType(Ty)) { |
104 | Ty = AT->getElementType(); |
105 | LValue = State->getLValue(Ty, SVB.makeZeroArrayIndex(), LValue); |
106 | IsArray = true; |
107 | } |
108 | |
109 | return LValue; |
110 | } |
111 | |
112 | std::pair<ProgramStateRef, SVal> ExprEngine::prepareForObjectConstruction( |
113 | const Expr *E, ProgramStateRef State, const LocationContext *LCtx, |
114 | const ConstructionContext *CC, EvalCallOptions &CallOpts) { |
115 | SValBuilder &SVB = getSValBuilder(); |
116 | MemRegionManager &MRMgr = SVB.getRegionManager(); |
117 | ASTContext &ACtx = SVB.getContext(); |
118 | |
119 | |
120 | |
121 | if (CC) { |
122 | switch (CC->getKind()) { |
123 | case ConstructionContext::CXX17ElidedCopyVariableKind: |
124 | case ConstructionContext::SimpleVariableKind: { |
125 | const auto *DSCC = cast<VariableConstructionContext>(CC); |
126 | const auto *DS = DSCC->getDeclStmt(); |
127 | const auto *Var = cast<VarDecl>(DS->getSingleDecl()); |
128 | SVal LValue = State->getLValue(Var, LCtx); |
129 | QualType Ty = Var->getType(); |
130 | LValue = |
131 | makeZeroElementRegion(State, LValue, Ty, CallOpts.IsArrayCtorOrDtor); |
132 | State = |
133 | addObjectUnderConstruction(State, DSCC->getDeclStmt(), LCtx, LValue); |
134 | return std::make_pair(State, LValue); |
135 | } |
136 | case ConstructionContext::CXX17ElidedCopyConstructorInitializerKind: |
137 | case ConstructionContext::SimpleConstructorInitializerKind: { |
138 | const auto *ICC = cast<ConstructorInitializerConstructionContext>(CC); |
139 | const auto *Init = ICC->getCXXCtorInitializer(); |
140 | isAnyMemberInitializer()", "/home/seafit/code_projects/clang_source/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp", 140, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert(Init->isAnyMemberInitializer()); |
141 | const CXXMethodDecl *CurCtor = cast<CXXMethodDecl>(LCtx->getDecl()); |
142 | Loc ThisPtr = |
143 | SVB.getCXXThis(CurCtor, LCtx->getStackFrame()); |
144 | SVal ThisVal = State->getSVal(ThisPtr); |
145 | |
146 | const ValueDecl *Field; |
147 | SVal FieldVal; |
148 | if (Init->isIndirectMemberInitializer()) { |
149 | Field = Init->getIndirectMember(); |
150 | FieldVal = State->getLValue(Init->getIndirectMember(), ThisVal); |
151 | } else { |
152 | Field = Init->getMember(); |
153 | FieldVal = State->getLValue(Init->getMember(), ThisVal); |
154 | } |
155 | |
156 | QualType Ty = Field->getType(); |
157 | FieldVal = makeZeroElementRegion(State, FieldVal, Ty, |
158 | CallOpts.IsArrayCtorOrDtor); |
159 | State = addObjectUnderConstruction(State, Init, LCtx, FieldVal); |
160 | return std::make_pair(State, FieldVal); |
161 | } |
162 | case ConstructionContext::NewAllocatedObjectKind: { |
163 | if (AMgr.getAnalyzerOptions().MayInlineCXXAllocator) { |
164 | const auto *NECC = cast<NewAllocatedObjectConstructionContext>(CC); |
165 | const auto *NE = NECC->getCXXNewExpr(); |
166 | SVal V = *getObjectUnderConstruction(State, NE, LCtx); |
167 | if (const SubRegion *MR = |
168 | dyn_cast_or_null<SubRegion>(V.getAsRegion())) { |
169 | if (NE->isArray()) { |
170 | |
171 | |
172 | CallOpts.IsArrayCtorOrDtor = true; |
173 | return std::make_pair( |
174 | State, loc::MemRegionVal(getStoreManager().GetElementZeroRegion( |
175 | MR, NE->getType()->getPointeeType()))); |
176 | } |
177 | return std::make_pair(State, V); |
178 | } |
179 | |
180 | |
181 | } |
182 | break; |
183 | } |
184 | case ConstructionContext::SimpleReturnedValueKind: |
185 | case ConstructionContext::CXX17ElidedCopyReturnedValueKind: { |
186 | |
187 | |
188 | |
189 | const StackFrameContext *SFC = LCtx->getStackFrame(); |
190 | if (const LocationContext *CallerLCtx = SFC->getParent()) { |
191 | auto RTC = (*SFC->getCallSiteBlock())[SFC->getIndex()] |
192 | .getAs<CFGCXXRecordTypedCall>(); |
193 | if (!RTC) { |
194 | |
195 | |
196 | |
197 | break; |
198 | } |
199 | return prepareForObjectConstruction( |
200 | cast<Expr>(SFC->getCallSite()), State, CallerLCtx, |
201 | RTC->getConstructionContext(), CallOpts); |
202 | } else { |
203 | |
204 | |
205 | |
206 | |
207 | |
208 | |
209 | |
210 | |
211 | |
212 | const auto *RCC = cast<ReturnedValueConstructionContext>(CC); |
213 | |
214 | |
215 | static const int TopLevelSymRegionTag = 0; |
216 | const Expr *RetE = RCC->getReturnStmt()->getRetValue(); |
217 | (0) . __assert_fail ("RetE && \"Void returns should not have a construction context\"", "/home/seafit/code_projects/clang_source/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp", 217, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert(RetE && "Void returns should not have a construction context"); |
218 | QualType ReturnTy = RetE->getType(); |
219 | QualType RegionTy = ACtx.getPointerType(ReturnTy); |
220 | SVal V = SVB.conjureSymbolVal(&TopLevelSymRegionTag, RetE, SFC, |
221 | RegionTy, currBldrCtx->blockCount()); |
222 | return std::make_pair(State, V); |
223 | } |
224 | llvm_unreachable("Unhandled return value construction context!"); |
225 | } |
226 | case ConstructionContext::ElidedTemporaryObjectKind: { |
227 | assert(AMgr.getAnalyzerOptions().ShouldElideConstructors); |
228 | const auto *TCC = cast<ElidedTemporaryObjectConstructionContext>(CC); |
229 | const CXXBindTemporaryExpr *BTE = TCC->getCXXBindTemporaryExpr(); |
230 | const MaterializeTemporaryExpr *MTE = TCC->getMaterializedTemporaryExpr(); |
231 | const CXXConstructExpr *CE = TCC->getConstructorAfterElision(); |
232 | |
233 | |
234 | |
235 | |
236 | |
237 | SVal V; |
238 | |
239 | |
240 | |
241 | ProgramStateRef PreElideState = State; |
242 | EvalCallOptions PreElideCallOpts = CallOpts; |
243 | |
244 | std::tie(State, V) = prepareForObjectConstruction( |
245 | CE, State, LCtx, TCC->getConstructionContextAfterElision(), CallOpts); |
246 | |
247 | |
248 | |
249 | |
250 | if (!CallOpts.IsCtorOrDtorWithImproperlyModeledTargetRegion) { |
251 | |
252 | State = addObjectUnderConstruction(State, CE, LCtx, V); |
253 | |
254 | |
255 | if (BTE) |
256 | State = elideDestructor(State, BTE, LCtx); |
257 | |
258 | |
259 | |
260 | if (MTE) |
261 | State = addObjectUnderConstruction(State, MTE, LCtx, V); |
262 | |
263 | return std::make_pair(State, V); |
264 | } else { |
265 | |
266 | |
267 | State = PreElideState; |
268 | CallOpts = PreElideCallOpts; |
269 | } |
270 | LLVM_FALLTHROUGH; |
271 | } |
272 | case ConstructionContext::SimpleTemporaryObjectKind: { |
273 | const auto *TCC = cast<TemporaryObjectConstructionContext>(CC); |
274 | const CXXBindTemporaryExpr *BTE = TCC->getCXXBindTemporaryExpr(); |
275 | const MaterializeTemporaryExpr *MTE = TCC->getMaterializedTemporaryExpr(); |
276 | SVal V = UnknownVal(); |
277 | |
278 | if (MTE) { |
279 | if (const ValueDecl *VD = MTE->getExtendingDecl()) { |
280 | getStorageDuration() != SD_FullExpression", "/home/seafit/code_projects/clang_source/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp", 280, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert(MTE->getStorageDuration() != SD_FullExpression); |
281 | if (!VD->getType()->isReferenceType()) { |
282 | |
283 | |
284 | |
285 | |
286 | |
287 | CallOpts.IsTemporaryLifetimeExtendedViaAggregate = true; |
288 | } |
289 | } |
290 | |
291 | if (MTE->getStorageDuration() == SD_Static || |
292 | MTE->getStorageDuration() == SD_Thread) |
293 | V = loc::MemRegionVal(MRMgr.getCXXStaticTempObjectRegion(E)); |
294 | } |
295 | |
296 | if (V.isUnknown()) |
297 | V = loc::MemRegionVal(MRMgr.getCXXTempObjectRegion(E, LCtx)); |
298 | |
299 | if (BTE) |
300 | State = addObjectUnderConstruction(State, BTE, LCtx, V); |
301 | |
302 | if (MTE) |
303 | State = addObjectUnderConstruction(State, MTE, LCtx, V); |
304 | |
305 | CallOpts.IsTemporaryCtorOrDtor = true; |
306 | return std::make_pair(State, V); |
307 | } |
308 | case ConstructionContext::ArgumentKind: { |
309 | |
310 | CallOpts.IsTemporaryCtorOrDtor = true; |
311 | |
312 | const auto *ACC = cast<ArgumentConstructionContext>(CC); |
313 | const Expr *E = ACC->getCallLikeExpr(); |
314 | unsigned Idx = ACC->getIndex(); |
315 | const CXXBindTemporaryExpr *BTE = ACC->getCXXBindTemporaryExpr(); |
316 | |
317 | CallEventManager &CEMgr = getStateManager().getCallEventManager(); |
318 | SVal V = UnknownVal(); |
319 | auto getArgLoc = [&](CallEventRef<> Caller) -> Optional<SVal> { |
320 | const LocationContext *FutureSFC = Caller->getCalleeStackFrame(); |
321 | |
322 | |
323 | if (!FutureSFC) |
324 | return None; |
325 | |
326 | |
327 | |
328 | |
329 | const Decl *CalleeD = FutureSFC->getDecl(); |
330 | |
331 | |
332 | if (CallEvent::isVariadic(CalleeD)) |
333 | return None; |
334 | |
335 | |
336 | |
337 | |
338 | const VarRegion *VR = Caller->getParameterLocation( |
339 | *Caller->getAdjustedParameterIndex(Idx)); |
340 | if (!VR) |
341 | return None; |
342 | |
343 | return loc::MemRegionVal(VR); |
344 | }; |
345 | |
346 | if (const auto *CE = dyn_cast<CallExpr>(E)) { |
347 | CallEventRef<> Caller = CEMgr.getSimpleCall(CE, State, LCtx); |
348 | if (auto OptV = getArgLoc(Caller)) |
349 | V = *OptV; |
350 | else |
351 | break; |
352 | State = addObjectUnderConstruction(State, {CE, Idx}, LCtx, V); |
353 | } else if (const auto *CCE = dyn_cast<CXXConstructExpr>(E)) { |
354 | |
355 | |
356 | CallEventRef<> Caller = |
357 | CEMgr.getCXXConstructorCall(CCE, , State, LCtx); |
358 | if (auto OptV = getArgLoc(Caller)) |
359 | V = *OptV; |
360 | else |
361 | break; |
362 | State = addObjectUnderConstruction(State, {CCE, Idx}, LCtx, V); |
363 | } else if (const auto *ME = dyn_cast<ObjCMessageExpr>(E)) { |
364 | CallEventRef<> Caller = CEMgr.getObjCMethodCall(ME, State, LCtx); |
365 | if (auto OptV = getArgLoc(Caller)) |
366 | V = *OptV; |
367 | else |
368 | break; |
369 | State = addObjectUnderConstruction(State, {ME, Idx}, LCtx, V); |
370 | } |
371 | |
372 | assert(!V.isUnknown()); |
373 | |
374 | if (BTE) |
375 | State = addObjectUnderConstruction(State, BTE, LCtx, V); |
376 | |
377 | return std::make_pair(State, V); |
378 | } |
379 | } |
380 | } |
381 | |
382 | |
383 | CallOpts.IsCtorOrDtorWithImproperlyModeledTargetRegion = true; |
384 | return std::make_pair( |
385 | State, loc::MemRegionVal(MRMgr.getCXXTempObjectRegion(E, LCtx))); |
386 | } |
387 | |
388 | void ExprEngine::VisitCXXConstructExpr(const CXXConstructExpr *CE, |
389 | ExplodedNode *Pred, |
390 | ExplodedNodeSet &destNodes) { |
391 | const LocationContext *LCtx = Pred->getLocationContext(); |
392 | ProgramStateRef State = Pred->getState(); |
393 | |
394 | SVal Target = UnknownVal(); |
395 | |
396 | if (Optional<SVal> ElidedTarget = |
397 | getObjectUnderConstruction(State, CE, LCtx)) { |
398 | |
399 | |
400 | |
401 | Target = *ElidedTarget; |
402 | StmtNodeBuilder Bldr(Pred, destNodes, *currBldrCtx); |
403 | State = finishObjectConstruction(State, CE, LCtx); |
404 | if (auto L = Target.getAs<Loc>()) |
405 | State = State->BindExpr(CE, LCtx, State->getSVal(*L, CE->getType())); |
406 | Bldr.generateNode(CE, Pred, State); |
407 | return; |
408 | } |
409 | |
410 | |
411 | |
412 | |
413 | |
414 | EvalCallOptions CallOpts; |
415 | auto C = getCurrentCFGElement().getAs<CFGConstructor>(); |
416 | ()", "/home/seafit/code_projects/clang_source/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp", 416, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert(C || getCurrentCFGElement().getAs<CFGStmt>()); |
417 | const ConstructionContext *CC = C ? C->getConstructionContext() : nullptr; |
418 | |
419 | switch (CE->getConstructionKind()) { |
420 | case CXXConstructExpr::CK_Complete: { |
421 | std::tie(State, Target) = |
422 | prepareForObjectConstruction(CE, State, LCtx, CC, CallOpts); |
423 | break; |
424 | } |
425 | case CXXConstructExpr::CK_VirtualBase: |
426 | |
427 | |
428 | if (const Stmt *Outer = LCtx->getStackFrame()->getCallSite()) { |
429 | const CXXConstructExpr *OuterCtor = dyn_cast<CXXConstructExpr>(Outer); |
430 | if (OuterCtor) { |
431 | switch (OuterCtor->getConstructionKind()) { |
432 | case CXXConstructExpr::CK_NonVirtualBase: |
433 | case CXXConstructExpr::CK_VirtualBase: |
434 | |
435 | destNodes.Add(Pred); |
436 | return; |
437 | case CXXConstructExpr::CK_Complete: |
438 | case CXXConstructExpr::CK_Delegating: |
439 | break; |
440 | } |
441 | } |
442 | } |
443 | LLVM_FALLTHROUGH; |
444 | case CXXConstructExpr::CK_NonVirtualBase: |
445 | |
446 | |
447 | |
448 | |
449 | |
450 | |
451 | |
452 | |
453 | |
454 | |
455 | |
456 | if (dyn_cast_or_null<InitListExpr>(LCtx->getParentMap().getParent(CE))) { |
457 | MemRegionManager &MRMgr = getSValBuilder().getRegionManager(); |
458 | Target = loc::MemRegionVal(MRMgr.getCXXTempObjectRegion(CE, LCtx)); |
459 | CallOpts.IsCtorOrDtorWithImproperlyModeledTargetRegion = true; |
460 | break; |
461 | } |
462 | LLVM_FALLTHROUGH; |
463 | case CXXConstructExpr::CK_Delegating: { |
464 | const CXXMethodDecl *CurCtor = cast<CXXMethodDecl>(LCtx->getDecl()); |
465 | Loc ThisPtr = getSValBuilder().getCXXThis(CurCtor, |
466 | LCtx->getStackFrame()); |
467 | SVal ThisVal = State->getSVal(ThisPtr); |
468 | |
469 | if (CE->getConstructionKind() == CXXConstructExpr::CK_Delegating) { |
470 | Target = ThisVal; |
471 | } else { |
472 | |
473 | bool IsVirtual = |
474 | (CE->getConstructionKind() == CXXConstructExpr::CK_VirtualBase); |
475 | SVal BaseVal = getStoreManager().evalDerivedToBase(ThisVal, CE->getType(), |
476 | IsVirtual); |
477 | Target = BaseVal; |
478 | } |
479 | break; |
480 | } |
481 | } |
482 | |
483 | if (State != Pred->getState()) { |
484 | static SimpleProgramPointTag T("ExprEngine", |
485 | "Prepare for object construction"); |
486 | ExplodedNodeSet DstPrepare; |
487 | StmtNodeBuilder BldrPrepare(Pred, DstPrepare, *currBldrCtx); |
488 | BldrPrepare.generateNode(CE, Pred, State, &T, ProgramPoint::PreStmtKind); |
489 | assert(DstPrepare.size() <= 1); |
490 | if (DstPrepare.size() == 0) |
491 | return; |
492 | Pred = *BldrPrepare.begin(); |
493 | } |
494 | |
495 | CallEventManager &CEMgr = getStateManager().getCallEventManager(); |
496 | CallEventRef<CXXConstructorCall> Call = |
497 | CEMgr.getCXXConstructorCall(CE, Target.getAsRegion(), State, LCtx); |
498 | |
499 | ExplodedNodeSet DstPreVisit; |
500 | getCheckerManager().runCheckersForPreStmt(DstPreVisit, Pred, CE, *this); |
501 | |
502 | |
503 | ExplodedNodeSet PreInitialized; |
504 | { |
505 | StmtNodeBuilder Bldr(DstPreVisit, PreInitialized, *currBldrCtx); |
506 | for (ExplodedNodeSet::iterator I = DstPreVisit.begin(), |
507 | E = DstPreVisit.end(); |
508 | I != E; ++I) { |
509 | ProgramStateRef State = (*I)->getState(); |
510 | if (CE->requiresZeroInitialization()) { |
511 | |
512 | |
513 | |
514 | |
515 | |
516 | |
517 | |
518 | |
519 | |
520 | |
521 | |
522 | |
523 | State = State->bindDefaultZero(Target, LCtx); |
524 | } |
525 | |
526 | Bldr.generateNode(CE, *I, State, , |
527 | ProgramPoint::PreStmtKind); |
528 | } |
529 | } |
530 | |
531 | ExplodedNodeSet DstPreCall; |
532 | getCheckerManager().runCheckersForPreCall(DstPreCall, PreInitialized, |
533 | *Call, *this); |
534 | |
535 | ExplodedNodeSet DstEvaluated; |
536 | StmtNodeBuilder Bldr(DstPreCall, DstEvaluated, *currBldrCtx); |
537 | |
538 | if (CE->getConstructor()->isTrivial() && |
539 | CE->getConstructor()->isCopyOrMoveConstructor() && |
540 | !CallOpts.IsArrayCtorOrDtor) { |
541 | |
542 | for (ExplodedNodeSet::iterator I = DstPreCall.begin(), E = DstPreCall.end(); |
543 | I != E; ++I) |
544 | performTrivialCopy(Bldr, *I, *Call); |
545 | |
546 | } else { |
547 | for (ExplodedNodeSet::iterator I = DstPreCall.begin(), E = DstPreCall.end(); |
548 | I != E; ++I) |
549 | defaultEvalCall(Bldr, *I, *Call, CallOpts); |
550 | } |
551 | |
552 | |
553 | |
554 | |
555 | |
556 | |
557 | |
558 | |
559 | const AnalysisDeclContext *ADC = LCtx->getAnalysisDeclContext(); |
560 | if (!ADC->getCFGBuildOptions().AddTemporaryDtors) { |
561 | const MemRegion *Target = Call->getCXXThisVal().getAsRegion(); |
562 | if (Target && isa<CXXTempObjectRegion>(Target) && |
563 | Call->getDecl()->getParent()->isAnyDestructorNoReturn()) { |
564 | |
565 | |
566 | |
567 | |
568 | |
569 | |
570 | |
571 | |
572 | (0) . __assert_fail ("!DstEvaluated.empty() && \"We should not have inlined this constructor!\"", "/home/seafit/code_projects/clang_source/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp", 573, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert(!DstEvaluated.empty() && |
573 | (0) . __assert_fail ("!DstEvaluated.empty() && \"We should not have inlined this constructor!\"", "/home/seafit/code_projects/clang_source/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp", 573, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true"> "We should not have inlined this constructor!"); |
574 | |
575 | for (ExplodedNode *N : DstEvaluated) { |
576 | Bldr.generateSink(CE, N, N->getState()); |
577 | } |
578 | |
579 | |
580 | |
581 | |
582 | return; |
583 | } |
584 | } |
585 | |
586 | ExplodedNodeSet DstPostArgumentCleanup; |
587 | for (auto I : DstEvaluated) |
588 | finishArgumentConstruction(DstPostArgumentCleanup, I, *Call); |
589 | |
590 | |
591 | |
592 | ExplodedNodeSet DstPostCall; |
593 | getCheckerManager().runCheckersForPostCall(DstPostCall, |
594 | DstPostArgumentCleanup, |
595 | *Call, *this); |
596 | getCheckerManager().runCheckersForPostStmt(destNodes, DstPostCall, CE, *this); |
597 | } |
598 | |
599 | void ExprEngine::VisitCXXDestructor(QualType ObjectType, |
600 | const MemRegion *Dest, |
601 | const Stmt *S, |
602 | bool IsBaseDtor, |
603 | ExplodedNode *Pred, |
604 | ExplodedNodeSet &Dst, |
605 | const EvalCallOptions &CallOpts) { |
606 | (0) . __assert_fail ("S && \"A destructor without a trigger!\"", "/home/seafit/code_projects/clang_source/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp", 606, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert(S && "A destructor without a trigger!"); |
607 | const LocationContext *LCtx = Pred->getLocationContext(); |
608 | ProgramStateRef State = Pred->getState(); |
609 | |
610 | const CXXRecordDecl *RecordDecl = ObjectType->getAsCXXRecordDecl(); |
611 | (0) . __assert_fail ("RecordDecl && \"Only CXXRecordDecls should have destructors\"", "/home/seafit/code_projects/clang_source/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp", 611, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert(RecordDecl && "Only CXXRecordDecls should have destructors"); |
612 | const CXXDestructorDecl *DtorDecl = RecordDecl->getDestructor(); |
613 | |
614 | |
615 | |
616 | if (!DtorDecl) { |
617 | |
618 | |
619 | static SimpleProgramPointTag T("ExprEngine", "SkipInvalidDestructor"); |
620 | |
621 | PostImplicitCall PP(, S->getEndLoc(), LCtx, &T); |
622 | NodeBuilder Bldr(Pred, Dst, *currBldrCtx); |
623 | Bldr.generateNode(PP, Pred->getState(), Pred); |
624 | return; |
625 | } |
626 | |
627 | CallEventManager &CEMgr = getStateManager().getCallEventManager(); |
628 | CallEventRef<CXXDestructorCall> Call = |
629 | CEMgr.getCXXDestructorCall(DtorDecl, S, Dest, IsBaseDtor, State, LCtx); |
630 | |
631 | PrettyStackTraceLoc CrashInfo(getContext().getSourceManager(), |
632 | Call->getSourceRange().getBegin(), |
633 | "Error evaluating destructor"); |
634 | |
635 | ExplodedNodeSet DstPreCall; |
636 | getCheckerManager().runCheckersForPreCall(DstPreCall, Pred, |
637 | *Call, *this); |
638 | |
639 | ExplodedNodeSet DstInvalidated; |
640 | StmtNodeBuilder Bldr(DstPreCall, DstInvalidated, *currBldrCtx); |
641 | for (ExplodedNodeSet::iterator I = DstPreCall.begin(), E = DstPreCall.end(); |
642 | I != E; ++I) |
643 | defaultEvalCall(Bldr, *I, *Call, CallOpts); |
644 | |
645 | getCheckerManager().runCheckersForPostCall(Dst, DstInvalidated, |
646 | *Call, *this); |
647 | } |
648 | |
649 | void ExprEngine::VisitCXXNewAllocatorCall(const CXXNewExpr *CNE, |
650 | ExplodedNode *Pred, |
651 | ExplodedNodeSet &Dst) { |
652 | ProgramStateRef State = Pred->getState(); |
653 | const LocationContext *LCtx = Pred->getLocationContext(); |
654 | PrettyStackTraceLoc CrashInfo(getContext().getSourceManager(), |
655 | CNE->getBeginLoc(), |
656 | "Error evaluating New Allocator Call"); |
657 | CallEventManager &CEMgr = getStateManager().getCallEventManager(); |
658 | CallEventRef<CXXAllocatorCall> Call = |
659 | CEMgr.getCXXAllocatorCall(CNE, State, LCtx); |
660 | |
661 | ExplodedNodeSet DstPreCall; |
662 | getCheckerManager().runCheckersForPreCall(DstPreCall, Pred, |
663 | *Call, *this); |
664 | |
665 | ExplodedNodeSet DstPostCall; |
666 | StmtNodeBuilder CallBldr(DstPreCall, DstPostCall, *currBldrCtx); |
667 | for (auto I : DstPreCall) { |
668 | |
669 | defaultEvalCall(CallBldr, I, *Call); |
670 | } |
671 | |
672 | |
673 | |
674 | |
675 | ExplodedNodeSet DstPostValue; |
676 | StmtNodeBuilder ValueBldr(DstPostCall, DstPostValue, *currBldrCtx); |
677 | for (auto I : DstPostCall) { |
678 | |
679 | |
680 | |
681 | |
682 | |
683 | |
684 | |
685 | |
686 | |
687 | ProgramStateRef State = I->getState(); |
688 | SVal RetVal = State->getSVal(CNE, LCtx); |
689 | |
690 | |
691 | |
692 | |
693 | |
694 | |
695 | |
696 | |
697 | if (const FunctionDecl *FD = CNE->getOperatorNew()) { |
698 | QualType Ty = FD->getType(); |
699 | if (const auto *ProtoType = Ty->getAs<FunctionProtoType>()) |
700 | if (!ProtoType->isNothrow()) |
701 | State = State->assume(RetVal.castAs<DefinedOrUnknownSVal>(), true); |
702 | } |
703 | |
704 | ValueBldr.generateNode( |
705 | CNE, I, addObjectUnderConstruction(State, CNE, LCtx, RetVal)); |
706 | } |
707 | |
708 | ExplodedNodeSet DstPostPostCallCallback; |
709 | getCheckerManager().runCheckersForPostCall(DstPostPostCallCallback, |
710 | DstPostValue, *Call, *this); |
711 | for (auto I : DstPostPostCallCallback) { |
712 | getCheckerManager().runCheckersForNewAllocator( |
713 | CNE, *getObjectUnderConstruction(I->getState(), CNE, LCtx), Dst, I, |
714 | *this); |
715 | } |
716 | } |
717 | |
718 | void ExprEngine::VisitCXXNewExpr(const CXXNewExpr *CNE, ExplodedNode *Pred, |
719 | ExplodedNodeSet &Dst) { |
720 | |
721 | |
722 | |
723 | |
724 | |
725 | unsigned blockCount = currBldrCtx->blockCount(); |
726 | const LocationContext *LCtx = Pred->getLocationContext(); |
727 | SVal symVal = UnknownVal(); |
728 | FunctionDecl *FD = CNE->getOperatorNew(); |
729 | |
730 | bool IsStandardGlobalOpNewFunction = |
731 | FD->isReplaceableGlobalAllocationFunction(); |
732 | |
733 | ProgramStateRef State = Pred->getState(); |
734 | |
735 | |
736 | if (AMgr.getAnalyzerOptions().MayInlineCXXAllocator) { |
737 | symVal = *getObjectUnderConstruction(State, CNE, LCtx); |
738 | State = finishObjectConstruction(State, CNE, LCtx); |
739 | } |
740 | |
741 | |
742 | |
743 | |
744 | if (symVal.isUnknown()) { |
745 | if (IsStandardGlobalOpNewFunction) |
746 | symVal = svalBuilder.getConjuredHeapSymbolVal(CNE, LCtx, blockCount); |
747 | else |
748 | symVal = svalBuilder.conjureSymbolVal(nullptr, CNE, LCtx, CNE->getType(), |
749 | blockCount); |
750 | } |
751 | |
752 | CallEventManager &CEMgr = getStateManager().getCallEventManager(); |
753 | CallEventRef<CXXAllocatorCall> Call = |
754 | CEMgr.getCXXAllocatorCall(CNE, State, LCtx); |
755 | |
756 | if (!AMgr.getAnalyzerOptions().MayInlineCXXAllocator) { |
757 | |
758 | |
759 | |
760 | State = Call->invalidateRegions(blockCount); |
761 | if (!State) |
762 | return; |
763 | |
764 | |
765 | |
766 | |
767 | |
768 | |
769 | |
770 | |
771 | if (FD) { |
772 | QualType Ty = FD->getType(); |
773 | if (const auto *ProtoType = Ty->getAs<FunctionProtoType>()) |
774 | if (!ProtoType->isNothrow()) |
775 | if (auto dSymVal = symVal.getAs<DefinedOrUnknownSVal>()) |
776 | State = State->assume(*dSymVal, true); |
777 | } |
778 | } |
779 | |
780 | StmtNodeBuilder Bldr(Pred, Dst, *currBldrCtx); |
781 | |
782 | SVal Result = symVal; |
783 | |
784 | if (CNE->isArray()) { |
785 | |
786 | |
787 | if (const SubRegion *NewReg = |
788 | dyn_cast_or_null<SubRegion>(symVal.getAsRegion())) { |
789 | QualType ObjTy = CNE->getType()->getAs<PointerType>()->getPointeeType(); |
790 | const ElementRegion *EleReg = |
791 | getStoreManager().GetElementZeroRegion(NewReg, ObjTy); |
792 | Result = loc::MemRegionVal(EleReg); |
793 | } |
794 | State = State->BindExpr(CNE, Pred->getLocationContext(), Result); |
795 | Bldr.generateNode(CNE, Pred, State); |
796 | return; |
797 | } |
798 | |
799 | |
800 | |
801 | |
802 | |
803 | if (FD && FD->isReservedGlobalPlacementOperator()) { |
804 | |
805 | SVal PlacementLoc = State->getSVal(CNE->getPlacementArg(0), LCtx); |
806 | Result = svalBuilder.evalCast(PlacementLoc, CNE->getType(), |
807 | CNE->getPlacementArg(0)->getType()); |
808 | } |
809 | |
810 | |
811 | State = State->BindExpr(CNE, LCtx, Result); |
812 | ExplodedNode *NewN = Bldr.generateNode(CNE, Pred, State); |
813 | if (!NewN) |
814 | return; |
815 | |
816 | |
817 | |
818 | if (const Expr *Init = CNE->getInitializer()) { |
819 | if (!isa<CXXConstructExpr>(Init)) { |
820 | assert(Bldr.getResults().size() == 1); |
821 | Bldr.takeNodes(NewN); |
822 | evalBind(Dst, CNE, NewN, Result, State->getSVal(Init, LCtx), |
823 | IsStandardGlobalOpNewFunction); |
824 | } |
825 | } |
826 | } |
827 | |
828 | void ExprEngine::VisitCXXDeleteExpr(const CXXDeleteExpr *CDE, |
829 | ExplodedNode *Pred, ExplodedNodeSet &Dst) { |
830 | StmtNodeBuilder Bldr(Pred, Dst, *currBldrCtx); |
831 | ProgramStateRef state = Pred->getState(); |
832 | Bldr.generateNode(CDE, Pred, state); |
833 | } |
834 | |
835 | void ExprEngine::VisitCXXCatchStmt(const CXXCatchStmt *CS, |
836 | ExplodedNode *Pred, |
837 | ExplodedNodeSet &Dst) { |
838 | const VarDecl *VD = CS->getExceptionDecl(); |
839 | if (!VD) { |
840 | Dst.Add(Pred); |
841 | return; |
842 | } |
843 | |
844 | const LocationContext *LCtx = Pred->getLocationContext(); |
845 | SVal V = svalBuilder.conjureSymbolVal(CS, LCtx, VD->getType(), |
846 | currBldrCtx->blockCount()); |
847 | ProgramStateRef state = Pred->getState(); |
848 | state = state->bindLoc(state->getLValue(VD, LCtx), V, LCtx); |
849 | |
850 | StmtNodeBuilder Bldr(Pred, Dst, *currBldrCtx); |
851 | Bldr.generateNode(CS, Pred, state); |
852 | } |
853 | |
854 | void ExprEngine::VisitCXXThisExpr(const CXXThisExpr *TE, ExplodedNode *Pred, |
855 | ExplodedNodeSet &Dst) { |
856 | StmtNodeBuilder Bldr(Pred, Dst, *currBldrCtx); |
857 | |
858 | |
859 | const LocationContext *LCtx = Pred->getLocationContext(); |
860 | const MemRegion *R = |
861 | svalBuilder.getRegionManager().getCXXThisRegion( |
862 | getContext().getCanonicalType(TE->getType()), |
863 | LCtx); |
864 | |
865 | ProgramStateRef state = Pred->getState(); |
866 | SVal V = state->getSVal(loc::MemRegionVal(R)); |
867 | Bldr.generateNode(TE, Pred, state->BindExpr(TE, LCtx, V)); |
868 | } |
869 | |
870 | void ExprEngine::VisitLambdaExpr(const LambdaExpr *LE, ExplodedNode *Pred, |
871 | ExplodedNodeSet &Dst) { |
872 | const LocationContext *LocCtxt = Pred->getLocationContext(); |
873 | |
874 | |
875 | const MemRegion *R = svalBuilder.getRegionManager().getCXXTempObjectRegion( |
876 | LE, LocCtxt); |
877 | SVal V = loc::MemRegionVal(R); |
878 | |
879 | ProgramStateRef State = Pred->getState(); |
880 | |
881 | |
882 | |
883 | CXXRecordDecl::field_iterator CurField = LE->getLambdaClass()->field_begin(); |
884 | for (LambdaExpr::const_capture_init_iterator i = LE->capture_init_begin(), |
885 | e = LE->capture_init_end(); |
886 | i != e; ++i, ++CurField) { |
887 | FieldDecl *FieldForCapture = *CurField; |
888 | SVal FieldLoc = State->getLValue(FieldForCapture, V); |
889 | |
890 | SVal InitVal; |
891 | if (!FieldForCapture->hasCapturedVLAType()) { |
892 | Expr *InitExpr = *i; |
893 | (0) . __assert_fail ("InitExpr && \"Capture missing initialization expression\"", "/home/seafit/code_projects/clang_source/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp", 893, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert(InitExpr && "Capture missing initialization expression"); |
894 | InitVal = State->getSVal(InitExpr, LocCtxt); |
895 | } else { |
896 | |
897 | |
898 | |
899 | Expr *SizeExpr = FieldForCapture->getCapturedVLAType()->getSizeExpr(); |
900 | InitVal = State->getSVal(SizeExpr, LocCtxt); |
901 | } |
902 | |
903 | State = State->bindLoc(FieldLoc, InitVal, LocCtxt); |
904 | } |
905 | |
906 | |
907 | |
908 | |
909 | SVal LambdaRVal = State->getSVal(R); |
910 | |
911 | ExplodedNodeSet Tmp; |
912 | StmtNodeBuilder Bldr(Pred, Tmp, *currBldrCtx); |
913 | |
914 | Bldr.generateNode(LE, Pred, |
915 | State->BindExpr(LE, LocCtxt, LambdaRVal), |
916 | nullptr, ProgramPoint::PostLValueKind); |
917 | |
918 | |
919 | getCheckerManager().runCheckersForPostStmt(Dst, Tmp, LE, *this); |
920 | } |
921 | |