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