1 //=-- ExprEngine.cpp - Path-Sensitive Expression-Level Dataflow ---*- 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 a meta-engine for path-sensitive dataflow analysis that
11 // is built on GREngine, but provides the boilerplate to execute transfer
12 // functions and build the ExplodedGraph at the expression level.
13 //
14 //===----------------------------------------------------------------------===//
15
16 #include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
17 #include "PrettyStackTraceLocationContext.h"
18 #include "clang/AST/CharUnits.h"
19 #include "clang/AST/ParentMap.h"
20 #include "clang/AST/StmtCXX.h"
21 #include "clang/AST/StmtObjC.h"
22 #include "clang/Basic/Builtins.h"
23 #include "clang/Basic/PrettyStackTrace.h"
24 #include "clang/Basic/SourceManager.h"
25 #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
26 #include "clang/StaticAnalyzer/Core/CheckerManager.h"
27 #include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"
28 #include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
29 #include "clang/StaticAnalyzer/Core/PathSensitive/LoopWidening.h"
30 #include "llvm/ADT/ImmutableList.h"
31 #include "llvm/ADT/Statistic.h"
32 #include "llvm/Support/raw_ostream.h"
33
34 #ifndef NDEBUG
35 #include "llvm/Support/GraphWriter.h"
36 #endif
37
38 using namespace clang;
39 using namespace ento;
40 using llvm::APSInt;
41
42 #define DEBUG_TYPE "ExprEngine"
43
44 STATISTIC(NumRemoveDeadBindings,
45 "The # of times RemoveDeadBindings is called");
46 STATISTIC(NumMaxBlockCountReached,
47 "The # of aborted paths due to reaching the maximum block count in "
48 "a top level function");
49 STATISTIC(NumMaxBlockCountReachedInInlined,
50 "The # of aborted paths due to reaching the maximum block count in "
51 "an inlined function");
52 STATISTIC(NumTimesRetriedWithoutInlining,
53 "The # of times we re-evaluated a call without inlining");
54
55 typedef std::pair<const CXXBindTemporaryExpr *, const StackFrameContext *>
56 CXXBindTemporaryContext;
57
58 // Keeps track of whether CXXBindTemporaryExpr nodes have been evaluated.
59 // The StackFrameContext assures that nested calls due to inlined recursive
60 // functions do not interfere.
61 REGISTER_TRAIT_WITH_PROGRAMSTATE(InitializedTemporariesSet,
62 llvm::ImmutableSet<CXXBindTemporaryContext>)
63
64 //===----------------------------------------------------------------------===//
65 // Engine construction and deletion.
66 //===----------------------------------------------------------------------===//
67
68 static const char* TagProviderName = "ExprEngine";
69
ExprEngine(AnalysisManager & mgr,bool gcEnabled,SetOfConstDecls * VisitedCalleesIn,FunctionSummariesTy * FS,InliningModes HowToInlineIn)70 ExprEngine::ExprEngine(AnalysisManager &mgr, bool gcEnabled,
71 SetOfConstDecls *VisitedCalleesIn,
72 FunctionSummariesTy *FS,
73 InliningModes HowToInlineIn)
74 : AMgr(mgr),
75 AnalysisDeclContexts(mgr.getAnalysisDeclContextManager()),
76 Engine(*this, FS),
77 G(Engine.getGraph()),
78 StateMgr(getContext(), mgr.getStoreManagerCreator(),
79 mgr.getConstraintManagerCreator(), G.getAllocator(),
80 this),
81 SymMgr(StateMgr.getSymbolManager()),
82 svalBuilder(StateMgr.getSValBuilder()),
83 currStmtIdx(0), currBldrCtx(nullptr),
84 ObjCNoRet(mgr.getASTContext()),
85 ObjCGCEnabled(gcEnabled), BR(mgr, *this),
86 VisitedCallees(VisitedCalleesIn),
87 HowToInline(HowToInlineIn)
88 {
89 unsigned TrimInterval = mgr.options.getGraphTrimInterval();
90 if (TrimInterval != 0) {
91 // Enable eager node reclaimation when constructing the ExplodedGraph.
92 G.enableNodeReclamation(TrimInterval);
93 }
94 }
95
~ExprEngine()96 ExprEngine::~ExprEngine() {
97 BR.FlushReports();
98 }
99
100 //===----------------------------------------------------------------------===//
101 // Utility methods.
102 //===----------------------------------------------------------------------===//
103
getInitialState(const LocationContext * InitLoc)104 ProgramStateRef ExprEngine::getInitialState(const LocationContext *InitLoc) {
105 ProgramStateRef state = StateMgr.getInitialState(InitLoc);
106 const Decl *D = InitLoc->getDecl();
107
108 // Preconditions.
109 // FIXME: It would be nice if we had a more general mechanism to add
110 // such preconditions. Some day.
111 do {
112
113 if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
114 // Precondition: the first argument of 'main' is an integer guaranteed
115 // to be > 0.
116 const IdentifierInfo *II = FD->getIdentifier();
117 if (!II || !(II->getName() == "main" && FD->getNumParams() > 0))
118 break;
119
120 const ParmVarDecl *PD = FD->getParamDecl(0);
121 QualType T = PD->getType();
122 const BuiltinType *BT = dyn_cast<BuiltinType>(T);
123 if (!BT || !BT->isInteger())
124 break;
125
126 const MemRegion *R = state->getRegion(PD, InitLoc);
127 if (!R)
128 break;
129
130 SVal V = state->getSVal(loc::MemRegionVal(R));
131 SVal Constraint_untested = evalBinOp(state, BO_GT, V,
132 svalBuilder.makeZeroVal(T),
133 svalBuilder.getConditionType());
134
135 Optional<DefinedOrUnknownSVal> Constraint =
136 Constraint_untested.getAs<DefinedOrUnknownSVal>();
137
138 if (!Constraint)
139 break;
140
141 if (ProgramStateRef newState = state->assume(*Constraint, true))
142 state = newState;
143 }
144 break;
145 }
146 while (0);
147
148 if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) {
149 // Precondition: 'self' is always non-null upon entry to an Objective-C
150 // method.
151 const ImplicitParamDecl *SelfD = MD->getSelfDecl();
152 const MemRegion *R = state->getRegion(SelfD, InitLoc);
153 SVal V = state->getSVal(loc::MemRegionVal(R));
154
155 if (Optional<Loc> LV = V.getAs<Loc>()) {
156 // Assume that the pointer value in 'self' is non-null.
157 state = state->assume(*LV, true);
158 assert(state && "'self' cannot be null");
159 }
160 }
161
162 if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(D)) {
163 if (!MD->isStatic()) {
164 // Precondition: 'this' is always non-null upon entry to the
165 // top-level function. This is our starting assumption for
166 // analyzing an "open" program.
167 const StackFrameContext *SFC = InitLoc->getCurrentStackFrame();
168 if (SFC->getParent() == nullptr) {
169 loc::MemRegionVal L = svalBuilder.getCXXThis(MD, SFC);
170 SVal V = state->getSVal(L);
171 if (Optional<Loc> LV = V.getAs<Loc>()) {
172 state = state->assume(*LV, true);
173 assert(state && "'this' cannot be null");
174 }
175 }
176 }
177 }
178
179 return state;
180 }
181
182 ProgramStateRef
createTemporaryRegionIfNeeded(ProgramStateRef State,const LocationContext * LC,const Expr * Ex,const Expr * Result)183 ExprEngine::createTemporaryRegionIfNeeded(ProgramStateRef State,
184 const LocationContext *LC,
185 const Expr *Ex,
186 const Expr *Result) {
187 SVal V = State->getSVal(Ex, LC);
188 if (!Result) {
189 // If we don't have an explicit result expression, we're in "if needed"
190 // mode. Only create a region if the current value is a NonLoc.
191 if (!V.getAs<NonLoc>())
192 return State;
193 Result = Ex;
194 } else {
195 // We need to create a region no matter what. For sanity, make sure we don't
196 // try to stuff a Loc into a non-pointer temporary region.
197 assert(!V.getAs<Loc>() || Loc::isLocType(Result->getType()) ||
198 Result->getType()->isMemberPointerType());
199 }
200
201 ProgramStateManager &StateMgr = State->getStateManager();
202 MemRegionManager &MRMgr = StateMgr.getRegionManager();
203 StoreManager &StoreMgr = StateMgr.getStoreManager();
204
205 // We need to be careful about treating a derived type's value as
206 // bindings for a base type. Unless we're creating a temporary pointer region,
207 // start by stripping and recording base casts.
208 SmallVector<const CastExpr *, 4> Casts;
209 const Expr *Inner = Ex->IgnoreParens();
210 if (!Loc::isLocType(Result->getType())) {
211 while (const CastExpr *CE = dyn_cast<CastExpr>(Inner)) {
212 if (CE->getCastKind() == CK_DerivedToBase ||
213 CE->getCastKind() == CK_UncheckedDerivedToBase)
214 Casts.push_back(CE);
215 else if (CE->getCastKind() != CK_NoOp)
216 break;
217
218 Inner = CE->getSubExpr()->IgnoreParens();
219 }
220 }
221
222 // Create a temporary object region for the inner expression (which may have
223 // a more derived type) and bind the value into it.
224 const TypedValueRegion *TR = nullptr;
225 if (const MaterializeTemporaryExpr *MT =
226 dyn_cast<MaterializeTemporaryExpr>(Result)) {
227 StorageDuration SD = MT->getStorageDuration();
228 // If this object is bound to a reference with static storage duration, we
229 // put it in a different region to prevent "address leakage" warnings.
230 if (SD == SD_Static || SD == SD_Thread)
231 TR = MRMgr.getCXXStaticTempObjectRegion(Inner);
232 }
233 if (!TR)
234 TR = MRMgr.getCXXTempObjectRegion(Inner, LC);
235
236 SVal Reg = loc::MemRegionVal(TR);
237
238 if (V.isUnknown())
239 V = getSValBuilder().conjureSymbolVal(Result, LC, TR->getValueType(),
240 currBldrCtx->blockCount());
241 State = State->bindLoc(Reg, V);
242
243 // Re-apply the casts (from innermost to outermost) for type sanity.
244 for (SmallVectorImpl<const CastExpr *>::reverse_iterator I = Casts.rbegin(),
245 E = Casts.rend();
246 I != E; ++I) {
247 Reg = StoreMgr.evalDerivedToBase(Reg, *I);
248 }
249
250 State = State->BindExpr(Result, LC, Reg);
251 return State;
252 }
253
254 //===----------------------------------------------------------------------===//
255 // Top-level transfer function logic (Dispatcher).
256 //===----------------------------------------------------------------------===//
257
258 /// evalAssume - Called by ConstraintManager. Used to call checker-specific
259 /// logic for handling assumptions on symbolic values.
processAssume(ProgramStateRef state,SVal cond,bool assumption)260 ProgramStateRef ExprEngine::processAssume(ProgramStateRef state,
261 SVal cond, bool assumption) {
262 return getCheckerManager().runCheckersForEvalAssume(state, cond, assumption);
263 }
264
wantsRegionChangeUpdate(ProgramStateRef state)265 bool ExprEngine::wantsRegionChangeUpdate(ProgramStateRef state) {
266 return getCheckerManager().wantsRegionChangeUpdate(state);
267 }
268
269 ProgramStateRef
processRegionChanges(ProgramStateRef state,const InvalidatedSymbols * invalidated,ArrayRef<const MemRegion * > Explicits,ArrayRef<const MemRegion * > Regions,const CallEvent * Call)270 ExprEngine::processRegionChanges(ProgramStateRef state,
271 const InvalidatedSymbols *invalidated,
272 ArrayRef<const MemRegion *> Explicits,
273 ArrayRef<const MemRegion *> Regions,
274 const CallEvent *Call) {
275 return getCheckerManager().runCheckersForRegionChanges(state, invalidated,
276 Explicits, Regions, Call);
277 }
278
printState(raw_ostream & Out,ProgramStateRef State,const char * NL,const char * Sep)279 void ExprEngine::printState(raw_ostream &Out, ProgramStateRef State,
280 const char *NL, const char *Sep) {
281 getCheckerManager().runCheckersForPrintState(Out, State, NL, Sep);
282 }
283
processEndWorklist(bool hasWorkRemaining)284 void ExprEngine::processEndWorklist(bool hasWorkRemaining) {
285 getCheckerManager().runCheckersForEndAnalysis(G, BR, *this);
286 }
287
processCFGElement(const CFGElement E,ExplodedNode * Pred,unsigned StmtIdx,NodeBuilderContext * Ctx)288 void ExprEngine::processCFGElement(const CFGElement E, ExplodedNode *Pred,
289 unsigned StmtIdx, NodeBuilderContext *Ctx) {
290 PrettyStackTraceLocationContext CrashInfo(Pred->getLocationContext());
291 currStmtIdx = StmtIdx;
292 currBldrCtx = Ctx;
293
294 switch (E.getKind()) {
295 case CFGElement::Statement:
296 ProcessStmt(const_cast<Stmt*>(E.castAs<CFGStmt>().getStmt()), Pred);
297 return;
298 case CFGElement::Initializer:
299 ProcessInitializer(E.castAs<CFGInitializer>().getInitializer(), Pred);
300 return;
301 case CFGElement::NewAllocator:
302 ProcessNewAllocator(E.castAs<CFGNewAllocator>().getAllocatorExpr(),
303 Pred);
304 return;
305 case CFGElement::AutomaticObjectDtor:
306 case CFGElement::DeleteDtor:
307 case CFGElement::BaseDtor:
308 case CFGElement::MemberDtor:
309 case CFGElement::TemporaryDtor:
310 ProcessImplicitDtor(E.castAs<CFGImplicitDtor>(), Pred);
311 return;
312 }
313 }
314
shouldRemoveDeadBindings(AnalysisManager & AMgr,const CFGStmt S,const ExplodedNode * Pred,const LocationContext * LC)315 static bool shouldRemoveDeadBindings(AnalysisManager &AMgr,
316 const CFGStmt S,
317 const ExplodedNode *Pred,
318 const LocationContext *LC) {
319
320 // Are we never purging state values?
321 if (AMgr.options.AnalysisPurgeOpt == PurgeNone)
322 return false;
323
324 // Is this the beginning of a basic block?
325 if (Pred->getLocation().getAs<BlockEntrance>())
326 return true;
327
328 // Is this on a non-expression?
329 if (!isa<Expr>(S.getStmt()))
330 return true;
331
332 // Run before processing a call.
333 if (CallEvent::isCallStmt(S.getStmt()))
334 return true;
335
336 // Is this an expression that is consumed by another expression? If so,
337 // postpone cleaning out the state.
338 ParentMap &PM = LC->getAnalysisDeclContext()->getParentMap();
339 return !PM.isConsumedExpr(cast<Expr>(S.getStmt()));
340 }
341
removeDead(ExplodedNode * Pred,ExplodedNodeSet & Out,const Stmt * ReferenceStmt,const LocationContext * LC,const Stmt * DiagnosticStmt,ProgramPoint::Kind K)342 void ExprEngine::removeDead(ExplodedNode *Pred, ExplodedNodeSet &Out,
343 const Stmt *ReferenceStmt,
344 const LocationContext *LC,
345 const Stmt *DiagnosticStmt,
346 ProgramPoint::Kind K) {
347 assert((K == ProgramPoint::PreStmtPurgeDeadSymbolsKind ||
348 ReferenceStmt == nullptr || isa<ReturnStmt>(ReferenceStmt))
349 && "PostStmt is not generally supported by the SymbolReaper yet");
350 assert(LC && "Must pass the current (or expiring) LocationContext");
351
352 if (!DiagnosticStmt) {
353 DiagnosticStmt = ReferenceStmt;
354 assert(DiagnosticStmt && "Required for clearing a LocationContext");
355 }
356
357 NumRemoveDeadBindings++;
358 ProgramStateRef CleanedState = Pred->getState();
359
360 // LC is the location context being destroyed, but SymbolReaper wants a
361 // location context that is still live. (If this is the top-level stack
362 // frame, this will be null.)
363 if (!ReferenceStmt) {
364 assert(K == ProgramPoint::PostStmtPurgeDeadSymbolsKind &&
365 "Use PostStmtPurgeDeadSymbolsKind for clearing a LocationContext");
366 LC = LC->getParent();
367 }
368
369 const StackFrameContext *SFC = LC ? LC->getCurrentStackFrame() : nullptr;
370 SymbolReaper SymReaper(SFC, ReferenceStmt, SymMgr, getStoreManager());
371
372 getCheckerManager().runCheckersForLiveSymbols(CleanedState, SymReaper);
373
374 // Create a state in which dead bindings are removed from the environment
375 // and the store. TODO: The function should just return new env and store,
376 // not a new state.
377 CleanedState = StateMgr.removeDeadBindings(CleanedState, SFC, SymReaper);
378
379 // Process any special transfer function for dead symbols.
380 // A tag to track convenience transitions, which can be removed at cleanup.
381 static SimpleProgramPointTag cleanupTag(TagProviderName, "Clean Node");
382 if (!SymReaper.hasDeadSymbols()) {
383 // Generate a CleanedNode that has the environment and store cleaned
384 // up. Since no symbols are dead, we can optimize and not clean out
385 // the constraint manager.
386 StmtNodeBuilder Bldr(Pred, Out, *currBldrCtx);
387 Bldr.generateNode(DiagnosticStmt, Pred, CleanedState, &cleanupTag, K);
388
389 } else {
390 // Call checkers with the non-cleaned state so that they could query the
391 // values of the soon to be dead symbols.
392 ExplodedNodeSet CheckedSet;
393 getCheckerManager().runCheckersForDeadSymbols(CheckedSet, Pred, SymReaper,
394 DiagnosticStmt, *this, K);
395
396 // For each node in CheckedSet, generate CleanedNodes that have the
397 // environment, the store, and the constraints cleaned up but have the
398 // user-supplied states as the predecessors.
399 StmtNodeBuilder Bldr(CheckedSet, Out, *currBldrCtx);
400 for (ExplodedNodeSet::const_iterator
401 I = CheckedSet.begin(), E = CheckedSet.end(); I != E; ++I) {
402 ProgramStateRef CheckerState = (*I)->getState();
403
404 // The constraint manager has not been cleaned up yet, so clean up now.
405 CheckerState = getConstraintManager().removeDeadBindings(CheckerState,
406 SymReaper);
407
408 assert(StateMgr.haveEqualEnvironments(CheckerState, Pred->getState()) &&
409 "Checkers are not allowed to modify the Environment as a part of "
410 "checkDeadSymbols processing.");
411 assert(StateMgr.haveEqualStores(CheckerState, Pred->getState()) &&
412 "Checkers are not allowed to modify the Store as a part of "
413 "checkDeadSymbols processing.");
414
415 // Create a state based on CleanedState with CheckerState GDM and
416 // generate a transition to that state.
417 ProgramStateRef CleanedCheckerSt =
418 StateMgr.getPersistentStateWithGDM(CleanedState, CheckerState);
419 Bldr.generateNode(DiagnosticStmt, *I, CleanedCheckerSt, &cleanupTag, K);
420 }
421 }
422 }
423
ProcessStmt(const CFGStmt S,ExplodedNode * Pred)424 void ExprEngine::ProcessStmt(const CFGStmt S,
425 ExplodedNode *Pred) {
426 // Reclaim any unnecessary nodes in the ExplodedGraph.
427 G.reclaimRecentlyAllocatedNodes();
428
429 const Stmt *currStmt = S.getStmt();
430 PrettyStackTraceLoc CrashInfo(getContext().getSourceManager(),
431 currStmt->getLocStart(),
432 "Error evaluating statement");
433
434 // Remove dead bindings and symbols.
435 ExplodedNodeSet CleanedStates;
436 if (shouldRemoveDeadBindings(AMgr, S, Pred, Pred->getLocationContext())){
437 removeDead(Pred, CleanedStates, currStmt, Pred->getLocationContext());
438 } else
439 CleanedStates.Add(Pred);
440
441 // Visit the statement.
442 ExplodedNodeSet Dst;
443 for (ExplodedNodeSet::iterator I = CleanedStates.begin(),
444 E = CleanedStates.end(); I != E; ++I) {
445 ExplodedNodeSet DstI;
446 // Visit the statement.
447 Visit(currStmt, *I, DstI);
448 Dst.insert(DstI);
449 }
450
451 // Enqueue the new nodes onto the work list.
452 Engine.enqueue(Dst, currBldrCtx->getBlock(), currStmtIdx);
453 }
454
ProcessInitializer(const CFGInitializer Init,ExplodedNode * Pred)455 void ExprEngine::ProcessInitializer(const CFGInitializer Init,
456 ExplodedNode *Pred) {
457 const CXXCtorInitializer *BMI = Init.getInitializer();
458
459 PrettyStackTraceLoc CrashInfo(getContext().getSourceManager(),
460 BMI->getSourceLocation(),
461 "Error evaluating initializer");
462
463 // We don't clean up dead bindings here.
464 const StackFrameContext *stackFrame =
465 cast<StackFrameContext>(Pred->getLocationContext());
466 const CXXConstructorDecl *decl =
467 cast<CXXConstructorDecl>(stackFrame->getDecl());
468
469 ProgramStateRef State = Pred->getState();
470 SVal thisVal = State->getSVal(svalBuilder.getCXXThis(decl, stackFrame));
471
472 ExplodedNodeSet Tmp(Pred);
473 SVal FieldLoc;
474
475 // Evaluate the initializer, if necessary
476 if (BMI->isAnyMemberInitializer()) {
477 // Constructors build the object directly in the field,
478 // but non-objects must be copied in from the initializer.
479 if (auto *CtorExpr = findDirectConstructorForCurrentCFGElement()) {
480 assert(BMI->getInit()->IgnoreImplicit() == CtorExpr);
481 (void)CtorExpr;
482 // The field was directly constructed, so there is no need to bind.
483 } else {
484 const Expr *Init = BMI->getInit()->IgnoreImplicit();
485 const ValueDecl *Field;
486 if (BMI->isIndirectMemberInitializer()) {
487 Field = BMI->getIndirectMember();
488 FieldLoc = State->getLValue(BMI->getIndirectMember(), thisVal);
489 } else {
490 Field = BMI->getMember();
491 FieldLoc = State->getLValue(BMI->getMember(), thisVal);
492 }
493
494 SVal InitVal;
495 if (BMI->getNumArrayIndices() > 0) {
496 // Handle arrays of trivial type. We can represent this with a
497 // primitive load/copy from the base array region.
498 const ArraySubscriptExpr *ASE;
499 while ((ASE = dyn_cast<ArraySubscriptExpr>(Init)))
500 Init = ASE->getBase()->IgnoreImplicit();
501
502 SVal LValue = State->getSVal(Init, stackFrame);
503 if (Optional<Loc> LValueLoc = LValue.getAs<Loc>())
504 InitVal = State->getSVal(*LValueLoc);
505
506 // If we fail to get the value for some reason, use a symbolic value.
507 if (InitVal.isUnknownOrUndef()) {
508 SValBuilder &SVB = getSValBuilder();
509 InitVal = SVB.conjureSymbolVal(BMI->getInit(), stackFrame,
510 Field->getType(),
511 currBldrCtx->blockCount());
512 }
513 } else {
514 InitVal = State->getSVal(BMI->getInit(), stackFrame);
515 }
516
517 assert(Tmp.size() == 1 && "have not generated any new nodes yet");
518 assert(*Tmp.begin() == Pred && "have not generated any new nodes yet");
519 Tmp.clear();
520
521 PostInitializer PP(BMI, FieldLoc.getAsRegion(), stackFrame);
522 evalBind(Tmp, Init, Pred, FieldLoc, InitVal, /*isInit=*/true, &PP);
523 }
524 } else {
525 assert(BMI->isBaseInitializer() || BMI->isDelegatingInitializer());
526 // We already did all the work when visiting the CXXConstructExpr.
527 }
528
529 // Construct PostInitializer nodes whether the state changed or not,
530 // so that the diagnostics don't get confused.
531 PostInitializer PP(BMI, FieldLoc.getAsRegion(), stackFrame);
532 ExplodedNodeSet Dst;
533 NodeBuilder Bldr(Tmp, Dst, *currBldrCtx);
534 for (ExplodedNodeSet::iterator I = Tmp.begin(), E = Tmp.end(); I != E; ++I) {
535 ExplodedNode *N = *I;
536 Bldr.generateNode(PP, N->getState(), N);
537 }
538
539 // Enqueue the new nodes onto the work list.
540 Engine.enqueue(Dst, currBldrCtx->getBlock(), currStmtIdx);
541 }
542
ProcessImplicitDtor(const CFGImplicitDtor D,ExplodedNode * Pred)543 void ExprEngine::ProcessImplicitDtor(const CFGImplicitDtor D,
544 ExplodedNode *Pred) {
545 ExplodedNodeSet Dst;
546 switch (D.getKind()) {
547 case CFGElement::AutomaticObjectDtor:
548 ProcessAutomaticObjDtor(D.castAs<CFGAutomaticObjDtor>(), Pred, Dst);
549 break;
550 case CFGElement::BaseDtor:
551 ProcessBaseDtor(D.castAs<CFGBaseDtor>(), Pred, Dst);
552 break;
553 case CFGElement::MemberDtor:
554 ProcessMemberDtor(D.castAs<CFGMemberDtor>(), Pred, Dst);
555 break;
556 case CFGElement::TemporaryDtor:
557 ProcessTemporaryDtor(D.castAs<CFGTemporaryDtor>(), Pred, Dst);
558 break;
559 case CFGElement::DeleteDtor:
560 ProcessDeleteDtor(D.castAs<CFGDeleteDtor>(), Pred, Dst);
561 break;
562 default:
563 llvm_unreachable("Unexpected dtor kind.");
564 }
565
566 // Enqueue the new nodes onto the work list.
567 Engine.enqueue(Dst, currBldrCtx->getBlock(), currStmtIdx);
568 }
569
ProcessNewAllocator(const CXXNewExpr * NE,ExplodedNode * Pred)570 void ExprEngine::ProcessNewAllocator(const CXXNewExpr *NE,
571 ExplodedNode *Pred) {
572 ExplodedNodeSet Dst;
573 AnalysisManager &AMgr = getAnalysisManager();
574 AnalyzerOptions &Opts = AMgr.options;
575 // TODO: We're not evaluating allocators for all cases just yet as
576 // we're not handling the return value correctly, which causes false
577 // positives when the alpha.cplusplus.NewDeleteLeaks check is on.
578 if (Opts.mayInlineCXXAllocator())
579 VisitCXXNewAllocatorCall(NE, Pred, Dst);
580 else {
581 NodeBuilder Bldr(Pred, Dst, *currBldrCtx);
582 const LocationContext *LCtx = Pred->getLocationContext();
583 PostImplicitCall PP(NE->getOperatorNew(), NE->getLocStart(), LCtx);
584 Bldr.generateNode(PP, Pred->getState(), Pred);
585 }
586 Engine.enqueue(Dst, currBldrCtx->getBlock(), currStmtIdx);
587 }
588
ProcessAutomaticObjDtor(const CFGAutomaticObjDtor Dtor,ExplodedNode * Pred,ExplodedNodeSet & Dst)589 void ExprEngine::ProcessAutomaticObjDtor(const CFGAutomaticObjDtor Dtor,
590 ExplodedNode *Pred,
591 ExplodedNodeSet &Dst) {
592 const VarDecl *varDecl = Dtor.getVarDecl();
593 QualType varType = varDecl->getType();
594
595 ProgramStateRef state = Pred->getState();
596 SVal dest = state->getLValue(varDecl, Pred->getLocationContext());
597 const MemRegion *Region = dest.castAs<loc::MemRegionVal>().getRegion();
598
599 if (const ReferenceType *refType = varType->getAs<ReferenceType>()) {
600 varType = refType->getPointeeType();
601 Region = state->getSVal(Region).getAsRegion();
602 }
603
604 VisitCXXDestructor(varType, Region, Dtor.getTriggerStmt(), /*IsBase=*/ false,
605 Pred, Dst);
606 }
607
ProcessDeleteDtor(const CFGDeleteDtor Dtor,ExplodedNode * Pred,ExplodedNodeSet & Dst)608 void ExprEngine::ProcessDeleteDtor(const CFGDeleteDtor Dtor,
609 ExplodedNode *Pred,
610 ExplodedNodeSet &Dst) {
611 ProgramStateRef State = Pred->getState();
612 const LocationContext *LCtx = Pred->getLocationContext();
613 const CXXDeleteExpr *DE = Dtor.getDeleteExpr();
614 const Stmt *Arg = DE->getArgument();
615 SVal ArgVal = State->getSVal(Arg, LCtx);
616
617 // If the argument to delete is known to be a null value,
618 // don't run destructor.
619 if (State->isNull(ArgVal).isConstrainedTrue()) {
620 QualType DTy = DE->getDestroyedType();
621 QualType BTy = getContext().getBaseElementType(DTy);
622 const CXXRecordDecl *RD = BTy->getAsCXXRecordDecl();
623 const CXXDestructorDecl *Dtor = RD->getDestructor();
624
625 PostImplicitCall PP(Dtor, DE->getLocStart(), LCtx);
626 NodeBuilder Bldr(Pred, Dst, *currBldrCtx);
627 Bldr.generateNode(PP, Pred->getState(), Pred);
628 return;
629 }
630
631 VisitCXXDestructor(DE->getDestroyedType(),
632 ArgVal.getAsRegion(),
633 DE, /*IsBase=*/ false,
634 Pred, Dst);
635 }
636
ProcessBaseDtor(const CFGBaseDtor D,ExplodedNode * Pred,ExplodedNodeSet & Dst)637 void ExprEngine::ProcessBaseDtor(const CFGBaseDtor D,
638 ExplodedNode *Pred, ExplodedNodeSet &Dst) {
639 const LocationContext *LCtx = Pred->getLocationContext();
640
641 const CXXDestructorDecl *CurDtor = cast<CXXDestructorDecl>(LCtx->getDecl());
642 Loc ThisPtr = getSValBuilder().getCXXThis(CurDtor,
643 LCtx->getCurrentStackFrame());
644 SVal ThisVal = Pred->getState()->getSVal(ThisPtr);
645
646 // Create the base object region.
647 const CXXBaseSpecifier *Base = D.getBaseSpecifier();
648 QualType BaseTy = Base->getType();
649 SVal BaseVal = getStoreManager().evalDerivedToBase(ThisVal, BaseTy,
650 Base->isVirtual());
651
652 VisitCXXDestructor(BaseTy, BaseVal.castAs<loc::MemRegionVal>().getRegion(),
653 CurDtor->getBody(), /*IsBase=*/ true, Pred, Dst);
654 }
655
ProcessMemberDtor(const CFGMemberDtor D,ExplodedNode * Pred,ExplodedNodeSet & Dst)656 void ExprEngine::ProcessMemberDtor(const CFGMemberDtor D,
657 ExplodedNode *Pred, ExplodedNodeSet &Dst) {
658 const FieldDecl *Member = D.getFieldDecl();
659 ProgramStateRef State = Pred->getState();
660 const LocationContext *LCtx = Pred->getLocationContext();
661
662 const CXXDestructorDecl *CurDtor = cast<CXXDestructorDecl>(LCtx->getDecl());
663 Loc ThisVal = getSValBuilder().getCXXThis(CurDtor,
664 LCtx->getCurrentStackFrame());
665 SVal FieldVal =
666 State->getLValue(Member, State->getSVal(ThisVal).castAs<Loc>());
667
668 VisitCXXDestructor(Member->getType(),
669 FieldVal.castAs<loc::MemRegionVal>().getRegion(),
670 CurDtor->getBody(), /*IsBase=*/false, Pred, Dst);
671 }
672
ProcessTemporaryDtor(const CFGTemporaryDtor D,ExplodedNode * Pred,ExplodedNodeSet & Dst)673 void ExprEngine::ProcessTemporaryDtor(const CFGTemporaryDtor D,
674 ExplodedNode *Pred,
675 ExplodedNodeSet &Dst) {
676 ExplodedNodeSet CleanDtorState;
677 StmtNodeBuilder StmtBldr(Pred, CleanDtorState, *currBldrCtx);
678 ProgramStateRef State = Pred->getState();
679 if (State->contains<InitializedTemporariesSet>(
680 std::make_pair(D.getBindTemporaryExpr(), Pred->getStackFrame()))) {
681 // FIXME: Currently we insert temporary destructors for default parameters,
682 // but we don't insert the constructors.
683 State = State->remove<InitializedTemporariesSet>(
684 std::make_pair(D.getBindTemporaryExpr(), Pred->getStackFrame()));
685 }
686 StmtBldr.generateNode(D.getBindTemporaryExpr(), Pred, State);
687
688 QualType varType = D.getBindTemporaryExpr()->getSubExpr()->getType();
689 // FIXME: Currently CleanDtorState can be empty here due to temporaries being
690 // bound to default parameters.
691 assert(CleanDtorState.size() <= 1);
692 ExplodedNode *CleanPred =
693 CleanDtorState.empty() ? Pred : *CleanDtorState.begin();
694 // FIXME: Inlining of temporary destructors is not supported yet anyway, so
695 // we just put a NULL region for now. This will need to be changed later.
696 VisitCXXDestructor(varType, nullptr, D.getBindTemporaryExpr(),
697 /*IsBase=*/false, CleanPred, Dst);
698 }
699
processCleanupTemporaryBranch(const CXXBindTemporaryExpr * BTE,NodeBuilderContext & BldCtx,ExplodedNode * Pred,ExplodedNodeSet & Dst,const CFGBlock * DstT,const CFGBlock * DstF)700 void ExprEngine::processCleanupTemporaryBranch(const CXXBindTemporaryExpr *BTE,
701 NodeBuilderContext &BldCtx,
702 ExplodedNode *Pred,
703 ExplodedNodeSet &Dst,
704 const CFGBlock *DstT,
705 const CFGBlock *DstF) {
706 BranchNodeBuilder TempDtorBuilder(Pred, Dst, BldCtx, DstT, DstF);
707 if (Pred->getState()->contains<InitializedTemporariesSet>(
708 std::make_pair(BTE, Pred->getStackFrame()))) {
709 TempDtorBuilder.markInfeasible(false);
710 TempDtorBuilder.generateNode(Pred->getState(), true, Pred);
711 } else {
712 TempDtorBuilder.markInfeasible(true);
713 TempDtorBuilder.generateNode(Pred->getState(), false, Pred);
714 }
715 }
716
VisitCXXBindTemporaryExpr(const CXXBindTemporaryExpr * BTE,ExplodedNodeSet & PreVisit,ExplodedNodeSet & Dst)717 void ExprEngine::VisitCXXBindTemporaryExpr(const CXXBindTemporaryExpr *BTE,
718 ExplodedNodeSet &PreVisit,
719 ExplodedNodeSet &Dst) {
720 if (!getAnalysisManager().options.includeTemporaryDtorsInCFG()) {
721 // In case we don't have temporary destructors in the CFG, do not mark
722 // the initialization - we would otherwise never clean it up.
723 Dst = PreVisit;
724 return;
725 }
726 StmtNodeBuilder StmtBldr(PreVisit, Dst, *currBldrCtx);
727 for (ExplodedNode *Node : PreVisit) {
728 ProgramStateRef State = Node->getState();
729
730 if (!State->contains<InitializedTemporariesSet>(
731 std::make_pair(BTE, Node->getStackFrame()))) {
732 // FIXME: Currently the state might already contain the marker due to
733 // incorrect handling of temporaries bound to default parameters; for
734 // those, we currently skip the CXXBindTemporaryExpr but rely on adding
735 // temporary destructor nodes.
736 State = State->add<InitializedTemporariesSet>(
737 std::make_pair(BTE, Node->getStackFrame()));
738 }
739 StmtBldr.generateNode(BTE, Node, State);
740 }
741 }
742
Visit(const Stmt * S,ExplodedNode * Pred,ExplodedNodeSet & DstTop)743 void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred,
744 ExplodedNodeSet &DstTop) {
745 PrettyStackTraceLoc CrashInfo(getContext().getSourceManager(),
746 S->getLocStart(),
747 "Error evaluating statement");
748 ExplodedNodeSet Dst;
749 StmtNodeBuilder Bldr(Pred, DstTop, *currBldrCtx);
750
751 assert(!isa<Expr>(S) || S == cast<Expr>(S)->IgnoreParens());
752
753 switch (S->getStmtClass()) {
754 // C++ and ARC stuff we don't support yet.
755 case Expr::ObjCIndirectCopyRestoreExprClass:
756 case Stmt::CXXDependentScopeMemberExprClass:
757 case Stmt::CXXTryStmtClass:
758 case Stmt::CXXTypeidExprClass:
759 case Stmt::CXXUuidofExprClass:
760 case Stmt::CXXFoldExprClass:
761 case Stmt::MSPropertyRefExprClass:
762 case Stmt::MSPropertySubscriptExprClass:
763 case Stmt::CXXUnresolvedConstructExprClass:
764 case Stmt::DependentScopeDeclRefExprClass:
765 case Stmt::ArrayTypeTraitExprClass:
766 case Stmt::ExpressionTraitExprClass:
767 case Stmt::UnresolvedLookupExprClass:
768 case Stmt::UnresolvedMemberExprClass:
769 case Stmt::TypoExprClass:
770 case Stmt::CXXNoexceptExprClass:
771 case Stmt::PackExpansionExprClass:
772 case Stmt::SubstNonTypeTemplateParmPackExprClass:
773 case Stmt::FunctionParmPackExprClass:
774 case Stmt::CoroutineBodyStmtClass:
775 case Stmt::CoawaitExprClass:
776 case Stmt::CoreturnStmtClass:
777 case Stmt::CoyieldExprClass:
778 case Stmt::SEHTryStmtClass:
779 case Stmt::SEHExceptStmtClass:
780 case Stmt::SEHLeaveStmtClass:
781 case Stmt::SEHFinallyStmtClass: {
782 const ExplodedNode *node = Bldr.generateSink(S, Pred, Pred->getState());
783 Engine.addAbortedBlock(node, currBldrCtx->getBlock());
784 break;
785 }
786
787 case Stmt::ParenExprClass:
788 llvm_unreachable("ParenExprs already handled.");
789 case Stmt::GenericSelectionExprClass:
790 llvm_unreachable("GenericSelectionExprs already handled.");
791 // Cases that should never be evaluated simply because they shouldn't
792 // appear in the CFG.
793 case Stmt::BreakStmtClass:
794 case Stmt::CaseStmtClass:
795 case Stmt::CompoundStmtClass:
796 case Stmt::ContinueStmtClass:
797 case Stmt::CXXForRangeStmtClass:
798 case Stmt::DefaultStmtClass:
799 case Stmt::DoStmtClass:
800 case Stmt::ForStmtClass:
801 case Stmt::GotoStmtClass:
802 case Stmt::IfStmtClass:
803 case Stmt::IndirectGotoStmtClass:
804 case Stmt::LabelStmtClass:
805 case Stmt::NoStmtClass:
806 case Stmt::NullStmtClass:
807 case Stmt::SwitchStmtClass:
808 case Stmt::WhileStmtClass:
809 case Expr::MSDependentExistsStmtClass:
810 case Stmt::CapturedStmtClass:
811 case Stmt::OMPParallelDirectiveClass:
812 case Stmt::OMPSimdDirectiveClass:
813 case Stmt::OMPForDirectiveClass:
814 case Stmt::OMPForSimdDirectiveClass:
815 case Stmt::OMPSectionsDirectiveClass:
816 case Stmt::OMPSectionDirectiveClass:
817 case Stmt::OMPSingleDirectiveClass:
818 case Stmt::OMPMasterDirectiveClass:
819 case Stmt::OMPCriticalDirectiveClass:
820 case Stmt::OMPParallelForDirectiveClass:
821 case Stmt::OMPParallelForSimdDirectiveClass:
822 case Stmt::OMPParallelSectionsDirectiveClass:
823 case Stmt::OMPTaskDirectiveClass:
824 case Stmt::OMPTaskyieldDirectiveClass:
825 case Stmt::OMPBarrierDirectiveClass:
826 case Stmt::OMPTaskwaitDirectiveClass:
827 case Stmt::OMPTaskgroupDirectiveClass:
828 case Stmt::OMPFlushDirectiveClass:
829 case Stmt::OMPOrderedDirectiveClass:
830 case Stmt::OMPAtomicDirectiveClass:
831 case Stmt::OMPTargetDirectiveClass:
832 case Stmt::OMPTargetDataDirectiveClass:
833 case Stmt::OMPTeamsDirectiveClass:
834 case Stmt::OMPCancellationPointDirectiveClass:
835 case Stmt::OMPCancelDirectiveClass:
836 case Stmt::OMPTaskLoopDirectiveClass:
837 case Stmt::OMPTaskLoopSimdDirectiveClass:
838 case Stmt::OMPDistributeDirectiveClass:
839 llvm_unreachable("Stmt should not be in analyzer evaluation loop");
840
841 case Stmt::ObjCSubscriptRefExprClass:
842 case Stmt::ObjCPropertyRefExprClass:
843 llvm_unreachable("These are handled by PseudoObjectExpr");
844
845 case Stmt::GNUNullExprClass: {
846 // GNU __null is a pointer-width integer, not an actual pointer.
847 ProgramStateRef state = Pred->getState();
848 state = state->BindExpr(S, Pred->getLocationContext(),
849 svalBuilder.makeIntValWithPtrWidth(0, false));
850 Bldr.generateNode(S, Pred, state);
851 break;
852 }
853
854 case Stmt::ObjCAtSynchronizedStmtClass:
855 Bldr.takeNodes(Pred);
856 VisitObjCAtSynchronizedStmt(cast<ObjCAtSynchronizedStmt>(S), Pred, Dst);
857 Bldr.addNodes(Dst);
858 break;
859
860 case Stmt::ExprWithCleanupsClass:
861 // Handled due to fully linearised CFG.
862 break;
863
864 case Stmt::CXXBindTemporaryExprClass: {
865 Bldr.takeNodes(Pred);
866 ExplodedNodeSet PreVisit;
867 getCheckerManager().runCheckersForPreStmt(PreVisit, Pred, S, *this);
868 ExplodedNodeSet Next;
869 VisitCXXBindTemporaryExpr(cast<CXXBindTemporaryExpr>(S), PreVisit, Next);
870 getCheckerManager().runCheckersForPostStmt(Dst, Next, S, *this);
871 Bldr.addNodes(Dst);
872 break;
873 }
874
875 // Cases not handled yet; but will handle some day.
876 case Stmt::DesignatedInitExprClass:
877 case Stmt::DesignatedInitUpdateExprClass:
878 case Stmt::ExtVectorElementExprClass:
879 case Stmt::ImaginaryLiteralClass:
880 case Stmt::ObjCAtCatchStmtClass:
881 case Stmt::ObjCAtFinallyStmtClass:
882 case Stmt::ObjCAtTryStmtClass:
883 case Stmt::ObjCAutoreleasePoolStmtClass:
884 case Stmt::ObjCEncodeExprClass:
885 case Stmt::ObjCIsaExprClass:
886 case Stmt::ObjCProtocolExprClass:
887 case Stmt::ObjCSelectorExprClass:
888 case Stmt::ParenListExprClass:
889 case Stmt::ShuffleVectorExprClass:
890 case Stmt::ConvertVectorExprClass:
891 case Stmt::VAArgExprClass:
892 case Stmt::CUDAKernelCallExprClass:
893 case Stmt::OpaqueValueExprClass:
894 case Stmt::AsTypeExprClass:
895 case Stmt::AtomicExprClass:
896 // Fall through.
897
898 // Cases we intentionally don't evaluate, since they don't need
899 // to be explicitly evaluated.
900 case Stmt::PredefinedExprClass:
901 case Stmt::AddrLabelExprClass:
902 case Stmt::AttributedStmtClass:
903 case Stmt::IntegerLiteralClass:
904 case Stmt::CharacterLiteralClass:
905 case Stmt::ImplicitValueInitExprClass:
906 case Stmt::CXXScalarValueInitExprClass:
907 case Stmt::CXXBoolLiteralExprClass:
908 case Stmt::ObjCBoolLiteralExprClass:
909 case Stmt::FloatingLiteralClass:
910 case Stmt::NoInitExprClass:
911 case Stmt::SizeOfPackExprClass:
912 case Stmt::StringLiteralClass:
913 case Stmt::ObjCStringLiteralClass:
914 case Stmt::CXXPseudoDestructorExprClass:
915 case Stmt::SubstNonTypeTemplateParmExprClass:
916 case Stmt::CXXNullPtrLiteralExprClass:
917 case Stmt::OMPArraySectionExprClass:
918 case Stmt::TypeTraitExprClass: {
919 Bldr.takeNodes(Pred);
920 ExplodedNodeSet preVisit;
921 getCheckerManager().runCheckersForPreStmt(preVisit, Pred, S, *this);
922 getCheckerManager().runCheckersForPostStmt(Dst, preVisit, S, *this);
923 Bldr.addNodes(Dst);
924 break;
925 }
926
927 case Stmt::CXXDefaultArgExprClass:
928 case Stmt::CXXDefaultInitExprClass: {
929 Bldr.takeNodes(Pred);
930 ExplodedNodeSet PreVisit;
931 getCheckerManager().runCheckersForPreStmt(PreVisit, Pred, S, *this);
932
933 ExplodedNodeSet Tmp;
934 StmtNodeBuilder Bldr2(PreVisit, Tmp, *currBldrCtx);
935
936 const Expr *ArgE;
937 if (const CXXDefaultArgExpr *DefE = dyn_cast<CXXDefaultArgExpr>(S))
938 ArgE = DefE->getExpr();
939 else if (const CXXDefaultInitExpr *DefE = dyn_cast<CXXDefaultInitExpr>(S))
940 ArgE = DefE->getExpr();
941 else
942 llvm_unreachable("unknown constant wrapper kind");
943
944 bool IsTemporary = false;
945 if (const MaterializeTemporaryExpr *MTE =
946 dyn_cast<MaterializeTemporaryExpr>(ArgE)) {
947 ArgE = MTE->GetTemporaryExpr();
948 IsTemporary = true;
949 }
950
951 Optional<SVal> ConstantVal = svalBuilder.getConstantVal(ArgE);
952 if (!ConstantVal)
953 ConstantVal = UnknownVal();
954
955 const LocationContext *LCtx = Pred->getLocationContext();
956 for (ExplodedNodeSet::iterator I = PreVisit.begin(), E = PreVisit.end();
957 I != E; ++I) {
958 ProgramStateRef State = (*I)->getState();
959 State = State->BindExpr(S, LCtx, *ConstantVal);
960 if (IsTemporary)
961 State = createTemporaryRegionIfNeeded(State, LCtx,
962 cast<Expr>(S),
963 cast<Expr>(S));
964 Bldr2.generateNode(S, *I, State);
965 }
966
967 getCheckerManager().runCheckersForPostStmt(Dst, Tmp, S, *this);
968 Bldr.addNodes(Dst);
969 break;
970 }
971
972 // Cases we evaluate as opaque expressions, conjuring a symbol.
973 case Stmt::CXXStdInitializerListExprClass:
974 case Expr::ObjCArrayLiteralClass:
975 case Expr::ObjCDictionaryLiteralClass:
976 case Expr::ObjCBoxedExprClass: {
977 Bldr.takeNodes(Pred);
978
979 ExplodedNodeSet preVisit;
980 getCheckerManager().runCheckersForPreStmt(preVisit, Pred, S, *this);
981
982 ExplodedNodeSet Tmp;
983 StmtNodeBuilder Bldr2(preVisit, Tmp, *currBldrCtx);
984
985 const Expr *Ex = cast<Expr>(S);
986 QualType resultType = Ex->getType();
987
988 for (ExplodedNodeSet::iterator it = preVisit.begin(), et = preVisit.end();
989 it != et; ++it) {
990 ExplodedNode *N = *it;
991 const LocationContext *LCtx = N->getLocationContext();
992 SVal result = svalBuilder.conjureSymbolVal(nullptr, Ex, LCtx,
993 resultType,
994 currBldrCtx->blockCount());
995 ProgramStateRef state = N->getState()->BindExpr(Ex, LCtx, result);
996 Bldr2.generateNode(S, N, state);
997 }
998
999 getCheckerManager().runCheckersForPostStmt(Dst, Tmp, S, *this);
1000 Bldr.addNodes(Dst);
1001 break;
1002 }
1003
1004 case Stmt::ArraySubscriptExprClass:
1005 Bldr.takeNodes(Pred);
1006 VisitLvalArraySubscriptExpr(cast<ArraySubscriptExpr>(S), Pred, Dst);
1007 Bldr.addNodes(Dst);
1008 break;
1009
1010 case Stmt::GCCAsmStmtClass:
1011 Bldr.takeNodes(Pred);
1012 VisitGCCAsmStmt(cast<GCCAsmStmt>(S), Pred, Dst);
1013 Bldr.addNodes(Dst);
1014 break;
1015
1016 case Stmt::MSAsmStmtClass:
1017 Bldr.takeNodes(Pred);
1018 VisitMSAsmStmt(cast<MSAsmStmt>(S), Pred, Dst);
1019 Bldr.addNodes(Dst);
1020 break;
1021
1022 case Stmt::BlockExprClass:
1023 Bldr.takeNodes(Pred);
1024 VisitBlockExpr(cast<BlockExpr>(S), Pred, Dst);
1025 Bldr.addNodes(Dst);
1026 break;
1027
1028 case Stmt::LambdaExprClass:
1029 if (AMgr.options.shouldInlineLambdas()) {
1030 Bldr.takeNodes(Pred);
1031 VisitLambdaExpr(cast<LambdaExpr>(S), Pred, Dst);
1032 Bldr.addNodes(Dst);
1033 } else {
1034 const ExplodedNode *node = Bldr.generateSink(S, Pred, Pred->getState());
1035 Engine.addAbortedBlock(node, currBldrCtx->getBlock());
1036 }
1037 break;
1038
1039 case Stmt::BinaryOperatorClass: {
1040 const BinaryOperator* B = cast<BinaryOperator>(S);
1041 if (B->isLogicalOp()) {
1042 Bldr.takeNodes(Pred);
1043 VisitLogicalExpr(B, Pred, Dst);
1044 Bldr.addNodes(Dst);
1045 break;
1046 }
1047 else if (B->getOpcode() == BO_Comma) {
1048 ProgramStateRef state = Pred->getState();
1049 Bldr.generateNode(B, Pred,
1050 state->BindExpr(B, Pred->getLocationContext(),
1051 state->getSVal(B->getRHS(),
1052 Pred->getLocationContext())));
1053 break;
1054 }
1055
1056 Bldr.takeNodes(Pred);
1057
1058 if (AMgr.options.eagerlyAssumeBinOpBifurcation &&
1059 (B->isRelationalOp() || B->isEqualityOp())) {
1060 ExplodedNodeSet Tmp;
1061 VisitBinaryOperator(cast<BinaryOperator>(S), Pred, Tmp);
1062 evalEagerlyAssumeBinOpBifurcation(Dst, Tmp, cast<Expr>(S));
1063 }
1064 else
1065 VisitBinaryOperator(cast<BinaryOperator>(S), Pred, Dst);
1066
1067 Bldr.addNodes(Dst);
1068 break;
1069 }
1070
1071 case Stmt::CXXOperatorCallExprClass: {
1072 const CXXOperatorCallExpr *OCE = cast<CXXOperatorCallExpr>(S);
1073
1074 // For instance method operators, make sure the 'this' argument has a
1075 // valid region.
1076 const Decl *Callee = OCE->getCalleeDecl();
1077 if (const CXXMethodDecl *MD = dyn_cast_or_null<CXXMethodDecl>(Callee)) {
1078 if (MD->isInstance()) {
1079 ProgramStateRef State = Pred->getState();
1080 const LocationContext *LCtx = Pred->getLocationContext();
1081 ProgramStateRef NewState =
1082 createTemporaryRegionIfNeeded(State, LCtx, OCE->getArg(0));
1083 if (NewState != State) {
1084 Pred = Bldr.generateNode(OCE, Pred, NewState, /*Tag=*/nullptr,
1085 ProgramPoint::PreStmtKind);
1086 // Did we cache out?
1087 if (!Pred)
1088 break;
1089 }
1090 }
1091 }
1092 // FALLTHROUGH
1093 }
1094 case Stmt::CallExprClass:
1095 case Stmt::CXXMemberCallExprClass:
1096 case Stmt::UserDefinedLiteralClass: {
1097 Bldr.takeNodes(Pred);
1098 VisitCallExpr(cast<CallExpr>(S), Pred, Dst);
1099 Bldr.addNodes(Dst);
1100 break;
1101 }
1102
1103 case Stmt::CXXCatchStmtClass: {
1104 Bldr.takeNodes(Pred);
1105 VisitCXXCatchStmt(cast<CXXCatchStmt>(S), Pred, Dst);
1106 Bldr.addNodes(Dst);
1107 break;
1108 }
1109
1110 case Stmt::CXXTemporaryObjectExprClass:
1111 case Stmt::CXXConstructExprClass: {
1112 Bldr.takeNodes(Pred);
1113 VisitCXXConstructExpr(cast<CXXConstructExpr>(S), Pred, Dst);
1114 Bldr.addNodes(Dst);
1115 break;
1116 }
1117
1118 case Stmt::CXXNewExprClass: {
1119 Bldr.takeNodes(Pred);
1120 ExplodedNodeSet PostVisit;
1121 VisitCXXNewExpr(cast<CXXNewExpr>(S), Pred, PostVisit);
1122 getCheckerManager().runCheckersForPostStmt(Dst, PostVisit, S, *this);
1123 Bldr.addNodes(Dst);
1124 break;
1125 }
1126
1127 case Stmt::CXXDeleteExprClass: {
1128 Bldr.takeNodes(Pred);
1129 ExplodedNodeSet PreVisit;
1130 const CXXDeleteExpr *CDE = cast<CXXDeleteExpr>(S);
1131 getCheckerManager().runCheckersForPreStmt(PreVisit, Pred, S, *this);
1132
1133 for (ExplodedNodeSet::iterator i = PreVisit.begin(),
1134 e = PreVisit.end(); i != e ; ++i)
1135 VisitCXXDeleteExpr(CDE, *i, Dst);
1136
1137 Bldr.addNodes(Dst);
1138 break;
1139 }
1140 // FIXME: ChooseExpr is really a constant. We need to fix
1141 // the CFG do not model them as explicit control-flow.
1142
1143 case Stmt::ChooseExprClass: { // __builtin_choose_expr
1144 Bldr.takeNodes(Pred);
1145 const ChooseExpr *C = cast<ChooseExpr>(S);
1146 VisitGuardedExpr(C, C->getLHS(), C->getRHS(), Pred, Dst);
1147 Bldr.addNodes(Dst);
1148 break;
1149 }
1150
1151 case Stmt::CompoundAssignOperatorClass:
1152 Bldr.takeNodes(Pred);
1153 VisitBinaryOperator(cast<BinaryOperator>(S), Pred, Dst);
1154 Bldr.addNodes(Dst);
1155 break;
1156
1157 case Stmt::CompoundLiteralExprClass:
1158 Bldr.takeNodes(Pred);
1159 VisitCompoundLiteralExpr(cast<CompoundLiteralExpr>(S), Pred, Dst);
1160 Bldr.addNodes(Dst);
1161 break;
1162
1163 case Stmt::BinaryConditionalOperatorClass:
1164 case Stmt::ConditionalOperatorClass: { // '?' operator
1165 Bldr.takeNodes(Pred);
1166 const AbstractConditionalOperator *C
1167 = cast<AbstractConditionalOperator>(S);
1168 VisitGuardedExpr(C, C->getTrueExpr(), C->getFalseExpr(), Pred, Dst);
1169 Bldr.addNodes(Dst);
1170 break;
1171 }
1172
1173 case Stmt::CXXThisExprClass:
1174 Bldr.takeNodes(Pred);
1175 VisitCXXThisExpr(cast<CXXThisExpr>(S), Pred, Dst);
1176 Bldr.addNodes(Dst);
1177 break;
1178
1179 case Stmt::DeclRefExprClass: {
1180 Bldr.takeNodes(Pred);
1181 const DeclRefExpr *DE = cast<DeclRefExpr>(S);
1182 VisitCommonDeclRefExpr(DE, DE->getDecl(), Pred, Dst);
1183 Bldr.addNodes(Dst);
1184 break;
1185 }
1186
1187 case Stmt::DeclStmtClass:
1188 Bldr.takeNodes(Pred);
1189 VisitDeclStmt(cast<DeclStmt>(S), Pred, Dst);
1190 Bldr.addNodes(Dst);
1191 break;
1192
1193 case Stmt::ImplicitCastExprClass:
1194 case Stmt::CStyleCastExprClass:
1195 case Stmt::CXXStaticCastExprClass:
1196 case Stmt::CXXDynamicCastExprClass:
1197 case Stmt::CXXReinterpretCastExprClass:
1198 case Stmt::CXXConstCastExprClass:
1199 case Stmt::CXXFunctionalCastExprClass:
1200 case Stmt::ObjCBridgedCastExprClass: {
1201 Bldr.takeNodes(Pred);
1202 const CastExpr *C = cast<CastExpr>(S);
1203 // Handle the previsit checks.
1204 ExplodedNodeSet dstPrevisit;
1205 getCheckerManager().runCheckersForPreStmt(dstPrevisit, Pred, C, *this);
1206
1207 // Handle the expression itself.
1208 ExplodedNodeSet dstExpr;
1209 for (ExplodedNodeSet::iterator i = dstPrevisit.begin(),
1210 e = dstPrevisit.end(); i != e ; ++i) {
1211 VisitCast(C, C->getSubExpr(), *i, dstExpr);
1212 }
1213
1214 // Handle the postvisit checks.
1215 getCheckerManager().runCheckersForPostStmt(Dst, dstExpr, C, *this);
1216 Bldr.addNodes(Dst);
1217 break;
1218 }
1219
1220 case Expr::MaterializeTemporaryExprClass: {
1221 Bldr.takeNodes(Pred);
1222 const MaterializeTemporaryExpr *MTE = cast<MaterializeTemporaryExpr>(S);
1223 CreateCXXTemporaryObject(MTE, Pred, Dst);
1224 Bldr.addNodes(Dst);
1225 break;
1226 }
1227
1228 case Stmt::InitListExprClass:
1229 Bldr.takeNodes(Pred);
1230 VisitInitListExpr(cast<InitListExpr>(S), Pred, Dst);
1231 Bldr.addNodes(Dst);
1232 break;
1233
1234 case Stmt::MemberExprClass:
1235 Bldr.takeNodes(Pred);
1236 VisitMemberExpr(cast<MemberExpr>(S), Pred, Dst);
1237 Bldr.addNodes(Dst);
1238 break;
1239
1240 case Stmt::ObjCIvarRefExprClass:
1241 Bldr.takeNodes(Pred);
1242 VisitLvalObjCIvarRefExpr(cast<ObjCIvarRefExpr>(S), Pred, Dst);
1243 Bldr.addNodes(Dst);
1244 break;
1245
1246 case Stmt::ObjCForCollectionStmtClass:
1247 Bldr.takeNodes(Pred);
1248 VisitObjCForCollectionStmt(cast<ObjCForCollectionStmt>(S), Pred, Dst);
1249 Bldr.addNodes(Dst);
1250 break;
1251
1252 case Stmt::ObjCMessageExprClass:
1253 Bldr.takeNodes(Pred);
1254 VisitObjCMessage(cast<ObjCMessageExpr>(S), Pred, Dst);
1255 Bldr.addNodes(Dst);
1256 break;
1257
1258 case Stmt::ObjCAtThrowStmtClass:
1259 case Stmt::CXXThrowExprClass:
1260 // FIXME: This is not complete. We basically treat @throw as
1261 // an abort.
1262 Bldr.generateSink(S, Pred, Pred->getState());
1263 break;
1264
1265 case Stmt::ReturnStmtClass:
1266 Bldr.takeNodes(Pred);
1267 VisitReturnStmt(cast<ReturnStmt>(S), Pred, Dst);
1268 Bldr.addNodes(Dst);
1269 break;
1270
1271 case Stmt::OffsetOfExprClass:
1272 Bldr.takeNodes(Pred);
1273 VisitOffsetOfExpr(cast<OffsetOfExpr>(S), Pred, Dst);
1274 Bldr.addNodes(Dst);
1275 break;
1276
1277 case Stmt::UnaryExprOrTypeTraitExprClass:
1278 Bldr.takeNodes(Pred);
1279 VisitUnaryExprOrTypeTraitExpr(cast<UnaryExprOrTypeTraitExpr>(S),
1280 Pred, Dst);
1281 Bldr.addNodes(Dst);
1282 break;
1283
1284 case Stmt::StmtExprClass: {
1285 const StmtExpr *SE = cast<StmtExpr>(S);
1286
1287 if (SE->getSubStmt()->body_empty()) {
1288 // Empty statement expression.
1289 assert(SE->getType() == getContext().VoidTy
1290 && "Empty statement expression must have void type.");
1291 break;
1292 }
1293
1294 if (Expr *LastExpr = dyn_cast<Expr>(*SE->getSubStmt()->body_rbegin())) {
1295 ProgramStateRef state = Pred->getState();
1296 Bldr.generateNode(SE, Pred,
1297 state->BindExpr(SE, Pred->getLocationContext(),
1298 state->getSVal(LastExpr,
1299 Pred->getLocationContext())));
1300 }
1301 break;
1302 }
1303
1304 case Stmt::UnaryOperatorClass: {
1305 Bldr.takeNodes(Pred);
1306 const UnaryOperator *U = cast<UnaryOperator>(S);
1307 if (AMgr.options.eagerlyAssumeBinOpBifurcation && (U->getOpcode() == UO_LNot)) {
1308 ExplodedNodeSet Tmp;
1309 VisitUnaryOperator(U, Pred, Tmp);
1310 evalEagerlyAssumeBinOpBifurcation(Dst, Tmp, U);
1311 }
1312 else
1313 VisitUnaryOperator(U, Pred, Dst);
1314 Bldr.addNodes(Dst);
1315 break;
1316 }
1317
1318 case Stmt::PseudoObjectExprClass: {
1319 Bldr.takeNodes(Pred);
1320 ProgramStateRef state = Pred->getState();
1321 const PseudoObjectExpr *PE = cast<PseudoObjectExpr>(S);
1322 if (const Expr *Result = PE->getResultExpr()) {
1323 SVal V = state->getSVal(Result, Pred->getLocationContext());
1324 Bldr.generateNode(S, Pred,
1325 state->BindExpr(S, Pred->getLocationContext(), V));
1326 }
1327 else
1328 Bldr.generateNode(S, Pred,
1329 state->BindExpr(S, Pred->getLocationContext(),
1330 UnknownVal()));
1331
1332 Bldr.addNodes(Dst);
1333 break;
1334 }
1335 }
1336 }
1337
replayWithoutInlining(ExplodedNode * N,const LocationContext * CalleeLC)1338 bool ExprEngine::replayWithoutInlining(ExplodedNode *N,
1339 const LocationContext *CalleeLC) {
1340 const StackFrameContext *CalleeSF = CalleeLC->getCurrentStackFrame();
1341 const StackFrameContext *CallerSF = CalleeSF->getParent()->getCurrentStackFrame();
1342 assert(CalleeSF && CallerSF);
1343 ExplodedNode *BeforeProcessingCall = nullptr;
1344 const Stmt *CE = CalleeSF->getCallSite();
1345
1346 // Find the first node before we started processing the call expression.
1347 while (N) {
1348 ProgramPoint L = N->getLocation();
1349 BeforeProcessingCall = N;
1350 N = N->pred_empty() ? nullptr : *(N->pred_begin());
1351
1352 // Skip the nodes corresponding to the inlined code.
1353 if (L.getLocationContext()->getCurrentStackFrame() != CallerSF)
1354 continue;
1355 // We reached the caller. Find the node right before we started
1356 // processing the call.
1357 if (L.isPurgeKind())
1358 continue;
1359 if (L.getAs<PreImplicitCall>())
1360 continue;
1361 if (L.getAs<CallEnter>())
1362 continue;
1363 if (Optional<StmtPoint> SP = L.getAs<StmtPoint>())
1364 if (SP->getStmt() == CE)
1365 continue;
1366 break;
1367 }
1368
1369 if (!BeforeProcessingCall)
1370 return false;
1371
1372 // TODO: Clean up the unneeded nodes.
1373
1374 // Build an Epsilon node from which we will restart the analyzes.
1375 // Note that CE is permitted to be NULL!
1376 ProgramPoint NewNodeLoc =
1377 EpsilonPoint(BeforeProcessingCall->getLocationContext(), CE);
1378 // Add the special flag to GDM to signal retrying with no inlining.
1379 // Note, changing the state ensures that we are not going to cache out.
1380 ProgramStateRef NewNodeState = BeforeProcessingCall->getState();
1381 NewNodeState =
1382 NewNodeState->set<ReplayWithoutInlining>(const_cast<Stmt *>(CE));
1383
1384 // Make the new node a successor of BeforeProcessingCall.
1385 bool IsNew = false;
1386 ExplodedNode *NewNode = G.getNode(NewNodeLoc, NewNodeState, false, &IsNew);
1387 // We cached out at this point. Caching out is common due to us backtracking
1388 // from the inlined function, which might spawn several paths.
1389 if (!IsNew)
1390 return true;
1391
1392 NewNode->addPredecessor(BeforeProcessingCall, G);
1393
1394 // Add the new node to the work list.
1395 Engine.enqueueStmtNode(NewNode, CalleeSF->getCallSiteBlock(),
1396 CalleeSF->getIndex());
1397 NumTimesRetriedWithoutInlining++;
1398 return true;
1399 }
1400
1401 /// Block entrance. (Update counters).
processCFGBlockEntrance(const BlockEdge & L,NodeBuilderWithSinks & nodeBuilder,ExplodedNode * Pred)1402 void ExprEngine::processCFGBlockEntrance(const BlockEdge &L,
1403 NodeBuilderWithSinks &nodeBuilder,
1404 ExplodedNode *Pred) {
1405 PrettyStackTraceLocationContext CrashInfo(Pred->getLocationContext());
1406
1407 // If this block is terminated by a loop and it has already been visited the
1408 // maximum number of times, widen the loop.
1409 unsigned int BlockCount = nodeBuilder.getContext().blockCount();
1410 if (BlockCount == AMgr.options.maxBlockVisitOnPath - 1 &&
1411 AMgr.options.shouldWidenLoops()) {
1412 const Stmt *Term = nodeBuilder.getContext().getBlock()->getTerminator();
1413 if (!(Term &&
1414 (isa<ForStmt>(Term) || isa<WhileStmt>(Term) || isa<DoStmt>(Term))))
1415 return;
1416 // Widen.
1417 const LocationContext *LCtx = Pred->getLocationContext();
1418 ProgramStateRef WidenedState =
1419 getWidenedLoopState(Pred->getState(), LCtx, BlockCount, Term);
1420 nodeBuilder.generateNode(WidenedState, Pred);
1421 return;
1422 }
1423
1424 // FIXME: Refactor this into a checker.
1425 if (BlockCount >= AMgr.options.maxBlockVisitOnPath) {
1426 static SimpleProgramPointTag tag(TagProviderName, "Block count exceeded");
1427 const ExplodedNode *Sink =
1428 nodeBuilder.generateSink(Pred->getState(), Pred, &tag);
1429
1430 // Check if we stopped at the top level function or not.
1431 // Root node should have the location context of the top most function.
1432 const LocationContext *CalleeLC = Pred->getLocation().getLocationContext();
1433 const LocationContext *CalleeSF = CalleeLC->getCurrentStackFrame();
1434 const LocationContext *RootLC =
1435 (*G.roots_begin())->getLocation().getLocationContext();
1436 if (RootLC->getCurrentStackFrame() != CalleeSF) {
1437 Engine.FunctionSummaries->markReachedMaxBlockCount(CalleeSF->getDecl());
1438
1439 // Re-run the call evaluation without inlining it, by storing the
1440 // no-inlining policy in the state and enqueuing the new work item on
1441 // the list. Replay should almost never fail. Use the stats to catch it
1442 // if it does.
1443 if ((!AMgr.options.NoRetryExhausted &&
1444 replayWithoutInlining(Pred, CalleeLC)))
1445 return;
1446 NumMaxBlockCountReachedInInlined++;
1447 } else
1448 NumMaxBlockCountReached++;
1449
1450 // Make sink nodes as exhausted(for stats) only if retry failed.
1451 Engine.blocksExhausted.push_back(std::make_pair(L, Sink));
1452 }
1453 }
1454
1455 //===----------------------------------------------------------------------===//
1456 // Branch processing.
1457 //===----------------------------------------------------------------------===//
1458
1459 /// RecoverCastedSymbol - A helper function for ProcessBranch that is used
1460 /// to try to recover some path-sensitivity for casts of symbolic
1461 /// integers that promote their values (which are currently not tracked well).
1462 /// This function returns the SVal bound to Condition->IgnoreCasts if all the
1463 // cast(s) did was sign-extend the original value.
RecoverCastedSymbol(ProgramStateManager & StateMgr,ProgramStateRef state,const Stmt * Condition,const LocationContext * LCtx,ASTContext & Ctx)1464 static SVal RecoverCastedSymbol(ProgramStateManager& StateMgr,
1465 ProgramStateRef state,
1466 const Stmt *Condition,
1467 const LocationContext *LCtx,
1468 ASTContext &Ctx) {
1469
1470 const Expr *Ex = dyn_cast<Expr>(Condition);
1471 if (!Ex)
1472 return UnknownVal();
1473
1474 uint64_t bits = 0;
1475 bool bitsInit = false;
1476
1477 while (const CastExpr *CE = dyn_cast<CastExpr>(Ex)) {
1478 QualType T = CE->getType();
1479
1480 if (!T->isIntegralOrEnumerationType())
1481 return UnknownVal();
1482
1483 uint64_t newBits = Ctx.getTypeSize(T);
1484 if (!bitsInit || newBits < bits) {
1485 bitsInit = true;
1486 bits = newBits;
1487 }
1488
1489 Ex = CE->getSubExpr();
1490 }
1491
1492 // We reached a non-cast. Is it a symbolic value?
1493 QualType T = Ex->getType();
1494
1495 if (!bitsInit || !T->isIntegralOrEnumerationType() ||
1496 Ctx.getTypeSize(T) > bits)
1497 return UnknownVal();
1498
1499 return state->getSVal(Ex, LCtx);
1500 }
1501
1502 #ifndef NDEBUG
getRightmostLeaf(const Stmt * Condition)1503 static const Stmt *getRightmostLeaf(const Stmt *Condition) {
1504 while (Condition) {
1505 const BinaryOperator *BO = dyn_cast<BinaryOperator>(Condition);
1506 if (!BO || !BO->isLogicalOp()) {
1507 return Condition;
1508 }
1509 Condition = BO->getRHS()->IgnoreParens();
1510 }
1511 return nullptr;
1512 }
1513 #endif
1514
1515 // Returns the condition the branch at the end of 'B' depends on and whose value
1516 // has been evaluated within 'B'.
1517 // In most cases, the terminator condition of 'B' will be evaluated fully in
1518 // the last statement of 'B'; in those cases, the resolved condition is the
1519 // given 'Condition'.
1520 // If the condition of the branch is a logical binary operator tree, the CFG is
1521 // optimized: in that case, we know that the expression formed by all but the
1522 // rightmost leaf of the logical binary operator tree must be true, and thus
1523 // the branch condition is at this point equivalent to the truth value of that
1524 // rightmost leaf; the CFG block thus only evaluates this rightmost leaf
1525 // expression in its final statement. As the full condition in that case was
1526 // not evaluated, and is thus not in the SVal cache, we need to use that leaf
1527 // expression to evaluate the truth value of the condition in the current state
1528 // space.
ResolveCondition(const Stmt * Condition,const CFGBlock * B)1529 static const Stmt *ResolveCondition(const Stmt *Condition,
1530 const CFGBlock *B) {
1531 if (const Expr *Ex = dyn_cast<Expr>(Condition))
1532 Condition = Ex->IgnoreParens();
1533
1534 const BinaryOperator *BO = dyn_cast<BinaryOperator>(Condition);
1535 if (!BO || !BO->isLogicalOp())
1536 return Condition;
1537
1538 assert(!B->getTerminator().isTemporaryDtorsBranch() &&
1539 "Temporary destructor branches handled by processBindTemporary.");
1540
1541 // For logical operations, we still have the case where some branches
1542 // use the traditional "merge" approach and others sink the branch
1543 // directly into the basic blocks representing the logical operation.
1544 // We need to distinguish between those two cases here.
1545
1546 // The invariants are still shifting, but it is possible that the
1547 // last element in a CFGBlock is not a CFGStmt. Look for the last
1548 // CFGStmt as the value of the condition.
1549 CFGBlock::const_reverse_iterator I = B->rbegin(), E = B->rend();
1550 for (; I != E; ++I) {
1551 CFGElement Elem = *I;
1552 Optional<CFGStmt> CS = Elem.getAs<CFGStmt>();
1553 if (!CS)
1554 continue;
1555 const Stmt *LastStmt = CS->getStmt();
1556 assert(LastStmt == Condition || LastStmt == getRightmostLeaf(Condition));
1557 return LastStmt;
1558 }
1559 llvm_unreachable("could not resolve condition");
1560 }
1561
processBranch(const Stmt * Condition,const Stmt * Term,NodeBuilderContext & BldCtx,ExplodedNode * Pred,ExplodedNodeSet & Dst,const CFGBlock * DstT,const CFGBlock * DstF)1562 void ExprEngine::processBranch(const Stmt *Condition, const Stmt *Term,
1563 NodeBuilderContext& BldCtx,
1564 ExplodedNode *Pred,
1565 ExplodedNodeSet &Dst,
1566 const CFGBlock *DstT,
1567 const CFGBlock *DstF) {
1568 assert((!Condition || !isa<CXXBindTemporaryExpr>(Condition)) &&
1569 "CXXBindTemporaryExprs are handled by processBindTemporary.");
1570 const LocationContext *LCtx = Pred->getLocationContext();
1571 PrettyStackTraceLocationContext StackCrashInfo(LCtx);
1572 currBldrCtx = &BldCtx;
1573
1574 // Check for NULL conditions; e.g. "for(;;)"
1575 if (!Condition) {
1576 BranchNodeBuilder NullCondBldr(Pred, Dst, BldCtx, DstT, DstF);
1577 NullCondBldr.markInfeasible(false);
1578 NullCondBldr.generateNode(Pred->getState(), true, Pred);
1579 return;
1580 }
1581
1582 if (const Expr *Ex = dyn_cast<Expr>(Condition))
1583 Condition = Ex->IgnoreParens();
1584
1585 Condition = ResolveCondition(Condition, BldCtx.getBlock());
1586 PrettyStackTraceLoc CrashInfo(getContext().getSourceManager(),
1587 Condition->getLocStart(),
1588 "Error evaluating branch");
1589
1590 ExplodedNodeSet CheckersOutSet;
1591 getCheckerManager().runCheckersForBranchCondition(Condition, CheckersOutSet,
1592 Pred, *this);
1593 // We generated only sinks.
1594 if (CheckersOutSet.empty())
1595 return;
1596
1597 BranchNodeBuilder builder(CheckersOutSet, Dst, BldCtx, DstT, DstF);
1598 for (NodeBuilder::iterator I = CheckersOutSet.begin(),
1599 E = CheckersOutSet.end(); E != I; ++I) {
1600 ExplodedNode *PredI = *I;
1601
1602 if (PredI->isSink())
1603 continue;
1604
1605 ProgramStateRef PrevState = PredI->getState();
1606 SVal X = PrevState->getSVal(Condition, PredI->getLocationContext());
1607
1608 if (X.isUnknownOrUndef()) {
1609 // Give it a chance to recover from unknown.
1610 if (const Expr *Ex = dyn_cast<Expr>(Condition)) {
1611 if (Ex->getType()->isIntegralOrEnumerationType()) {
1612 // Try to recover some path-sensitivity. Right now casts of symbolic
1613 // integers that promote their values are currently not tracked well.
1614 // If 'Condition' is such an expression, try and recover the
1615 // underlying value and use that instead.
1616 SVal recovered = RecoverCastedSymbol(getStateManager(),
1617 PrevState, Condition,
1618 PredI->getLocationContext(),
1619 getContext());
1620
1621 if (!recovered.isUnknown()) {
1622 X = recovered;
1623 }
1624 }
1625 }
1626 }
1627
1628 // If the condition is still unknown, give up.
1629 if (X.isUnknownOrUndef()) {
1630 builder.generateNode(PrevState, true, PredI);
1631 builder.generateNode(PrevState, false, PredI);
1632 continue;
1633 }
1634
1635 DefinedSVal V = X.castAs<DefinedSVal>();
1636
1637 ProgramStateRef StTrue, StFalse;
1638 std::tie(StTrue, StFalse) = PrevState->assume(V);
1639
1640 // Process the true branch.
1641 if (builder.isFeasible(true)) {
1642 if (StTrue)
1643 builder.generateNode(StTrue, true, PredI);
1644 else
1645 builder.markInfeasible(true);
1646 }
1647
1648 // Process the false branch.
1649 if (builder.isFeasible(false)) {
1650 if (StFalse)
1651 builder.generateNode(StFalse, false, PredI);
1652 else
1653 builder.markInfeasible(false);
1654 }
1655 }
1656 currBldrCtx = nullptr;
1657 }
1658
1659 /// The GDM component containing the set of global variables which have been
1660 /// previously initialized with explicit initializers.
REGISTER_TRAIT_WITH_PROGRAMSTATE(InitializedGlobalsSet,llvm::ImmutableSet<const VarDecl * >)1661 REGISTER_TRAIT_WITH_PROGRAMSTATE(InitializedGlobalsSet,
1662 llvm::ImmutableSet<const VarDecl *>)
1663
1664 void ExprEngine::processStaticInitializer(const DeclStmt *DS,
1665 NodeBuilderContext &BuilderCtx,
1666 ExplodedNode *Pred,
1667 clang::ento::ExplodedNodeSet &Dst,
1668 const CFGBlock *DstT,
1669 const CFGBlock *DstF) {
1670 PrettyStackTraceLocationContext CrashInfo(Pred->getLocationContext());
1671 currBldrCtx = &BuilderCtx;
1672
1673 const VarDecl *VD = cast<VarDecl>(DS->getSingleDecl());
1674 ProgramStateRef state = Pred->getState();
1675 bool initHasRun = state->contains<InitializedGlobalsSet>(VD);
1676 BranchNodeBuilder builder(Pred, Dst, BuilderCtx, DstT, DstF);
1677
1678 if (!initHasRun) {
1679 state = state->add<InitializedGlobalsSet>(VD);
1680 }
1681
1682 builder.generateNode(state, initHasRun, Pred);
1683 builder.markInfeasible(!initHasRun);
1684
1685 currBldrCtx = nullptr;
1686 }
1687
1688 /// processIndirectGoto - Called by CoreEngine. Used to generate successor
1689 /// nodes by processing the 'effects' of a computed goto jump.
processIndirectGoto(IndirectGotoNodeBuilder & builder)1690 void ExprEngine::processIndirectGoto(IndirectGotoNodeBuilder &builder) {
1691
1692 ProgramStateRef state = builder.getState();
1693 SVal V = state->getSVal(builder.getTarget(), builder.getLocationContext());
1694
1695 // Three possibilities:
1696 //
1697 // (1) We know the computed label.
1698 // (2) The label is NULL (or some other constant), or Undefined.
1699 // (3) We have no clue about the label. Dispatch to all targets.
1700 //
1701
1702 typedef IndirectGotoNodeBuilder::iterator iterator;
1703
1704 if (Optional<loc::GotoLabel> LV = V.getAs<loc::GotoLabel>()) {
1705 const LabelDecl *L = LV->getLabel();
1706
1707 for (iterator I = builder.begin(), E = builder.end(); I != E; ++I) {
1708 if (I.getLabel() == L) {
1709 builder.generateNode(I, state);
1710 return;
1711 }
1712 }
1713
1714 llvm_unreachable("No block with label.");
1715 }
1716
1717 if (V.getAs<loc::ConcreteInt>() || V.getAs<UndefinedVal>()) {
1718 // Dispatch to the first target and mark it as a sink.
1719 //ExplodedNode* N = builder.generateNode(builder.begin(), state, true);
1720 // FIXME: add checker visit.
1721 // UndefBranches.insert(N);
1722 return;
1723 }
1724
1725 // This is really a catch-all. We don't support symbolics yet.
1726 // FIXME: Implement dispatch for symbolic pointers.
1727
1728 for (iterator I=builder.begin(), E=builder.end(); I != E; ++I)
1729 builder.generateNode(I, state);
1730 }
1731
1732 #if 0
1733 static bool stackFrameDoesNotContainInitializedTemporaries(ExplodedNode &Pred) {
1734 const StackFrameContext* Frame = Pred.getStackFrame();
1735 const llvm::ImmutableSet<CXXBindTemporaryContext> &Set =
1736 Pred.getState()->get<InitializedTemporariesSet>();
1737 return std::find_if(Set.begin(), Set.end(),
1738 [&](const CXXBindTemporaryContext &Ctx) {
1739 if (Ctx.second == Frame) {
1740 Ctx.first->dump();
1741 llvm::errs() << "\n";
1742 }
1743 return Ctx.second == Frame;
1744 }) == Set.end();
1745 }
1746 #endif
1747
1748 /// ProcessEndPath - Called by CoreEngine. Used to generate end-of-path
1749 /// nodes when the control reaches the end of a function.
processEndOfFunction(NodeBuilderContext & BC,ExplodedNode * Pred)1750 void ExprEngine::processEndOfFunction(NodeBuilderContext& BC,
1751 ExplodedNode *Pred) {
1752 // FIXME: Assert that stackFrameDoesNotContainInitializedTemporaries(*Pred)).
1753 // We currently cannot enable this assert, as lifetime extended temporaries
1754 // are not modelled correctly.
1755 PrettyStackTraceLocationContext CrashInfo(Pred->getLocationContext());
1756 StateMgr.EndPath(Pred->getState());
1757
1758 ExplodedNodeSet Dst;
1759 if (Pred->getLocationContext()->inTopFrame()) {
1760 // Remove dead symbols.
1761 ExplodedNodeSet AfterRemovedDead;
1762 removeDeadOnEndOfFunction(BC, Pred, AfterRemovedDead);
1763
1764 // Notify checkers.
1765 for (ExplodedNodeSet::iterator I = AfterRemovedDead.begin(),
1766 E = AfterRemovedDead.end(); I != E; ++I) {
1767 getCheckerManager().runCheckersForEndFunction(BC, Dst, *I, *this);
1768 }
1769 } else {
1770 getCheckerManager().runCheckersForEndFunction(BC, Dst, Pred, *this);
1771 }
1772
1773 Engine.enqueueEndOfFunction(Dst);
1774 }
1775
1776 /// ProcessSwitch - Called by CoreEngine. Used to generate successor
1777 /// nodes by processing the 'effects' of a switch statement.
processSwitch(SwitchNodeBuilder & builder)1778 void ExprEngine::processSwitch(SwitchNodeBuilder& builder) {
1779 typedef SwitchNodeBuilder::iterator iterator;
1780 ProgramStateRef state = builder.getState();
1781 const Expr *CondE = builder.getCondition();
1782 SVal CondV_untested = state->getSVal(CondE, builder.getLocationContext());
1783
1784 if (CondV_untested.isUndef()) {
1785 //ExplodedNode* N = builder.generateDefaultCaseNode(state, true);
1786 // FIXME: add checker
1787 //UndefBranches.insert(N);
1788
1789 return;
1790 }
1791 DefinedOrUnknownSVal CondV = CondV_untested.castAs<DefinedOrUnknownSVal>();
1792
1793 ProgramStateRef DefaultSt = state;
1794
1795 iterator I = builder.begin(), EI = builder.end();
1796 bool defaultIsFeasible = I == EI;
1797
1798 for ( ; I != EI; ++I) {
1799 // Successor may be pruned out during CFG construction.
1800 if (!I.getBlock())
1801 continue;
1802
1803 const CaseStmt *Case = I.getCase();
1804
1805 // Evaluate the LHS of the case value.
1806 llvm::APSInt V1 = Case->getLHS()->EvaluateKnownConstInt(getContext());
1807 assert(V1.getBitWidth() == getContext().getTypeSize(CondE->getType()));
1808
1809 // Get the RHS of the case, if it exists.
1810 llvm::APSInt V2;
1811 if (const Expr *E = Case->getRHS())
1812 V2 = E->EvaluateKnownConstInt(getContext());
1813 else
1814 V2 = V1;
1815
1816 ProgramStateRef StateCase;
1817 if (Optional<NonLoc> NL = CondV.getAs<NonLoc>())
1818 std::tie(StateCase, DefaultSt) =
1819 DefaultSt->assumeWithinInclusiveRange(*NL, V1, V2);
1820 else // UnknownVal
1821 StateCase = DefaultSt;
1822
1823 if (StateCase)
1824 builder.generateCaseStmtNode(I, StateCase);
1825
1826 // Now "assume" that the case doesn't match. Add this state
1827 // to the default state (if it is feasible).
1828 if (DefaultSt)
1829 defaultIsFeasible = true;
1830 else {
1831 defaultIsFeasible = false;
1832 break;
1833 }
1834 }
1835
1836 if (!defaultIsFeasible)
1837 return;
1838
1839 // If we have switch(enum value), the default branch is not
1840 // feasible if all of the enum constants not covered by 'case:' statements
1841 // are not feasible values for the switch condition.
1842 //
1843 // Note that this isn't as accurate as it could be. Even if there isn't
1844 // a case for a particular enum value as long as that enum value isn't
1845 // feasible then it shouldn't be considered for making 'default:' reachable.
1846 const SwitchStmt *SS = builder.getSwitch();
1847 const Expr *CondExpr = SS->getCond()->IgnoreParenImpCasts();
1848 if (CondExpr->getType()->getAs<EnumType>()) {
1849 if (SS->isAllEnumCasesCovered())
1850 return;
1851 }
1852
1853 builder.generateDefaultCaseNode(DefaultSt);
1854 }
1855
1856 //===----------------------------------------------------------------------===//
1857 // Transfer functions: Loads and stores.
1858 //===----------------------------------------------------------------------===//
1859
VisitCommonDeclRefExpr(const Expr * Ex,const NamedDecl * D,ExplodedNode * Pred,ExplodedNodeSet & Dst)1860 void ExprEngine::VisitCommonDeclRefExpr(const Expr *Ex, const NamedDecl *D,
1861 ExplodedNode *Pred,
1862 ExplodedNodeSet &Dst) {
1863 StmtNodeBuilder Bldr(Pred, Dst, *currBldrCtx);
1864
1865 ProgramStateRef state = Pred->getState();
1866 const LocationContext *LCtx = Pred->getLocationContext();
1867
1868 if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
1869 // C permits "extern void v", and if you cast the address to a valid type,
1870 // you can even do things with it. We simply pretend
1871 assert(Ex->isGLValue() || VD->getType()->isVoidType());
1872 const LocationContext *LocCtxt = Pred->getLocationContext();
1873 const Decl *D = LocCtxt->getDecl();
1874 const auto *MD = D ? dyn_cast<CXXMethodDecl>(D) : nullptr;
1875 const auto *DeclRefEx = dyn_cast<DeclRefExpr>(Ex);
1876 SVal V;
1877 bool IsReference;
1878 if (AMgr.options.shouldInlineLambdas() && DeclRefEx &&
1879 DeclRefEx->refersToEnclosingVariableOrCapture() && MD &&
1880 MD->getParent()->isLambda()) {
1881 // Lookup the field of the lambda.
1882 const CXXRecordDecl *CXXRec = MD->getParent();
1883 llvm::DenseMap<const VarDecl *, FieldDecl *> LambdaCaptureFields;
1884 FieldDecl *LambdaThisCaptureField;
1885 CXXRec->getCaptureFields(LambdaCaptureFields, LambdaThisCaptureField);
1886 const FieldDecl *FD = LambdaCaptureFields[VD];
1887 if (!FD) {
1888 // When a constant is captured, sometimes no corresponding field is
1889 // created in the lambda object.
1890 assert(VD->getType().isConstQualified());
1891 V = state->getLValue(VD, LocCtxt);
1892 IsReference = false;
1893 } else {
1894 Loc CXXThis =
1895 svalBuilder.getCXXThis(MD, LocCtxt->getCurrentStackFrame());
1896 SVal CXXThisVal = state->getSVal(CXXThis);
1897 V = state->getLValue(FD, CXXThisVal);
1898 IsReference = FD->getType()->isReferenceType();
1899 }
1900 } else {
1901 V = state->getLValue(VD, LocCtxt);
1902 IsReference = VD->getType()->isReferenceType();
1903 }
1904
1905 // For references, the 'lvalue' is the pointer address stored in the
1906 // reference region.
1907 if (IsReference) {
1908 if (const MemRegion *R = V.getAsRegion())
1909 V = state->getSVal(R);
1910 else
1911 V = UnknownVal();
1912 }
1913
1914 Bldr.generateNode(Ex, Pred, state->BindExpr(Ex, LCtx, V), nullptr,
1915 ProgramPoint::PostLValueKind);
1916 return;
1917 }
1918 if (const EnumConstantDecl *ED = dyn_cast<EnumConstantDecl>(D)) {
1919 assert(!Ex->isGLValue());
1920 SVal V = svalBuilder.makeIntVal(ED->getInitVal());
1921 Bldr.generateNode(Ex, Pred, state->BindExpr(Ex, LCtx, V));
1922 return;
1923 }
1924 if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
1925 SVal V = svalBuilder.getFunctionPointer(FD);
1926 Bldr.generateNode(Ex, Pred, state->BindExpr(Ex, LCtx, V), nullptr,
1927 ProgramPoint::PostLValueKind);
1928 return;
1929 }
1930 if (isa<FieldDecl>(D)) {
1931 // FIXME: Compute lvalue of field pointers-to-member.
1932 // Right now we just use a non-null void pointer, so that it gives proper
1933 // results in boolean contexts.
1934 SVal V = svalBuilder.conjureSymbolVal(Ex, LCtx, getContext().VoidPtrTy,
1935 currBldrCtx->blockCount());
1936 state = state->assume(V.castAs<DefinedOrUnknownSVal>(), true);
1937 Bldr.generateNode(Ex, Pred, state->BindExpr(Ex, LCtx, V), nullptr,
1938 ProgramPoint::PostLValueKind);
1939 return;
1940 }
1941
1942 llvm_unreachable("Support for this Decl not implemented.");
1943 }
1944
1945 /// VisitArraySubscriptExpr - Transfer function for array accesses
VisitLvalArraySubscriptExpr(const ArraySubscriptExpr * A,ExplodedNode * Pred,ExplodedNodeSet & Dst)1946 void ExprEngine::VisitLvalArraySubscriptExpr(const ArraySubscriptExpr *A,
1947 ExplodedNode *Pred,
1948 ExplodedNodeSet &Dst){
1949
1950 const Expr *Base = A->getBase()->IgnoreParens();
1951 const Expr *Idx = A->getIdx()->IgnoreParens();
1952
1953 ExplodedNodeSet checkerPreStmt;
1954 getCheckerManager().runCheckersForPreStmt(checkerPreStmt, Pred, A, *this);
1955
1956 StmtNodeBuilder Bldr(checkerPreStmt, Dst, *currBldrCtx);
1957 assert(A->isGLValue() ||
1958 (!AMgr.getLangOpts().CPlusPlus &&
1959 A->getType().isCForbiddenLValueType()));
1960
1961 for (ExplodedNodeSet::iterator it = checkerPreStmt.begin(),
1962 ei = checkerPreStmt.end(); it != ei; ++it) {
1963 const LocationContext *LCtx = (*it)->getLocationContext();
1964 ProgramStateRef state = (*it)->getState();
1965 SVal V = state->getLValue(A->getType(),
1966 state->getSVal(Idx, LCtx),
1967 state->getSVal(Base, LCtx));
1968 Bldr.generateNode(A, *it, state->BindExpr(A, LCtx, V), nullptr,
1969 ProgramPoint::PostLValueKind);
1970 }
1971 }
1972
1973 /// VisitMemberExpr - Transfer function for member expressions.
VisitMemberExpr(const MemberExpr * M,ExplodedNode * Pred,ExplodedNodeSet & Dst)1974 void ExprEngine::VisitMemberExpr(const MemberExpr *M, ExplodedNode *Pred,
1975 ExplodedNodeSet &Dst) {
1976
1977 // FIXME: Prechecks eventually go in ::Visit().
1978 ExplodedNodeSet CheckedSet;
1979 getCheckerManager().runCheckersForPreStmt(CheckedSet, Pred, M, *this);
1980
1981 ExplodedNodeSet EvalSet;
1982 ValueDecl *Member = M->getMemberDecl();
1983
1984 // Handle static member variables and enum constants accessed via
1985 // member syntax.
1986 if (isa<VarDecl>(Member) || isa<EnumConstantDecl>(Member)) {
1987 ExplodedNodeSet Dst;
1988 for (ExplodedNodeSet::iterator I = CheckedSet.begin(), E = CheckedSet.end();
1989 I != E; ++I) {
1990 VisitCommonDeclRefExpr(M, Member, Pred, EvalSet);
1991 }
1992 } else {
1993 StmtNodeBuilder Bldr(CheckedSet, EvalSet, *currBldrCtx);
1994 ExplodedNodeSet Tmp;
1995
1996 for (ExplodedNodeSet::iterator I = CheckedSet.begin(), E = CheckedSet.end();
1997 I != E; ++I) {
1998 ProgramStateRef state = (*I)->getState();
1999 const LocationContext *LCtx = (*I)->getLocationContext();
2000 Expr *BaseExpr = M->getBase();
2001
2002 // Handle C++ method calls.
2003 if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(Member)) {
2004 if (MD->isInstance())
2005 state = createTemporaryRegionIfNeeded(state, LCtx, BaseExpr);
2006
2007 SVal MDVal = svalBuilder.getFunctionPointer(MD);
2008 state = state->BindExpr(M, LCtx, MDVal);
2009
2010 Bldr.generateNode(M, *I, state);
2011 continue;
2012 }
2013
2014 // Handle regular struct fields / member variables.
2015 state = createTemporaryRegionIfNeeded(state, LCtx, BaseExpr);
2016 SVal baseExprVal = state->getSVal(BaseExpr, LCtx);
2017
2018 FieldDecl *field = cast<FieldDecl>(Member);
2019 SVal L = state->getLValue(field, baseExprVal);
2020
2021 if (M->isGLValue() || M->getType()->isArrayType()) {
2022 // We special-case rvalues of array type because the analyzer cannot
2023 // reason about them, since we expect all regions to be wrapped in Locs.
2024 // We instead treat these as lvalues and assume that they will decay to
2025 // pointers as soon as they are used.
2026 if (!M->isGLValue()) {
2027 assert(M->getType()->isArrayType());
2028 const ImplicitCastExpr *PE =
2029 dyn_cast<ImplicitCastExpr>((*I)->getParentMap().getParent(M));
2030 if (!PE || PE->getCastKind() != CK_ArrayToPointerDecay) {
2031 llvm_unreachable("should always be wrapped in ArrayToPointerDecay");
2032 }
2033 }
2034
2035 if (field->getType()->isReferenceType()) {
2036 if (const MemRegion *R = L.getAsRegion())
2037 L = state->getSVal(R);
2038 else
2039 L = UnknownVal();
2040 }
2041
2042 Bldr.generateNode(M, *I, state->BindExpr(M, LCtx, L), nullptr,
2043 ProgramPoint::PostLValueKind);
2044 } else {
2045 Bldr.takeNodes(*I);
2046 evalLoad(Tmp, M, M, *I, state, L);
2047 Bldr.addNodes(Tmp);
2048 }
2049 }
2050 }
2051
2052 getCheckerManager().runCheckersForPostStmt(Dst, EvalSet, M, *this);
2053 }
2054
2055 namespace {
2056 class CollectReachableSymbolsCallback final : public SymbolVisitor {
2057 InvalidatedSymbols Symbols;
2058
2059 public:
CollectReachableSymbolsCallback(ProgramStateRef State)2060 CollectReachableSymbolsCallback(ProgramStateRef State) {}
getSymbols() const2061 const InvalidatedSymbols &getSymbols() const { return Symbols; }
2062
VisitSymbol(SymbolRef Sym)2063 bool VisitSymbol(SymbolRef Sym) override {
2064 Symbols.insert(Sym);
2065 return true;
2066 }
2067 };
2068 } // end anonymous namespace
2069
2070 // A value escapes in three possible cases:
2071 // (1) We are binding to something that is not a memory region.
2072 // (2) We are binding to a MemrRegion that does not have stack storage.
2073 // (3) We are binding to a MemRegion with stack storage that the store
2074 // does not understand.
processPointerEscapedOnBind(ProgramStateRef State,SVal Loc,SVal Val)2075 ProgramStateRef ExprEngine::processPointerEscapedOnBind(ProgramStateRef State,
2076 SVal Loc, SVal Val) {
2077 // Are we storing to something that causes the value to "escape"?
2078 bool escapes = true;
2079
2080 // TODO: Move to StoreManager.
2081 if (Optional<loc::MemRegionVal> regionLoc = Loc.getAs<loc::MemRegionVal>()) {
2082 escapes = !regionLoc->getRegion()->hasStackStorage();
2083
2084 if (!escapes) {
2085 // To test (3), generate a new state with the binding added. If it is
2086 // the same state, then it escapes (since the store cannot represent
2087 // the binding).
2088 // Do this only if we know that the store is not supposed to generate the
2089 // same state.
2090 SVal StoredVal = State->getSVal(regionLoc->getRegion());
2091 if (StoredVal != Val)
2092 escapes = (State == (State->bindLoc(*regionLoc, Val)));
2093 }
2094 }
2095
2096 // If our store can represent the binding and we aren't storing to something
2097 // that doesn't have local storage then just return and have the simulation
2098 // state continue as is.
2099 if (!escapes)
2100 return State;
2101
2102 // Otherwise, find all symbols referenced by 'val' that we are tracking
2103 // and stop tracking them.
2104 CollectReachableSymbolsCallback Scanner =
2105 State->scanReachableSymbols<CollectReachableSymbolsCallback>(Val);
2106 const InvalidatedSymbols &EscapedSymbols = Scanner.getSymbols();
2107 State = getCheckerManager().runCheckersForPointerEscape(State,
2108 EscapedSymbols,
2109 /*CallEvent*/ nullptr,
2110 PSK_EscapeOnBind,
2111 nullptr);
2112
2113 return State;
2114 }
2115
2116 ProgramStateRef
notifyCheckersOfPointerEscape(ProgramStateRef State,const InvalidatedSymbols * Invalidated,ArrayRef<const MemRegion * > ExplicitRegions,ArrayRef<const MemRegion * > Regions,const CallEvent * Call,RegionAndSymbolInvalidationTraits & ITraits)2117 ExprEngine::notifyCheckersOfPointerEscape(ProgramStateRef State,
2118 const InvalidatedSymbols *Invalidated,
2119 ArrayRef<const MemRegion *> ExplicitRegions,
2120 ArrayRef<const MemRegion *> Regions,
2121 const CallEvent *Call,
2122 RegionAndSymbolInvalidationTraits &ITraits) {
2123
2124 if (!Invalidated || Invalidated->empty())
2125 return State;
2126
2127 if (!Call)
2128 return getCheckerManager().runCheckersForPointerEscape(State,
2129 *Invalidated,
2130 nullptr,
2131 PSK_EscapeOther,
2132 &ITraits);
2133
2134 // If the symbols were invalidated by a call, we want to find out which ones
2135 // were invalidated directly due to being arguments to the call.
2136 InvalidatedSymbols SymbolsDirectlyInvalidated;
2137 for (ArrayRef<const MemRegion *>::iterator I = ExplicitRegions.begin(),
2138 E = ExplicitRegions.end(); I != E; ++I) {
2139 if (const SymbolicRegion *R = (*I)->StripCasts()->getAs<SymbolicRegion>())
2140 SymbolsDirectlyInvalidated.insert(R->getSymbol());
2141 }
2142
2143 InvalidatedSymbols SymbolsIndirectlyInvalidated;
2144 for (InvalidatedSymbols::const_iterator I=Invalidated->begin(),
2145 E = Invalidated->end(); I!=E; ++I) {
2146 SymbolRef sym = *I;
2147 if (SymbolsDirectlyInvalidated.count(sym))
2148 continue;
2149 SymbolsIndirectlyInvalidated.insert(sym);
2150 }
2151
2152 if (!SymbolsDirectlyInvalidated.empty())
2153 State = getCheckerManager().runCheckersForPointerEscape(State,
2154 SymbolsDirectlyInvalidated, Call, PSK_DirectEscapeOnCall, &ITraits);
2155
2156 // Notify about the symbols that get indirectly invalidated by the call.
2157 if (!SymbolsIndirectlyInvalidated.empty())
2158 State = getCheckerManager().runCheckersForPointerEscape(State,
2159 SymbolsIndirectlyInvalidated, Call, PSK_IndirectEscapeOnCall, &ITraits);
2160
2161 return State;
2162 }
2163
2164 /// evalBind - Handle the semantics of binding a value to a specific location.
2165 /// This method is used by evalStore and (soon) VisitDeclStmt, and others.
evalBind(ExplodedNodeSet & Dst,const Stmt * StoreE,ExplodedNode * Pred,SVal location,SVal Val,bool atDeclInit,const ProgramPoint * PP)2166 void ExprEngine::evalBind(ExplodedNodeSet &Dst, const Stmt *StoreE,
2167 ExplodedNode *Pred,
2168 SVal location, SVal Val,
2169 bool atDeclInit, const ProgramPoint *PP) {
2170
2171 const LocationContext *LC = Pred->getLocationContext();
2172 PostStmt PS(StoreE, LC);
2173 if (!PP)
2174 PP = &PS;
2175
2176 // Do a previsit of the bind.
2177 ExplodedNodeSet CheckedSet;
2178 getCheckerManager().runCheckersForBind(CheckedSet, Pred, location, Val,
2179 StoreE, *this, *PP);
2180
2181 StmtNodeBuilder Bldr(CheckedSet, Dst, *currBldrCtx);
2182
2183 // If the location is not a 'Loc', it will already be handled by
2184 // the checkers. There is nothing left to do.
2185 if (!location.getAs<Loc>()) {
2186 const ProgramPoint L = PostStore(StoreE, LC, /*Loc*/nullptr,
2187 /*tag*/nullptr);
2188 ProgramStateRef state = Pred->getState();
2189 state = processPointerEscapedOnBind(state, location, Val);
2190 Bldr.generateNode(L, state, Pred);
2191 return;
2192 }
2193
2194 for (ExplodedNodeSet::iterator I = CheckedSet.begin(), E = CheckedSet.end();
2195 I!=E; ++I) {
2196 ExplodedNode *PredI = *I;
2197 ProgramStateRef state = PredI->getState();
2198
2199 state = processPointerEscapedOnBind(state, location, Val);
2200
2201 // When binding the value, pass on the hint that this is a initialization.
2202 // For initializations, we do not need to inform clients of region
2203 // changes.
2204 state = state->bindLoc(location.castAs<Loc>(),
2205 Val, /* notifyChanges = */ !atDeclInit);
2206
2207 const MemRegion *LocReg = nullptr;
2208 if (Optional<loc::MemRegionVal> LocRegVal =
2209 location.getAs<loc::MemRegionVal>()) {
2210 LocReg = LocRegVal->getRegion();
2211 }
2212
2213 const ProgramPoint L = PostStore(StoreE, LC, LocReg, nullptr);
2214 Bldr.generateNode(L, state, PredI);
2215 }
2216 }
2217
2218 /// evalStore - Handle the semantics of a store via an assignment.
2219 /// @param Dst The node set to store generated state nodes
2220 /// @param AssignE The assignment expression if the store happens in an
2221 /// assignment.
2222 /// @param LocationE The location expression that is stored to.
2223 /// @param state The current simulation state
2224 /// @param location The location to store the value
2225 /// @param Val The value to be stored
evalStore(ExplodedNodeSet & Dst,const Expr * AssignE,const Expr * LocationE,ExplodedNode * Pred,ProgramStateRef state,SVal location,SVal Val,const ProgramPointTag * tag)2226 void ExprEngine::evalStore(ExplodedNodeSet &Dst, const Expr *AssignE,
2227 const Expr *LocationE,
2228 ExplodedNode *Pred,
2229 ProgramStateRef state, SVal location, SVal Val,
2230 const ProgramPointTag *tag) {
2231 // Proceed with the store. We use AssignE as the anchor for the PostStore
2232 // ProgramPoint if it is non-NULL, and LocationE otherwise.
2233 const Expr *StoreE = AssignE ? AssignE : LocationE;
2234
2235 // Evaluate the location (checks for bad dereferences).
2236 ExplodedNodeSet Tmp;
2237 evalLocation(Tmp, AssignE, LocationE, Pred, state, location, tag, false);
2238
2239 if (Tmp.empty())
2240 return;
2241
2242 if (location.isUndef())
2243 return;
2244
2245 for (ExplodedNodeSet::iterator NI=Tmp.begin(), NE=Tmp.end(); NI!=NE; ++NI)
2246 evalBind(Dst, StoreE, *NI, location, Val, false);
2247 }
2248
evalLoad(ExplodedNodeSet & Dst,const Expr * NodeEx,const Expr * BoundEx,ExplodedNode * Pred,ProgramStateRef state,SVal location,const ProgramPointTag * tag,QualType LoadTy)2249 void ExprEngine::evalLoad(ExplodedNodeSet &Dst,
2250 const Expr *NodeEx,
2251 const Expr *BoundEx,
2252 ExplodedNode *Pred,
2253 ProgramStateRef state,
2254 SVal location,
2255 const ProgramPointTag *tag,
2256 QualType LoadTy)
2257 {
2258 assert(!location.getAs<NonLoc>() && "location cannot be a NonLoc.");
2259
2260 // Are we loading from a region? This actually results in two loads; one
2261 // to fetch the address of the referenced value and one to fetch the
2262 // referenced value.
2263 if (const TypedValueRegion *TR =
2264 dyn_cast_or_null<TypedValueRegion>(location.getAsRegion())) {
2265
2266 QualType ValTy = TR->getValueType();
2267 if (const ReferenceType *RT = ValTy->getAs<ReferenceType>()) {
2268 static SimpleProgramPointTag
2269 loadReferenceTag(TagProviderName, "Load Reference");
2270 ExplodedNodeSet Tmp;
2271 evalLoadCommon(Tmp, NodeEx, BoundEx, Pred, state,
2272 location, &loadReferenceTag,
2273 getContext().getPointerType(RT->getPointeeType()));
2274
2275 // Perform the load from the referenced value.
2276 for (ExplodedNodeSet::iterator I=Tmp.begin(), E=Tmp.end() ; I!=E; ++I) {
2277 state = (*I)->getState();
2278 location = state->getSVal(BoundEx, (*I)->getLocationContext());
2279 evalLoadCommon(Dst, NodeEx, BoundEx, *I, state, location, tag, LoadTy);
2280 }
2281 return;
2282 }
2283 }
2284
2285 evalLoadCommon(Dst, NodeEx, BoundEx, Pred, state, location, tag, LoadTy);
2286 }
2287
evalLoadCommon(ExplodedNodeSet & Dst,const Expr * NodeEx,const Expr * BoundEx,ExplodedNode * Pred,ProgramStateRef state,SVal location,const ProgramPointTag * tag,QualType LoadTy)2288 void ExprEngine::evalLoadCommon(ExplodedNodeSet &Dst,
2289 const Expr *NodeEx,
2290 const Expr *BoundEx,
2291 ExplodedNode *Pred,
2292 ProgramStateRef state,
2293 SVal location,
2294 const ProgramPointTag *tag,
2295 QualType LoadTy) {
2296 assert(NodeEx);
2297 assert(BoundEx);
2298 // Evaluate the location (checks for bad dereferences).
2299 ExplodedNodeSet Tmp;
2300 evalLocation(Tmp, NodeEx, BoundEx, Pred, state, location, tag, true);
2301 if (Tmp.empty())
2302 return;
2303
2304 StmtNodeBuilder Bldr(Tmp, Dst, *currBldrCtx);
2305 if (location.isUndef())
2306 return;
2307
2308 // Proceed with the load.
2309 for (ExplodedNodeSet::iterator NI=Tmp.begin(), NE=Tmp.end(); NI!=NE; ++NI) {
2310 state = (*NI)->getState();
2311 const LocationContext *LCtx = (*NI)->getLocationContext();
2312
2313 SVal V = UnknownVal();
2314 if (location.isValid()) {
2315 if (LoadTy.isNull())
2316 LoadTy = BoundEx->getType();
2317 V = state->getSVal(location.castAs<Loc>(), LoadTy);
2318 }
2319
2320 Bldr.generateNode(NodeEx, *NI, state->BindExpr(BoundEx, LCtx, V), tag,
2321 ProgramPoint::PostLoadKind);
2322 }
2323 }
2324
evalLocation(ExplodedNodeSet & Dst,const Stmt * NodeEx,const Stmt * BoundEx,ExplodedNode * Pred,ProgramStateRef state,SVal location,const ProgramPointTag * tag,bool isLoad)2325 void ExprEngine::evalLocation(ExplodedNodeSet &Dst,
2326 const Stmt *NodeEx,
2327 const Stmt *BoundEx,
2328 ExplodedNode *Pred,
2329 ProgramStateRef state,
2330 SVal location,
2331 const ProgramPointTag *tag,
2332 bool isLoad) {
2333 StmtNodeBuilder BldrTop(Pred, Dst, *currBldrCtx);
2334 // Early checks for performance reason.
2335 if (location.isUnknown()) {
2336 return;
2337 }
2338
2339 ExplodedNodeSet Src;
2340 BldrTop.takeNodes(Pred);
2341 StmtNodeBuilder Bldr(Pred, Src, *currBldrCtx);
2342 if (Pred->getState() != state) {
2343 // Associate this new state with an ExplodedNode.
2344 // FIXME: If I pass null tag, the graph is incorrect, e.g for
2345 // int *p;
2346 // p = 0;
2347 // *p = 0xDEADBEEF;
2348 // "p = 0" is not noted as "Null pointer value stored to 'p'" but
2349 // instead "int *p" is noted as
2350 // "Variable 'p' initialized to a null pointer value"
2351
2352 static SimpleProgramPointTag tag(TagProviderName, "Location");
2353 Bldr.generateNode(NodeEx, Pred, state, &tag);
2354 }
2355 ExplodedNodeSet Tmp;
2356 getCheckerManager().runCheckersForLocation(Tmp, Src, location, isLoad,
2357 NodeEx, BoundEx, *this);
2358 BldrTop.addNodes(Tmp);
2359 }
2360
2361 std::pair<const ProgramPointTag *, const ProgramPointTag*>
geteagerlyAssumeBinOpBifurcationTags()2362 ExprEngine::geteagerlyAssumeBinOpBifurcationTags() {
2363 static SimpleProgramPointTag
2364 eagerlyAssumeBinOpBifurcationTrue(TagProviderName,
2365 "Eagerly Assume True"),
2366 eagerlyAssumeBinOpBifurcationFalse(TagProviderName,
2367 "Eagerly Assume False");
2368 return std::make_pair(&eagerlyAssumeBinOpBifurcationTrue,
2369 &eagerlyAssumeBinOpBifurcationFalse);
2370 }
2371
evalEagerlyAssumeBinOpBifurcation(ExplodedNodeSet & Dst,ExplodedNodeSet & Src,const Expr * Ex)2372 void ExprEngine::evalEagerlyAssumeBinOpBifurcation(ExplodedNodeSet &Dst,
2373 ExplodedNodeSet &Src,
2374 const Expr *Ex) {
2375 StmtNodeBuilder Bldr(Src, Dst, *currBldrCtx);
2376
2377 for (ExplodedNodeSet::iterator I=Src.begin(), E=Src.end(); I!=E; ++I) {
2378 ExplodedNode *Pred = *I;
2379 // Test if the previous node was as the same expression. This can happen
2380 // when the expression fails to evaluate to anything meaningful and
2381 // (as an optimization) we don't generate a node.
2382 ProgramPoint P = Pred->getLocation();
2383 if (!P.getAs<PostStmt>() || P.castAs<PostStmt>().getStmt() != Ex) {
2384 continue;
2385 }
2386
2387 ProgramStateRef state = Pred->getState();
2388 SVal V = state->getSVal(Ex, Pred->getLocationContext());
2389 Optional<nonloc::SymbolVal> SEV = V.getAs<nonloc::SymbolVal>();
2390 if (SEV && SEV->isExpression()) {
2391 const std::pair<const ProgramPointTag *, const ProgramPointTag*> &tags =
2392 geteagerlyAssumeBinOpBifurcationTags();
2393
2394 ProgramStateRef StateTrue, StateFalse;
2395 std::tie(StateTrue, StateFalse) = state->assume(*SEV);
2396
2397 // First assume that the condition is true.
2398 if (StateTrue) {
2399 SVal Val = svalBuilder.makeIntVal(1U, Ex->getType());
2400 StateTrue = StateTrue->BindExpr(Ex, Pred->getLocationContext(), Val);
2401 Bldr.generateNode(Ex, Pred, StateTrue, tags.first);
2402 }
2403
2404 // Next, assume that the condition is false.
2405 if (StateFalse) {
2406 SVal Val = svalBuilder.makeIntVal(0U, Ex->getType());
2407 StateFalse = StateFalse->BindExpr(Ex, Pred->getLocationContext(), Val);
2408 Bldr.generateNode(Ex, Pred, StateFalse, tags.second);
2409 }
2410 }
2411 }
2412 }
2413
VisitGCCAsmStmt(const GCCAsmStmt * A,ExplodedNode * Pred,ExplodedNodeSet & Dst)2414 void ExprEngine::VisitGCCAsmStmt(const GCCAsmStmt *A, ExplodedNode *Pred,
2415 ExplodedNodeSet &Dst) {
2416 StmtNodeBuilder Bldr(Pred, Dst, *currBldrCtx);
2417 // We have processed both the inputs and the outputs. All of the outputs
2418 // should evaluate to Locs. Nuke all of their values.
2419
2420 // FIXME: Some day in the future it would be nice to allow a "plug-in"
2421 // which interprets the inline asm and stores proper results in the
2422 // outputs.
2423
2424 ProgramStateRef state = Pred->getState();
2425
2426 for (const Expr *O : A->outputs()) {
2427 SVal X = state->getSVal(O, Pred->getLocationContext());
2428 assert (!X.getAs<NonLoc>()); // Should be an Lval, or unknown, undef.
2429
2430 if (Optional<Loc> LV = X.getAs<Loc>())
2431 state = state->bindLoc(*LV, UnknownVal());
2432 }
2433
2434 Bldr.generateNode(A, Pred, state);
2435 }
2436
VisitMSAsmStmt(const MSAsmStmt * A,ExplodedNode * Pred,ExplodedNodeSet & Dst)2437 void ExprEngine::VisitMSAsmStmt(const MSAsmStmt *A, ExplodedNode *Pred,
2438 ExplodedNodeSet &Dst) {
2439 StmtNodeBuilder Bldr(Pred, Dst, *currBldrCtx);
2440 Bldr.generateNode(A, Pred, Pred->getState());
2441 }
2442
2443 //===----------------------------------------------------------------------===//
2444 // Visualization.
2445 //===----------------------------------------------------------------------===//
2446
2447 #ifndef NDEBUG
2448 static ExprEngine* GraphPrintCheckerState;
2449 static SourceManager* GraphPrintSourceManager;
2450
2451 namespace llvm {
2452 template<>
2453 struct DOTGraphTraits<ExplodedNode*> :
2454 public DefaultDOTGraphTraits {
2455
DOTGraphTraitsllvm::DOTGraphTraits2456 DOTGraphTraits (bool isSimple=false) : DefaultDOTGraphTraits(isSimple) {}
2457
2458 // FIXME: Since we do not cache error nodes in ExprEngine now, this does not
2459 // work.
getNodeAttributesllvm::DOTGraphTraits2460 static std::string getNodeAttributes(const ExplodedNode *N, void*) {
2461
2462 #if 0
2463 // FIXME: Replace with a general scheme to tell if the node is
2464 // an error node.
2465 if (GraphPrintCheckerState->isImplicitNullDeref(N) ||
2466 GraphPrintCheckerState->isExplicitNullDeref(N) ||
2467 GraphPrintCheckerState->isUndefDeref(N) ||
2468 GraphPrintCheckerState->isUndefStore(N) ||
2469 GraphPrintCheckerState->isUndefControlFlow(N) ||
2470 GraphPrintCheckerState->isUndefResult(N) ||
2471 GraphPrintCheckerState->isBadCall(N) ||
2472 GraphPrintCheckerState->isUndefArg(N))
2473 return "color=\"red\",style=\"filled\"";
2474
2475 if (GraphPrintCheckerState->isNoReturnCall(N))
2476 return "color=\"blue\",style=\"filled\"";
2477 #endif
2478 return "";
2479 }
2480
printLocationllvm::DOTGraphTraits2481 static void printLocation(raw_ostream &Out, SourceLocation SLoc) {
2482 if (SLoc.isFileID()) {
2483 Out << "\\lline="
2484 << GraphPrintSourceManager->getExpansionLineNumber(SLoc)
2485 << " col="
2486 << GraphPrintSourceManager->getExpansionColumnNumber(SLoc)
2487 << "\\l";
2488 }
2489 }
2490
getNodeLabelllvm::DOTGraphTraits2491 static std::string getNodeLabel(const ExplodedNode *N, void*){
2492
2493 std::string sbuf;
2494 llvm::raw_string_ostream Out(sbuf);
2495
2496 // Program Location.
2497 ProgramPoint Loc = N->getLocation();
2498
2499 switch (Loc.getKind()) {
2500 case ProgramPoint::BlockEntranceKind: {
2501 Out << "Block Entrance: B"
2502 << Loc.castAs<BlockEntrance>().getBlock()->getBlockID();
2503 if (const NamedDecl *ND =
2504 dyn_cast<NamedDecl>(Loc.getLocationContext()->getDecl())) {
2505 Out << " (";
2506 ND->printName(Out);
2507 Out << ")";
2508 }
2509 break;
2510 }
2511
2512 case ProgramPoint::BlockExitKind:
2513 assert (false);
2514 break;
2515
2516 case ProgramPoint::CallEnterKind:
2517 Out << "CallEnter";
2518 break;
2519
2520 case ProgramPoint::CallExitBeginKind:
2521 Out << "CallExitBegin";
2522 break;
2523
2524 case ProgramPoint::CallExitEndKind:
2525 Out << "CallExitEnd";
2526 break;
2527
2528 case ProgramPoint::PostStmtPurgeDeadSymbolsKind:
2529 Out << "PostStmtPurgeDeadSymbols";
2530 break;
2531
2532 case ProgramPoint::PreStmtPurgeDeadSymbolsKind:
2533 Out << "PreStmtPurgeDeadSymbols";
2534 break;
2535
2536 case ProgramPoint::EpsilonKind:
2537 Out << "Epsilon Point";
2538 break;
2539
2540 case ProgramPoint::PreImplicitCallKind: {
2541 ImplicitCallPoint PC = Loc.castAs<ImplicitCallPoint>();
2542 Out << "PreCall: ";
2543
2544 // FIXME: Get proper printing options.
2545 PC.getDecl()->print(Out, LangOptions());
2546 printLocation(Out, PC.getLocation());
2547 break;
2548 }
2549
2550 case ProgramPoint::PostImplicitCallKind: {
2551 ImplicitCallPoint PC = Loc.castAs<ImplicitCallPoint>();
2552 Out << "PostCall: ";
2553
2554 // FIXME: Get proper printing options.
2555 PC.getDecl()->print(Out, LangOptions());
2556 printLocation(Out, PC.getLocation());
2557 break;
2558 }
2559
2560 case ProgramPoint::PostInitializerKind: {
2561 Out << "PostInitializer: ";
2562 const CXXCtorInitializer *Init =
2563 Loc.castAs<PostInitializer>().getInitializer();
2564 if (const FieldDecl *FD = Init->getAnyMember())
2565 Out << *FD;
2566 else {
2567 QualType Ty = Init->getTypeSourceInfo()->getType();
2568 Ty = Ty.getLocalUnqualifiedType();
2569 LangOptions LO; // FIXME.
2570 Ty.print(Out, LO);
2571 }
2572 break;
2573 }
2574
2575 case ProgramPoint::BlockEdgeKind: {
2576 const BlockEdge &E = Loc.castAs<BlockEdge>();
2577 Out << "Edge: (B" << E.getSrc()->getBlockID() << ", B"
2578 << E.getDst()->getBlockID() << ')';
2579
2580 if (const Stmt *T = E.getSrc()->getTerminator()) {
2581 SourceLocation SLoc = T->getLocStart();
2582
2583 Out << "\\|Terminator: ";
2584 LangOptions LO; // FIXME.
2585 E.getSrc()->printTerminator(Out, LO);
2586
2587 if (SLoc.isFileID()) {
2588 Out << "\\lline="
2589 << GraphPrintSourceManager->getExpansionLineNumber(SLoc)
2590 << " col="
2591 << GraphPrintSourceManager->getExpansionColumnNumber(SLoc);
2592 }
2593
2594 if (isa<SwitchStmt>(T)) {
2595 const Stmt *Label = E.getDst()->getLabel();
2596
2597 if (Label) {
2598 if (const CaseStmt *C = dyn_cast<CaseStmt>(Label)) {
2599 Out << "\\lcase ";
2600 LangOptions LO; // FIXME.
2601 if (C->getLHS())
2602 C->getLHS()->printPretty(Out, nullptr, PrintingPolicy(LO));
2603
2604 if (const Stmt *RHS = C->getRHS()) {
2605 Out << " .. ";
2606 RHS->printPretty(Out, nullptr, PrintingPolicy(LO));
2607 }
2608
2609 Out << ":";
2610 }
2611 else {
2612 assert (isa<DefaultStmt>(Label));
2613 Out << "\\ldefault:";
2614 }
2615 }
2616 else
2617 Out << "\\l(implicit) default:";
2618 }
2619 else if (isa<IndirectGotoStmt>(T)) {
2620 // FIXME
2621 }
2622 else {
2623 Out << "\\lCondition: ";
2624 if (*E.getSrc()->succ_begin() == E.getDst())
2625 Out << "true";
2626 else
2627 Out << "false";
2628 }
2629
2630 Out << "\\l";
2631 }
2632
2633 #if 0
2634 // FIXME: Replace with a general scheme to determine
2635 // the name of the check.
2636 if (GraphPrintCheckerState->isUndefControlFlow(N)) {
2637 Out << "\\|Control-flow based on\\lUndefined value.\\l";
2638 }
2639 #endif
2640 break;
2641 }
2642
2643 default: {
2644 const Stmt *S = Loc.castAs<StmtPoint>().getStmt();
2645 assert(S != nullptr && "Expecting non-null Stmt");
2646
2647 Out << S->getStmtClassName() << ' ' << (const void*) S << ' ';
2648 LangOptions LO; // FIXME.
2649 S->printPretty(Out, nullptr, PrintingPolicy(LO));
2650 printLocation(Out, S->getLocStart());
2651
2652 if (Loc.getAs<PreStmt>())
2653 Out << "\\lPreStmt\\l;";
2654 else if (Loc.getAs<PostLoad>())
2655 Out << "\\lPostLoad\\l;";
2656 else if (Loc.getAs<PostStore>())
2657 Out << "\\lPostStore\\l";
2658 else if (Loc.getAs<PostLValue>())
2659 Out << "\\lPostLValue\\l";
2660
2661 #if 0
2662 // FIXME: Replace with a general scheme to determine
2663 // the name of the check.
2664 if (GraphPrintCheckerState->isImplicitNullDeref(N))
2665 Out << "\\|Implicit-Null Dereference.\\l";
2666 else if (GraphPrintCheckerState->isExplicitNullDeref(N))
2667 Out << "\\|Explicit-Null Dereference.\\l";
2668 else if (GraphPrintCheckerState->isUndefDeref(N))
2669 Out << "\\|Dereference of undefialied value.\\l";
2670 else if (GraphPrintCheckerState->isUndefStore(N))
2671 Out << "\\|Store to Undefined Loc.";
2672 else if (GraphPrintCheckerState->isUndefResult(N))
2673 Out << "\\|Result of operation is undefined.";
2674 else if (GraphPrintCheckerState->isNoReturnCall(N))
2675 Out << "\\|Call to function marked \"noreturn\".";
2676 else if (GraphPrintCheckerState->isBadCall(N))
2677 Out << "\\|Call to NULL/Undefined.";
2678 else if (GraphPrintCheckerState->isUndefArg(N))
2679 Out << "\\|Argument in call is undefined";
2680 #endif
2681
2682 break;
2683 }
2684 }
2685
2686 ProgramStateRef state = N->getState();
2687 Out << "\\|StateID: " << (const void*) state.get()
2688 << " NodeID: " << (const void*) N << "\\|";
2689 state->printDOT(Out);
2690
2691 Out << "\\l";
2692
2693 if (const ProgramPointTag *tag = Loc.getTag()) {
2694 Out << "\\|Tag: " << tag->getTagDescription();
2695 Out << "\\l";
2696 }
2697 return Out.str();
2698 }
2699 };
2700 } // end llvm namespace
2701 #endif
2702
ViewGraph(bool trim)2703 void ExprEngine::ViewGraph(bool trim) {
2704 #ifndef NDEBUG
2705 if (trim) {
2706 std::vector<const ExplodedNode*> Src;
2707
2708 // Flush any outstanding reports to make sure we cover all the nodes.
2709 // This does not cause them to get displayed.
2710 for (BugReporter::iterator I=BR.begin(), E=BR.end(); I!=E; ++I)
2711 const_cast<BugType*>(*I)->FlushReports(BR);
2712
2713 // Iterate through the reports and get their nodes.
2714 for (BugReporter::EQClasses_iterator
2715 EI = BR.EQClasses_begin(), EE = BR.EQClasses_end(); EI != EE; ++EI) {
2716 ExplodedNode *N = const_cast<ExplodedNode*>(EI->begin()->getErrorNode());
2717 if (N) Src.push_back(N);
2718 }
2719
2720 ViewGraph(Src);
2721 }
2722 else {
2723 GraphPrintCheckerState = this;
2724 GraphPrintSourceManager = &getContext().getSourceManager();
2725
2726 llvm::ViewGraph(*G.roots_begin(), "ExprEngine");
2727
2728 GraphPrintCheckerState = nullptr;
2729 GraphPrintSourceManager = nullptr;
2730 }
2731 #endif
2732 }
2733
ViewGraph(ArrayRef<const ExplodedNode * > Nodes)2734 void ExprEngine::ViewGraph(ArrayRef<const ExplodedNode*> Nodes) {
2735 #ifndef NDEBUG
2736 GraphPrintCheckerState = this;
2737 GraphPrintSourceManager = &getContext().getSourceManager();
2738
2739 std::unique_ptr<ExplodedGraph> TrimmedG(G.trim(Nodes));
2740
2741 if (!TrimmedG.get())
2742 llvm::errs() << "warning: Trimmed ExplodedGraph is empty.\n";
2743 else
2744 llvm::ViewGraph(*TrimmedG->roots_begin(), "TrimmedExprEngine");
2745
2746 GraphPrintCheckerState = nullptr;
2747 GraphPrintSourceManager = nullptr;
2748 #endif
2749 }
2750