clang 24.0.0git
CheckerManager.cpp
Go to the documentation of this file.
1//===- CheckerManager.cpp - Static Analyzer Checker Manager ---------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// Defines the Static Analyzer Checker Manager.
10//
11//===----------------------------------------------------------------------===//
12
14#include "clang/AST/DeclBase.h"
15#include "clang/AST/Stmt.h"
18#include "clang/Basic/LLVM.h"
26#include "llvm/ADT/STLExtras.h"
27#include "llvm/ADT/SmallVector.h"
28#include "llvm/Support/ErrorHandling.h"
29#include "llvm/Support/FormatVariadic.h"
30#include "llvm/Support/TimeProfiler.h"
31#include <cassert>
32#include <optional>
33#include <vector>
34
35using namespace clang;
36using namespace ento;
37
39 const auto IfAnyAreNonEmpty = [](const auto &...Callbacks) -> bool {
40 return (!Callbacks.empty() || ...);
41 };
42 return IfAnyAreNonEmpty(
43 StmtCheckers, PreObjCMessageCheckers, ObjCMessageNilCheckers,
44 PostObjCMessageCheckers, PreCallCheckers, PostCallCheckers,
45 LifetimeEndCheckers, LocationCheckers, BindCheckers,
46 BlockEntranceCheckers, EndAnalysisCheckers, BeginFunctionCheckers,
47 EndFunctionCheckers, BranchConditionCheckers, NewAllocatorCheckers,
48 LiveSymbolsCheckers, DeadSymbolsCheckers, RegionChangesCheckers,
49 PointerEscapeCheckers, EvalAssumeCheckers, EvalCallCheckers,
50 EndOfTranslationUnitCheckers);
51}
52
54 const CheckerFrontend *Checker, StringRef OptionName,
55 StringRef ExpectedValueDesc) const {
56
57 getDiagnostics().Report(diag::err_analyzer_checker_option_invalid_input)
58 << (llvm::Twine(Checker->getName()) + ":" + OptionName).str()
59 << ExpectedValueDesc;
60}
61
62//===----------------------------------------------------------------------===//
63// Functions for running checkers for AST traversing..
64//===----------------------------------------------------------------------===//
65
67 BugReporter &BR) {
68 assert(D);
69
70 unsigned DeclKind = D->getKind();
71 auto [CCI, Inserted] = CachedDeclCheckersMap.try_emplace(DeclKind);
72 CachedDeclCheckers *checkers = &(CCI->second);
73 if (Inserted) {
74 // Find the checkers that should run for this Decl and cache them.
75 for (const auto &info : DeclCheckers)
76 if (info.IsForDeclFn(D))
77 checkers->push_back(info.CheckFn);
78 }
79
80 assert(checkers);
81 for (const auto &checker : *checkers)
82 checker(D, mgr, BR);
83}
84
86 BugReporter &BR) {
87 assert(D && D->hasBody());
88
89 for (const auto &BodyChecker : BodyCheckers)
90 BodyChecker(D, mgr, BR);
91}
92
93//===----------------------------------------------------------------------===//
94// Functions for running checkers for path-sensitive checking.
95//===----------------------------------------------------------------------===//
96
97template <typename CHECK_CTX>
98static void expandGraphWithCheckers(CHECK_CTX checkCtx, ExplodedNodeSet &Dst,
99 const ExplodedNodeSet &Src) {
100 if (Src.empty())
101 return;
102
103 typename CHECK_CTX::CheckersTy::const_iterator
104 I = checkCtx.checkers_begin(), E = checkCtx.checkers_end();
105 if (I == E) {
106 Dst.insert(Src);
107 return;
108 }
109
110 ExplodedNodeSet Tmp1, Tmp2;
111 const ExplodedNodeSet *PrevSet = &Src;
112
113 for (; I != E; ++I) {
114 ExplodedNodeSet *CurrSet = nullptr;
115 if (I+1 == E)
116 CurrSet = &Dst;
117 else {
118 CurrSet = (PrevSet == &Tmp1) ? &Tmp2 : &Tmp1;
119 CurrSet->clear();
120 }
121
122 CurrSet->insert(*PrevSet);
123 for (const auto &NI : *PrevSet)
124 checkCtx.runChecker(*I, NI, *CurrSet);
125
126 // If all the produced transitions are sinks, stop.
127 if (CurrSet->empty())
128 return;
129
130 // Update which NodeSet is the current one.
131 PrevSet = CurrSet;
132 }
133}
134
135namespace {
136
137std::string checkerScopeName(StringRef Name, const CheckerBackend *Checker) {
138 if (!llvm::timeTraceProfilerEnabled())
139 return "";
140 StringRef CheckerTag = Checker ? Checker->getDebugTag() : "<unknown>";
141 return (Name + ":" + CheckerTag).str();
142}
143
144 struct CheckStmtContext {
145 using CheckersTy = SmallVectorImpl<CheckerManager::CheckStmtFunc>;
146
147 bool IsPreVisit;
148 const CheckersTy &Checkers;
149 const Stmt *S;
150 ExprEngine &Eng;
151 bool WasInlined;
152
153 CheckStmtContext(bool isPreVisit, const CheckersTy &checkers,
154 const Stmt *s, ExprEngine &eng, bool wasInlined = false)
155 : IsPreVisit(isPreVisit), Checkers(checkers), S(s), Eng(eng),
156 WasInlined(wasInlined) {}
157
158 CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); }
159 CheckersTy::const_iterator checkers_end() { return Checkers.end(); }
160
161 void runChecker(CheckerManager::CheckStmtFunc checkFn, ExplodedNode *Pred,
162 ExplodedNodeSet &Dst) {
163 llvm::TimeTraceScope TimeScope(checkerScopeName("Stmt", checkFn.Checker));
164 // FIXME: Remove respondsToCallback from CheckerContext;
168 S, K, Pred->getStackFrame(), checkFn.Checker);
169 CheckerContext C(Eng, Pred, Dst, L, WasInlined);
170 checkFn(S, C);
171 }
172 };
173
174} // namespace
175
176/// Run checkers for visiting Stmts.
178 ExplodedNodeSet &Dst,
179 const ExplodedNodeSet &Src,
180 const Stmt *S,
181 ExprEngine &Eng,
182 bool WasInlined) {
183 CheckStmtContext C(isPreVisit, getCachedStmtCheckersFor(S, isPreVisit),
184 S, Eng, WasInlined);
185 llvm::TimeTraceScope TimeScope(
186 isPreVisit ? "CheckerManager::runCheckersForStmt (Pre)"
187 : "CheckerManager::runCheckersForStmt (Post)");
188 expandGraphWithCheckers(C, Dst, Src);
189}
190
191namespace {
192
193 struct CheckObjCMessageContext {
194 using CheckersTy = std::vector<CheckerManager::CheckObjCMessageFunc>;
195
197 bool WasInlined;
198 const CheckersTy &Checkers;
199 const ObjCMethodCall &Msg;
200 ExprEngine &Eng;
201
202 CheckObjCMessageContext(ObjCMessageVisitKind visitKind,
203 const CheckersTy &checkers,
204 const ObjCMethodCall &msg, ExprEngine &eng,
205 bool wasInlined)
206 : Kind(visitKind), WasInlined(wasInlined), Checkers(checkers), Msg(msg),
207 Eng(eng) {}
208
209 CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); }
210 CheckersTy::const_iterator checkers_end() { return Checkers.end(); }
211
212 void runChecker(CheckerManager::CheckObjCMessageFunc checkFn,
213 ExplodedNode *Pred, ExplodedNodeSet &Dst) {
214 llvm::TimeTraceScope TimeScope(
215 checkerScopeName("ObjCMsg", checkFn.Checker));
216 bool IsPreVisit;
217
218 switch (Kind) {
219 case ObjCMessageVisitKind::Pre:
220 IsPreVisit = true;
221 break;
222 case ObjCMessageVisitKind::MessageNil:
223 case ObjCMessageVisitKind::Post:
224 IsPreVisit = false;
225 break;
226 }
227
228 const ProgramPoint &L = Msg.getProgramPoint(IsPreVisit,checkFn.Checker);
229 CheckerContext C(Eng, Pred, Dst, L, WasInlined);
230
231 checkFn(*Msg.cloneWithState<ObjCMethodCall>(Pred->getState()), C);
232 }
233 };
234
235} // namespace
236
237/// Run checkers for visiting obj-c messages.
239 ExplodedNodeSet &Dst,
240 const ExplodedNodeSet &Src,
241 const ObjCMethodCall &msg,
242 ExprEngine &Eng,
243 bool WasInlined) {
244 const auto &checkers = getObjCMessageCheckers(visitKind);
245 CheckObjCMessageContext C(visitKind, checkers, msg, Eng, WasInlined);
246 llvm::TimeTraceScope TimeScope("CheckerManager::runCheckersForObjCMessage");
247 expandGraphWithCheckers(C, Dst, Src);
248}
249
250const std::vector<CheckerManager::CheckObjCMessageFunc> &
251CheckerManager::getObjCMessageCheckers(ObjCMessageVisitKind Kind) const {
252 switch (Kind) {
254 return PreObjCMessageCheckers;
255 break;
257 return PostObjCMessageCheckers;
259 return ObjCMessageNilCheckers;
260 }
261 llvm_unreachable("Unknown Kind");
262}
263
264namespace {
265
266 // FIXME: This has all the same signatures as CheckObjCMessageContext.
267 // Is there a way we can merge the two?
268 struct CheckCallContext {
269 using CheckersTy = std::vector<CheckerManager::CheckCallFunc>;
270
271 bool IsPreVisit, WasInlined;
272 const CheckersTy &Checkers;
273 const CallEvent &Call;
274 ExprEngine &Eng;
275
276 CheckCallContext(bool isPreVisit, const CheckersTy &checkers,
277 const CallEvent &call, ExprEngine &eng,
278 bool wasInlined)
279 : IsPreVisit(isPreVisit), WasInlined(wasInlined), Checkers(checkers),
280 Call(call), Eng(eng) {}
281
282 CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); }
283 CheckersTy::const_iterator checkers_end() { return Checkers.end(); }
284
285 void runChecker(CheckerManager::CheckCallFunc checkFn, ExplodedNode *Pred,
286 ExplodedNodeSet &Dst) {
287 llvm::TimeTraceScope TimeScope(checkerScopeName("Call", checkFn.Checker));
288 const ProgramPoint &L = Call.getProgramPoint(IsPreVisit,checkFn.Checker);
289 CheckerContext C(Eng, Pred, Dst, L, WasInlined);
290
291 checkFn(*Call.cloneWithState(Pred->getState()), C);
292 }
293 };
294
295} // namespace
296
297/// Run checkers for visiting an abstract call event.
299 ExplodedNodeSet &Dst,
300 const ExplodedNodeSet &Src,
301 const CallEvent &Call,
302 ExprEngine &Eng,
303 bool WasInlined) {
304 CheckCallContext C(isPreVisit,
305 isPreVisit ? PreCallCheckers
306 : PostCallCheckers,
307 Call, Eng, WasInlined);
308 llvm::TimeTraceScope TimeScope(
309 isPreVisit ? "CheckerManager::runCheckersForCallEvent (Pre)"
310 : "CheckerManager::runCheckersForCallEvent (Post)");
311 expandGraphWithCheckers(C, Dst, Src);
312}
313
314namespace {
315
316struct CheckLifetimeEndContext {
317 using CheckersTy = std::vector<CheckerManager::CheckLifetimeEndFunc>;
318
319 const CheckersTy &Checkers;
320 const VarDecl *Decl;
321 ExprEngine &Eng;
322
323 CheckLifetimeEndContext(const CheckersTy &checkers, const VarDecl *decl,
324 ExprEngine &eng)
325 : Checkers(checkers), Decl(decl), Eng(eng) {}
326
327 CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); }
328 CheckersTy::const_iterator checkers_end() { return Checkers.end(); }
329
330 void runChecker(CheckerManager::CheckLifetimeEndFunc checkFn,
331 ExplodedNode *Pred, ExplodedNodeSet &Dst) {
332 assert(Pred->getLocation().getAs<LifetimeEnd>().has_value());
333 const ProgramPoint L = Pred->getLocation().withTag(checkFn.Checker);
334 CheckerContext C(Eng, Pred, Dst, L);
335 checkFn(Decl, C);
336 }
337};
338
339} // namespace
340
341/// Run checkers for end of variable lifetime
343 const ExplodedNodeSet &Src,
344 const VarDecl *Decl,
345 ExprEngine &Eng) {
346 llvm::TimeTraceScope TimeScope("CheckerManager::runCheckersForLifetimeEnd");
347 CheckLifetimeEndContext C(LifetimeEndCheckers, Decl, Eng);
348 expandGraphWithCheckers(C, Dst, Src);
349}
350
351namespace {
352
353 struct CheckLocationContext {
354 using CheckersTy = std::vector<CheckerManager::CheckLocationFunc>;
355
356 const CheckersTy &Checkers;
357 SVal Loc;
358 bool IsLoad;
359 const Stmt *NodeEx; /* Will become a CFGStmt */
360 const Stmt *BoundEx;
361 ExprEngine &Eng;
362
363 CheckLocationContext(const CheckersTy &checkers,
364 SVal loc, bool isLoad, const Stmt *NodeEx,
365 const Stmt *BoundEx,
366 ExprEngine &eng)
367 : Checkers(checkers), Loc(loc), IsLoad(isLoad), NodeEx(NodeEx),
368 BoundEx(BoundEx), Eng(eng) {}
369
370 CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); }
371 CheckersTy::const_iterator checkers_end() { return Checkers.end(); }
372
373 void runChecker(CheckerManager::CheckLocationFunc checkFn,
374 ExplodedNode *Pred, ExplodedNodeSet &Dst) {
375 llvm::TimeTraceScope TimeScope(checkerScopeName("Loc", checkFn.Checker));
379 NodeEx, K, Pred->getStackFrame(), checkFn.Checker);
380 CheckerContext C(Eng, Pred, Dst, L);
381 checkFn(Loc, IsLoad, BoundEx, C);
382 }
383 };
384
385} // namespace
386
387/// Run checkers for load/store of a location.
388
390 const ExplodedNodeSet &Src,
391 SVal location, bool isLoad,
392 const Stmt *NodeEx,
393 const Stmt *BoundEx,
394 ExprEngine &Eng) {
395 CheckLocationContext C(LocationCheckers, location, isLoad, NodeEx,
396 BoundEx, Eng);
397 llvm::TimeTraceScope TimeScope(
398 isLoad ? "CheckerManager::runCheckersForLocation (Load)"
399 : "CheckerManager::runCheckersForLocation (Store)");
400 expandGraphWithCheckers(C, Dst, Src);
401}
402
403namespace {
404
405 struct CheckBindContext {
406 using CheckersTy = std::vector<CheckerManager::CheckBindFunc>;
407
408 const CheckersTy &Checkers;
409 SVal Loc;
410 SVal Val;
411 const Stmt *S;
412 ExprEngine &Eng;
413 const ProgramPoint &PP;
414 bool AtDeclInit;
415
416 CheckBindContext(const CheckersTy &checkers, SVal loc, SVal val,
417 const Stmt *s, bool AtDeclInit, ExprEngine &eng,
418 const ProgramPoint &pp)
419 : Checkers(checkers), Loc(loc), Val(val), S(s), Eng(eng), PP(pp),
420 AtDeclInit(AtDeclInit) {}
421
422 CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); }
423 CheckersTy::const_iterator checkers_end() { return Checkers.end(); }
424
425 void runChecker(CheckerManager::CheckBindFunc checkFn, ExplodedNode *Pred,
426 ExplodedNodeSet &Dst) {
427 llvm::TimeTraceScope TimeScope(checkerScopeName("Bind", checkFn.Checker));
428 const ProgramPoint &L = PP.withTag(checkFn.Checker);
429 CheckerContext C(Eng, Pred, Dst, L);
430
431 checkFn(Loc, Val, S, AtDeclInit, C);
432 }
433 };
434
435 llvm::TimeTraceMetadata getTimeTraceBindMetadata(SVal Val) {
436 assert(llvm::timeTraceProfilerEnabled());
437 std::string Name;
438 llvm::raw_string_ostream OS(Name);
439 Val.dumpToStream(OS);
440 return llvm::TimeTraceMetadata{OS.str(), ""};
441 }
442
443} // namespace
444
445/// Run checkers for binding of a value to a location.
447 const ExplodedNodeSet &Src,
448 SVal location, SVal val, const Stmt *S,
449 bool AtDeclInit, ExprEngine &Eng,
450 const ProgramPoint &PP) {
451 CheckBindContext C(BindCheckers, location, val, S, AtDeclInit, Eng, PP);
452 llvm::TimeTraceScope TimeScope{
453 "CheckerManager::runCheckersForBind",
454 [&val]() { return getTimeTraceBindMetadata(val); }};
455 expandGraphWithCheckers(C, Dst, Src);
456}
457
458namespace {
459struct CheckBlockEntranceContext {
460 using CheckBlockEntranceFunc = CheckerManager::CheckBlockEntranceFunc;
461 using CheckersTy = std::vector<CheckBlockEntranceFunc>;
462
463 const CheckersTy &Checkers;
464 const BlockEntrance &Entrance;
465 ExprEngine &Eng;
466
467 CheckBlockEntranceContext(const CheckersTy &Checkers,
468 const BlockEntrance &Entrance, ExprEngine &Eng)
469 : Checkers(Checkers), Entrance(Entrance), Eng(Eng) {}
470
471 auto checkers_begin() const { return Checkers.begin(); }
472 auto checkers_end() const { return Checkers.end(); }
473
474 void runChecker(CheckBlockEntranceFunc CheckFn, ExplodedNode *Pred,
475 ExplodedNodeSet &Dst) {
476 llvm::TimeTraceScope TimeScope(
477 checkerScopeName("BlockEntrance", CheckFn.Checker));
478 CheckerContext C(Eng, Pred, Dst, Entrance.withTag(CheckFn.Checker));
479 CheckFn(Entrance, C);
480 }
481};
482
483} // namespace
484
486 const ExplodedNodeSet &Src,
487 const BlockEntrance &Entrance,
488 ExprEngine &Eng) const {
489 CheckBlockEntranceContext C(BlockEntranceCheckers, Entrance, Eng);
490 llvm::TimeTraceScope TimeScope{"CheckerManager::runCheckersForBlockEntrance"};
491 expandGraphWithCheckers(C, Dst, Src);
492}
493
495 BugReporter &BR,
496 ExprEngine &Eng) {
497 for (const auto &EndAnalysisChecker : EndAnalysisCheckers)
498 EndAnalysisChecker(G, BR, Eng);
499}
500
501namespace {
502
503struct CheckBeginFunctionContext {
504 using CheckersTy = std::vector<CheckerManager::CheckBeginFunctionFunc>;
505
506 const CheckersTy &Checkers;
507 ExprEngine &Eng;
508 const ProgramPoint &PP;
509
510 CheckBeginFunctionContext(const CheckersTy &Checkers, ExprEngine &Eng,
511 const ProgramPoint &PP)
512 : Checkers(Checkers), Eng(Eng), PP(PP) {}
513
514 CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); }
515 CheckersTy::const_iterator checkers_end() { return Checkers.end(); }
516
517 void runChecker(CheckerManager::CheckBeginFunctionFunc checkFn,
518 ExplodedNode *Pred, ExplodedNodeSet &Dst) {
519 llvm::TimeTraceScope TimeScope(checkerScopeName("Begin", checkFn.Checker));
520 const ProgramPoint &L = PP.withTag(checkFn.Checker);
521 CheckerContext C(Eng, Pred, Dst, L);
522
523 checkFn(C);
524 }
525};
526
527} // namespace
528
530 const BlockEdge &L,
531 ExplodedNode *Pred,
532 ExprEngine &Eng) {
533 ExplodedNodeSet Src;
534 Src.insert(Pred);
535 CheckBeginFunctionContext C(BeginFunctionCheckers, Eng, L);
536 llvm::TimeTraceScope TimeScope("CheckerManager::runCheckersForBeginFunction");
537 expandGraphWithCheckers(C, Dst, Src);
538}
539
540namespace {
541
542struct CheckEndFunctionContext {
543 using CheckersTy = std::vector<CheckerManager::CheckEndFunctionFunc>;
544
545 const CheckersTy &Checkers;
546 const ReturnStmt *RS;
547 ExprEngine &Eng;
548
549 CheckEndFunctionContext(const CheckersTy &Checkers, const ReturnStmt *RS,
550 ExprEngine &Eng)
551 : Checkers(Checkers), RS(RS), Eng(Eng) {}
552
553 CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); }
554 CheckersTy::const_iterator checkers_end() { return Checkers.end(); }
555
556 void runChecker(CheckerManager::CheckEndFunctionFunc checkFn,
557 ExplodedNode *Pred, ExplodedNodeSet &Dst) {
558 llvm::TimeTraceScope TimeScope(checkerScopeName("End", checkFn.Checker));
559 const ProgramPoint &L =
560 FunctionExitPoint(RS, Pred->getStackFrame(), checkFn.Checker);
561 CheckerContext C(Eng, Pred, Dst, L);
562
563 checkFn(RS, C);
564 }
565};
566
567} // namespace
568
569/// Run checkers for end of a function (either the entrypoint or another
570/// function that was inlined).
572 ExplodedNode *Pred,
573 ExprEngine &Eng,
574 const ReturnStmt *RS) {
575 ExplodedNodeSet Src;
576 Src.insert(Pred);
577 CheckEndFunctionContext C(EndFunctionCheckers, RS, Eng);
578 llvm::TimeTraceScope TimeScope("CheckerManager::runCheckersForEndFunction");
579 expandGraphWithCheckers(C, Dst, Src);
580}
581
582namespace {
583
584 struct CheckBranchConditionContext {
585 using CheckersTy = std::vector<CheckerManager::CheckBranchConditionFunc>;
586
587 const CheckersTy &Checkers;
588 const Stmt *Condition;
589 ExprEngine &Eng;
590
591 CheckBranchConditionContext(const CheckersTy &checkers,
592 const Stmt *Cond, ExprEngine &eng)
593 : Checkers(checkers), Condition(Cond), Eng(eng) {}
594
595 CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); }
596 CheckersTy::const_iterator checkers_end() { return Checkers.end(); }
597
598 void runChecker(CheckerManager::CheckBranchConditionFunc checkFn,
599 ExplodedNode *Pred, ExplodedNodeSet &Dst) {
600 llvm::TimeTraceScope TimeScope(
601 checkerScopeName("BranchCond", checkFn.Checker));
602 ProgramPoint L =
603 PostCondition(Condition, Pred->getStackFrame(), checkFn.Checker);
604 CheckerContext C(Eng, Pred, Dst, L);
605 checkFn(Condition, C);
606 }
607 };
608
609} // namespace
610
611/// Run checkers for branch condition.
613 ExplodedNodeSet &Dst,
614 ExplodedNode *Pred,
615 ExprEngine &Eng) {
616 ExplodedNodeSet Src;
617 Src.insert(Pred);
618 CheckBranchConditionContext C(BranchConditionCheckers, Condition, Eng);
619 llvm::TimeTraceScope TimeScope(
620 "CheckerManager::runCheckersForBranchCondition");
621 expandGraphWithCheckers(C, Dst, Src);
622}
623
624namespace {
625
626 struct CheckNewAllocatorContext {
627 using CheckersTy = std::vector<CheckerManager::CheckNewAllocatorFunc>;
628
629 const CheckersTy &Checkers;
630 const CXXAllocatorCall &Call;
631 bool WasInlined;
632 ExprEngine &Eng;
633
634 CheckNewAllocatorContext(const CheckersTy &Checkers,
635 const CXXAllocatorCall &Call, bool WasInlined,
636 ExprEngine &Eng)
637 : Checkers(Checkers), Call(Call), WasInlined(WasInlined), Eng(Eng) {}
638
639 CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); }
640 CheckersTy::const_iterator checkers_end() { return Checkers.end(); }
641
642 void runChecker(CheckerManager::CheckNewAllocatorFunc checkFn,
643 ExplodedNode *Pred, ExplodedNodeSet &Dst) {
644 llvm::TimeTraceScope TimeScope(
645 checkerScopeName("Allocator", checkFn.Checker));
646 ProgramPoint L = PostAllocatorCall(
647 Call.getOriginExpr(), Pred->getStackFrame(), checkFn.Checker);
648 CheckerContext C(Eng, Pred, Dst, L, WasInlined);
649 checkFn(cast<CXXAllocatorCall>(*Call.cloneWithState(Pred->getState())),
650 C);
651 }
652 };
653
654} // namespace
655
657 ExplodedNodeSet &Dst,
658 ExplodedNode *Pred,
659 ExprEngine &Eng,
660 bool WasInlined) {
661 ExplodedNodeSet Src;
662 Src.insert(Pred);
663 CheckNewAllocatorContext C(NewAllocatorCheckers, Call, WasInlined, Eng);
664 llvm::TimeTraceScope TimeScope("CheckerManager::runCheckersForNewAllocator");
665 expandGraphWithCheckers(C, Dst, Src);
666}
667
668/// Run checkers for live symbols.
670 SymbolReaper &SymReaper) {
671 for (const auto &LiveSymbolsChecker : LiveSymbolsCheckers)
672 LiveSymbolsChecker(state, SymReaper);
673}
674
675namespace {
676
677 struct CheckDeadSymbolsContext {
678 using CheckersTy = std::vector<CheckerManager::CheckDeadSymbolsFunc>;
679
680 const CheckersTy &Checkers;
681 SymbolReaper &SR;
682 const Stmt *S;
683 ExprEngine &Eng;
684 ProgramPoint::Kind ProgramPointKind;
685
686 CheckDeadSymbolsContext(const CheckersTy &checkers, SymbolReaper &sr,
687 const Stmt *s, ExprEngine &eng,
689 : Checkers(checkers), SR(sr), S(s), Eng(eng), ProgramPointKind(K) {}
690
691 CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); }
692 CheckersTy::const_iterator checkers_end() { return Checkers.end(); }
693
694 void runChecker(CheckerManager::CheckDeadSymbolsFunc checkFn,
695 ExplodedNode *Pred, ExplodedNodeSet &Dst) {
696 llvm::TimeTraceScope TimeScope(
697 checkerScopeName("DeadSymbols", checkFn.Checker));
699 S, ProgramPointKind, Pred->getStackFrame(), checkFn.Checker);
700 CheckerContext C(Eng, Pred, Dst, L);
701
702 // Note, do not pass the statement to the checkers without letting them
703 // differentiate if we ran remove dead bindings before or after the
704 // statement.
705 checkFn(SR, C);
706 }
707 };
708
709} // namespace
710
711/// Run checkers for dead symbols.
713 const ExplodedNodeSet &Src,
714 SymbolReaper &SymReaper,
715 const Stmt *S,
716 ExprEngine &Eng,
718 CheckDeadSymbolsContext C(DeadSymbolsCheckers, SymReaper, S, Eng, K);
719 llvm::TimeTraceScope TimeScope("CheckerManager::runCheckersForDeadSymbols");
720 expandGraphWithCheckers(C, Dst, Src);
721}
722
723/// Run checkers for region changes.
725 ProgramStateRef state, const InvalidatedSymbols *invalidated,
726 ArrayRef<const MemRegion *> ExplicitRegions,
727 ArrayRef<const MemRegion *> Regions, const StackFrame *SF,
728 const CallEvent *Call) {
729 for (const auto &RegionChangesChecker : RegionChangesCheckers) {
730 // If any checker declares the state infeasible (or if it starts that way),
731 // bail out.
732 if (!state)
733 return nullptr;
734 state = RegionChangesChecker(state, invalidated, ExplicitRegions, Regions,
735 SF, Call);
736 }
737 return state;
738}
739
740/// Run checkers to process symbol escape event.
743 const InvalidatedSymbols &Escaped,
744 const CallEvent *Call,
747 assert((Call != nullptr ||
748 (Kind != PSK_DirectEscapeOnCall &&
749 Kind != PSK_IndirectEscapeOnCall)) &&
750 "Call must not be NULL when escaping on call");
751 for (const auto &PointerEscapeChecker : PointerEscapeCheckers) {
752 // If any checker declares the state infeasible (or if it starts that
753 // way), bail out.
754 if (!State)
755 return nullptr;
756 State = PointerEscapeChecker(State, Escaped, Call, Kind, ETraits);
757 }
758 return State;
759}
760
761/// Run checkers for handling assumptions on symbolic values.
764 SVal Cond, bool Assumption) {
765 for (const auto &EvalAssumeChecker : EvalAssumeCheckers) {
766 // If any checker declares the state infeasible (or if it starts that way),
767 // bail out.
768 if (!state)
769 return nullptr;
770 state = EvalAssumeChecker(state, Cond, Assumption);
771 }
772 return state;
773}
774
775/// Run checkers for evaluating a call.
776/// Only one checker will evaluate the call.
778 const ExplodedNodeSet &Src,
779 const CallEvent &Call,
780 ExprEngine &Eng,
781 const EvalCallOptions &CallOpts) {
782 for (auto *const Pred : Src) {
783 std::optional<StringRef> evaluatorChecker;
784
785 ExplodedNodeSet checkDst{Pred};
786
787 ProgramStateRef State = Pred->getState();
788 CallEventRef<> UpdatedCall = Call.cloneWithState(State);
789
790 // Check if any of the EvalCall callbacks can evaluate the call.
791 for (const auto &EvalCallChecker : EvalCallCheckers) {
792 // TODO: Support the situation when the call doesn't correspond
793 // to any Expr.
795 UpdatedCall->getOriginExpr(), ProgramPoint::PostStmtKind,
796 Pred->getStackFrame(), EvalCallChecker.Checker);
797
798 CheckerContext C(Eng, Pred, checkDst, L);
799 bool evaluated = EvalCallChecker(*UpdatedCall, C);
800#ifndef NDEBUG
801 if (evaluated && evaluatorChecker) {
802 const auto toString = [](const CallEvent &Call) -> std::string {
803 std::string Buf;
804 llvm::raw_string_ostream OS(Buf);
805 Call.dump(OS);
806 return Buf;
807 };
808 std::string AssertionMessage = llvm::formatv(
809 "The '{0}' call has been already evaluated by the {1} checker, "
810 "while the {2} checker also tried to evaluate the same call. At "
811 "most one checker supposed to evaluate a call.",
812 toString(Call), evaluatorChecker,
813 EvalCallChecker.Checker->getDebugTag());
814 llvm_unreachable(AssertionMessage.c_str());
815 }
816#endif
817 if (evaluated) {
818 evaluatorChecker = EvalCallChecker.Checker->getDebugTag();
819 Dst.insert(checkDst);
820#ifdef NDEBUG
821 break; // on release don't check that no other checker also evals.
822#endif
823 }
824 }
825
826 // If none of the checkers evaluated the call, ask ExprEngine to handle it.
827 if (!evaluatorChecker)
828 Eng.defaultEvalCall(Dst, Pred, *UpdatedCall, CallOpts);
829 }
830}
831
832/// Run checkers for the entire Translation Unit.
834 const TranslationUnitDecl *TU,
835 AnalysisManager &mgr,
836 BugReporter &BR) {
837 for (const auto &EndOfTranslationUnitChecker : EndOfTranslationUnitCheckers)
838 EndOfTranslationUnitChecker(TU, mgr, BR);
839}
840
842 ProgramStateRef State,
843 const char *NL,
844 unsigned int Space,
845 bool IsDot) const {
846 Indent(Out, Space, IsDot) << "\"checker_messages\": ";
847
848 // Create a temporary stream to see whether we have any message.
849 SmallString<1024> TempBuf;
850 llvm::raw_svector_ostream TempOut(TempBuf);
851 unsigned int InnerSpace = Space + 2;
852
853 // Create the new-line in JSON with enough space.
854 SmallString<128> NewLine;
855 llvm::raw_svector_ostream NLOut(NewLine);
856 NLOut << "\", " << NL; // Inject the ending and a new line
857 Indent(NLOut, InnerSpace, IsDot) << "\""; // then begin the next message.
858
859 ++Space;
860
861 std::vector<std::pair<std::string, std::string>> CheckerMsgs;
862 for (const auto &CT : CheckerTags) {
863 CT.second->printState(TempOut, State, /*NL=*/NewLine.c_str(), /*Sep=*/"");
864 const std::string Msg = TempBuf.str().trim().str();
865 TempBuf.clear();
866
867 if (!Msg.empty())
868 CheckerMsgs.push_back({CT.second->getDebugTag().str(), Msg});
869 }
870 llvm::sort(CheckerMsgs);
871
872 if (!CheckerMsgs.empty())
873 Out << '[' << NL;
874
875 llvm::interleave(
876 CheckerMsgs,
877 [&](const std::pair<std::string, std::string> &CM) {
878 Indent(Out, Space, IsDot)
879 << "{ \"checker\": \"" << CM.first << "\", \"messages\": [" << NL;
880 Indent(Out, InnerSpace, IsDot) << '\"' << CM.second << '\"' << NL;
881 Indent(Out, Space, IsDot) << "]}";
882 },
883 [&] { Out << ',' << NL; });
884
885 // It is the last element of the 'program_state' so do not add a comma.
886 if (!CheckerMsgs.empty()) {
887 Out << NL;
888 Indent(Out, --Space, IsDot) << "]";
889 } else {
890 Out << "null";
891 }
892
893 Out << NL;
894}
895
896//===----------------------------------------------------------------------===//
897// Internal registration functions for AST traversing.
898//===----------------------------------------------------------------------===//
899
901 HandlesDeclFunc isForDeclFn) {
902 DeclCheckerInfo info = { checkfn, isForDeclFn };
903 DeclCheckers.push_back(info);
904}
905
907 BodyCheckers.push_back(checkfn);
908}
909
910//===----------------------------------------------------------------------===//
911// Internal registration functions for path-sensitive checking.
912//===----------------------------------------------------------------------===//
913
915 HandlesStmtFunc isForStmtFn) {
916 StmtCheckerInfo info = { checkfn, isForStmtFn, /*IsPreVisit*/true };
917 StmtCheckers.push_back(info);
918}
919
921 HandlesStmtFunc isForStmtFn) {
922 StmtCheckerInfo info = { checkfn, isForStmtFn, /*IsPreVisit*/false };
923 StmtCheckers.push_back(info);
924}
925
927 PreObjCMessageCheckers.push_back(checkfn);
928}
929
931 ObjCMessageNilCheckers.push_back(checkfn);
932}
933
935 PostObjCMessageCheckers.push_back(checkfn);
936}
937
939 PreCallCheckers.push_back(checkfn);
940}
942 PostCallCheckers.push_back(checkfn);
943}
944
946 LifetimeEndCheckers.push_back(checkfn);
947}
948
950 LocationCheckers.push_back(checkfn);
951}
952
954 BindCheckers.push_back(checkfn);
955}
956
958 BlockEntranceCheckers.push_back(checkfn);
959}
960
962 EndAnalysisCheckers.push_back(checkfn);
963}
964
966 BeginFunctionCheckers.push_back(checkfn);
967}
968
970 EndFunctionCheckers.push_back(checkfn);
971}
972
974 CheckBranchConditionFunc checkfn) {
975 BranchConditionCheckers.push_back(checkfn);
976}
977
979 NewAllocatorCheckers.push_back(checkfn);
980}
981
983 LiveSymbolsCheckers.push_back(checkfn);
984}
985
987 DeadSymbolsCheckers.push_back(checkfn);
988}
989
991 RegionChangesCheckers.push_back(checkfn);
992}
993
995 PointerEscapeCheckers.push_back(checkfn);
996}
997
999 CheckPointerEscapeFunc checkfn) {
1000 PointerEscapeCheckers.push_back(checkfn);
1001}
1002
1004 EvalAssumeCheckers.push_back(checkfn);
1005}
1006
1008 EvalCallCheckers.push_back(checkfn);
1009}
1010
1012 CheckEndOfTranslationUnit checkfn) {
1013 EndOfTranslationUnitCheckers.push_back(checkfn);
1014}
1015
1016//===----------------------------------------------------------------------===//
1017// Implementation details.
1018//===----------------------------------------------------------------------===//
1019
1020const CheckerManager::CachedStmtCheckers &
1021CheckerManager::getCachedStmtCheckersFor(const Stmt *S, bool isPreVisit) {
1022 assert(S);
1023
1024 unsigned Key = (S->getStmtClass() << 1) | unsigned(isPreVisit);
1025 auto [CCI, Inserted] = CachedStmtCheckersMap.try_emplace(Key);
1026 CachedStmtCheckers &Checkers = CCI->second;
1027 if (Inserted) {
1028 // Find the checkers that should run for this Stmt and cache them.
1029 for (const auto &Info : StmtCheckers)
1030 if (Info.IsPreVisit == isPreVisit && Info.IsForStmtFn(S))
1031 Checkers.push_back(Info.CheckFn);
1032 }
1033 return Checkers;
1034}
static void expandGraphWithCheckers(CHECK_CTX checkCtx, ExplodedNodeSet &Dst, const ExplodedNodeSet &Src)
Forward-declares and imports various common LLVM datatypes that clang wants to use unqualified.
static std::string toString(const clang::SanitizerSet &Sanitizers)
Produce a string containing comma-separated names of sanitizers in Sanitizers set.
Decl - This represents one declaration (or definition), e.g.
Definition DeclBase.h:86
virtual bool hasBody() const
Returns true if this Decl represents a declaration for a body of code, such as a function or method d...
Definition DeclBase.h:1111
Kind getKind() const
Definition DeclBase.h:451
DiagnosticBuilder Report(SourceLocation Loc, unsigned DiagID)
Issue the message to the client.
static ProgramPoint getProgramPoint(const Stmt *S, ProgramPoint::Kind K, const StackFrame *SF, const ProgramPointTag *tag)
ProgramPoint withTag(const ProgramPointTag *NewTag) const
Create a new ProgramPoint object that is the same as the original except for using the specified tag ...
std::optional< T > getAs() const
Convert to the specified ProgramPoint type, returning std::nullopt if this ProgramPoint is not of the...
ReturnStmt - This represents a return, optionally of an expression: return; return 4;.
Definition Stmt.h:3173
It represents a stack frame of the call stack.
Stmt - This represents one statement.
Definition Stmt.h:85
StmtClass getStmtClass() const
Definition Stmt.h:1504
The top declaration context.
Definition Decl.h:107
Represents a variable declaration or definition.
Definition Decl.h:934
BugReporter is a utility class for generating PathDiagnostics for analysis.
Represents the memory allocation call in a C++ new-expression.
Definition CallEvent.h:1120
Represents an abstract call to a function or method along a particular path.
Definition CallEvent.h:152
CallEventRef< T > cloneWithState(ProgramStateRef NewState) const
Returns a copy of this CallEvent, but using the given state.
Definition CallEvent.h:1477
ProgramPoint getProgramPoint(bool IsPreVisit=false, const ProgramPointTag *Tag=nullptr) const
Returns an appropriate ProgramPoint for this call.
CheckerBackend is an abstract base class that serves as the common ancestor of all the Checker<....
Definition Checker.h:544
StringRef getDebugTag() const override
Attached to nodes created by this checker class when the ExplodedGraph is dumped for debugging.
Definition Checker.cpp:20
A CheckerFrontend instance is what the user recognizes as "one checker": it has a public canonical na...
Definition Checker.h:526
CheckerNameRef getName() const
Definition Checker.h:536
void _registerForLiveSymbols(CheckLiveSymbolsFunc checkfn)
void _registerForEndOfTranslationUnit(CheckEndOfTranslationUnit checkfn)
ProgramStateRef runCheckersForRegionChanges(ProgramStateRef state, const InvalidatedSymbols *invalidated, ArrayRef< const MemRegion * > ExplicitRegions, ArrayRef< const MemRegion * > Regions, const StackFrame *SF, const CallEvent *Call)
Run checkers for region changes.
void _registerForBeginFunction(CheckBeginFunctionFunc checkfn)
void _registerForNewAllocator(CheckNewAllocatorFunc checkfn)
CheckerFn< void(const Decl *, AnalysisManager &, BugReporter &)> CheckDeclFunc
void _registerForPreCall(CheckCallFunc checkfn)
CheckerFn< ProgramStateRef(ProgramStateRef, SVal cond, bool assumption)> EvalAssumeFunc
void _registerForObjCMessageNil(CheckObjCMessageFunc checkfn)
CheckerFn< ProgramStateRef(ProgramStateRef, const InvalidatedSymbols &Escaped, const CallEvent *Call, PointerEscapeKind Kind, RegionAndSymbolInvalidationTraits *ITraits)> CheckPointerEscapeFunc
bool(*)(const Decl *D) HandlesDeclFunc
void runCheckersForObjCMessage(ObjCMessageVisitKind visitKind, ExplodedNodeSet &Dst, const ExplodedNodeSet &Src, const ObjCMethodCall &msg, ExprEngine &Eng, bool wasInlined=false)
Run checkers for visiting obj-c messages.
void runCheckersOnASTDecl(const Decl *D, AnalysisManager &mgr, BugReporter &BR)
Run checkers handling Decls.
void _registerForDecl(CheckDeclFunc checkfn, HandlesDeclFunc isForDeclFn)
CheckerFn< void(const ReturnStmt *, CheckerContext &)> CheckEndFunctionFunc
CheckerFn< void(const Stmt *, CheckerContext &)> CheckBranchConditionFunc
void _registerForPreObjCMessage(CheckObjCMessageFunc checkfn)
void runCheckersOnEndOfTranslationUnit(const TranslationUnitDecl *TU, AnalysisManager &mgr, BugReporter &BR)
Run checkers for the entire Translation Unit.
CheckerFn< bool(const CallEvent &, CheckerContext &)> EvalCallFunc
CheckerFn< void(CheckerContext &)> CheckBeginFunctionFunc
CheckerFn< void(ExplodedGraph &, BugReporter &, ExprEngine &)> CheckEndAnalysisFunc
void _registerForEvalAssume(EvalAssumeFunc checkfn)
void _registerForEndAnalysis(CheckEndAnalysisFunc checkfn)
void _registerForBody(CheckDeclFunc checkfn)
DiagnosticsEngine & getDiagnostics() const
void runCheckersForLocation(ExplodedNodeSet &Dst, const ExplodedNodeSet &Src, SVal location, bool isLoad, const Stmt *NodeEx, const Stmt *BoundEx, ExprEngine &Eng)
Run checkers for load/store of a location.
CheckerFn< void(const Stmt *, CheckerContext &)> CheckStmtFunc
CheckerFn< void(SVal location, SVal val, const Stmt *S, bool AtDeclInit, CheckerContext &)> CheckBindFunc
void runCheckersForBind(ExplodedNodeSet &Dst, const ExplodedNodeSet &Src, SVal location, SVal val, const Stmt *S, bool AtDeclInit, ExprEngine &Eng, const ProgramPoint &PP)
Run checkers for binding of a value to a location.
void reportInvalidCheckerOptionValue(const CheckerFrontend *Checker, StringRef OptionName, StringRef ExpectedValueDesc) const
Emits an error through a DiagnosticsEngine about an invalid user supplied checker option value.
void runCheckersForEndAnalysis(ExplodedGraph &G, BugReporter &BR, ExprEngine &Eng)
Run checkers for end of analysis.
CheckerFn< void(const CXXAllocatorCall &Call, CheckerContext &)> CheckNewAllocatorFunc
CheckerFn< void(const VarDecl *, CheckerContext &)> CheckLifetimeEndFunc
void runCheckersForPrintStateJson(raw_ostream &Out, ProgramStateRef State, const char *NL="\n", unsigned int Space=0, bool IsDot=false) const
Run checkers for debug-printing a ProgramState.
void _registerForDeadSymbols(CheckDeadSymbolsFunc checkfn)
void runCheckersForDeadSymbols(ExplodedNodeSet &Dst, const ExplodedNodeSet &Src, SymbolReaper &SymReaper, const Stmt *S, ExprEngine &Eng, ProgramPoint::Kind K)
Run checkers for dead symbols.
void _registerForPostObjCMessage(CheckObjCMessageFunc checkfn)
void _registerForRegionChanges(CheckRegionChangesFunc checkfn)
void runCheckersForEndFunction(ExplodedNodeSet &Dst, ExplodedNode *Pred, ExprEngine &Eng, const ReturnStmt *RS)
Run checkers on end of function.
void _registerForBind(CheckBindFunc checkfn)
void runCheckersForLiveSymbols(ProgramStateRef state, SymbolReaper &SymReaper)
Run checkers for live symbols.
void _registerForPointerEscape(CheckPointerEscapeFunc checkfn)
CheckerFn< void(const TranslationUnitDecl *, AnalysisManager &, BugReporter &)> CheckEndOfTranslationUnit
void _registerForPreStmt(CheckStmtFunc checkfn, HandlesStmtFunc isForStmtFn)
void runCheckersForEvalCall(ExplodedNodeSet &Dst, const ExplodedNodeSet &Src, const CallEvent &CE, ExprEngine &Eng, const EvalCallOptions &CallOpts)
Run checkers for evaluating a call.
void _registerForPostStmt(CheckStmtFunc checkfn, HandlesStmtFunc isForStmtFn)
void runCheckersForBeginFunction(ExplodedNodeSet &Dst, const BlockEdge &L, ExplodedNode *Pred, ExprEngine &Eng)
Run checkers on beginning of function.
void runCheckersForNewAllocator(const CXXAllocatorCall &Call, ExplodedNodeSet &Dst, ExplodedNode *Pred, ExprEngine &Eng, bool wasInlined=false)
Run checkers between C++ operator new and constructor calls.
CheckerFn< void(const CallEvent &, CheckerContext &)> CheckCallFunc
void _registerForBranchCondition(CheckBranchConditionFunc checkfn)
CheckerFn< void(SymbolReaper &, CheckerContext &)> CheckDeadSymbolsFunc
CheckerFn< void(SVal location, bool isLoad, const Stmt *S, CheckerContext &)> CheckLocationFunc
void runCheckersForBlockEntrance(ExplodedNodeSet &Dst, const ExplodedNodeSet &Src, const BlockEntrance &Entrance, ExprEngine &Eng) const
Run checkers after taking a control flow edge.
void runCheckersForStmt(bool isPreVisit, ExplodedNodeSet &Dst, const ExplodedNodeSet &Src, const Stmt *S, ExprEngine &Eng, bool wasInlined=false)
Run checkers for visiting Stmts.
void _registerForEvalCall(EvalCallFunc checkfn)
void _registerForEndFunction(CheckEndFunctionFunc checkfn)
void _registerForBlockEntrance(CheckBlockEntranceFunc checkfn)
CheckerFn< ProgramStateRef( ProgramStateRef, const InvalidatedSymbols *symbols, ArrayRef< const MemRegion * > ExplicitRegions, ArrayRef< const MemRegion * > Regions, const StackFrame *SF, const CallEvent *Call)> CheckRegionChangesFunc
void runCheckersForBranchCondition(const Stmt *condition, ExplodedNodeSet &Dst, ExplodedNode *Pred, ExprEngine &Eng)
Run checkers for branch condition.
CheckerFn< void(const ObjCMethodCall &, CheckerContext &)> CheckObjCMessageFunc
void _registerForLocation(CheckLocationFunc checkfn)
ProgramStateRef runCheckersForPointerEscape(ProgramStateRef State, const InvalidatedSymbols &Escaped, const CallEvent *Call, PointerEscapeKind Kind, RegionAndSymbolInvalidationTraits *ITraits)
Run checkers when pointers escape.
void _registerForConstPointerEscape(CheckPointerEscapeFunc checkfn)
CheckerFn< void(const BlockEntrance &, CheckerContext &)> CheckBlockEntranceFunc
CheckerFn< void(ProgramStateRef, SymbolReaper &)> CheckLiveSymbolsFunc
void runCheckersForCallEvent(bool isPreVisit, ExplodedNodeSet &Dst, const ExplodedNodeSet &Src, const CallEvent &Call, ExprEngine &Eng, bool wasInlined=false)
Run checkers for visiting function calls (including methods, constructors, destructors etc.
bool(*)(const Stmt *D) HandlesStmtFunc
void _registerForPostCall(CheckCallFunc checkfn)
void runCheckersOnASTBody(const Decl *D, AnalysisManager &mgr, BugReporter &BR)
Run checkers handling Decls containing a Stmt body.
void runCheckersForLifetimeEnd(ExplodedNodeSet &Dst, const ExplodedNodeSet &Src, const VarDecl *Decl, ExprEngine &Eng)
Run checkers for the end of a variable's lifetime.
void _registerForLifetimeEnd(CheckLifetimeEndFunc checkfn)
ProgramStateRef runCheckersForEvalAssume(ProgramStateRef state, SVal Cond, bool Assumption)
Run checkers for handling assumptions on symbolic values.
Simple checker classes that implement one frontend (i.e.
Definition Checker.h:565
ExplodedNodeSet is a set of ExplodedNode * elements with the invariant that its elements cannot be nu...
void insert(ExplodedNode *N)
const ProgramStateRef & getState() const
ProgramPoint getLocation() const
getLocation - Returns the edge associated with the given node.
const StackFrame * getStackFrame() const
void defaultEvalCall(ExplodedNodeSet &Dst, ExplodedNode *Pred, const CallEvent &Call, const EvalCallOptions &CallOpts={})
Default implementation of call evaluation.
Represents any expression that calls an Objective-C method.
Definition CallEvent.h:1249
Information about invalidation for a particular region/symbol.
Definition MemRegion.h:1663
SVal - This represents a symbolic expression, which can be either an L-value or an R-value.
Definition SVals.h:57
void dumpToStream(raw_ostream &OS) const
Definition SVals.cpp:293
A class responsible for cleaning up unused symbols.
const internal::VariadicAllOfMatcher< Decl > decl
Matches declarations.
PointerEscapeKind
Describes the different reasons a pointer escapes during analysis.
@ PSK_DirectEscapeOnCall
The pointer has been passed to a function call directly.
@ PSK_IndirectEscapeOnCall
The pointer has been passed to a function indirectly.
llvm::DenseSet< SymbolRef > InvalidatedSymbols
Definition Store.h:50
IntrusiveRefCntPtr< const ProgramState > ProgramStateRef
@ OS
Indicates that the tracking object is a descendant of a referenced-counted OSObject,...
const Fact * ProgramPoint
A ProgramPoint identifies a location in the CFG by pointing to a specific Fact.
Definition Facts.h:157
Top level wrappers for InstallAPI frontend operations.
raw_ostream & Indent(raw_ostream &Out, const unsigned int Space, bool IsDot)
Definition JsonSupport.h:21
U cast(CodeGen::Address addr)
Definition Address.h:327
Hints for figuring out if a call should be inlined during evalCall().
Definition ExprEngine.h:92