clang  9.0.0svn
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"
17 #include "clang/Basic/LLVM.h"
24 #include "llvm/ADT/SmallVector.h"
25 #include "llvm/Support/Casting.h"
26 #include "llvm/Support/ErrorHandling.h"
27 #include <cassert>
28 #include <vector>
29 
30 using namespace clang;
31 using namespace ento;
32 
34  return !StmtCheckers.empty() ||
35  !PreObjCMessageCheckers.empty() ||
36  !PostObjCMessageCheckers.empty() ||
37  !PreCallCheckers.empty() ||
38  !PostCallCheckers.empty() ||
39  !LocationCheckers.empty() ||
40  !BindCheckers.empty() ||
41  !EndAnalysisCheckers.empty() ||
42  !EndFunctionCheckers.empty() ||
43  !BranchConditionCheckers.empty() ||
44  !LiveSymbolsCheckers.empty() ||
45  !DeadSymbolsCheckers.empty() ||
46  !RegionChangesCheckers.empty() ||
47  !EvalAssumeCheckers.empty() ||
48  !EvalCallCheckers.empty();
49 }
50 
52 #ifndef NDEBUG
53  // Make sure that for every event that has listeners, there is at least
54  // one dispatcher registered for it.
55  for (const auto &Event : Events)
56  assert(Event.second.HasDispatcher &&
57  "No dispatcher registered for an event");
58 #endif
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  CachedDeclCheckers *checkers = nullptr;
71  CachedDeclCheckersMapTy::iterator CCI = CachedDeclCheckersMap.find(DeclKind);
72  if (CCI != CachedDeclCheckersMap.end()) {
73  checkers = &(CCI->second);
74  } else {
75  // Find the checkers that should run for this Decl and cache them.
76  checkers = &CachedDeclCheckersMap[DeclKind];
77  for (const auto &info : DeclCheckers)
78  if (info.IsForDeclFn(D))
79  checkers->push_back(info.CheckFn);
80  }
81 
82  assert(checkers);
83  for (const auto checker : *checkers)
84  checker(D, mgr, BR);
85 }
86 
88  BugReporter &BR) {
89  assert(D && D->hasBody());
90 
91  for (const auto BodyChecker : BodyCheckers)
92  BodyChecker(D, mgr, BR);
93 }
94 
95 //===----------------------------------------------------------------------===//
96 // Functions for running checkers for path-sensitive checking.
97 //===----------------------------------------------------------------------===//
98 
99 template <typename CHECK_CTX>
100 static void expandGraphWithCheckers(CHECK_CTX checkCtx,
101  ExplodedNodeSet &Dst,
102  const ExplodedNodeSet &Src) {
103  const NodeBuilderContext &BldrCtx = checkCtx.Eng.getBuilderContext();
104  if (Src.empty())
105  return;
106 
107  typename CHECK_CTX::CheckersTy::const_iterator
108  I = checkCtx.checkers_begin(), E = checkCtx.checkers_end();
109  if (I == E) {
110  Dst.insert(Src);
111  return;
112  }
113 
114  ExplodedNodeSet Tmp1, Tmp2;
115  const ExplodedNodeSet *PrevSet = &Src;
116 
117  for (; I != E; ++I) {
118  ExplodedNodeSet *CurrSet = nullptr;
119  if (I+1 == E)
120  CurrSet = &Dst;
121  else {
122  CurrSet = (PrevSet == &Tmp1) ? &Tmp2 : &Tmp1;
123  CurrSet->clear();
124  }
125 
126  NodeBuilder B(*PrevSet, *CurrSet, BldrCtx);
127  for (const auto &NI : *PrevSet)
128  checkCtx.runChecker(*I, B, NI);
129 
130  // If all the produced transitions are sinks, stop.
131  if (CurrSet->empty())
132  return;
133 
134  // Update which NodeSet is the current one.
135  PrevSet = CurrSet;
136  }
137 }
138 
139 namespace {
140 
141  struct CheckStmtContext {
143 
144  bool IsPreVisit;
145  const CheckersTy &Checkers;
146  const Stmt *S;
147  ExprEngine &Eng;
148  bool WasInlined;
149 
150  CheckStmtContext(bool isPreVisit, const CheckersTy &checkers,
151  const Stmt *s, ExprEngine &eng, bool wasInlined = false)
152  : IsPreVisit(isPreVisit), Checkers(checkers), S(s), Eng(eng),
153  WasInlined(wasInlined) {}
154 
155  CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); }
156  CheckersTy::const_iterator checkers_end() { return Checkers.end(); }
157 
158  void runChecker(CheckerManager::CheckStmtFunc checkFn,
159  NodeBuilder &Bldr, ExplodedNode *Pred) {
160  // FIXME: Remove respondsToCallback from CheckerContext;
164  Pred->getLocationContext(), checkFn.Checker);
165  CheckerContext C(Bldr, Eng, Pred, L, WasInlined);
166  checkFn(S, C);
167  }
168  };
169 
170 } // namespace
171 
172 /// Run checkers for visiting Stmts.
174  ExplodedNodeSet &Dst,
175  const ExplodedNodeSet &Src,
176  const Stmt *S,
177  ExprEngine &Eng,
178  bool WasInlined) {
179  CheckStmtContext C(isPreVisit, getCachedStmtCheckersFor(S, isPreVisit),
180  S, Eng, WasInlined);
181  expandGraphWithCheckers(C, Dst, Src);
182 }
183 
184 namespace {
185 
186  struct CheckObjCMessageContext {
187  using CheckersTy = std::vector<CheckerManager::CheckObjCMessageFunc>;
188 
190  bool WasInlined;
191  const CheckersTy &Checkers;
192  const ObjCMethodCall &Msg;
193  ExprEngine &Eng;
194 
195  CheckObjCMessageContext(ObjCMessageVisitKind visitKind,
196  const CheckersTy &checkers,
197  const ObjCMethodCall &msg, ExprEngine &eng,
198  bool wasInlined)
199  : Kind(visitKind), WasInlined(wasInlined), Checkers(checkers), Msg(msg),
200  Eng(eng) {}
201 
202  CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); }
203  CheckersTy::const_iterator checkers_end() { return Checkers.end(); }
204 
205  void runChecker(CheckerManager::CheckObjCMessageFunc checkFn,
206  NodeBuilder &Bldr, ExplodedNode *Pred) {
207  bool IsPreVisit;
208 
209  switch (Kind) {
211  IsPreVisit = true;
212  break;
215  IsPreVisit = false;
216  break;
217  }
218 
219  const ProgramPoint &L = Msg.getProgramPoint(IsPreVisit,checkFn.Checker);
220  CheckerContext C(Bldr, Eng, Pred, L, WasInlined);
221 
222  checkFn(*Msg.cloneWithState<ObjCMethodCall>(Pred->getState()), C);
223  }
224  };
225 
226 } // namespace
227 
228 /// Run checkers for visiting obj-c messages.
230  ExplodedNodeSet &Dst,
231  const ExplodedNodeSet &Src,
232  const ObjCMethodCall &msg,
233  ExprEngine &Eng,
234  bool WasInlined) {
235  auto &checkers = getObjCMessageCheckers(visitKind);
236  CheckObjCMessageContext C(visitKind, checkers, msg, Eng, WasInlined);
237  expandGraphWithCheckers(C, Dst, Src);
238 }
239 
240 const std::vector<CheckerManager::CheckObjCMessageFunc> &
241 CheckerManager::getObjCMessageCheckers(ObjCMessageVisitKind Kind) {
242  switch (Kind) {
244  return PreObjCMessageCheckers;
245  break;
247  return PostObjCMessageCheckers;
249  return ObjCMessageNilCheckers;
250  }
251  llvm_unreachable("Unknown Kind");
252 }
253 
254 namespace {
255 
256  // FIXME: This has all the same signatures as CheckObjCMessageContext.
257  // Is there a way we can merge the two?
258  struct CheckCallContext {
259  using CheckersTy = std::vector<CheckerManager::CheckCallFunc>;
260 
261  bool IsPreVisit, WasInlined;
262  const CheckersTy &Checkers;
263  const CallEvent &Call;
264  ExprEngine &Eng;
265 
266  CheckCallContext(bool isPreVisit, const CheckersTy &checkers,
267  const CallEvent &call, ExprEngine &eng,
268  bool wasInlined)
269  : IsPreVisit(isPreVisit), WasInlined(wasInlined), Checkers(checkers),
270  Call(call), Eng(eng) {}
271 
272  CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); }
273  CheckersTy::const_iterator checkers_end() { return Checkers.end(); }
274 
275  void runChecker(CheckerManager::CheckCallFunc checkFn,
276  NodeBuilder &Bldr, ExplodedNode *Pred) {
277  const ProgramPoint &L = Call.getProgramPoint(IsPreVisit,checkFn.Checker);
278  CheckerContext C(Bldr, Eng, Pred, L, WasInlined);
279 
280  checkFn(*Call.cloneWithState(Pred->getState()), C);
281  }
282  };
283 
284 } // namespace
285 
286 /// Run checkers for visiting an abstract call event.
288  ExplodedNodeSet &Dst,
289  const ExplodedNodeSet &Src,
290  const CallEvent &Call,
291  ExprEngine &Eng,
292  bool WasInlined) {
293  CheckCallContext C(isPreVisit,
294  isPreVisit ? PreCallCheckers
295  : PostCallCheckers,
296  Call, Eng, WasInlined);
297  expandGraphWithCheckers(C, Dst, Src);
298 }
299 
300 namespace {
301 
302  struct CheckLocationContext {
303  using CheckersTy = std::vector<CheckerManager::CheckLocationFunc>;
304 
305  const CheckersTy &Checkers;
306  SVal Loc;
307  bool IsLoad;
308  const Stmt *NodeEx; /* Will become a CFGStmt */
309  const Stmt *BoundEx;
310  ExprEngine &Eng;
311 
312  CheckLocationContext(const CheckersTy &checkers,
313  SVal loc, bool isLoad, const Stmt *NodeEx,
314  const Stmt *BoundEx,
315  ExprEngine &eng)
316  : Checkers(checkers), Loc(loc), IsLoad(isLoad), NodeEx(NodeEx),
317  BoundEx(BoundEx), Eng(eng) {}
318 
319  CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); }
320  CheckersTy::const_iterator checkers_end() { return Checkers.end(); }
321 
322  void runChecker(CheckerManager::CheckLocationFunc checkFn,
323  NodeBuilder &Bldr, ExplodedNode *Pred) {
326  const ProgramPoint &L =
328  Pred->getLocationContext(),
329  checkFn.Checker);
330  CheckerContext C(Bldr, Eng, Pred, L);
331  checkFn(Loc, IsLoad, BoundEx, C);
332  }
333  };
334 
335 } // namespace
336 
337 /// Run checkers for load/store of a location.
338 
340  const ExplodedNodeSet &Src,
341  SVal location, bool isLoad,
342  const Stmt *NodeEx,
343  const Stmt *BoundEx,
344  ExprEngine &Eng) {
345  CheckLocationContext C(LocationCheckers, location, isLoad, NodeEx,
346  BoundEx, Eng);
347  expandGraphWithCheckers(C, Dst, Src);
348 }
349 
350 namespace {
351 
352  struct CheckBindContext {
353  using CheckersTy = std::vector<CheckerManager::CheckBindFunc>;
354 
355  const CheckersTy &Checkers;
356  SVal Loc;
357  SVal Val;
358  const Stmt *S;
359  ExprEngine &Eng;
360  const ProgramPoint &PP;
361 
362  CheckBindContext(const CheckersTy &checkers,
363  SVal loc, SVal val, const Stmt *s, ExprEngine &eng,
364  const ProgramPoint &pp)
365  : Checkers(checkers), Loc(loc), Val(val), S(s), Eng(eng), PP(pp) {}
366 
367  CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); }
368  CheckersTy::const_iterator checkers_end() { return Checkers.end(); }
369 
370  void runChecker(CheckerManager::CheckBindFunc checkFn,
371  NodeBuilder &Bldr, ExplodedNode *Pred) {
372  const ProgramPoint &L = PP.withTag(checkFn.Checker);
373  CheckerContext C(Bldr, Eng, Pred, L);
374 
375  checkFn(Loc, Val, S, C);
376  }
377  };
378 
379 } // namespace
380 
381 /// Run checkers for binding of a value to a location.
383  const ExplodedNodeSet &Src,
384  SVal location, SVal val,
385  const Stmt *S, ExprEngine &Eng,
386  const ProgramPoint &PP) {
387  CheckBindContext C(BindCheckers, location, val, S, Eng, PP);
388  expandGraphWithCheckers(C, Dst, Src);
389 }
390 
392  BugReporter &BR,
393  ExprEngine &Eng) {
394  for (const auto EndAnalysisChecker : EndAnalysisCheckers)
395  EndAnalysisChecker(G, BR, Eng);
396 }
397 
398 namespace {
399 
400 struct CheckBeginFunctionContext {
401  using CheckersTy = std::vector<CheckerManager::CheckBeginFunctionFunc>;
402 
403  const CheckersTy &Checkers;
404  ExprEngine &Eng;
405  const ProgramPoint &PP;
406 
407  CheckBeginFunctionContext(const CheckersTy &Checkers, ExprEngine &Eng,
408  const ProgramPoint &PP)
409  : Checkers(Checkers), Eng(Eng), PP(PP) {}
410 
411  CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); }
412  CheckersTy::const_iterator checkers_end() { return Checkers.end(); }
413 
414  void runChecker(CheckerManager::CheckBeginFunctionFunc checkFn,
415  NodeBuilder &Bldr, ExplodedNode *Pred) {
416  const ProgramPoint &L = PP.withTag(checkFn.Checker);
417  CheckerContext C(Bldr, Eng, Pred, L);
418 
419  checkFn(C);
420  }
421 };
422 
423 } // namespace
424 
426  const BlockEdge &L,
427  ExplodedNode *Pred,
428  ExprEngine &Eng) {
429  ExplodedNodeSet Src;
430  Src.insert(Pred);
431  CheckBeginFunctionContext C(BeginFunctionCheckers, Eng, L);
432  expandGraphWithCheckers(C, Dst, Src);
433 }
434 
435 /// Run checkers for end of path.
436 // Note, We do not chain the checker output (like in expandGraphWithCheckers)
437 // for this callback since end of path nodes are expected to be final.
439  ExplodedNodeSet &Dst,
440  ExplodedNode *Pred,
441  ExprEngine &Eng,
442  const ReturnStmt *RS) {
443  // We define the builder outside of the loop because if at least one checker
444  // creates a successor for Pred, we do not need to generate an
445  // autotransition for it.
446  NodeBuilder Bldr(Pred, Dst, BC);
447  for (const auto checkFn : EndFunctionCheckers) {
448  const ProgramPoint &L =
449  FunctionExitPoint(RS, Pred->getLocationContext(), checkFn.Checker);
450  CheckerContext C(Bldr, Eng, Pred, L);
451  checkFn(RS, C);
452  }
453 }
454 
455 namespace {
456 
457  struct CheckBranchConditionContext {
458  using CheckersTy = std::vector<CheckerManager::CheckBranchConditionFunc>;
459 
460  const CheckersTy &Checkers;
461  const Stmt *Condition;
462  ExprEngine &Eng;
463 
464  CheckBranchConditionContext(const CheckersTy &checkers,
465  const Stmt *Cond, ExprEngine &eng)
466  : Checkers(checkers), Condition(Cond), Eng(eng) {}
467 
468  CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); }
469  CheckersTy::const_iterator checkers_end() { return Checkers.end(); }
470 
471  void runChecker(CheckerManager::CheckBranchConditionFunc checkFn,
472  NodeBuilder &Bldr, ExplodedNode *Pred) {
473  ProgramPoint L = PostCondition(Condition, Pred->getLocationContext(),
474  checkFn.Checker);
475  CheckerContext C(Bldr, Eng, Pred, L);
476  checkFn(Condition, C);
477  }
478  };
479 
480 } // namespace
481 
482 /// Run checkers for branch condition.
484  ExplodedNodeSet &Dst,
485  ExplodedNode *Pred,
486  ExprEngine &Eng) {
487  ExplodedNodeSet Src;
488  Src.insert(Pred);
489  CheckBranchConditionContext C(BranchConditionCheckers, Condition, Eng);
490  expandGraphWithCheckers(C, Dst, Src);
491 }
492 
493 namespace {
494 
495  struct CheckNewAllocatorContext {
496  using CheckersTy = std::vector<CheckerManager::CheckNewAllocatorFunc>;
497 
498  const CheckersTy &Checkers;
499  const CXXNewExpr *NE;
500  SVal Target;
501  bool WasInlined;
502  ExprEngine &Eng;
503 
504  CheckNewAllocatorContext(const CheckersTy &Checkers, const CXXNewExpr *NE,
505  SVal Target, bool WasInlined, ExprEngine &Eng)
506  : Checkers(Checkers), NE(NE), Target(Target), WasInlined(WasInlined),
507  Eng(Eng) {}
508 
509  CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); }
510  CheckersTy::const_iterator checkers_end() { return Checkers.end(); }
511 
512  void runChecker(CheckerManager::CheckNewAllocatorFunc checkFn,
513  NodeBuilder &Bldr, ExplodedNode *Pred) {
515  CheckerContext C(Bldr, Eng, Pred, L, WasInlined);
516  checkFn(NE, Target, C);
517  }
518  };
519 
520 } // namespace
521 
523  const CXXNewExpr *NE, SVal Target, ExplodedNodeSet &Dst, ExplodedNode *Pred,
524  ExprEngine &Eng, bool WasInlined) {
525  ExplodedNodeSet Src;
526  Src.insert(Pred);
527  CheckNewAllocatorContext C(NewAllocatorCheckers, NE, Target, WasInlined, Eng);
528  expandGraphWithCheckers(C, Dst, Src);
529 }
530 
531 /// Run checkers for live symbols.
533  SymbolReaper &SymReaper) {
534  for (const auto LiveSymbolsChecker : LiveSymbolsCheckers)
535  LiveSymbolsChecker(state, SymReaper);
536 }
537 
538 namespace {
539 
540  struct CheckDeadSymbolsContext {
541  using CheckersTy = std::vector<CheckerManager::CheckDeadSymbolsFunc>;
542 
543  const CheckersTy &Checkers;
544  SymbolReaper &SR;
545  const Stmt *S;
546  ExprEngine &Eng;
547  ProgramPoint::Kind ProgarmPointKind;
548 
549  CheckDeadSymbolsContext(const CheckersTy &checkers, SymbolReaper &sr,
550  const Stmt *s, ExprEngine &eng,
552  : Checkers(checkers), SR(sr), S(s), Eng(eng), ProgarmPointKind(K) {}
553 
554  CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); }
555  CheckersTy::const_iterator checkers_end() { return Checkers.end(); }
556 
557  void runChecker(CheckerManager::CheckDeadSymbolsFunc checkFn,
558  NodeBuilder &Bldr, ExplodedNode *Pred) {
559  const ProgramPoint &L = ProgramPoint::getProgramPoint(S, ProgarmPointKind,
560  Pred->getLocationContext(), checkFn.Checker);
561  CheckerContext C(Bldr, Eng, Pred, L);
562 
563  // Note, do not pass the statement to the checkers without letting them
564  // differentiate if we ran remove dead bindings before or after the
565  // statement.
566  checkFn(SR, C);
567  }
568  };
569 
570 } // namespace
571 
572 /// Run checkers for dead symbols.
574  const ExplodedNodeSet &Src,
575  SymbolReaper &SymReaper,
576  const Stmt *S,
577  ExprEngine &Eng,
578  ProgramPoint::Kind K) {
579  CheckDeadSymbolsContext C(DeadSymbolsCheckers, SymReaper, S, Eng, K);
580  expandGraphWithCheckers(C, Dst, Src);
581 }
582 
583 /// Run checkers for region changes.
586  const InvalidatedSymbols *invalidated,
587  ArrayRef<const MemRegion *> ExplicitRegions,
589  const LocationContext *LCtx,
590  const CallEvent *Call) {
591  for (const auto RegionChangesChecker : RegionChangesCheckers) {
592  // If any checker declares the state infeasible (or if it starts that way),
593  // bail out.
594  if (!state)
595  return nullptr;
596  state = RegionChangesChecker(state, invalidated, ExplicitRegions, Regions,
597  LCtx, Call);
598  }
599  return state;
600 }
601 
602 /// Run checkers to process symbol escape event.
605  const InvalidatedSymbols &Escaped,
606  const CallEvent *Call,
609  assert((Call != nullptr ||
610  (Kind != PSK_DirectEscapeOnCall &&
611  Kind != PSK_IndirectEscapeOnCall)) &&
612  "Call must not be NULL when escaping on call");
613  for (const auto PointerEscapeChecker : PointerEscapeCheckers) {
614  // If any checker declares the state infeasible (or if it starts that
615  // way), bail out.
616  if (!State)
617  return nullptr;
618  State = PointerEscapeChecker(State, Escaped, Call, Kind, ETraits);
619  }
620  return State;
621 }
622 
623 /// Run checkers for handling assumptions on symbolic values.
626  SVal Cond, bool Assumption) {
627  for (const auto EvalAssumeChecker : EvalAssumeCheckers) {
628  // If any checker declares the state infeasible (or if it starts that way),
629  // bail out.
630  if (!state)
631  return nullptr;
632  state = EvalAssumeChecker(state, Cond, Assumption);
633  }
634  return state;
635 }
636 
637 /// Run checkers for evaluating a call.
638 /// Only one checker will evaluate the call.
640  const ExplodedNodeSet &Src,
641  const CallEvent &Call,
642  ExprEngine &Eng) {
643  const CallExpr *CE = cast<CallExpr>(Call.getOriginExpr());
644  for (const auto Pred : Src) {
645  bool anyEvaluated = false;
646 
647  ExplodedNodeSet checkDst;
648  NodeBuilder B(Pred, checkDst, Eng.getBuilderContext());
649 
650  // Check if any of the EvalCall callbacks can evaluate the call.
651  for (const auto EvalCallChecker : EvalCallCheckers) {
653  const ProgramPoint &L =
654  ProgramPoint::getProgramPoint(CE, K, Pred->getLocationContext(),
655  EvalCallChecker.Checker);
656  bool evaluated = false;
657  { // CheckerContext generates transitions(populates checkDest) on
658  // destruction, so introduce the scope to make sure it gets properly
659  // populated.
660  CheckerContext C(B, Eng, Pred, L);
661  evaluated = EvalCallChecker(CE, C);
662  }
663  assert(!(evaluated && anyEvaluated)
664  && "There are more than one checkers evaluating the call");
665  if (evaluated) {
666  anyEvaluated = true;
667  Dst.insert(checkDst);
668 #ifdef NDEBUG
669  break; // on release don't check that no other checker also evals.
670 #endif
671  }
672  }
673 
674  // If none of the checkers evaluated the call, ask ExprEngine to handle it.
675  if (!anyEvaluated) {
676  NodeBuilder B(Pred, Dst, Eng.getBuilderContext());
677  Eng.defaultEvalCall(B, Pred, Call);
678  }
679  }
680 }
681 
682 /// Run checkers for the entire Translation Unit.
684  const TranslationUnitDecl *TU,
685  AnalysisManager &mgr,
686  BugReporter &BR) {
687  for (const auto EndOfTranslationUnitChecker : EndOfTranslationUnitCheckers)
688  EndOfTranslationUnitChecker(TU, mgr, BR);
689 }
690 
693  const char *NL, const char *Sep) {
694  for (const auto &CheckerTag : CheckerTags)
695  CheckerTag.second->printState(Out, State, NL, Sep);
696 }
697 
698 //===----------------------------------------------------------------------===//
699 // Internal registration functions for AST traversing.
700 //===----------------------------------------------------------------------===//
701 
703  HandlesDeclFunc isForDeclFn) {
704  DeclCheckerInfo info = { checkfn, isForDeclFn };
705  DeclCheckers.push_back(info);
706 }
707 
709  BodyCheckers.push_back(checkfn);
710 }
711 
712 //===----------------------------------------------------------------------===//
713 // Internal registration functions for path-sensitive checking.
714 //===----------------------------------------------------------------------===//
715 
717  HandlesStmtFunc isForStmtFn) {
718  StmtCheckerInfo info = { checkfn, isForStmtFn, /*IsPreVisit*/true };
719  StmtCheckers.push_back(info);
720 }
721 
723  HandlesStmtFunc isForStmtFn) {
724  StmtCheckerInfo info = { checkfn, isForStmtFn, /*IsPreVisit*/false };
725  StmtCheckers.push_back(info);
726 }
727 
729  PreObjCMessageCheckers.push_back(checkfn);
730 }
731 
733  ObjCMessageNilCheckers.push_back(checkfn);
734 }
735 
737  PostObjCMessageCheckers.push_back(checkfn);
738 }
739 
741  PreCallCheckers.push_back(checkfn);
742 }
744  PostCallCheckers.push_back(checkfn);
745 }
746 
748  LocationCheckers.push_back(checkfn);
749 }
750 
752  BindCheckers.push_back(checkfn);
753 }
754 
756  EndAnalysisCheckers.push_back(checkfn);
757 }
758 
760  BeginFunctionCheckers.push_back(checkfn);
761 }
762 
764  EndFunctionCheckers.push_back(checkfn);
765 }
766 
768  CheckBranchConditionFunc checkfn) {
769  BranchConditionCheckers.push_back(checkfn);
770 }
771 
773  NewAllocatorCheckers.push_back(checkfn);
774 }
775 
777  LiveSymbolsCheckers.push_back(checkfn);
778 }
779 
781  DeadSymbolsCheckers.push_back(checkfn);
782 }
783 
785  RegionChangesCheckers.push_back(checkfn);
786 }
787 
789  PointerEscapeCheckers.push_back(checkfn);
790 }
791 
793  CheckPointerEscapeFunc checkfn) {
794  PointerEscapeCheckers.push_back(checkfn);
795 }
796 
798  EvalAssumeCheckers.push_back(checkfn);
799 }
800 
802  EvalCallCheckers.push_back(checkfn);
803 }
804 
806  CheckEndOfTranslationUnit checkfn) {
807  EndOfTranslationUnitCheckers.push_back(checkfn);
808 }
809 
810 //===----------------------------------------------------------------------===//
811 // Implementation details.
812 //===----------------------------------------------------------------------===//
813 
815 CheckerManager::getCachedStmtCheckersFor(const Stmt *S, bool isPreVisit) {
816  assert(S);
817 
818  unsigned Key = (S->getStmtClass() << 1) | unsigned(isPreVisit);
819  CachedStmtCheckersMapTy::iterator CCI = CachedStmtCheckersMap.find(Key);
820  if (CCI != CachedStmtCheckersMap.end())
821  return CCI->second;
822 
823  // Find the checkers that should run for this Stmt and cache them.
824  CachedStmtCheckers &Checkers = CachedStmtCheckersMap[Key];
825  for (const auto &Info : StmtCheckers)
826  if (Info.IsPreVisit == isPreVisit && Info.IsForStmtFn(S))
827  Checkers.push_back(Info.CheckFn);
828  return Checkers;
829 }
830 
832  for (const auto CheckerDtor : CheckerDtors)
833  CheckerDtor();
834 }
CallEventRef< T > cloneWithState(ProgramStateRef NewState) const
Returns a copy of this CallEvent, but using the given state.
void _registerForDeadSymbols(CheckDeadSymbolsFunc checkfn)
Stmt - This represents one statement.
Definition: Stmt.h:65
Information about invalidation for a particular region/symbol.
Definition: MemRegion.h:1442
ProgramPoint getProgramPoint(bool IsPreVisit=false, const ProgramPointTag *Tag=nullptr) const
Returns an appropriate ProgramPoint for this call.
Definition: CallEvent.cpp:338
static void expandGraphWithCheckers(CHECK_CTX checkCtx, ExplodedNodeSet &Dst, const ExplodedNodeSet &Src)
Decl - This represents one declaration (or definition), e.g.
Definition: DeclBase.h:86
ProgramPoint withTag(const ProgramPointTag *tag) const
Create a new ProgramPoint object that is the same as the original except for using the specified tag ...
Definition: ProgramPoint.h:133
The pointer has been passed to a function indirectly.
const ProgramStateRef & getState() const
const Expr * getOriginExpr() const
Returns the expression whose value will be the result of this call.
Definition: CallEvent.h:254
void _registerForRegionChanges(CheckRegionChangesFunc checkfn)
void _registerForObjCMessageNil(CheckObjCMessageFunc checkfn)
const NodeBuilderContext & getBuilderContext()
Definition: ExprEngine.h:202
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.
static ProgramPoint getProgramPoint(const Stmt *S, ProgramPoint::Kind K, const LocationContext *LC, const ProgramPointTag *tag)
ProgramStateRef runCheckersForPointerEscape(ProgramStateRef State, const InvalidatedSymbols &Escaped, const CallEvent *Call, PointerEscapeKind Kind, RegionAndSymbolInvalidationTraits *ITraits)
Run checkers when pointers escape.
void _registerForPreCall(CheckCallFunc checkfn)
LineState State
void runCheckersForLiveSymbols(ProgramStateRef state, SymbolReaper &SymReaper)
Run checkers for live symbols.
i32 captured_struct **param SharedsTy A type which contains references the shared variables *param Shareds Context with the list of shared variables from the p *TaskFunction *param Data Additional data for task generation like final * state
void _registerForEndOfTranslationUnit(CheckEndOfTranslationUnit checkfn)
Represents any expression that calls an Objective-C method.
Definition: CallEvent.h:969
bool(*)(const Stmt *D) HandlesStmtFunc
Forward-declares and imports various common LLVM datatypes that clang wants to use unqualified...
const LocationContext * getLocationContext() const
void _registerForLiveSymbols(CheckLiveSymbolsFunc checkfn)
void runCheckersOnASTDecl(const Decl *D, AnalysisManager &mgr, BugReporter &BR)
Run checkers handling Decls.
void runCheckersForEndFunction(NodeBuilderContext &BC, ExplodedNodeSet &Dst, ExplodedNode *Pred, ExprEngine &Eng, const ReturnStmt *RS)
Run checkers on end of function.
void runCheckersForPrintState(raw_ostream &Out, ProgramStateRef State, const char *NL, const char *Sep)
Run checkers for debug-printing a ProgramState.
void runCheckersForBind(ExplodedNodeSet &Dst, const ExplodedNodeSet &Src, SVal location, SVal val, const Stmt *S, ExprEngine &Eng, const ProgramPoint &PP)
Run checkers for binding of a value to a location.
void _registerForBody(CheckDeclFunc checkfn)
for(unsigned I=0, E=TL.getNumArgs();I !=E;++I)
This is the simplest builder which generates nodes in the ExplodedGraph.
Definition: CoreEngine.h:227
void _registerForEndAnalysis(CheckEndAnalysisFunc checkfn)
void _registerForLocation(CheckLocationFunc checkfn)
The pointer has been passed to a function call directly.
void _registerForPointerEscape(CheckPointerEscapeFunc checkfn)
void runCheckersForEvalCall(ExplodedNodeSet &Dst, const ExplodedNodeSet &Src, const CallEvent &CE, ExprEngine &Eng)
Run checkers for evaluating a call.
ReturnStmt - This represents a return, optionally of an expression: return; return 4;...
Definition: Stmt.h:2442
void _registerForPostCall(CheckCallFunc checkfn)
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:984
BugReporter is a utility class for generating PathDiagnostics for analysis.
Definition: BugReporter.h:411
void runCheckersForNewAllocator(const CXXNewExpr *NE, SVal Target, ExplodedNodeSet &Dst, ExplodedNode *Pred, ExprEngine &Eng, bool wasInlined=false)
Run checkers between C++ operator new and constructor calls.
void _registerForPreObjCMessage(CheckObjCMessageFunc checkfn)
Kind
void runCheckersForBranchCondition(const Stmt *condition, ExplodedNodeSet &Dst, ExplodedNode *Pred, ExprEngine &Eng)
Run checkers for branch condition.
Represents a new-expression for memory allocation and constructor calls, e.g: "new CXXNewExpr(foo)"...
Definition: ExprCXX.h:1913
SVal - This represents a symbolic expression, which can be either an L-value or an R-value...
Definition: SVals.h:75
void _registerForBranchCondition(CheckBranchConditionFunc checkfn)
ProgramStateRef runCheckersForEvalAssume(ProgramStateRef state, SVal Cond, bool Assumption)
Run checkers for handling assumptions on symbolic values.
void runCheckersForObjCMessage(ObjCMessageVisitKind visitKind, ExplodedNodeSet &Dst, const ExplodedNodeSet &Src, const ObjCMethodCall &msg, ExprEngine &Eng, bool wasInlined=false)
Run checkers for visiting obj-c messages.
A class responsible for cleaning up unused symbols.
void runCheckersOnASTBody(const Decl *D, AnalysisManager &mgr, BugReporter &BR)
Run checkers handling Decls containing a Stmt body.
CheckerFn< void(const Stmt *, CheckerContext &)> CheckStmtFunc
void insert(const ExplodedNodeSet &S)
void runCheckersForDeadSymbols(ExplodedNodeSet &Dst, const ExplodedNodeSet &Src, SymbolReaper &SymReaper, const Stmt *S, ExprEngine &Eng, ProgramPoint::Kind K)
Run checkers for dead symbols.
Dataflow Directional Tag Classes.
StmtClass getStmtClass() const
Definition: Stmt.h:1028
void runCheckersForStmt(bool isPreVisit, ExplodedNodeSet &Dst, const ExplodedNodeSet &Src, const Stmt *S, ExprEngine &Eng, bool wasInlined=false)
Run checkers for visiting Stmts.
Kind getKind() const
Definition: DeclBase.h:420
void _registerForDecl(CheckDeclFunc checkfn, HandlesDeclFunc isForDeclFn)
void _registerForPostObjCMessage(CheckObjCMessageFunc checkfn)
Represents an abstract call to a function or method along a particular path.
Definition: CallEvent.h:170
void _registerForEndFunction(CheckEndFunctionFunc checkfn)
void _registerForEvalAssume(EvalAssumeFunc checkfn)
void _registerForPostStmt(CheckStmtFunc checkfn, HandlesStmtFunc isForStmtFn)
PointerEscapeKind
Describes the different reasons a pointer escapes during analysis.
void defaultEvalCall(NodeBuilder &B, ExplodedNode *Pred, const CallEvent &Call, const EvalCallOptions &CallOpts={})
Default implementation of call evaluation.
void _registerForNewAllocator(CheckNewAllocatorFunc checkfn)
void runCheckersForCallEvent(bool isPreVisit, ExplodedNodeSet &Dst, const ExplodedNodeSet &Src, const CallEvent &Call, ExprEngine &Eng, bool wasInlined=false)
Run checkers for visiting obj-c messages.
void runCheckersForEndAnalysis(ExplodedGraph &G, BugReporter &BR, ExprEngine &Eng)
Run checkers for end of analysis.
void _registerForBeginFunction(CheckBeginFunctionFunc checkfn)
void _registerForEvalCall(EvalCallFunc checkfn)
CheckerFn< void()> CheckerDtor
bool(*)(const Decl *D) HandlesDeclFunc
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
Definition: Expr.h:2402
ProgramStateRef runCheckersForRegionChanges(ProgramStateRef state, const InvalidatedSymbols *invalidated, ArrayRef< const MemRegion *> ExplicitRegions, ArrayRef< const MemRegion *> Regions, const LocationContext *LCtx, const CallEvent *Call)
Run checkers for region changes.
void runCheckersForBeginFunction(ExplodedNodeSet &Dst, const BlockEdge &L, ExplodedNode *Pred, ExprEngine &Eng)
Run checkers on beginning of function.
The top declaration context.
Definition: Decl.h:107
void _registerForConstPointerEscape(CheckPointerEscapeFunc checkfn)
void runCheckersOnEndOfTranslationUnit(const TranslationUnitDecl *TU, AnalysisManager &mgr, BugReporter &BR)
Run checkers for the entire Translation Unit.
void _registerForPreStmt(CheckStmtFunc checkfn, HandlesStmtFunc isForStmtFn)
void _registerForBind(CheckBindFunc checkfn)