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
539/// Run checkers for end of a function (either the entrypoint or another
540/// function that was inlined). Note that this function places the
541/// checker activations on separate execution paths:
542/// /-[checker1]-> N1 ...
543/// Pred --[checker2]-> N2 ...
544/// \-[checker3]-> N3 ...
545/// (If none of the checkers produce a transition, we continue with 'Pred'.)
546///
547/// This differs from the handling of all the other checker callbacks, where
548/// the checker activations are chained sequentially on a single path:
549/// Pred --[checker1]-> N1 --[checker2]-> N2 --[checker3]-> N3 ...
550///
551/// This difference has historical reasons: originally this callback was called
552/// 'EndPath' and only activated at the end of an execution paths, and
553/// (according to an old comment) those 'EndPath' checkers expected that they
554/// create an "end of path" node which will be final.
555/// TODO: Check whether this exceptional behavior is still justified.
557 ExplodedNode *Pred,
558 ExprEngine &Eng,
559 const ReturnStmt *RS) {
560 // By default, continue from 'Pred' -- this will be removed from 'Dst' if any
561 // checker generates a transition from it.
562 Dst.insert(Pred);
563
564 for (const auto &checkFn : EndFunctionCheckers) {
565 const ProgramPoint &L =
566 FunctionExitPoint(RS, Pred->getStackFrame(), checkFn.Checker);
567 CheckerContext C(Eng, Pred, Dst, L);
568 llvm::TimeTraceScope TimeScope(checkerScopeName("End", checkFn.Checker));
569 checkFn(RS, C);
570 }
571}
572
573namespace {
574
575 struct CheckBranchConditionContext {
576 using CheckersTy = std::vector<CheckerManager::CheckBranchConditionFunc>;
577
578 const CheckersTy &Checkers;
579 const Stmt *Condition;
580 ExprEngine &Eng;
581
582 CheckBranchConditionContext(const CheckersTy &checkers,
583 const Stmt *Cond, ExprEngine &eng)
584 : Checkers(checkers), Condition(Cond), Eng(eng) {}
585
586 CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); }
587 CheckersTy::const_iterator checkers_end() { return Checkers.end(); }
588
589 void runChecker(CheckerManager::CheckBranchConditionFunc checkFn,
590 ExplodedNode *Pred, ExplodedNodeSet &Dst) {
591 llvm::TimeTraceScope TimeScope(
592 checkerScopeName("BranchCond", checkFn.Checker));
593 ProgramPoint L =
594 PostCondition(Condition, Pred->getStackFrame(), checkFn.Checker);
595 CheckerContext C(Eng, Pred, Dst, L);
596 checkFn(Condition, C);
597 }
598 };
599
600} // namespace
601
602/// Run checkers for branch condition.
604 ExplodedNodeSet &Dst,
605 ExplodedNode *Pred,
606 ExprEngine &Eng) {
607 ExplodedNodeSet Src;
608 Src.insert(Pred);
609 CheckBranchConditionContext C(BranchConditionCheckers, Condition, Eng);
610 llvm::TimeTraceScope TimeScope(
611 "CheckerManager::runCheckersForBranchCondition");
612 expandGraphWithCheckers(C, Dst, Src);
613}
614
615namespace {
616
617 struct CheckNewAllocatorContext {
618 using CheckersTy = std::vector<CheckerManager::CheckNewAllocatorFunc>;
619
620 const CheckersTy &Checkers;
621 const CXXAllocatorCall &Call;
622 bool WasInlined;
623 ExprEngine &Eng;
624
625 CheckNewAllocatorContext(const CheckersTy &Checkers,
626 const CXXAllocatorCall &Call, bool WasInlined,
627 ExprEngine &Eng)
628 : Checkers(Checkers), Call(Call), WasInlined(WasInlined), Eng(Eng) {}
629
630 CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); }
631 CheckersTy::const_iterator checkers_end() { return Checkers.end(); }
632
633 void runChecker(CheckerManager::CheckNewAllocatorFunc checkFn,
634 ExplodedNode *Pred, ExplodedNodeSet &Dst) {
635 llvm::TimeTraceScope TimeScope(
636 checkerScopeName("Allocator", checkFn.Checker));
637 ProgramPoint L = PostAllocatorCall(
638 Call.getOriginExpr(), Pred->getStackFrame(), checkFn.Checker);
639 CheckerContext C(Eng, Pred, Dst, L, WasInlined);
640 checkFn(cast<CXXAllocatorCall>(*Call.cloneWithState(Pred->getState())),
641 C);
642 }
643 };
644
645} // namespace
646
648 ExplodedNodeSet &Dst,
649 ExplodedNode *Pred,
650 ExprEngine &Eng,
651 bool WasInlined) {
652 ExplodedNodeSet Src;
653 Src.insert(Pred);
654 CheckNewAllocatorContext C(NewAllocatorCheckers, Call, WasInlined, Eng);
655 llvm::TimeTraceScope TimeScope("CheckerManager::runCheckersForNewAllocator");
656 expandGraphWithCheckers(C, Dst, Src);
657}
658
659/// Run checkers for live symbols.
661 SymbolReaper &SymReaper) {
662 for (const auto &LiveSymbolsChecker : LiveSymbolsCheckers)
663 LiveSymbolsChecker(state, SymReaper);
664}
665
666namespace {
667
668 struct CheckDeadSymbolsContext {
669 using CheckersTy = std::vector<CheckerManager::CheckDeadSymbolsFunc>;
670
671 const CheckersTy &Checkers;
672 SymbolReaper &SR;
673 const Stmt *S;
674 ExprEngine &Eng;
675 ProgramPoint::Kind ProgramPointKind;
676
677 CheckDeadSymbolsContext(const CheckersTy &checkers, SymbolReaper &sr,
678 const Stmt *s, ExprEngine &eng,
680 : Checkers(checkers), SR(sr), S(s), Eng(eng), ProgramPointKind(K) {}
681
682 CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); }
683 CheckersTy::const_iterator checkers_end() { return Checkers.end(); }
684
685 void runChecker(CheckerManager::CheckDeadSymbolsFunc checkFn,
686 ExplodedNode *Pred, ExplodedNodeSet &Dst) {
687 llvm::TimeTraceScope TimeScope(
688 checkerScopeName("DeadSymbols", checkFn.Checker));
690 S, ProgramPointKind, Pred->getStackFrame(), checkFn.Checker);
691 CheckerContext C(Eng, Pred, Dst, L);
692
693 // Note, do not pass the statement to the checkers without letting them
694 // differentiate if we ran remove dead bindings before or after the
695 // statement.
696 checkFn(SR, C);
697 }
698 };
699
700} // namespace
701
702/// Run checkers for dead symbols.
704 const ExplodedNodeSet &Src,
705 SymbolReaper &SymReaper,
706 const Stmt *S,
707 ExprEngine &Eng,
709 CheckDeadSymbolsContext C(DeadSymbolsCheckers, SymReaper, S, Eng, K);
710 llvm::TimeTraceScope TimeScope("CheckerManager::runCheckersForDeadSymbols");
711 expandGraphWithCheckers(C, Dst, Src);
712}
713
714/// Run checkers for region changes.
716 ProgramStateRef state, const InvalidatedSymbols *invalidated,
717 ArrayRef<const MemRegion *> ExplicitRegions,
718 ArrayRef<const MemRegion *> Regions, const StackFrame *SF,
719 const CallEvent *Call) {
720 for (const auto &RegionChangesChecker : RegionChangesCheckers) {
721 // If any checker declares the state infeasible (or if it starts that way),
722 // bail out.
723 if (!state)
724 return nullptr;
725 state = RegionChangesChecker(state, invalidated, ExplicitRegions, Regions,
726 SF, Call);
727 }
728 return state;
729}
730
731/// Run checkers to process symbol escape event.
734 const InvalidatedSymbols &Escaped,
735 const CallEvent *Call,
738 assert((Call != nullptr ||
739 (Kind != PSK_DirectEscapeOnCall &&
740 Kind != PSK_IndirectEscapeOnCall)) &&
741 "Call must not be NULL when escaping on call");
742 for (const auto &PointerEscapeChecker : PointerEscapeCheckers) {
743 // If any checker declares the state infeasible (or if it starts that
744 // way), bail out.
745 if (!State)
746 return nullptr;
747 State = PointerEscapeChecker(State, Escaped, Call, Kind, ETraits);
748 }
749 return State;
750}
751
752/// Run checkers for handling assumptions on symbolic values.
755 SVal Cond, bool Assumption) {
756 for (const auto &EvalAssumeChecker : EvalAssumeCheckers) {
757 // If any checker declares the state infeasible (or if it starts that way),
758 // bail out.
759 if (!state)
760 return nullptr;
761 state = EvalAssumeChecker(state, Cond, Assumption);
762 }
763 return state;
764}
765
766/// Run checkers for evaluating a call.
767/// Only one checker will evaluate the call.
769 const ExplodedNodeSet &Src,
770 const CallEvent &Call,
771 ExprEngine &Eng,
772 const EvalCallOptions &CallOpts) {
773 for (auto *const Pred : Src) {
774 std::optional<StringRef> evaluatorChecker;
775
776 ExplodedNodeSet checkDst{Pred};
777
778 ProgramStateRef State = Pred->getState();
779 CallEventRef<> UpdatedCall = Call.cloneWithState(State);
780
781 // Check if any of the EvalCall callbacks can evaluate the call.
782 for (const auto &EvalCallChecker : EvalCallCheckers) {
783 // TODO: Support the situation when the call doesn't correspond
784 // to any Expr.
786 UpdatedCall->getOriginExpr(), ProgramPoint::PostStmtKind,
787 Pred->getStackFrame(), EvalCallChecker.Checker);
788
789 CheckerContext C(Eng, Pred, checkDst, L);
790 bool evaluated = EvalCallChecker(*UpdatedCall, C);
791#ifndef NDEBUG
792 if (evaluated && evaluatorChecker) {
793 const auto toString = [](const CallEvent &Call) -> std::string {
794 std::string Buf;
795 llvm::raw_string_ostream OS(Buf);
796 Call.dump(OS);
797 return Buf;
798 };
799 std::string AssertionMessage = llvm::formatv(
800 "The '{0}' call has been already evaluated by the {1} checker, "
801 "while the {2} checker also tried to evaluate the same call. At "
802 "most one checker supposed to evaluate a call.",
803 toString(Call), evaluatorChecker,
804 EvalCallChecker.Checker->getDebugTag());
805 llvm_unreachable(AssertionMessage.c_str());
806 }
807#endif
808 if (evaluated) {
809 evaluatorChecker = EvalCallChecker.Checker->getDebugTag();
810 Dst.insert(checkDst);
811#ifdef NDEBUG
812 break; // on release don't check that no other checker also evals.
813#endif
814 }
815 }
816
817 // If none of the checkers evaluated the call, ask ExprEngine to handle it.
818 if (!evaluatorChecker)
819 Eng.defaultEvalCall(Dst, Pred, *UpdatedCall, CallOpts);
820 }
821}
822
823/// Run checkers for the entire Translation Unit.
825 const TranslationUnitDecl *TU,
826 AnalysisManager &mgr,
827 BugReporter &BR) {
828 for (const auto &EndOfTranslationUnitChecker : EndOfTranslationUnitCheckers)
829 EndOfTranslationUnitChecker(TU, mgr, BR);
830}
831
833 ProgramStateRef State,
834 const char *NL,
835 unsigned int Space,
836 bool IsDot) const {
837 Indent(Out, Space, IsDot) << "\"checker_messages\": ";
838
839 // Create a temporary stream to see whether we have any message.
840 SmallString<1024> TempBuf;
841 llvm::raw_svector_ostream TempOut(TempBuf);
842 unsigned int InnerSpace = Space + 2;
843
844 // Create the new-line in JSON with enough space.
845 SmallString<128> NewLine;
846 llvm::raw_svector_ostream NLOut(NewLine);
847 NLOut << "\", " << NL; // Inject the ending and a new line
848 Indent(NLOut, InnerSpace, IsDot) << "\""; // then begin the next message.
849
850 ++Space;
851 bool HasMessage = false;
852
853 // Store the last CheckerTag.
854 const void *LastCT = nullptr;
855 for (const auto &CT : CheckerTags) {
856 // See whether the current checker has a message.
857 CT.second->printState(TempOut, State, /*NL=*/NewLine.c_str(), /*Sep=*/"");
858
859 if (TempBuf.empty())
860 continue;
861
862 if (!HasMessage) {
863 Out << '[' << NL;
864 HasMessage = true;
865 }
866
867 LastCT = &CT;
868 TempBuf.clear();
869 }
870
871 for (const auto &CT : CheckerTags) {
872 // See whether the current checker has a message.
873 CT.second->printState(TempOut, State, /*NL=*/NewLine.c_str(), /*Sep=*/"");
874
875 if (TempBuf.empty())
876 continue;
877
878 Indent(Out, Space, IsDot) << "{ \"checker\": \"" << CT.second->getDebugTag()
879 << "\", \"messages\": [" << NL;
880 Indent(Out, InnerSpace, IsDot)
881 << '\"' << TempBuf.str().trim() << '\"' << NL;
882 Indent(Out, Space, IsDot) << "]}";
883
884 if (&CT != LastCT)
885 Out << ',';
886 Out << NL;
887
888 TempBuf.clear();
889 }
890
891 // It is the last element of the 'program_state' so do not add a comma.
892 if (HasMessage)
893 Indent(Out, --Space, IsDot) << "]";
894 else
895 Out << "null";
896
897 Out << NL;
898}
899
900//===----------------------------------------------------------------------===//
901// Internal registration functions for AST traversing.
902//===----------------------------------------------------------------------===//
903
905 HandlesDeclFunc isForDeclFn) {
906 DeclCheckerInfo info = { checkfn, isForDeclFn };
907 DeclCheckers.push_back(info);
908}
909
911 BodyCheckers.push_back(checkfn);
912}
913
914//===----------------------------------------------------------------------===//
915// Internal registration functions for path-sensitive checking.
916//===----------------------------------------------------------------------===//
917
919 HandlesStmtFunc isForStmtFn) {
920 StmtCheckerInfo info = { checkfn, isForStmtFn, /*IsPreVisit*/true };
921 StmtCheckers.push_back(info);
922}
923
925 HandlesStmtFunc isForStmtFn) {
926 StmtCheckerInfo info = { checkfn, isForStmtFn, /*IsPreVisit*/false };
927 StmtCheckers.push_back(info);
928}
929
931 PreObjCMessageCheckers.push_back(checkfn);
932}
933
935 ObjCMessageNilCheckers.push_back(checkfn);
936}
937
939 PostObjCMessageCheckers.push_back(checkfn);
940}
941
943 PreCallCheckers.push_back(checkfn);
944}
946 PostCallCheckers.push_back(checkfn);
947}
948
950 LifetimeEndCheckers.push_back(checkfn);
951}
952
954 LocationCheckers.push_back(checkfn);
955}
956
958 BindCheckers.push_back(checkfn);
959}
960
962 BlockEntranceCheckers.push_back(checkfn);
963}
964
966 EndAnalysisCheckers.push_back(checkfn);
967}
968
970 BeginFunctionCheckers.push_back(checkfn);
971}
972
974 EndFunctionCheckers.push_back(checkfn);
975}
976
978 CheckBranchConditionFunc checkfn) {
979 BranchConditionCheckers.push_back(checkfn);
980}
981
983 NewAllocatorCheckers.push_back(checkfn);
984}
985
987 LiveSymbolsCheckers.push_back(checkfn);
988}
989
991 DeadSymbolsCheckers.push_back(checkfn);
992}
993
995 RegionChangesCheckers.push_back(checkfn);
996}
997
999 PointerEscapeCheckers.push_back(checkfn);
1000}
1001
1003 CheckPointerEscapeFunc checkfn) {
1004 PointerEscapeCheckers.push_back(checkfn);
1005}
1006
1008 EvalAssumeCheckers.push_back(checkfn);
1009}
1010
1012 EvalCallCheckers.push_back(checkfn);
1013}
1014
1016 CheckEndOfTranslationUnit checkfn) {
1017 EndOfTranslationUnitCheckers.push_back(checkfn);
1018}
1019
1020//===----------------------------------------------------------------------===//
1021// Implementation details.
1022//===----------------------------------------------------------------------===//
1023
1024const CheckerManager::CachedStmtCheckers &
1025CheckerManager::getCachedStmtCheckersFor(const Stmt *S, bool isPreVisit) {
1026 assert(S);
1027
1028 unsigned Key = (S->getStmtClass() << 1) | unsigned(isPreVisit);
1029 auto [CCI, Inserted] = CachedStmtCheckersMap.try_emplace(Key);
1030 CachedStmtCheckers &Checkers = CCI->second;
1031 if (Inserted) {
1032 // Find the checkers that should run for this Stmt and cache them.
1033 for (const auto &Info : StmtCheckers)
1034 if (Info.IsPreVisit == isPreVisit && Info.IsForStmtFn(S))
1035 Checkers.push_back(Info.CheckFn);
1036 }
1037 return Checkers;
1038}
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