Clang Project

clang_source_code/lib/StaticAnalyzer/Core/CheckerManager.cpp
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
13#include "clang/StaticAnalyzer/Core/CheckerManager.h"
14#include "clang/AST/DeclBase.h"
15#include "clang/AST/Stmt.h"
16#include "clang/Analysis/ProgramPoint.h"
17#include "clang/Basic/LLVM.h"
18#include "clang/Driver/DriverDiagnostic.h"
19#include "clang/StaticAnalyzer/Core/Checker.h"
20#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
21#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
22#include "clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h"
23#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
24#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
25#include "llvm/ADT/SmallVector.h"
26#include "llvm/Support/Casting.h"
27#include "llvm/Support/ErrorHandling.h"
28#include <cassert>
29#include <vector>
30
31using namespace clang;
32using namespace ento;
33
34bool CheckerManager::hasPathSensitiveCheckers() const {
35  return !StmtCheckers.empty()              ||
36         !PreObjCMessageCheckers.empty()    ||
37         !PostObjCMessageCheckers.empty()   ||
38         !PreCallCheckers.empty()    ||
39         !PostCallCheckers.empty()   ||
40         !LocationCheckers.empty()          ||
41         !BindCheckers.empty()              ||
42         !EndAnalysisCheckers.empty()       ||
43         !EndFunctionCheckers.empty()           ||
44         !BranchConditionCheckers.empty()   ||
45         !LiveSymbolsCheckers.empty()       ||
46         !DeadSymbolsCheckers.empty()       ||
47         !RegionChangesCheckers.empty()     ||
48         !EvalAssumeCheckers.empty()        ||
49         !EvalCallCheckers.empty();
50}
51
52void CheckerManager::finishedCheckerRegistration() {
53#ifndef NDEBUG
54  // Make sure that for every event that has listeners, there is at least
55  // one dispatcher registered for it.
56  for (const auto &Event : Events)
57     (0) . __assert_fail ("Event.second.HasDispatcher && \"No dispatcher registered for an event\"", "/home/seafit/code_projects/clang_source/clang/lib/StaticAnalyzer/Core/CheckerManager.cpp", 58, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert(Event.second.HasDispatcher &&
58 (0) . __assert_fail ("Event.second.HasDispatcher && \"No dispatcher registered for an event\"", "/home/seafit/code_projects/clang_source/clang/lib/StaticAnalyzer/Core/CheckerManager.cpp", 58, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">           "No dispatcher registered for an event");
59#endif
60}
61
62void CheckerManager::reportInvalidCheckerOptionValue(
63    const CheckerBase *CStringRef OptionNameStringRef ExpectedValueDesc) {
64
65  Context.getDiagnostics()
66      .Report(diag::err_analyzer_checker_option_invalid_input)
67          << (llvm::Twine() + C->getTagDescription() + ":" + OptionName).str()
68          << ExpectedValueDesc;
69}
70
71//===----------------------------------------------------------------------===//
72// Functions for running checkers for AST traversing..
73//===----------------------------------------------------------------------===//
74
75void CheckerManager::runCheckersOnASTDecl(const Decl *DAnalysisManagermgr,
76                                          BugReporter &BR) {
77  assert(D);
78
79  unsigned DeclKind = D->getKind();
80  CachedDeclCheckers *checkers = nullptr;
81  CachedDeclCheckersMapTy::iterator CCI = CachedDeclCheckersMap.find(DeclKind);
82  if (CCI != CachedDeclCheckersMap.end()) {
83    checkers = &(CCI->second);
84  } else {
85    // Find the checkers that should run for this Decl and cache them.
86    checkers = &CachedDeclCheckersMap[DeclKind];
87    for (const auto &info : DeclCheckers)
88      if (info.IsForDeclFn(D))
89        checkers->push_back(info.CheckFn);
90  }
91
92  assert(checkers);
93  for (const auto checker : *checkers)
94    checker(D, mgr, BR);
95}
96
97void CheckerManager::runCheckersOnASTBody(const Decl *DAnalysisManagermgr,
98                                          BugReporter &BR) {
99  hasBody()", "/home/seafit/code_projects/clang_source/clang/lib/StaticAnalyzer/Core/CheckerManager.cpp", 99, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert(D && D->hasBody());
100
101  for (const auto BodyChecker : BodyCheckers)
102    BodyChecker(DmgrBR);
103}
104
105//===----------------------------------------------------------------------===//
106// Functions for running checkers for path-sensitive checking.
107//===----------------------------------------------------------------------===//
108
109template <typename CHECK_CTX>
110static void expandGraphWithCheckers(CHECK_CTX checkCtx,
111                                    ExplodedNodeSet &Dst,
112                                    const ExplodedNodeSet &Src) {
113  const NodeBuilderContext &BldrCtx = checkCtx.Eng.getBuilderContext();
114  if (Src.empty())
115    return;
116
117  typename CHECK_CTX::CheckersTy::const_iterator
118      I = checkCtx.checkers_begin(), E = checkCtx.checkers_end();
119  if (I == E) {
120    Dst.insert(Src);
121    return;
122  }
123
124  ExplodedNodeSet Tmp1Tmp2;
125  const ExplodedNodeSet *PrevSet = &Src;
126
127  for (; I != E; ++I) {
128    ExplodedNodeSet *CurrSet = nullptr;
129    if (I+1 == E)
130      CurrSet = &Dst;
131    else {
132      CurrSet = (PrevSet == &Tmp1) ? &Tmp2 : &Tmp1;
133      CurrSet->clear();
134    }
135
136    NodeBuilder B(*PrevSet, *CurrSetBldrCtx);
137    for (const auto &NI : *PrevSet)
138      checkCtx.runChecker(*I, B, NI);
139
140    // If all the produced transitions are sinks, stop.
141    if (CurrSet->empty())
142      return;
143
144    // Update which NodeSet is the current one.
145    PrevSet = CurrSet;
146  }
147}
148
149namespace {
150
151  struct CheckStmtContext {
152    using CheckersTy = SmallVectorImpl<CheckerManager::CheckStmtFunc>;
153
154    bool IsPreVisit;
155    const CheckersTy &Checkers;
156    const Stmt *S;
157    ExprEngine &Eng;
158    bool WasInlined;
159
160    CheckStmtContext(bool isPreVisitconst CheckersTy &checkers,
161                     const Stmt *sExprEngine &engbool wasInlined = false)
162        : IsPreVisit(isPreVisit), Checkers(checkers), S(s), Eng(eng),
163          WasInlined(wasInlined) {}
164
165    CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); }
166    CheckersTy::const_iterator checkers_end() { return Checkers.end(); }
167
168    void runChecker(CheckerManager::CheckStmtFunc checkFn,
169                    NodeBuilder &BldrExplodedNode *Pred) {
170      // FIXME: Remove respondsToCallback from CheckerContext;
171      ProgramPoint::Kind K =  IsPreVisit ? ProgramPoint::PreStmtKind :
172                                           ProgramPoint::PostStmtKind;
173      const ProgramPoint &L = ProgramPoint::getProgramPoint(SK,
174                                Pred->getLocationContext(), checkFn.Checker);
175      CheckerContext C(BldrEngPredLWasInlined);
176      checkFn(SC);
177    }
178  };
179
180// namespace
181
182/// Run checkers for visiting Stmts.
183void CheckerManager::runCheckersForStmt(bool isPreVisit,
184                                        ExplodedNodeSet &Dst,
185                                        const ExplodedNodeSet &Src,
186                                        const Stmt *S,
187                                        ExprEngine &Eng,
188                                        bool WasInlined) {
189  CheckStmtContext C(isPreVisitgetCachedStmtCheckersFor(SisPreVisit),
190                     SEngWasInlined);
191  expandGraphWithCheckers(CDstSrc);
192}
193
194namespace {
195
196  struct CheckObjCMessageContext {
197    using CheckersTy = std::vector<CheckerManager::CheckObjCMessageFunc>;
198
199    ObjCMessageVisitKind Kind;
200    bool WasInlined;
201    const CheckersTy &Checkers;
202    const ObjCMethodCall &Msg;
203    ExprEngine &Eng;
204
205    CheckObjCMessageContext(ObjCMessageVisitKind visitKind,
206                            const CheckersTy &checkers,
207                            const ObjCMethodCall &msgExprEngine &eng,
208                            bool wasInlined)
209        : Kind(visitKind), WasInlined(wasInlined), Checkers(checkers), Msg(msg),
210          Eng(eng) {}
211
212    CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); }
213    CheckersTy::const_iterator checkers_end() { return Checkers.end(); }
214
215    void runChecker(CheckerManager::CheckObjCMessageFunc checkFn,
216                    NodeBuilder &BldrExplodedNode *Pred) {
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(BldrEngPredLWasInlined);
231
232      checkFn(*Msg.cloneWithState<ObjCMethodCall>(Pred->getState()), C);
233    }
234  };
235
236// namespace
237
238/// Run checkers for visiting obj-c messages.
239void CheckerManager::runCheckersForObjCMessage(ObjCMessageVisitKind visitKind,
240                                               ExplodedNodeSet &Dst,
241                                               const ExplodedNodeSet &Src,
242                                               const ObjCMethodCall &msg,
243                                               ExprEngine &Eng,
244                                               bool WasInlined) {
245  auto &checkers = getObjCMessageCheckers(visitKind);
246  CheckObjCMessageContext C(visitKindcheckersmsgEngWasInlined);
247  expandGraphWithCheckers(CDstSrc);
248}
249
250const std::vector<CheckerManager::CheckObjCMessageFunc> &
251CheckerManager::getObjCMessageCheckers(ObjCMessageVisitKind Kind) {
252  switch (Kind) {
253  case ObjCMessageVisitKind::Pre:
254    return PreObjCMessageCheckers;
255    break;
256  case ObjCMessageVisitKind::Post:
257    return PostObjCMessageCheckers;
258  case ObjCMessageVisitKind::MessageNil:
259    return ObjCMessageNilCheckers;
260  }
261  llvm_unreachable("Unknown Kind");
262}
263
264namespace {
265
266  // FIXME: This has all the same signatures as CheckObjCMessageContext.
267  // Is there a way we can merge the two?
268  struct CheckCallContext {
269    using CheckersTy = std::vector<CheckerManager::CheckCallFunc>;
270
271    bool IsPreVisitWasInlined;
272    const CheckersTy &Checkers;
273    const CallEvent &Call;
274    ExprEngine &Eng;
275
276    CheckCallContext(bool isPreVisitconst CheckersTy &checkers,
277                     const CallEvent &callExprEngine &eng,
278                     bool wasInlined)
279        : IsPreVisit(isPreVisit), WasInlined(wasInlined), Checkers(checkers),
280          Call(call), Eng(eng) {}
281
282    CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); }
283    CheckersTy::const_iterator checkers_end() { return Checkers.end(); }
284
285    void runChecker(CheckerManager::CheckCallFunc checkFn,
286                    NodeBuilder &BldrExplodedNode *Pred) {
287      const ProgramPoint &L = Call.getProgramPoint(IsPreVisit,checkFn.Checker);
288      CheckerContext C(BldrEngPredLWasInlined);
289
290      checkFn(*Call.cloneWithState(Pred->getState()), C);
291    }
292  };
293
294// namespace
295
296/// Run checkers for visiting an abstract call event.
297void CheckerManager::runCheckersForCallEvent(bool isPreVisit,
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                     CallEngWasInlined);
307  expandGraphWithCheckers(CDstSrc);
308}
309
310namespace {
311
312  struct CheckLocationContext {
313    using CheckersTy = std::vector<CheckerManager::CheckLocationFunc>;
314
315    const CheckersTy &Checkers;
316    SVal Loc;
317    bool IsLoad;
318    const Stmt *NodeEx/* Will become a CFGStmt */
319    const Stmt *BoundEx;
320    ExprEngine &Eng;
321
322    CheckLocationContext(const CheckersTy &checkers,
323                         SVal locbool isLoadconst Stmt *NodeEx,
324                         const Stmt *BoundEx,
325                         ExprEngine &eng)
326        : Checkers(checkers), Loc(loc), IsLoad(isLoad), NodeEx(NodeEx),
327          BoundEx(BoundEx), Eng(eng) {}
328
329    CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); }
330    CheckersTy::const_iterator checkers_end() { return Checkers.end(); }
331
332    void runChecker(CheckerManager::CheckLocationFunc checkFn,
333                    NodeBuilder &BldrExplodedNode *Pred) {
334      ProgramPoint::Kind K =  IsLoad ? ProgramPoint::PreLoadKind :
335                                       ProgramPoint::PreStoreKind;
336      const ProgramPoint &L =
337        ProgramPoint::getProgramPoint(NodeExK,
338                                      Pred->getLocationContext(),
339                                      checkFn.Checker);
340      CheckerContext C(BldrEngPredL);
341      checkFn(LocIsLoadBoundExC);
342    }
343  };
344
345// namespace
346
347/// Run checkers for load/store of a location.
348
349void CheckerManager::runCheckersForLocation(ExplodedNodeSet &Dst,
350                                            const ExplodedNodeSet &Src,
351                                            SVal locationbool isLoad,
352                                            const Stmt *NodeEx,
353                                            const Stmt *BoundEx,
354                                            ExprEngine &Eng) {
355  CheckLocationContext C(LocationCheckerslocationisLoadNodeEx,
356                         BoundExEng);
357  expandGraphWithCheckers(CDstSrc);
358}
359
360namespace {
361
362  struct CheckBindContext {
363    using CheckersTy = std::vector<CheckerManager::CheckBindFunc>;
364
365    const CheckersTy &Checkers;
366    SVal Loc;
367    SVal Val;
368    const Stmt *S;
369    ExprEngine &Eng;
370    const ProgramPoint &PP;
371
372    CheckBindContext(const CheckersTy &checkers,
373                     SVal locSVal valconst Stmt *sExprEngine &eng,
374                     const ProgramPoint &pp)
375        : Checkers(checkers), Loc(loc), Val(val), S(s), Eng(eng), PP(pp) {}
376
377    CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); }
378    CheckersTy::const_iterator checkers_end() { return Checkers.end(); }
379
380    void runChecker(CheckerManager::CheckBindFunc checkFn,
381                    NodeBuilder &BldrExplodedNode *Pred) {
382      const ProgramPoint &L = PP.withTag(checkFn.Checker);
383      CheckerContext C(BldrEngPredL);
384
385      checkFn(LocValSC);
386    }
387  };
388
389// namespace
390
391/// Run checkers for binding of a value to a location.
392void CheckerManager::runCheckersForBind(ExplodedNodeSet &Dst,
393                                        const ExplodedNodeSet &Src,
394                                        SVal locationSVal val,
395                                        const Stmt *SExprEngine &Eng,
396                                        const ProgramPoint &PP) {
397  CheckBindContext C(BindCheckerslocationvalSEngPP);
398  expandGraphWithCheckers(CDstSrc);
399}
400
401void CheckerManager::runCheckersForEndAnalysis(ExplodedGraph &G,
402                                               BugReporter &BR,
403                                               ExprEngine &Eng) {
404  for (const auto EndAnalysisChecker : EndAnalysisCheckers)
405    EndAnalysisChecker(GBREng);
406}
407
408namespace {
409
410struct CheckBeginFunctionContext {
411  using CheckersTy = std::vector<CheckerManager::CheckBeginFunctionFunc>;
412
413  const CheckersTy &Checkers;
414  ExprEngine &Eng;
415  const ProgramPoint &PP;
416
417  CheckBeginFunctionContext(const CheckersTy &CheckersExprEngine &Eng,
418                            const ProgramPoint &PP)
419      : Checkers(Checkers), Eng(Eng), PP(PP) {}
420
421  CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); }
422  CheckersTy::const_iterator checkers_end() { return Checkers.end(); }
423
424  void runChecker(CheckerManager::CheckBeginFunctionFunc checkFn,
425                  NodeBuilder &BldrExplodedNode *Pred) {
426    const ProgramPoint &L = PP.withTag(checkFn.Checker);
427    CheckerContext C(BldrEngPredL);
428
429    checkFn(C);
430  }
431};
432
433// namespace
434
435void CheckerManager::runCheckersForBeginFunction(ExplodedNodeSet &Dst,
436                                                 const BlockEdge &L,
437                                                 ExplodedNode *Pred,
438                                                 ExprEngine &Eng) {
439  ExplodedNodeSet Src;
440  Src.insert(Pred);
441  CheckBeginFunctionContext C(BeginFunctionCheckersEngL);
442  expandGraphWithCheckers(CDstSrc);
443}
444
445/// Run checkers for end of path.
446// Note, We do not chain the checker output (like in expandGraphWithCheckers)
447// for this callback since end of path nodes are expected to be final.
448void CheckerManager::runCheckersForEndFunction(NodeBuilderContext &BC,
449                                               ExplodedNodeSet &Dst,
450                                               ExplodedNode *Pred,
451                                               ExprEngine &Eng,
452                                               const ReturnStmt *RS) {
453  // We define the builder outside of the loop because if at least one checker
454  // creates a successor for Pred, we do not need to generate an
455  // autotransition for it.
456  NodeBuilder Bldr(PredDstBC);
457  for (const auto checkFn : EndFunctionCheckers) {
458    const ProgramPoint &L =
459        FunctionExitPoint(RSPred->getLocationContext(), checkFn.Checker);
460    CheckerContext C(BldrEngPredL);
461    checkFn(RSC);
462  }
463}
464
465namespace {
466
467  struct CheckBranchConditionContext {
468    using CheckersTy = std::vector<CheckerManager::CheckBranchConditionFunc>;
469
470    const CheckersTy &Checkers;
471    const Stmt *Condition;
472    ExprEngine &Eng;
473
474    CheckBranchConditionContext(const CheckersTy &checkers,
475                                const Stmt *CondExprEngine &eng)
476        : Checkers(checkers), Condition(Cond), Eng(eng) {}
477
478    CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); }
479    CheckersTy::const_iterator checkers_end() { return Checkers.end(); }
480
481    void runChecker(CheckerManager::CheckBranchConditionFunc checkFn,
482                    NodeBuilder &BldrExplodedNode *Pred) {
483      ProgramPoint L = PostCondition(ConditionPred->getLocationContext(),
484                                     checkFn.Checker);
485      CheckerContext C(BldrEngPredL);
486      checkFn(ConditionC);
487    }
488  };
489
490// namespace
491
492/// Run checkers for branch condition.
493void CheckerManager::runCheckersForBranchCondition(const Stmt *Condition,
494                                                   ExplodedNodeSet &Dst,
495                                                   ExplodedNode *Pred,
496                                                   ExprEngine &Eng) {
497  ExplodedNodeSet Src;
498  Src.insert(Pred);
499  CheckBranchConditionContext C(BranchConditionCheckersConditionEng);
500  expandGraphWithCheckers(CDstSrc);
501}
502
503namespace {
504
505  struct CheckNewAllocatorContext {
506    using CheckersTy = std::vector<CheckerManager::CheckNewAllocatorFunc>;
507
508    const CheckersTy &Checkers;
509    const CXXNewExpr *NE;
510    SVal Target;
511    bool WasInlined;
512    ExprEngine &Eng;
513
514    CheckNewAllocatorContext(const CheckersTy &Checkersconst CXXNewExpr *NE,
515                             SVal Targetbool WasInlinedExprEngine &Eng)
516        : Checkers(Checkers), NE(NE), Target(Target), WasInlined(WasInlined),
517          Eng(Eng) {}
518
519    CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); }
520    CheckersTy::const_iterator checkers_end() { return Checkers.end(); }
521
522    void runChecker(CheckerManager::CheckNewAllocatorFunc checkFn,
523                    NodeBuilder &BldrExplodedNode *Pred) {
524      ProgramPoint L = PostAllocatorCall(NEPred->getLocationContext());
525      CheckerContext C(BldrEngPredLWasInlined);
526      checkFn(NETargetC);
527    }
528  };
529
530// namespace
531
532void CheckerManager::runCheckersForNewAllocator(
533    const CXXNewExpr *NESVal TargetExplodedNodeSet &DstExplodedNode *Pred,
534    ExprEngine &Engbool WasInlined) {
535  ExplodedNodeSet Src;
536  Src.insert(Pred);
537  CheckNewAllocatorContext C(NewAllocatorCheckersNETargetWasInlinedEng);
538  expandGraphWithCheckers(CDstSrc);
539}
540
541/// Run checkers for live symbols.
542void CheckerManager::runCheckersForLiveSymbols(ProgramStateRef state,
543                                               SymbolReaper &SymReaper) {
544  for (const auto LiveSymbolsChecker : LiveSymbolsCheckers)
545    LiveSymbolsChecker(state, SymReaper);
546}
547
548namespace {
549
550  struct CheckDeadSymbolsContext {
551    using CheckersTy = std::vector<CheckerManager::CheckDeadSymbolsFunc>;
552
553    const CheckersTy &Checkers;
554    SymbolReaper &SR;
555    const Stmt *S;
556    ExprEngine &Eng;
557    ProgramPoint::Kind ProgarmPointKind;
558
559    CheckDeadSymbolsContext(const CheckersTy &checkersSymbolReaper &sr,
560                            const Stmt *sExprEngine &eng,
561                            ProgramPoint::Kind K)
562        : Checkers(checkers), SR(sr), S(s), Eng(eng), ProgarmPointKind(K) {}
563
564    CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); }
565    CheckersTy::const_iterator checkers_end() { return Checkers.end(); }
566
567    void runChecker(CheckerManager::CheckDeadSymbolsFunc checkFn,
568                    NodeBuilder &BldrExplodedNode *Pred) {
569      const ProgramPoint &L = ProgramPoint::getProgramPoint(SProgarmPointKind,
570                                Pred->getLocationContext(), checkFn.Checker);
571      CheckerContext C(BldrEngPredL);
572
573      // Note, do not pass the statement to the checkers without letting them
574      // differentiate if we ran remove dead bindings before or after the
575      // statement.
576      checkFn(SRC);
577    }
578  };
579
580// namespace
581
582/// Run checkers for dead symbols.
583void CheckerManager::runCheckersForDeadSymbols(ExplodedNodeSet &Dst,
584                                               const ExplodedNodeSet &Src,
585                                               SymbolReaper &SymReaper,
586                                               const Stmt *S,
587                                               ExprEngine &Eng,
588                                               ProgramPoint::Kind K) {
589  CheckDeadSymbolsContext C(DeadSymbolsCheckersSymReaperSEngK);
590  expandGraphWithCheckers(CDstSrc);
591}
592
593/// Run checkers for region changes.
594ProgramStateRef
595CheckerManager::runCheckersForRegionChanges(ProgramStateRef state,
596                                            const InvalidatedSymbols *invalidated,
597                                            ArrayRef<const MemRegion *> ExplicitRegions,
598                                            ArrayRef<const MemRegion *> Regions,
599                                            const LocationContext *LCtx,
600                                            const CallEvent *Call) {
601  for (const auto RegionChangesChecker : RegionChangesCheckers) {
602    // If any checker declares the state infeasible (or if it starts that way),
603    // bail out.
604    if (!state)
605      return nullptr;
606    state = RegionChangesChecker(state, invalidated, ExplicitRegions, Regions,
607                                 LCtx, Call);
608  }
609  return state;
610}
611
612/// Run checkers to process symbol escape event.
613ProgramStateRef
614CheckerManager::runCheckersForPointerEscape(ProgramStateRef State,
615                                   const InvalidatedSymbols &Escaped,
616                                   const CallEvent *Call,
617                                   PointerEscapeKind Kind,
618                                   RegionAndSymbolInvalidationTraits *ETraits) {
619   (0) . __assert_fail ("(Call != nullptr || (Kind != PSK_DirectEscapeOnCall && Kind != PSK_IndirectEscapeOnCall)) && \"Call must not be NULL when escaping on call\"", "/home/seafit/code_projects/clang_source/clang/lib/StaticAnalyzer/Core/CheckerManager.cpp", 622, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert((Call != nullptr ||
620 (0) . __assert_fail ("(Call != nullptr || (Kind != PSK_DirectEscapeOnCall && Kind != PSK_IndirectEscapeOnCall)) && \"Call must not be NULL when escaping on call\"", "/home/seafit/code_projects/clang_source/clang/lib/StaticAnalyzer/Core/CheckerManager.cpp", 622, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">          (Kind != PSK_DirectEscapeOnCall &&
621 (0) . __assert_fail ("(Call != nullptr || (Kind != PSK_DirectEscapeOnCall && Kind != PSK_IndirectEscapeOnCall)) && \"Call must not be NULL when escaping on call\"", "/home/seafit/code_projects/clang_source/clang/lib/StaticAnalyzer/Core/CheckerManager.cpp", 622, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">           Kind != PSK_IndirectEscapeOnCall)) &&
622 (0) . __assert_fail ("(Call != nullptr || (Kind != PSK_DirectEscapeOnCall && Kind != PSK_IndirectEscapeOnCall)) && \"Call must not be NULL when escaping on call\"", "/home/seafit/code_projects/clang_source/clang/lib/StaticAnalyzer/Core/CheckerManager.cpp", 622, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">         "Call must not be NULL when escaping on call");
623  for (const auto PointerEscapeChecker : PointerEscapeCheckers) {
624    // If any checker declares the state infeasible (or if it starts that
625    //  way), bail out.
626    if (!State)
627      return nullptr;
628    State = PointerEscapeChecker(State, Escaped, Call, Kind, ETraits);
629  }
630  return State;
631}
632
633/// Run checkers for handling assumptions on symbolic values.
634ProgramStateRef
635CheckerManager::runCheckersForEvalAssume(ProgramStateRef state,
636                                         SVal Condbool Assumption) {
637  for (const auto EvalAssumeChecker : EvalAssumeCheckers) {
638    // If any checker declares the state infeasible (or if it starts that way),
639    // bail out.
640    if (!state)
641      return nullptr;
642    state = EvalAssumeChecker(state, Cond, Assumption);
643  }
644  return state;
645}
646
647/// Run checkers for evaluating a call.
648/// Only one checker will evaluate the call.
649void CheckerManager::runCheckersForEvalCall(ExplodedNodeSet &Dst,
650                                            const ExplodedNodeSet &Src,
651                                            const CallEvent &Call,
652                                            ExprEngine &Eng) {
653  const CallExpr *CE = cast<CallExpr>(Call.getOriginExpr());
654  for (const auto Pred : Src) {
655    bool anyEvaluated = false;
656
657    ExplodedNodeSet checkDst;
658    NodeBuilder B(Pred, checkDst, Eng.getBuilderContext());
659
660    // Check if any of the EvalCall callbacks can evaluate the call.
661    for (const auto EvalCallChecker : EvalCallCheckers) {
662      ProgramPoint::Kind K = ProgramPoint::PostStmtKind;
663      const ProgramPoint &L =
664          ProgramPoint::getProgramPoint(CE, K, Pred->getLocationContext(),
665                                        EvalCallChecker.Checker);
666      bool evaluated = false;
667      { // CheckerContext generates transitions(populates checkDest) on
668        // destruction, so introduce the scope to make sure it gets properly
669        // populated.
670        CheckerContext C(B, Eng, Pred, L);
671        evaluated = EvalCallChecker(CE, C);
672      }
673       (0) . __assert_fail ("!(evaluated && anyEvaluated) && \"There are more than one checkers evaluating the call\"", "/home/seafit/code_projects/clang_source/clang/lib/StaticAnalyzer/Core/CheckerManager.cpp", 674, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert(!(evaluated && anyEvaluated)
674 (0) . __assert_fail ("!(evaluated && anyEvaluated) && \"There are more than one checkers evaluating the call\"", "/home/seafit/code_projects/clang_source/clang/lib/StaticAnalyzer/Core/CheckerManager.cpp", 674, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">             && "There are more than one checkers evaluating the call");
675      if (evaluated) {
676        anyEvaluated = true;
677        Dst.insert(checkDst);
678#ifdef NDEBUG
679        break// on release don't check that no other checker also evals.
680#endif
681      }
682    }
683
684    // If none of the checkers evaluated the call, ask ExprEngine to handle it.
685    if (!anyEvaluated) {
686      NodeBuilder B(Pred, Dst, Eng.getBuilderContext());
687      Eng.defaultEvalCall(B, Pred, Call);
688    }
689  }
690}
691
692/// Run checkers for the entire Translation Unit.
693void CheckerManager::runCheckersOnEndOfTranslationUnit(
694                                                  const TranslationUnitDecl *TU,
695                                                  AnalysisManager &mgr,
696                                                  BugReporter &BR) {
697  for (const auto EndOfTranslationUnitChecker : EndOfTranslationUnitCheckers)
698    EndOfTranslationUnitChecker(TUmgrBR);
699}
700
701void CheckerManager::runCheckersForPrintState(raw_ostream &Out,
702                                              ProgramStateRef State,
703                                              const char *NLconst char *Sep) {
704  for (const auto &CheckerTag : CheckerTags)
705    CheckerTag.second->printState(Out, State, NL, Sep);
706}
707
708//===----------------------------------------------------------------------===//
709// Internal registration functions for AST traversing.
710//===----------------------------------------------------------------------===//
711
712void CheckerManager::_registerForDecl(CheckDeclFunc checkfn,
713                                      HandlesDeclFunc isForDeclFn) {
714  DeclCheckerInfo info = { checkfnisForDeclFn };
715  DeclCheckers.push_back(info);
716}
717
718void CheckerManager::_registerForBody(CheckDeclFunc checkfn) {
719  BodyCheckers.push_back(checkfn);
720}
721
722//===----------------------------------------------------------------------===//
723// Internal registration functions for path-sensitive checking.
724//===----------------------------------------------------------------------===//
725
726void CheckerManager::_registerForPreStmt(CheckStmtFunc checkfn,
727                                         HandlesStmtFunc isForStmtFn) {
728  StmtCheckerInfo info = { checkfnisForStmtFn/*IsPreVisit*/true };
729  StmtCheckers.push_back(info);
730}
731
732void CheckerManager::_registerForPostStmt(CheckStmtFunc checkfn,
733                                          HandlesStmtFunc isForStmtFn) {
734  StmtCheckerInfo info = { checkfnisForStmtFn/*IsPreVisit*/false };
735  StmtCheckers.push_back(info);
736}
737
738void CheckerManager::_registerForPreObjCMessage(CheckObjCMessageFunc checkfn) {
739  PreObjCMessageCheckers.push_back(checkfn);
740}
741
742void CheckerManager::_registerForObjCMessageNil(CheckObjCMessageFunc checkfn) {
743  ObjCMessageNilCheckers.push_back(checkfn);
744}
745
746void CheckerManager::_registerForPostObjCMessage(CheckObjCMessageFunc checkfn) {
747  PostObjCMessageCheckers.push_back(checkfn);
748}
749
750void CheckerManager::_registerForPreCall(CheckCallFunc checkfn) {
751  PreCallCheckers.push_back(checkfn);
752}
753void CheckerManager::_registerForPostCall(CheckCallFunc checkfn) {
754  PostCallCheckers.push_back(checkfn);
755}
756
757void CheckerManager::_registerForLocation(CheckLocationFunc checkfn) {
758  LocationCheckers.push_back(checkfn);
759}
760
761void CheckerManager::_registerForBind(CheckBindFunc checkfn) {
762  BindCheckers.push_back(checkfn);
763}
764
765void CheckerManager::_registerForEndAnalysis(CheckEndAnalysisFunc checkfn) {
766  EndAnalysisCheckers.push_back(checkfn);
767}
768
769void CheckerManager::_registerForBeginFunction(CheckBeginFunctionFunc checkfn) {
770  BeginFunctionCheckers.push_back(checkfn);
771}
772
773void CheckerManager::_registerForEndFunction(CheckEndFunctionFunc checkfn) {
774  EndFunctionCheckers.push_back(checkfn);
775}
776
777void CheckerManager::_registerForBranchCondition(
778                                             CheckBranchConditionFunc checkfn) {
779  BranchConditionCheckers.push_back(checkfn);
780}
781
782void CheckerManager::_registerForNewAllocator(CheckNewAllocatorFunc checkfn) {
783  NewAllocatorCheckers.push_back(checkfn);
784}
785
786void CheckerManager::_registerForLiveSymbols(CheckLiveSymbolsFunc checkfn) {
787  LiveSymbolsCheckers.push_back(checkfn);
788}
789
790void CheckerManager::_registerForDeadSymbols(CheckDeadSymbolsFunc checkfn) {
791  DeadSymbolsCheckers.push_back(checkfn);
792}
793
794void CheckerManager::_registerForRegionChanges(CheckRegionChangesFunc checkfn) {
795  RegionChangesCheckers.push_back(checkfn);
796}
797
798void CheckerManager::_registerForPointerEscape(CheckPointerEscapeFunc checkfn){
799  PointerEscapeCheckers.push_back(checkfn);
800}
801
802void CheckerManager::_registerForConstPointerEscape(
803                                          CheckPointerEscapeFunc checkfn) {
804  PointerEscapeCheckers.push_back(checkfn);
805}
806
807void CheckerManager::_registerForEvalAssume(EvalAssumeFunc checkfn) {
808  EvalAssumeCheckers.push_back(checkfn);
809}
810
811void CheckerManager::_registerForEvalCall(EvalCallFunc checkfn) {
812  EvalCallCheckers.push_back(checkfn);
813}
814
815void CheckerManager::_registerForEndOfTranslationUnit(
816                                            CheckEndOfTranslationUnit checkfn) {
817  EndOfTranslationUnitCheckers.push_back(checkfn);
818}
819
820//===----------------------------------------------------------------------===//
821// Implementation details.
822//===----------------------------------------------------------------------===//
823
824const CheckerManager::CachedStmtCheckers &
825CheckerManager::getCachedStmtCheckersFor(const Stmt *Sbool isPreVisit) {
826  assert(S);
827
828  unsigned Key = (S->getStmtClass() << 1) | unsigned(isPreVisit);
829  CachedStmtCheckersMapTy::iterator CCI = CachedStmtCheckersMap.find(Key);
830  if (CCI != CachedStmtCheckersMap.end())
831    return CCI->second;
832
833  // Find the checkers that should run for this Stmt and cache them.
834  CachedStmtCheckers &Checkers = CachedStmtCheckersMap[Key];
835  for (const auto &Info : StmtCheckers)
836    if (Info.IsPreVisit == isPreVisit && Info.IsForStmtFn(S))
837      Checkers.push_back(Info.CheckFn);
838  return Checkers;
839}
840
841CheckerManager::~CheckerManager() {
842  for (const auto CheckerDtor : CheckerDtors)
843    CheckerDtor();
844}
845
clang::ento::CheckerManager::hasPathSensitiveCheckers
clang::ento::CheckerManager::finishedCheckerRegistration
clang::ento::CheckerManager::reportInvalidCheckerOptionValue
clang::ento::CheckerManager::runCheckersOnASTDecl
clang::ento::CheckerManager::runCheckersOnASTBody
clang::ento::CheckerManager::runCheckersForStmt
clang::ento::CheckerManager::runCheckersForObjCMessage
clang::ento::CheckerManager::getObjCMessageCheckers
clang::ento::CheckerManager::runCheckersForCallEvent
clang::ento::CheckerManager::runCheckersForLocation
clang::ento::CheckerManager::runCheckersForBind
clang::ento::CheckerManager::runCheckersForEndAnalysis
clang::ento::CheckerManager::runCheckersForBeginFunction
clang::ento::CheckerManager::runCheckersForEndFunction
clang::ento::CheckerManager::runCheckersForBranchCondition
clang::ento::CheckerManager::runCheckersForNewAllocator
clang::ento::CheckerManager::runCheckersForLiveSymbols
clang::ento::CheckerManager::runCheckersForDeadSymbols
clang::ento::CheckerManager::runCheckersForRegionChanges
clang::ento::CheckerManager::runCheckersForPointerEscape
clang::ento::CheckerManager::runCheckersForEvalAssume
clang::ento::CheckerManager::runCheckersForEvalCall
clang::ento::CheckerManager::runCheckersOnEndOfTranslationUnit
clang::ento::CheckerManager::runCheckersForPrintState
clang::ento::CheckerManager::_registerForDecl
clang::ento::CheckerManager::_registerForBody
clang::ento::CheckerManager::_registerForPreStmt
clang::ento::CheckerManager::_registerForPostStmt
clang::ento::CheckerManager::_registerForPreObjCMessage
clang::ento::CheckerManager::_registerForObjCMessageNil
clang::ento::CheckerManager::_registerForPostObjCMessage
clang::ento::CheckerManager::_registerForPreCall
clang::ento::CheckerManager::_registerForPostCall
clang::ento::CheckerManager::_registerForLocation
clang::ento::CheckerManager::_registerForBind
clang::ento::CheckerManager::_registerForEndAnalysis
clang::ento::CheckerManager::_registerForBeginFunction
clang::ento::CheckerManager::_registerForEndFunction
clang::ento::CheckerManager::_registerForBranchCondition
clang::ento::CheckerManager::_registerForNewAllocator
clang::ento::CheckerManager::_registerForLiveSymbols
clang::ento::CheckerManager::_registerForDeadSymbols
clang::ento::CheckerManager::_registerForRegionChanges
clang::ento::CheckerManager::_registerForPointerEscape
clang::ento::CheckerManager::_registerForConstPointerEscape
clang::ento::CheckerManager::_registerForEvalAssume
clang::ento::CheckerManager::_registerForEvalCall
clang::ento::CheckerManager::_registerForEndOfTranslationUnit
clang::ento::CheckerManager::getCachedStmtCheckersFor