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/SmallVector.h"
27#include "llvm/Support/ErrorHandling.h"
28#include "llvm/Support/FormatVariadic.h"
29#include "llvm/Support/TimeProfiler.h"
30#include <cassert>
31#include <optional>
32#include <vector>
33
34using namespace clang;
35using namespace ento;
36
38 const auto IfAnyAreNonEmpty = [](const auto &...Callbacks) -> bool {
39 return (!Callbacks.empty() || ...);
40 };
41 return IfAnyAreNonEmpty(
42 StmtCheckers, PreObjCMessageCheckers, ObjCMessageNilCheckers,
43 PostObjCMessageCheckers, PreCallCheckers, PostCallCheckers,
44 LifetimeEndCheckers, LocationCheckers, BindCheckers,
45 BlockEntranceCheckers, EndAnalysisCheckers, BeginFunctionCheckers,
46 EndFunctionCheckers, BranchConditionCheckers, NewAllocatorCheckers,
47 LiveSymbolsCheckers, DeadSymbolsCheckers, RegionChangesCheckers,
48 PointerEscapeCheckers, EvalAssumeCheckers, EvalCallCheckers,
49 EndOfTranslationUnitCheckers);
50}
51
53 const CheckerFrontend *Checker, StringRef OptionName,
54 StringRef ExpectedValueDesc) const {
55
56 getDiagnostics().Report(diag::err_analyzer_checker_option_invalid_input)
57 << (llvm::Twine(Checker->getName()) + ":" + OptionName).str()
58 << ExpectedValueDesc;
59}
60
61//===----------------------------------------------------------------------===//
62// Functions for running checkers for AST traversing..
63//===----------------------------------------------------------------------===//
64
66 BugReporter &BR) {
67 assert(D);
68
69 unsigned DeclKind = D->getKind();
70 auto [CCI, Inserted] = CachedDeclCheckersMap.try_emplace(DeclKind);
71 CachedDeclCheckers *checkers = &(CCI->second);
72 if (Inserted) {
73 // Find the checkers that should run for this Decl and cache them.
74 for (const auto &info : DeclCheckers)
75 if (info.IsForDeclFn(D))
76 checkers->push_back(info.CheckFn);
77 }
78
79 assert(checkers);
80 for (const auto &checker : *checkers)
81 checker(D, mgr, BR);
82}
83
85 BugReporter &BR) {
86 assert(D && D->hasBody());
87
88 for (const auto &BodyChecker : BodyCheckers)
89 BodyChecker(D, mgr, BR);
90}
91
92//===----------------------------------------------------------------------===//
93// Functions for running checkers for path-sensitive checking.
94//===----------------------------------------------------------------------===//
95
96template <typename CHECK_CTX>
97static void expandGraphWithCheckers(CHECK_CTX checkCtx, ExplodedNodeSet &Dst,
98 const ExplodedNodeSet &Src) {
99 if (Src.empty())
100 return;
101
102 typename CHECK_CTX::CheckersTy::const_iterator
103 I = checkCtx.checkers_begin(), E = checkCtx.checkers_end();
104 if (I == E) {
105 Dst.insert(Src);
106 return;
107 }
108
109 ExplodedNodeSet Tmp1, Tmp2;
110 const ExplodedNodeSet *PrevSet = &Src;
111
112 for (; I != E; ++I) {
113 ExplodedNodeSet *CurrSet = nullptr;
114 if (I+1 == E)
115 CurrSet = &Dst;
116 else {
117 CurrSet = (PrevSet == &Tmp1) ? &Tmp2 : &Tmp1;
118 CurrSet->clear();
119 }
120
121 CurrSet->insert(*PrevSet);
122 for (const auto &NI : *PrevSet)
123 checkCtx.runChecker(*I, NI, *CurrSet);
124
125 // If all the produced transitions are sinks, stop.
126 if (CurrSet->empty())
127 return;
128
129 // Update which NodeSet is the current one.
130 PrevSet = CurrSet;
131 }
132}
133
134namespace {
135
136std::string checkerScopeName(StringRef Name, const CheckerBackend *Checker) {
137 if (!llvm::timeTraceProfilerEnabled())
138 return "";
139 StringRef CheckerTag = Checker ? Checker->getDebugTag() : "<unknown>";
140 return (Name + ":" + CheckerTag).str();
141}
142
143 struct CheckStmtContext {
144 using CheckersTy = SmallVectorImpl<CheckerManager::CheckStmtFunc>;
145
146 bool IsPreVisit;
147 const CheckersTy &Checkers;
148 const Stmt *S;
149 ExprEngine &Eng;
150 bool WasInlined;
151
152 CheckStmtContext(bool isPreVisit, const CheckersTy &checkers,
153 const Stmt *s, ExprEngine &eng, bool wasInlined = false)
154 : IsPreVisit(isPreVisit), Checkers(checkers), S(s), Eng(eng),
155 WasInlined(wasInlined) {}
156
157 CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); }
158 CheckersTy::const_iterator checkers_end() { return Checkers.end(); }
159
160 void runChecker(CheckerManager::CheckStmtFunc checkFn, ExplodedNode *Pred,
161 ExplodedNodeSet &Dst) {
162 llvm::TimeTraceScope TimeScope(checkerScopeName("Stmt", checkFn.Checker));
163 // FIXME: Remove respondsToCallback from CheckerContext;
167 S, K, Pred->getStackFrame(), checkFn.Checker);
168 CheckerContext C(Eng, Pred, Dst, L, WasInlined);
169 checkFn(S, C);
170 }
171 };
172
173} // namespace
174
175/// Run checkers for visiting Stmts.
177 ExplodedNodeSet &Dst,
178 const ExplodedNodeSet &Src,
179 const Stmt *S,
180 ExprEngine &Eng,
181 bool WasInlined) {
182 CheckStmtContext C(isPreVisit, getCachedStmtCheckersFor(S, isPreVisit),
183 S, Eng, WasInlined);
184 llvm::TimeTraceScope TimeScope(
185 isPreVisit ? "CheckerManager::runCheckersForStmt (Pre)"
186 : "CheckerManager::runCheckersForStmt (Post)");
187 expandGraphWithCheckers(C, Dst, Src);
188}
189
190namespace {
191
192 struct CheckObjCMessageContext {
193 using CheckersTy = std::vector<CheckerManager::CheckObjCMessageFunc>;
194
196 bool WasInlined;
197 const CheckersTy &Checkers;
198 const ObjCMethodCall &Msg;
199 ExprEngine &Eng;
200
201 CheckObjCMessageContext(ObjCMessageVisitKind visitKind,
202 const CheckersTy &checkers,
203 const ObjCMethodCall &msg, ExprEngine &eng,
204 bool wasInlined)
205 : Kind(visitKind), WasInlined(wasInlined), Checkers(checkers), Msg(msg),
206 Eng(eng) {}
207
208 CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); }
209 CheckersTy::const_iterator checkers_end() { return Checkers.end(); }
210
211 void runChecker(CheckerManager::CheckObjCMessageFunc checkFn,
212 ExplodedNode *Pred, ExplodedNodeSet &Dst) {
213 llvm::TimeTraceScope TimeScope(
214 checkerScopeName("ObjCMsg", checkFn.Checker));
215 bool IsPreVisit;
216
217 switch (Kind) {
218 case ObjCMessageVisitKind::Pre:
219 IsPreVisit = true;
220 break;
221 case ObjCMessageVisitKind::MessageNil:
222 case ObjCMessageVisitKind::Post:
223 IsPreVisit = false;
224 break;
225 }
226
227 const ProgramPoint &L = Msg.getProgramPoint(IsPreVisit,checkFn.Checker);
228 CheckerContext C(Eng, Pred, Dst, L, WasInlined);
229
230 checkFn(*Msg.cloneWithState<ObjCMethodCall>(Pred->getState()), C);
231 }
232 };
233
234} // namespace
235
236/// Run checkers for visiting obj-c messages.
238 ExplodedNodeSet &Dst,
239 const ExplodedNodeSet &Src,
240 const ObjCMethodCall &msg,
241 ExprEngine &Eng,
242 bool WasInlined) {
243 const auto &checkers = getObjCMessageCheckers(visitKind);
244 CheckObjCMessageContext C(visitKind, checkers, msg, Eng, WasInlined);
245 llvm::TimeTraceScope TimeScope("CheckerManager::runCheckersForObjCMessage");
246 expandGraphWithCheckers(C, Dst, Src);
247}
248
249const std::vector<CheckerManager::CheckObjCMessageFunc> &
250CheckerManager::getObjCMessageCheckers(ObjCMessageVisitKind Kind) const {
251 switch (Kind) {
253 return PreObjCMessageCheckers;
254 break;
256 return PostObjCMessageCheckers;
258 return ObjCMessageNilCheckers;
259 }
260 llvm_unreachable("Unknown Kind");
261}
262
263namespace {
264
265 // FIXME: This has all the same signatures as CheckObjCMessageContext.
266 // Is there a way we can merge the two?
267 struct CheckCallContext {
268 using CheckersTy = std::vector<CheckerManager::CheckCallFunc>;
269
270 bool IsPreVisit, WasInlined;
271 const CheckersTy &Checkers;
272 const CallEvent &Call;
273 ExprEngine &Eng;
274
275 CheckCallContext(bool isPreVisit, const CheckersTy &checkers,
276 const CallEvent &call, ExprEngine &eng,
277 bool wasInlined)
278 : IsPreVisit(isPreVisit), WasInlined(wasInlined), Checkers(checkers),
279 Call(call), Eng(eng) {}
280
281 CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); }
282 CheckersTy::const_iterator checkers_end() { return Checkers.end(); }
283
284 void runChecker(CheckerManager::CheckCallFunc checkFn, ExplodedNode *Pred,
285 ExplodedNodeSet &Dst) {
286 llvm::TimeTraceScope TimeScope(checkerScopeName("Call", checkFn.Checker));
287 const ProgramPoint &L = Call.getProgramPoint(IsPreVisit,checkFn.Checker);
288 CheckerContext C(Eng, Pred, Dst, L, WasInlined);
289
290 checkFn(*Call.cloneWithState(Pred->getState()), C);
291 }
292 };
293
294} // namespace
295
296/// Run checkers for visiting an abstract call event.
298 ExplodedNodeSet &Dst,
299 const ExplodedNodeSet &Src,
300 const CallEvent &Call,
301 ExprEngine &Eng,
302 bool WasInlined) {
303 CheckCallContext C(isPreVisit,
304 isPreVisit ? PreCallCheckers
305 : PostCallCheckers,
306 Call, Eng, WasInlined);
307 llvm::TimeTraceScope TimeScope(
308 isPreVisit ? "CheckerManager::runCheckersForCallEvent (Pre)"
309 : "CheckerManager::runCheckersForCallEvent (Post)");
310 expandGraphWithCheckers(C, Dst, Src);
311}
312
313namespace {
314
315struct CheckLifetimeEndContext {
316 using CheckersTy = std::vector<CheckerManager::CheckLifetimeEndFunc>;
317
318 const CheckersTy &Checkers;
319 const VarDecl *Decl;
320 ExprEngine &Eng;
321
322 CheckLifetimeEndContext(const CheckersTy &checkers, const VarDecl *decl,
323 ExprEngine &eng)
324 : Checkers(checkers), Decl(decl), Eng(eng) {}
325
326 CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); }
327 CheckersTy::const_iterator checkers_end() { return Checkers.end(); }
328
329 void runChecker(CheckerManager::CheckLifetimeEndFunc checkFn,
330 ExplodedNode *Pred, ExplodedNodeSet &Dst) {
331 assert(Pred->getLocation().getAs<LifetimeEnd>().has_value());
332 const ProgramPoint L = Pred->getLocation().withTag(checkFn.Checker);
333 CheckerContext C(Eng, Pred, Dst, L);
334 checkFn(Decl, C);
335 }
336};
337
338} // namespace
339
340/// Run checkers for end of variable lifetime
342 const ExplodedNodeSet &Src,
343 const VarDecl *Decl,
344 ExprEngine &Eng) {
345 llvm::TimeTraceScope TimeScope("CheckerManager::runCheckersForLifetimeEnd");
346 CheckLifetimeEndContext C(LifetimeEndCheckers, Decl, Eng);
347 expandGraphWithCheckers(C, Dst, Src);
348}
349
350namespace {
351
352 struct CheckLocationContext {
353 using CheckersTy = std::vector<CheckerManager::CheckLocationFunc>;
354
355 const CheckersTy &Checkers;
356 SVal Loc;
357 bool IsLoad;
358 const Stmt *NodeEx; /* Will become a CFGStmt */
359 const Stmt *BoundEx;
360 ExprEngine &Eng;
361
362 CheckLocationContext(const CheckersTy &checkers,
363 SVal loc, bool isLoad, const Stmt *NodeEx,
364 const Stmt *BoundEx,
365 ExprEngine &eng)
366 : Checkers(checkers), Loc(loc), IsLoad(isLoad), NodeEx(NodeEx),
367 BoundEx(BoundEx), Eng(eng) {}
368
369 CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); }
370 CheckersTy::const_iterator checkers_end() { return Checkers.end(); }
371
372 void runChecker(CheckerManager::CheckLocationFunc checkFn,
373 ExplodedNode *Pred, ExplodedNodeSet &Dst) {
374 llvm::TimeTraceScope TimeScope(checkerScopeName("Loc", checkFn.Checker));
378 NodeEx, K, Pred->getStackFrame(), checkFn.Checker);
379 CheckerContext C(Eng, Pred, Dst, L);
380 checkFn(Loc, IsLoad, BoundEx, C);
381 }
382 };
383
384} // namespace
385
386/// Run checkers for load/store of a location.
387
389 const ExplodedNodeSet &Src,
390 SVal location, bool isLoad,
391 const Stmt *NodeEx,
392 const Stmt *BoundEx,
393 ExprEngine &Eng) {
394 CheckLocationContext C(LocationCheckers, location, isLoad, NodeEx,
395 BoundEx, Eng);
396 llvm::TimeTraceScope TimeScope(
397 isLoad ? "CheckerManager::runCheckersForLocation (Load)"
398 : "CheckerManager::runCheckersForLocation (Store)");
399 expandGraphWithCheckers(C, Dst, Src);
400}
401
402namespace {
403
404 struct CheckBindContext {
405 using CheckersTy = std::vector<CheckerManager::CheckBindFunc>;
406
407 const CheckersTy &Checkers;
408 SVal Loc;
409 SVal Val;
410 const Stmt *S;
411 ExprEngine &Eng;
412 const ProgramPoint &PP;
413 bool AtDeclInit;
414
415 CheckBindContext(const CheckersTy &checkers, SVal loc, SVal val,
416 const Stmt *s, bool AtDeclInit, ExprEngine &eng,
417 const ProgramPoint &pp)
418 : Checkers(checkers), Loc(loc), Val(val), S(s), Eng(eng), PP(pp),
419 AtDeclInit(AtDeclInit) {}
420
421 CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); }
422 CheckersTy::const_iterator checkers_end() { return Checkers.end(); }
423
424 void runChecker(CheckerManager::CheckBindFunc checkFn, ExplodedNode *Pred,
425 ExplodedNodeSet &Dst) {
426 llvm::TimeTraceScope TimeScope(checkerScopeName("Bind", checkFn.Checker));
427 const ProgramPoint &L = PP.withTag(checkFn.Checker);
428 CheckerContext C(Eng, Pred, Dst, L);
429
430 checkFn(Loc, Val, S, AtDeclInit, C);
431 }
432 };
433
434 llvm::TimeTraceMetadata getTimeTraceBindMetadata(SVal Val) {
435 assert(llvm::timeTraceProfilerEnabled());
436 std::string Name;
437 llvm::raw_string_ostream OS(Name);
438 Val.dumpToStream(OS);
439 return llvm::TimeTraceMetadata{OS.str(), ""};
440 }
441
442} // namespace
443
444/// Run checkers for binding of a value to a location.
446 const ExplodedNodeSet &Src,
447 SVal location, SVal val, const Stmt *S,
448 bool AtDeclInit, ExprEngine &Eng,
449 const ProgramPoint &PP) {
450 CheckBindContext C(BindCheckers, location, val, S, AtDeclInit, Eng, PP);
451 llvm::TimeTraceScope TimeScope{
452 "CheckerManager::runCheckersForBind",
453 [&val]() { return getTimeTraceBindMetadata(val); }};
454 expandGraphWithCheckers(C, Dst, Src);
455}
456
457namespace {
458struct CheckBlockEntranceContext {
459 using CheckBlockEntranceFunc = CheckerManager::CheckBlockEntranceFunc;
460 using CheckersTy = std::vector<CheckBlockEntranceFunc>;
461
462 const CheckersTy &Checkers;
463 const BlockEntrance &Entrance;
464 ExprEngine &Eng;
465
466 CheckBlockEntranceContext(const CheckersTy &Checkers,
467 const BlockEntrance &Entrance, ExprEngine &Eng)
468 : Checkers(Checkers), Entrance(Entrance), Eng(Eng) {}
469
470 auto checkers_begin() const { return Checkers.begin(); }
471 auto checkers_end() const { return Checkers.end(); }
472
473 void runChecker(CheckBlockEntranceFunc CheckFn, ExplodedNode *Pred,
474 ExplodedNodeSet &Dst) {
475 llvm::TimeTraceScope TimeScope(
476 checkerScopeName("BlockEntrance", CheckFn.Checker));
477 CheckerContext C(Eng, Pred, Dst, Entrance.withTag(CheckFn.Checker));
478 CheckFn(Entrance, C);
479 }
480};
481
482} // namespace
483
485 const ExplodedNodeSet &Src,
486 const BlockEntrance &Entrance,
487 ExprEngine &Eng) const {
488 CheckBlockEntranceContext C(BlockEntranceCheckers, Entrance, Eng);
489 llvm::TimeTraceScope TimeScope{"CheckerManager::runCheckersForBlockEntrance"};
490 expandGraphWithCheckers(C, Dst, Src);
491}
492
494 BugReporter &BR,
495 ExprEngine &Eng) {
496 for (const auto &EndAnalysisChecker : EndAnalysisCheckers)
497 EndAnalysisChecker(G, BR, Eng);
498}
499
500namespace {
501
502struct CheckBeginFunctionContext {
503 using CheckersTy = std::vector<CheckerManager::CheckBeginFunctionFunc>;
504
505 const CheckersTy &Checkers;
506 ExprEngine &Eng;
507 const ProgramPoint &PP;
508
509 CheckBeginFunctionContext(const CheckersTy &Checkers, ExprEngine &Eng,
510 const ProgramPoint &PP)
511 : Checkers(Checkers), Eng(Eng), PP(PP) {}
512
513 CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); }
514 CheckersTy::const_iterator checkers_end() { return Checkers.end(); }
515
516 void runChecker(CheckerManager::CheckBeginFunctionFunc checkFn,
517 ExplodedNode *Pred, ExplodedNodeSet &Dst) {
518 llvm::TimeTraceScope TimeScope(checkerScopeName("Begin", checkFn.Checker));
519 const ProgramPoint &L = PP.withTag(checkFn.Checker);
520 CheckerContext C(Eng, Pred, Dst, L);
521
522 checkFn(C);
523 }
524};
525
526} // namespace
527
529 const BlockEdge &L,
530 ExplodedNode *Pred,
531 ExprEngine &Eng) {
532 ExplodedNodeSet Src;
533 Src.insert(Pred);
534 CheckBeginFunctionContext C(BeginFunctionCheckers, Eng, L);
535 llvm::TimeTraceScope TimeScope("CheckerManager::runCheckersForBeginFunction");
536 expandGraphWithCheckers(C, Dst, Src);
537}
538
539namespace {
540
541struct CheckEndFunctionContext {
542 using CheckersTy = std::vector<CheckerManager::CheckEndFunctionFunc>;
543
544 const CheckersTy &Checkers;
545 const ReturnStmt *RS;
546 ExprEngine &Eng;
547
548 CheckEndFunctionContext(const CheckersTy &Checkers, const ReturnStmt *RS,
549 ExprEngine &Eng)
550 : Checkers(Checkers), RS(RS), Eng(Eng) {}
551
552 CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); }
553 CheckersTy::const_iterator checkers_end() { return Checkers.end(); }
554
555 void runChecker(CheckerManager::CheckEndFunctionFunc checkFn,
556 ExplodedNode *Pred, ExplodedNodeSet &Dst) {
557 llvm::TimeTraceScope TimeScope(checkerScopeName("End", checkFn.Checker));
558 const ProgramPoint &L =
559 FunctionExitPoint(RS, Pred->getStackFrame(), checkFn.Checker);
560 CheckerContext C(Eng, Pred, Dst, L);
561
562 checkFn(RS, C);
563 }
564};
565
566} // namespace
567
568/// Run checkers for end of a function (either the entrypoint or another
569/// function that was inlined).
571 ExplodedNode *Pred,
572 ExprEngine &Eng,
573 const ReturnStmt *RS) {
574 ExplodedNodeSet Src;
575 Src.insert(Pred);
576 CheckEndFunctionContext C(EndFunctionCheckers, RS, Eng);
577 llvm::TimeTraceScope TimeScope("CheckerManager::runCheckersForEndFunction");
578 expandGraphWithCheckers(C, Dst, Src);
579}
580
581namespace {
582
583 struct CheckBranchConditionContext {
584 using CheckersTy = std::vector<CheckerManager::CheckBranchConditionFunc>;
585
586 const CheckersTy &Checkers;
587 const Stmt *Condition;
588 ExprEngine &Eng;
589
590 CheckBranchConditionContext(const CheckersTy &checkers,
591 const Stmt *Cond, ExprEngine &eng)
592 : Checkers(checkers), Condition(Cond), Eng(eng) {}
593
594 CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); }
595 CheckersTy::const_iterator checkers_end() { return Checkers.end(); }
596
597 void runChecker(CheckerManager::CheckBranchConditionFunc checkFn,
598 ExplodedNode *Pred, ExplodedNodeSet &Dst) {
599 llvm::TimeTraceScope TimeScope(
600 checkerScopeName("BranchCond", checkFn.Checker));
601 ProgramPoint L =
602 PostCondition(Condition, Pred->getStackFrame(), checkFn.Checker);
603 CheckerContext C(Eng, Pred, Dst, L);
604 checkFn(Condition, C);
605 }
606 };
607
608} // namespace
609
610/// Run checkers for branch condition.
612 ExplodedNodeSet &Dst,
613 ExplodedNode *Pred,
614 ExprEngine &Eng) {
615 ExplodedNodeSet Src;
616 Src.insert(Pred);
617 CheckBranchConditionContext C(BranchConditionCheckers, Condition, Eng);
618 llvm::TimeTraceScope TimeScope(
619 "CheckerManager::runCheckersForBranchCondition");
620 expandGraphWithCheckers(C, Dst, Src);
621}
622
623namespace {
624
625 struct CheckNewAllocatorContext {
626 using CheckersTy = std::vector<CheckerManager::CheckNewAllocatorFunc>;
627
628 const CheckersTy &Checkers;
629 const CXXAllocatorCall &Call;
630 bool WasInlined;
631 ExprEngine &Eng;
632
633 CheckNewAllocatorContext(const CheckersTy &Checkers,
634 const CXXAllocatorCall &Call, bool WasInlined,
635 ExprEngine &Eng)
636 : Checkers(Checkers), Call(Call), WasInlined(WasInlined), Eng(Eng) {}
637
638 CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); }
639 CheckersTy::const_iterator checkers_end() { return Checkers.end(); }
640
641 void runChecker(CheckerManager::CheckNewAllocatorFunc checkFn,
642 ExplodedNode *Pred, ExplodedNodeSet &Dst) {
643 llvm::TimeTraceScope TimeScope(
644 checkerScopeName("Allocator", checkFn.Checker));
645 ProgramPoint L = PostAllocatorCall(
646 Call.getOriginExpr(), Pred->getStackFrame(), checkFn.Checker);
647 CheckerContext C(Eng, Pred, Dst, L, WasInlined);
648 checkFn(cast<CXXAllocatorCall>(*Call.cloneWithState(Pred->getState())),
649 C);
650 }
651 };
652
653} // namespace
654
656 ExplodedNodeSet &Dst,
657 ExplodedNode *Pred,
658 ExprEngine &Eng,
659 bool WasInlined) {
660 ExplodedNodeSet Src;
661 Src.insert(Pred);
662 CheckNewAllocatorContext C(NewAllocatorCheckers, Call, WasInlined, Eng);
663 llvm::TimeTraceScope TimeScope("CheckerManager::runCheckersForNewAllocator");
664 expandGraphWithCheckers(C, Dst, Src);
665}
666
667/// Run checkers for live symbols.
669 SymbolReaper &SymReaper) {
670 for (const auto &LiveSymbolsChecker : LiveSymbolsCheckers)
671 LiveSymbolsChecker(state, SymReaper);
672}
673
674namespace {
675
676 struct CheckDeadSymbolsContext {
677 using CheckersTy = std::vector<CheckerManager::CheckDeadSymbolsFunc>;
678
679 const CheckersTy &Checkers;
680 SymbolReaper &SR;
681 const Stmt *S;
682 ExprEngine &Eng;
683 ProgramPoint::Kind ProgramPointKind;
684
685 CheckDeadSymbolsContext(const CheckersTy &checkers, SymbolReaper &sr,
686 const Stmt *s, ExprEngine &eng,
688 : Checkers(checkers), SR(sr), S(s), Eng(eng), ProgramPointKind(K) {}
689
690 CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); }
691 CheckersTy::const_iterator checkers_end() { return Checkers.end(); }
692
693 void runChecker(CheckerManager::CheckDeadSymbolsFunc checkFn,
694 ExplodedNode *Pred, ExplodedNodeSet &Dst) {
695 llvm::TimeTraceScope TimeScope(
696 checkerScopeName("DeadSymbols", checkFn.Checker));
698 S, ProgramPointKind, Pred->getStackFrame(), checkFn.Checker);
699 CheckerContext C(Eng, Pred, Dst, L);
700
701 // Note, do not pass the statement to the checkers without letting them
702 // differentiate if we ran remove dead bindings before or after the
703 // statement.
704 checkFn(SR, C);
705 }
706 };
707
708} // namespace
709
710/// Run checkers for dead symbols.
712 const ExplodedNodeSet &Src,
713 SymbolReaper &SymReaper,
714 const Stmt *S,
715 ExprEngine &Eng,
717 CheckDeadSymbolsContext C(DeadSymbolsCheckers, SymReaper, S, Eng, K);
718 llvm::TimeTraceScope TimeScope("CheckerManager::runCheckersForDeadSymbols");
719 expandGraphWithCheckers(C, Dst, Src);
720}
721
722/// Run checkers for region changes.
724 ProgramStateRef state, const InvalidatedSymbols *invalidated,
725 ArrayRef<const MemRegion *> ExplicitRegions,
726 ArrayRef<const MemRegion *> Regions, const StackFrame *SF,
727 const CallEvent *Call) {
728 for (const auto &RegionChangesChecker : RegionChangesCheckers) {
729 // If any checker declares the state infeasible (or if it starts that way),
730 // bail out.
731 if (!state)
732 return nullptr;
733 state = RegionChangesChecker(state, invalidated, ExplicitRegions, Regions,
734 SF, Call);
735 }
736 return state;
737}
738
739/// Run checkers to process symbol escape event.
742 const InvalidatedSymbols &Escaped,
743 const CallEvent *Call,
746 assert((Call != nullptr ||
747 (Kind != PSK_DirectEscapeOnCall &&
748 Kind != PSK_IndirectEscapeOnCall)) &&
749 "Call must not be NULL when escaping on call");
750 for (const auto &PointerEscapeChecker : PointerEscapeCheckers) {
751 // If any checker declares the state infeasible (or if it starts that
752 // way), bail out.
753 if (!State)
754 return nullptr;
755 State = PointerEscapeChecker(State, Escaped, Call, Kind, ETraits);
756 }
757 return State;
758}
759
760/// Run checkers for handling assumptions on symbolic values.
763 SVal Cond, bool Assumption) {
764 for (const auto &EvalAssumeChecker : EvalAssumeCheckers) {
765 // If any checker declares the state infeasible (or if it starts that way),
766 // bail out.
767 if (!state)
768 return nullptr;
769 state = EvalAssumeChecker(state, Cond, Assumption);
770 }
771 return state;
772}
773
774/// Run checkers for evaluating a call.
775/// Only one checker will evaluate the call.
777 const ExplodedNodeSet &Src,
778 const CallEvent &Call,
779 ExprEngine &Eng,
780 const EvalCallOptions &CallOpts) {
781 for (auto *const Pred : Src) {
782 std::optional<StringRef> evaluatorChecker;
783
784 ExplodedNodeSet checkDst{Pred};
785
786 ProgramStateRef State = Pred->getState();
787 CallEventRef<> UpdatedCall = Call.cloneWithState(State);
788
789 // Check if any of the EvalCall callbacks can evaluate the call.
790 for (const auto &EvalCallChecker : EvalCallCheckers) {
791 // TODO: Support the situation when the call doesn't correspond
792 // to any Expr.
794 UpdatedCall->getOriginExpr(), ProgramPoint::PostStmtKind,
795 Pred->getStackFrame(), EvalCallChecker.Checker);
796
797 CheckerContext C(Eng, Pred, checkDst, L);
798 bool evaluated = EvalCallChecker(*UpdatedCall, C);
799#ifndef NDEBUG
800 if (evaluated && evaluatorChecker) {
801 const auto toString = [](const CallEvent &Call) -> std::string {
802 std::string Buf;
803 llvm::raw_string_ostream OS(Buf);
804 Call.dump(OS);
805 return Buf;
806 };
807 std::string AssertionMessage = llvm::formatv(
808 "The '{0}' call has been already evaluated by the {1} checker, "
809 "while the {2} checker also tried to evaluate the same call. At "
810 "most one checker supposed to evaluate a call.",
811 toString(Call), evaluatorChecker,
812 EvalCallChecker.Checker->getDebugTag());
813 llvm_unreachable(AssertionMessage.c_str());
814 }
815#endif
816 if (evaluated) {
817 evaluatorChecker = EvalCallChecker.Checker->getDebugTag();
818 Dst.insert(checkDst);
819#ifdef NDEBUG
820 break; // on release don't check that no other checker also evals.
821#endif
822 }
823 }
824
825 // If none of the checkers evaluated the call, ask ExprEngine to handle it.
826 if (!evaluatorChecker)
827 Eng.defaultEvalCall(Dst, Pred, *UpdatedCall, CallOpts);
828 }
829}
830
831/// Run checkers for the entire Translation Unit.
833 const TranslationUnitDecl *TU,
834 AnalysisManager &mgr,
835 BugReporter &BR) {
836 for (const auto &EndOfTranslationUnitChecker : EndOfTranslationUnitCheckers)
837 EndOfTranslationUnitChecker(TU, mgr, BR);
838}
839
841 ProgramStateRef State,
842 const char *NL,
843 unsigned int Space,
844 bool IsDot) const {
845 Indent(Out, Space, IsDot) << "\"checker_messages\": ";
846
847 // Create a temporary stream to see whether we have any message.
848 SmallString<1024> TempBuf;
849 llvm::raw_svector_ostream TempOut(TempBuf);
850 unsigned int InnerSpace = Space + 2;
851
852 // Create the new-line in JSON with enough space.
853 SmallString<128> NewLine;
854 llvm::raw_svector_ostream NLOut(NewLine);
855 NLOut << "\", " << NL; // Inject the ending and a new line
856 Indent(NLOut, InnerSpace, IsDot) << "\""; // then begin the next message.
857
858 ++Space;
859 bool HasMessage = false;
860
861 // Store the last CheckerTag.
862 const void *LastCT = nullptr;
863 for (const auto &CT : CheckerTags) {
864 // See whether the current checker has a message.
865 CT.second->printState(TempOut, State, /*NL=*/NewLine.c_str(), /*Sep=*/"");
866
867 if (TempBuf.empty())
868 continue;
869
870 if (!HasMessage) {
871 Out << '[' << NL;
872 HasMessage = true;
873 }
874
875 LastCT = &CT;
876 TempBuf.clear();
877 }
878
879 for (const auto &CT : CheckerTags) {
880 // See whether the current checker has a message.
881 CT.second->printState(TempOut, State, /*NL=*/NewLine.c_str(), /*Sep=*/"");
882
883 if (TempBuf.empty())
884 continue;
885
886 Indent(Out, Space, IsDot) << "{ \"checker\": \"" << CT.second->getDebugTag()
887 << "\", \"messages\": [" << NL;
888 Indent(Out, InnerSpace, IsDot)
889 << '\"' << TempBuf.str().trim() << '\"' << NL;
890 Indent(Out, Space, IsDot) << "]}";
891
892 if (&CT != LastCT)
893 Out << ',';
894 Out << NL;
895
896 TempBuf.clear();
897 }
898
899 // It is the last element of the 'program_state' so do not add a comma.
900 if (HasMessage)
901 Indent(Out, --Space, IsDot) << "]";
902 else
903 Out << "null";
904
905 Out << NL;
906}
907
908//===----------------------------------------------------------------------===//
909// Internal registration functions for AST traversing.
910//===----------------------------------------------------------------------===//
911
913 HandlesDeclFunc isForDeclFn) {
914 DeclCheckerInfo info = { checkfn, isForDeclFn };
915 DeclCheckers.push_back(info);
916}
917
919 BodyCheckers.push_back(checkfn);
920}
921
922//===----------------------------------------------------------------------===//
923// Internal registration functions for path-sensitive checking.
924//===----------------------------------------------------------------------===//
925
927 HandlesStmtFunc isForStmtFn) {
928 StmtCheckerInfo info = { checkfn, isForStmtFn, /*IsPreVisit*/true };
929 StmtCheckers.push_back(info);
930}
931
933 HandlesStmtFunc isForStmtFn) {
934 StmtCheckerInfo info = { checkfn, isForStmtFn, /*IsPreVisit*/false };
935 StmtCheckers.push_back(info);
936}
937
939 PreObjCMessageCheckers.push_back(checkfn);
940}
941
943 ObjCMessageNilCheckers.push_back(checkfn);
944}
945
947 PostObjCMessageCheckers.push_back(checkfn);
948}
949
951 PreCallCheckers.push_back(checkfn);
952}
954 PostCallCheckers.push_back(checkfn);
955}
956
958 LifetimeEndCheckers.push_back(checkfn);
959}
960
962 LocationCheckers.push_back(checkfn);
963}
964
966 BindCheckers.push_back(checkfn);
967}
968
970 BlockEntranceCheckers.push_back(checkfn);
971}
972
974 EndAnalysisCheckers.push_back(checkfn);
975}
976
978 BeginFunctionCheckers.push_back(checkfn);
979}
980
982 EndFunctionCheckers.push_back(checkfn);
983}
984
986 CheckBranchConditionFunc checkfn) {
987 BranchConditionCheckers.push_back(checkfn);
988}
989
991 NewAllocatorCheckers.push_back(checkfn);
992}
993
995 LiveSymbolsCheckers.push_back(checkfn);
996}
997
999 DeadSymbolsCheckers.push_back(checkfn);
1000}
1001
1003 RegionChangesCheckers.push_back(checkfn);
1004}
1005
1007 PointerEscapeCheckers.push_back(checkfn);
1008}
1009
1011 CheckPointerEscapeFunc checkfn) {
1012 PointerEscapeCheckers.push_back(checkfn);
1013}
1014
1016 EvalAssumeCheckers.push_back(checkfn);
1017}
1018
1020 EvalCallCheckers.push_back(checkfn);
1021}
1022
1024 CheckEndOfTranslationUnit checkfn) {
1025 EndOfTranslationUnitCheckers.push_back(checkfn);
1026}
1027
1028//===----------------------------------------------------------------------===//
1029// Implementation details.
1030//===----------------------------------------------------------------------===//
1031
1032const CheckerManager::CachedStmtCheckers &
1033CheckerManager::getCachedStmtCheckersFor(const Stmt *S, bool isPreVisit) {
1034 assert(S);
1035
1036 unsigned Key = (S->getStmtClass() << 1) | unsigned(isPreVisit);
1037 auto [CCI, Inserted] = CachedStmtCheckersMap.try_emplace(Key);
1038 CachedStmtCheckers &Checkers = CCI->second;
1039 if (Inserted) {
1040 // Find the checkers that should run for this Stmt and cache them.
1041 for (const auto &Info : StmtCheckers)
1042 if (Info.IsPreVisit == isPreVisit && Info.IsForStmtFn(S))
1043 Checkers.push_back(Info.CheckFn);
1044 }
1045 return Checkers;
1046}
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:1110
Kind getKind() const
Definition DeclBase.h:450
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 *tag) 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:3172
It represents a stack frame of the call stack.
Stmt - This represents one statement.
Definition Stmt.h:85
StmtClass getStmtClass() const
Definition Stmt.h:1505
The top declaration context.
Definition Decl.h:106
Represents a variable declaration or definition.
Definition Decl.h:933
BugReporter is a utility class for generating PathDiagnostics for analysis.
Represents the memory allocation call in a C++ new-expression.
Definition CallEvent.h:1122
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:1479
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:1251
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:98
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