CheckerManager.cpp revision 9be6e7ce5788e50c62d40c59b0bbc2ea423683f7
14186ad56cfe70ab065d3ca7aadcded814574fa42Chris Lattner//===--- CheckerManager.cpp - Static Analyzer Checker Manager -------------===//
2fd93908ae8b9684fe71c239e3c6cfe13ff6a2663Misha Brukman//
3b576c94c15af9a440f69d9d03c2afead7971118cJohn Criswell//                     The LLVM Compiler Infrastructure
4b576c94c15af9a440f69d9d03c2afead7971118cJohn Criswell//
54ee451de366474b9c228b4e5fa573795a715216dChris Lattner// This file is distributed under the University of Illinois Open Source
64ee451de366474b9c228b4e5fa573795a715216dChris Lattner// License. See LICENSE.TXT for details.
7fd93908ae8b9684fe71c239e3c6cfe13ff6a2663Misha Brukman//
8b576c94c15af9a440f69d9d03c2afead7971118cJohn Criswell//===----------------------------------------------------------------------===//
9573527bd5dc546a198a122cd6d1da62246d2d9beChris Lattner//
104cf4b69330f0b2a3ba325bcdb1ff41847c022260Chris Lattner// Defines the Static Analyzer Checker Manager.
114cf4b69330f0b2a3ba325bcdb1ff41847c022260Chris Lattner//
12573527bd5dc546a198a122cd6d1da62246d2d9beChris Lattner//===----------------------------------------------------------------------===//
13c86b67742a3298c0a5a715b57a64f11107b8a3f2Gordon Henriksen
14c86b67742a3298c0a5a715b57a64f11107b8a3f2Gordon Henriksen#include "clang/StaticAnalyzer/Core/CheckerManager.h"
15573527bd5dc546a198a122cd6d1da62246d2d9beChris Lattner#include "clang/StaticAnalyzer/Core/CheckerProvider.h"
16c86b67742a3298c0a5a715b57a64f11107b8a3f2Gordon Henriksen#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
17c86b67742a3298c0a5a715b57a64f11107b8a3f2Gordon Henriksen#include "clang/Analysis/ProgramPoint.h"
184cf4b69330f0b2a3ba325bcdb1ff41847c022260Chris Lattner#include "clang/AST/DeclBase.h"
194cf4b69330f0b2a3ba325bcdb1ff41847c022260Chris Lattner
204cf4b69330f0b2a3ba325bcdb1ff41847c022260Chris Lattnerusing namespace clang;
21573527bd5dc546a198a122cd6d1da62246d2d9beChris Lattnerusing namespace ento;
22573527bd5dc546a198a122cd6d1da62246d2d9beChris Lattner
23573527bd5dc546a198a122cd6d1da62246d2d9beChris Lattnerbool CheckerManager::hasPathSensitiveCheckers() const {
24573527bd5dc546a198a122cd6d1da62246d2d9beChris Lattner  return !StmtCheckers.empty()              ||
25d04a8d4b33ff316ca4cf961e06c9e312eff8e64fChandler Carruth         !PreObjCMessageCheckers.empty()    ||
26d04a8d4b33ff316ca4cf961e06c9e312eff8e64fChandler Carruth         !PostObjCMessageCheckers.empty()   ||
27d04a8d4b33ff316ca4cf961e06c9e312eff8e64fChandler Carruth         !LocationCheckers.empty()          ||
28be04929f7fd76a921540e9901f24563e51dc1219Chandler Carruth         !BindCheckers.empty()              ||
290b8c9a80f20772c3793201ab5b251d3520b9cea3Chandler Carruth         !EndAnalysisCheckers.empty()       ||
3036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines         !EndPathCheckers.empty()           ||
310b8c9a80f20772c3793201ab5b251d3520b9cea3Chandler Carruth         !BranchConditionCheckers.empty()   ||
320b8c9a80f20772c3793201ab5b251d3520b9cea3Chandler Carruth         !LiveSymbolsCheckers.empty()       ||
330b8c9a80f20772c3793201ab5b251d3520b9cea3Chandler Carruth         !DeadSymbolsCheckers.empty()       ||
340b8c9a80f20772c3793201ab5b251d3520b9cea3Chandler Carruth         !RegionChangesCheckers.empty()     ||
350b8c9a80f20772c3793201ab5b251d3520b9cea3Chandler Carruth         !EvalAssumeCheckers.empty()        ||
36573527bd5dc546a198a122cd6d1da62246d2d9beChris Lattner         !EvalCallCheckers.empty();
37d04a8d4b33ff316ca4cf961e06c9e312eff8e64fChandler Carruth}
38d7456026629fc1760a45e6e955e9834246493147Chris Lattner
39d0fde30ce850b78371fd1386338350591f9ff494Brian Gaekevoid CheckerManager::finishedCheckerRegistration() {
40dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines#ifndef NDEBUG
41dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  // Make sure that for every event that has listeners, there is at least
420e5f499638c8d277b9dc4a4385712177c53b5681Chris Lattner  // one dispatcher registered for it.
43a92f696b74a99325026ebbdbffd2a44317e0c10bChris Lattner  for (llvm::DenseMap<EventTag, EventInfo>::iterator
440e5f499638c8d277b9dc4a4385712177c53b5681Chris Lattner         I = Events.begin(), E = Events.end(); I != E; ++I)
4557e6b2d1f3de0bf459e96f7038e692d624f7e580Tom Stellard    assert(I->second.HasDispatcher && "No dispatcher registered for an event");
4657e6b2d1f3de0bf459e96f7038e692d624f7e580Tom Stellard#endif
4701d7203ef8316fdd71c3cec59f8e68fb869e0dbfTom Stellard}
4801d7203ef8316fdd71c3cec59f8e68fb869e0dbfTom Stellard
4957e6b2d1f3de0bf459e96f7038e692d624f7e580Tom Stellard//===----------------------------------------------------------------------===//
5036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines// Functions for running checkers for AST traversing..
5101d7203ef8316fdd71c3cec59f8e68fb869e0dbfTom Stellard//===----------------------------------------------------------------------===//
5236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
5357e6b2d1f3de0bf459e96f7038e692d624f7e580Tom Stellardvoid CheckerManager::runCheckersOnASTDecl(const Decl *D, AnalysisManager& mgr,
5457e6b2d1f3de0bf459e96f7038e692d624f7e580Tom Stellard                                          BugReporter &BR) {
5557e6b2d1f3de0bf459e96f7038e692d624f7e580Tom Stellard  assert(D);
56573527bd5dc546a198a122cd6d1da62246d2d9beChris Lattner
57573527bd5dc546a198a122cd6d1da62246d2d9beChris Lattner  unsigned DeclKind = D->getKind();
5801d7203ef8316fdd71c3cec59f8e68fb869e0dbfTom Stellard  CachedDeclCheckers *checkers = 0;
5901d7203ef8316fdd71c3cec59f8e68fb869e0dbfTom Stellard  CachedDeclCheckersMapTy::iterator CCI = CachedDeclCheckersMap.find(DeclKind);
6057e6b2d1f3de0bf459e96f7038e692d624f7e580Tom Stellard  if (CCI != CachedDeclCheckersMap.end()) {
615f46c3c2e8d13c6ac8d3863d84e887f84c73f27aChandler Carruth    checkers = &(CCI->second);
6201d7203ef8316fdd71c3cec59f8e68fb869e0dbfTom Stellard  } else {
6357e6b2d1f3de0bf459e96f7038e692d624f7e580Tom Stellard    // Find the checkers that should run for this Decl and cache them.
64844731a7f1909f55935e3514c9e713a62d67662eDan Gohman    checkers = &CachedDeclCheckersMap[DeclKind];
65d0fde30ce850b78371fd1386338350591f9ff494Brian Gaeke    for (unsigned i = 0, e = DeclCheckers.size(); i != e; ++i) {
6601d7203ef8316fdd71c3cec59f8e68fb869e0dbfTom Stellard      DeclCheckerInfo &info = DeclCheckers[i];
6701d7203ef8316fdd71c3cec59f8e68fb869e0dbfTom Stellard      if (info.IsForDeclFn(D))
68573527bd5dc546a198a122cd6d1da62246d2d9beChris Lattner        checkers->push_back(info.CheckFn);
69573527bd5dc546a198a122cd6d1da62246d2d9beChris Lattner    }
70557a20a23494c13fbcef90fcc8454f2c8aa33c22Jim Grosbach  }
711a0e7081c3e94ae69f2768465da34a3dceaaa5f6Chris Lattner
72557a20a23494c13fbcef90fcc8454f2c8aa33c22Jim Grosbach  assert(checkers);
731a0e7081c3e94ae69f2768465da34a3dceaaa5f6Chris Lattner  for (CachedDeclCheckers::iterator
74a94d6e87c4c49f2e81b01d66d8bfb591277f8f96Nadav Rotem         I = checkers->begin(), E = checkers->end(); I != E; ++I)
75dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    (*I)(D, mgr, BR);
76a94d6e87c4c49f2e81b01d66d8bfb591277f8f96Nadav Rotem}
771a0e7081c3e94ae69f2768465da34a3dceaaa5f6Chris Lattner
781a0e7081c3e94ae69f2768465da34a3dceaaa5f6Chris Lattnervoid CheckerManager::runCheckersOnASTBody(const Decl *D, AnalysisManager& mgr,
791a0e7081c3e94ae69f2768465da34a3dceaaa5f6Chris Lattner                                          BugReporter &BR) {
80a94d6e87c4c49f2e81b01d66d8bfb591277f8f96Nadav Rotem  assert(D && D->hasBody());
811a0e7081c3e94ae69f2768465da34a3dceaaa5f6Chris Lattner
821a0e7081c3e94ae69f2768465da34a3dceaaa5f6Chris Lattner  for (unsigned i = 0, e = BodyCheckers.size(); i != e; ++i)
83dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    BodyCheckers[i](D, mgr, BR);
84a94d6e87c4c49f2e81b01d66d8bfb591277f8f96Nadav Rotem}
851a0e7081c3e94ae69f2768465da34a3dceaaa5f6Chris Lattner
861a0e7081c3e94ae69f2768465da34a3dceaaa5f6Chris Lattner//===----------------------------------------------------------------------===//
871a0e7081c3e94ae69f2768465da34a3dceaaa5f6Chris Lattner// Functions for running checkers for path-sensitive checking.
881a0e7081c3e94ae69f2768465da34a3dceaaa5f6Chris Lattner//===----------------------------------------------------------------------===//
891a0e7081c3e94ae69f2768465da34a3dceaaa5f6Chris Lattner
901a0e7081c3e94ae69f2768465da34a3dceaaa5f6Chris Lattnertemplate <typename CHECK_CTX>
91ead138bc628b57bfd0a03f6f7644ceb10128bb52Bill Wendlingstatic void expandGraphWithCheckers(CHECK_CTX checkCtx,
92ead138bc628b57bfd0a03f6f7644ceb10128bb52Bill Wendling                                    ExplodedNodeSet &Dst,
93ead138bc628b57bfd0a03f6f7644ceb10128bb52Bill Wendling                                    const ExplodedNodeSet &Src) {
94ead138bc628b57bfd0a03f6f7644ceb10128bb52Bill Wendling
95ead138bc628b57bfd0a03f6f7644ceb10128bb52Bill Wendling  typename CHECK_CTX::CheckersTy::const_iterator
96ead138bc628b57bfd0a03f6f7644ceb10128bb52Bill Wendling      I = checkCtx.checkers_begin(), E = checkCtx.checkers_end();
97ead138bc628b57bfd0a03f6f7644ceb10128bb52Bill Wendling  if (I == E) {
981a0e7081c3e94ae69f2768465da34a3dceaaa5f6Chris Lattner    Dst.insert(Src);
991a0e7081c3e94ae69f2768465da34a3dceaaa5f6Chris Lattner    return;
100ead138bc628b57bfd0a03f6f7644ceb10128bb52Bill Wendling  }
1011a0e7081c3e94ae69f2768465da34a3dceaaa5f6Chris Lattner
102dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  ExplodedNodeSet Tmp1, Tmp2;
1031a0e7081c3e94ae69f2768465da34a3dceaaa5f6Chris Lattner  const ExplodedNodeSet *PrevSet = &Src;
1041a0e7081c3e94ae69f2768465da34a3dceaaa5f6Chris Lattner
1051a0e7081c3e94ae69f2768465da34a3dceaaa5f6Chris Lattner  for (; I != E; ++I) {
106a94d6e87c4c49f2e81b01d66d8bfb591277f8f96Nadav Rotem    ExplodedNodeSet *CurrSet = 0;
1071a0e7081c3e94ae69f2768465da34a3dceaaa5f6Chris Lattner    if (I+1 == E)
1081a0e7081c3e94ae69f2768465da34a3dceaaa5f6Chris Lattner      CurrSet = &Dst;
109a94d6e87c4c49f2e81b01d66d8bfb591277f8f96Nadav Rotem    else {
1101a0e7081c3e94ae69f2768465da34a3dceaaa5f6Chris Lattner      CurrSet = (PrevSet == &Tmp1) ? &Tmp2 : &Tmp1;
1111a0e7081c3e94ae69f2768465da34a3dceaaa5f6Chris Lattner      CurrSet->clear();
1121a0e7081c3e94ae69f2768465da34a3dceaaa5f6Chris Lattner    }
1131a0e7081c3e94ae69f2768465da34a3dceaaa5f6Chris Lattner
114a94d6e87c4c49f2e81b01d66d8bfb591277f8f96Nadav Rotem    for (ExplodedNodeSet::iterator NI = PrevSet->begin(), NE = PrevSet->end();
1151a0e7081c3e94ae69f2768465da34a3dceaaa5f6Chris Lattner         NI != NE; ++NI)
1161a0e7081c3e94ae69f2768465da34a3dceaaa5f6Chris Lattner      checkCtx.runChecker(*I, *CurrSet, *NI);
1171a0e7081c3e94ae69f2768465da34a3dceaaa5f6Chris Lattner
1181a0e7081c3e94ae69f2768465da34a3dceaaa5f6Chris Lattner    // Update which NodeSet is the current one.
1191a0e7081c3e94ae69f2768465da34a3dceaaa5f6Chris Lattner    PrevSet = CurrSet;
120a94d6e87c4c49f2e81b01d66d8bfb591277f8f96Nadav Rotem  }
1211a0e7081c3e94ae69f2768465da34a3dceaaa5f6Chris Lattner}
1221a0e7081c3e94ae69f2768465da34a3dceaaa5f6Chris Lattner
123dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hinesnamespace {
124ca704957972df96a86f4ef90ce992bce5a9b60e9Devang Patel  struct CheckStmtContext {
125d8b4fb4aab4d6fedb2b14bed1b846451b17bde7cJay Foad    typedef llvm::SmallVectorImpl<CheckerManager::CheckStmtFunc> CheckersTy;
1263ecfc861b4365f341c5c969b40e1afccde676e6fJay Foad    bool IsPreVisit;
1273ecfc861b4365f341c5c969b40e1afccde676e6fJay Foad    const CheckersTy &Checkers;
1281a0e7081c3e94ae69f2768465da34a3dceaaa5f6Chris Lattner    const Stmt *S;
129a94d6e87c4c49f2e81b01d66d8bfb591277f8f96Nadav Rotem    ExprEngine &Eng;
130d8b4fb4aab4d6fedb2b14bed1b846451b17bde7cJay Foad
1311a0e7081c3e94ae69f2768465da34a3dceaaa5f6Chris Lattner    CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); }
1321a0e7081c3e94ae69f2768465da34a3dceaaa5f6Chris Lattner    CheckersTy::const_iterator checkers_end() { return Checkers.end(); }
1331a0e7081c3e94ae69f2768465da34a3dceaaa5f6Chris Lattner
134a94d6e87c4c49f2e81b01d66d8bfb591277f8f96Nadav Rotem    CheckStmtContext(bool isPreVisit, const CheckersTy &checkers,
1351a0e7081c3e94ae69f2768465da34a3dceaaa5f6Chris Lattner                     const Stmt *s, ExprEngine &eng)
1361a0e7081c3e94ae69f2768465da34a3dceaaa5f6Chris Lattner      : IsPreVisit(isPreVisit), Checkers(checkers), S(s), Eng(eng) { }
1371a0e7081c3e94ae69f2768465da34a3dceaaa5f6Chris Lattner
1381a0e7081c3e94ae69f2768465da34a3dceaaa5f6Chris Lattner    void runChecker(CheckerManager::CheckStmtFunc checkFn,
1391a0e7081c3e94ae69f2768465da34a3dceaaa5f6Chris Lattner                    ExplodedNodeSet &Dst, ExplodedNode *Pred) {
1401a0e7081c3e94ae69f2768465da34a3dceaaa5f6Chris Lattner      // FIXME: Remove respondsToCallback from CheckerContext;
1411a0e7081c3e94ae69f2768465da34a3dceaaa5f6Chris Lattner      CheckerContext C(Dst, Eng.getBuilder(), Eng, Pred, checkFn.Checker,
142a94d6e87c4c49f2e81b01d66d8bfb591277f8f96Nadav Rotem                       IsPreVisit ? ProgramPoint::PreStmtKind :
1431a0e7081c3e94ae69f2768465da34a3dceaaa5f6Chris Lattner                                    ProgramPoint::PostStmtKind, 0, S);
1441a0e7081c3e94ae69f2768465da34a3dceaaa5f6Chris Lattner      checkFn(S, C);
1451a0e7081c3e94ae69f2768465da34a3dceaaa5f6Chris Lattner    }
146557a20a23494c13fbcef90fcc8454f2c8aa33c22Jim Grosbach  };
147b42c8f71017f29d006741f0fa4ce8de227e7226fChris Lattner}
1485f46c3c2e8d13c6ac8d3863d84e887f84c73f27aChandler Carruth
14936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines/// \brief Run checkers for visiting Stmts.
150b42c8f71017f29d006741f0fa4ce8de227e7226fChris Lattnervoid CheckerManager::runCheckersForStmt(bool isPreVisit,
151573527bd5dc546a198a122cd6d1da62246d2d9beChris Lattner                                        ExplodedNodeSet &Dst,
152573527bd5dc546a198a122cd6d1da62246d2d9beChris Lattner                                        const ExplodedNodeSet &Src,
153573527bd5dc546a198a122cd6d1da62246d2d9beChris Lattner                                        const Stmt *S,
154a94d6e87c4c49f2e81b01d66d8bfb591277f8f96Nadav Rotem                                        ExprEngine &Eng) {
155e2c6d131d12c779a410740e0a90545def75e0f48Dan Gohman  CheckStmtContext C(isPreVisit, *getCachedStmtCheckersFor(S, isPreVisit),
156573527bd5dc546a198a122cd6d1da62246d2d9beChris Lattner                     S, Eng);
157e2c6d131d12c779a410740e0a90545def75e0f48Dan Gohman  expandGraphWithCheckers(C, Dst, Src);
15836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines}
159573527bd5dc546a198a122cd6d1da62246d2d9beChris Lattner
160573527bd5dc546a198a122cd6d1da62246d2d9beChris Lattnernamespace {
161573527bd5dc546a198a122cd6d1da62246d2d9beChris Lattner  struct CheckObjCMessageContext {
162573527bd5dc546a198a122cd6d1da62246d2d9beChris Lattner    typedef std::vector<CheckerManager::CheckObjCMessageFunc> CheckersTy;
163573527bd5dc546a198a122cd6d1da62246d2d9beChris Lattner    bool IsPreVisit;
164573527bd5dc546a198a122cd6d1da62246d2d9beChris Lattner    const CheckersTy &Checkers;
165573527bd5dc546a198a122cd6d1da62246d2d9beChris Lattner    const ObjCMessage &Msg;
166573527bd5dc546a198a122cd6d1da62246d2d9beChris Lattner    ExprEngine &Eng;
167b42c8f71017f29d006741f0fa4ce8de227e7226fChris Lattner
168b42c8f71017f29d006741f0fa4ce8de227e7226fChris Lattner    CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); }
169b42c8f71017f29d006741f0fa4ce8de227e7226fChris Lattner    CheckersTy::const_iterator checkers_end() { return Checkers.end(); }
170b42c8f71017f29d006741f0fa4ce8de227e7226fChris Lattner
171b42c8f71017f29d006741f0fa4ce8de227e7226fChris Lattner    CheckObjCMessageContext(bool isPreVisit, const CheckersTy &checkers,
17236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines                            const ObjCMessage &msg, ExprEngine &eng)
17336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      : IsPreVisit(isPreVisit), Checkers(checkers), Msg(msg), Eng(eng) { }
17436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
1755f46c3c2e8d13c6ac8d3863d84e887f84c73f27aChandler Carruth    void runChecker(CheckerManager::CheckObjCMessageFunc checkFn,
17636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines                    ExplodedNodeSet &Dst, ExplodedNode *Pred) {
177dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines      CheckerContext C(Dst, Eng.getBuilder(), Eng, Pred, checkFn.Checker,
1784f96b7e1478be0b33cda589db40635a1e3a40c11Peter Collingbourne                       IsPreVisit ? ProgramPoint::PreStmtKind :
179557a20a23494c13fbcef90fcc8454f2c8aa33c22Jim Grosbach                                    ProgramPoint::PostStmtKind, 0,
18036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines                       Msg.getOriginExpr());
18158e9ee85fda5083e2eea987917e8eab6ba31fe5eJakob Stoklund Olesen      checkFn(Msg, C);
182b42c8f71017f29d006741f0fa4ce8de227e7226fChris Lattner    }
183b42c8f71017f29d006741f0fa4ce8de227e7226fChris Lattner  };
184b42c8f71017f29d006741f0fa4ce8de227e7226fChris Lattner}
185557a20a23494c13fbcef90fcc8454f2c8aa33c22Jim Grosbach
1864f96b7e1478be0b33cda589db40635a1e3a40c11Peter Collingbourne/// \brief Run checkers for visiting obj-c messages.
187b42c8f71017f29d006741f0fa4ce8de227e7226fChris Lattnervoid CheckerManager::runCheckersForObjCMessage(bool isPreVisit,
188557a20a23494c13fbcef90fcc8454f2c8aa33c22Jim Grosbach                                               ExplodedNodeSet &Dst,
1894f96b7e1478be0b33cda589db40635a1e3a40c11Peter Collingbourne                                               const ExplodedNodeSet &Src,
1904f96b7e1478be0b33cda589db40635a1e3a40c11Peter Collingbourne                                               const ObjCMessage &msg,
191b42c8f71017f29d006741f0fa4ce8de227e7226fChris Lattner                                               ExprEngine &Eng) {
19258e9ee85fda5083e2eea987917e8eab6ba31fe5eJakob Stoklund Olesen  CheckObjCMessageContext C(isPreVisit,
193b42c8f71017f29d006741f0fa4ce8de227e7226fChris Lattner                            isPreVisit ? PreObjCMessageCheckers
19436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines                                       : PostObjCMessageCheckers,
1954f96b7e1478be0b33cda589db40635a1e3a40c11Peter Collingbourne                            msg, Eng);
196b42c8f71017f29d006741f0fa4ce8de227e7226fChris Lattner  expandGraphWithCheckers(C, Dst, Src);
19758e9ee85fda5083e2eea987917e8eab6ba31fe5eJakob Stoklund Olesen}
198b42c8f71017f29d006741f0fa4ce8de227e7226fChris Lattner
199b42c8f71017f29d006741f0fa4ce8de227e7226fChris Lattnernamespace {
200  struct CheckLocationContext {
201    typedef std::vector<CheckerManager::CheckLocationFunc> CheckersTy;
202    const CheckersTy &Checkers;
203    SVal Loc;
204    bool IsLoad;
205    const Stmt *S;
206    ExprEngine &Eng;
207
208    CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); }
209    CheckersTy::const_iterator checkers_end() { return Checkers.end(); }
210
211    CheckLocationContext(const CheckersTy &checkers,
212                         SVal loc, bool isLoad, const Stmt *s, ExprEngine &eng)
213      : Checkers(checkers), Loc(loc), IsLoad(isLoad), S(s), Eng(eng) { }
214
215    void runChecker(CheckerManager::CheckLocationFunc checkFn,
216                    ExplodedNodeSet &Dst, ExplodedNode *Pred) {
217      CheckerContext C(Dst, Eng.getBuilder(), Eng, Pred, checkFn.Checker,
218                       IsLoad ? ProgramPoint::PreLoadKind :
219                       ProgramPoint::PreStoreKind, 0, S);
220      checkFn(Loc, IsLoad, C);
221    }
222  };
223}
224
225/// \brief Run checkers for load/store of a location.
226void CheckerManager::runCheckersForLocation(ExplodedNodeSet &Dst,
227                                            const ExplodedNodeSet &Src,
228                                            SVal location, bool isLoad,
229                                            const Stmt *S, ExprEngine &Eng) {
230  CheckLocationContext C(LocationCheckers, location, isLoad, S, Eng);
231  expandGraphWithCheckers(C, Dst, Src);
232}
233
234namespace {
235  struct CheckBindContext {
236    typedef std::vector<CheckerManager::CheckBindFunc> CheckersTy;
237    const CheckersTy &Checkers;
238    SVal Loc;
239    SVal Val;
240    const Stmt *S;
241    ExprEngine &Eng;
242
243    CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); }
244    CheckersTy::const_iterator checkers_end() { return Checkers.end(); }
245
246    CheckBindContext(const CheckersTy &checkers,
247                     SVal loc, SVal val, const Stmt *s, ExprEngine &eng)
248      : Checkers(checkers), Loc(loc), Val(val), S(s), Eng(eng) { }
249
250    void runChecker(CheckerManager::CheckBindFunc checkFn,
251                    ExplodedNodeSet &Dst, ExplodedNode *Pred) {
252      CheckerContext C(Dst, Eng.getBuilder(), Eng, Pred, checkFn.Checker,
253                       ProgramPoint::PreStmtKind, 0, S);
254      checkFn(Loc, Val, C);
255    }
256  };
257}
258
259/// \brief Run checkers for binding of a value to a location.
260void CheckerManager::runCheckersForBind(ExplodedNodeSet &Dst,
261                                        const ExplodedNodeSet &Src,
262                                        SVal location, SVal val,
263                                        const Stmt *S, ExprEngine &Eng) {
264  CheckBindContext C(BindCheckers, location, val, S, Eng);
265  expandGraphWithCheckers(C, Dst, Src);
266}
267
268void CheckerManager::runCheckersForEndAnalysis(ExplodedGraph &G,
269                                               BugReporter &BR,
270                                               ExprEngine &Eng) {
271  for (unsigned i = 0, e = EndAnalysisCheckers.size(); i != e; ++i)
272    EndAnalysisCheckers[i](G, BR, Eng);
273}
274
275/// \brief Run checkers for end of path.
276void CheckerManager::runCheckersForEndPath(EndOfFunctionNodeBuilder &B,
277                                           ExprEngine &Eng) {
278  for (unsigned i = 0, e = EndPathCheckers.size(); i != e; ++i) {
279    CheckEndPathFunc fn = EndPathCheckers[i];
280    EndOfFunctionNodeBuilder specialB = B.withCheckerTag(fn.Checker);
281    fn(specialB, Eng);
282  }
283}
284
285/// \brief Run checkers for branch condition.
286void CheckerManager::runCheckersForBranchCondition(const Stmt *condition,
287                                                   BranchNodeBuilder &B,
288                                                   ExprEngine &Eng) {
289  for (unsigned i = 0, e = BranchConditionCheckers.size(); i != e; ++i) {
290    CheckBranchConditionFunc fn = BranchConditionCheckers[i];
291    fn(condition, B, Eng);
292  }
293}
294
295/// \brief Run checkers for live symbols.
296void CheckerManager::runCheckersForLiveSymbols(const GRState *state,
297                                               SymbolReaper &SymReaper) {
298  for (unsigned i = 0, e = LiveSymbolsCheckers.size(); i != e; ++i)
299    LiveSymbolsCheckers[i](state, SymReaper);
300}
301
302namespace {
303  struct CheckDeadSymbolsContext {
304    typedef std::vector<CheckerManager::CheckDeadSymbolsFunc> CheckersTy;
305    const CheckersTy &Checkers;
306    SymbolReaper &SR;
307    const Stmt *S;
308    ExprEngine &Eng;
309
310    CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); }
311    CheckersTy::const_iterator checkers_end() { return Checkers.end(); }
312
313    CheckDeadSymbolsContext(const CheckersTy &checkers, SymbolReaper &sr,
314                            const Stmt *s, ExprEngine &eng)
315      : Checkers(checkers), SR(sr), S(s), Eng(eng) { }
316
317    void runChecker(CheckerManager::CheckDeadSymbolsFunc checkFn,
318                    ExplodedNodeSet &Dst, ExplodedNode *Pred) {
319      CheckerContext C(Dst, Eng.getBuilder(), Eng, Pred, checkFn.Checker,
320                       ProgramPoint::PostPurgeDeadSymbolsKind, 0, S);
321      checkFn(SR, C);
322    }
323  };
324}
325
326/// \brief Run checkers for dead symbols.
327void CheckerManager::runCheckersForDeadSymbols(ExplodedNodeSet &Dst,
328                                               const ExplodedNodeSet &Src,
329                                               SymbolReaper &SymReaper,
330                                               const Stmt *S,
331                                               ExprEngine &Eng) {
332  CheckDeadSymbolsContext C(DeadSymbolsCheckers, SymReaper, S, Eng);
333  expandGraphWithCheckers(C, Dst, Src);
334}
335
336/// \brief True if at least one checker wants to check region changes.
337bool CheckerManager::wantsRegionChangeUpdate(const GRState *state) {
338  for (unsigned i = 0, e = RegionChangesCheckers.size(); i != e; ++i)
339    if (RegionChangesCheckers[i].WantUpdateFn(state))
340      return true;
341
342  return false;
343}
344
345/// \brief Run checkers for region changes.
346const GRState *
347CheckerManager::runCheckersForRegionChanges(const GRState *state,
348                            const StoreManager::InvalidatedSymbols *invalidated,
349                                            const MemRegion * const *Begin,
350                                            const MemRegion * const *End) {
351  for (unsigned i = 0, e = RegionChangesCheckers.size(); i != e; ++i) {
352    // If any checker declares the state infeasible (or if it starts that way),
353    // bail out.
354    if (!state)
355      return NULL;
356    state = RegionChangesCheckers[i].CheckFn(state, invalidated, Begin, End);
357  }
358  return state;
359}
360
361/// \brief Run checkers for handling assumptions on symbolic values.
362const GRState *
363CheckerManager::runCheckersForEvalAssume(const GRState *state,
364                                         SVal Cond, bool Assumption) {
365  for (unsigned i = 0, e = EvalAssumeCheckers.size(); i != e; ++i) {
366    // If any checker declares the state infeasible (or if it starts that way),
367    // bail out.
368    if (!state)
369      return NULL;
370    state = EvalAssumeCheckers[i](state, Cond, Assumption);
371  }
372  return state;
373}
374
375/// \brief Run checkers for evaluating a call.
376/// Only one checker will evaluate the call.
377void CheckerManager::runCheckersForEvalCall(ExplodedNodeSet &Dst,
378                                            const ExplodedNodeSet &Src,
379                                            const CallExpr *CE,
380                                            ExprEngine &Eng,
381                                            GraphExpander *defaultEval) {
382  if (EvalCallCheckers.empty() && defaultEval == 0) {
383    Dst.insert(Src);
384    return;
385  }
386
387  for (ExplodedNodeSet::iterator
388         NI = Src.begin(), NE = Src.end(); NI != NE; ++NI) {
389
390    ExplodedNode *Pred = *NI;
391    bool anyEvaluated = false;
392    for (std::vector<EvalCallFunc>::iterator
393           EI = EvalCallCheckers.begin(), EE = EvalCallCheckers.end();
394         EI != EE; ++EI) {
395      ExplodedNodeSet checkDst;
396      CheckerContext C(checkDst, Eng.getBuilder(), Eng, Pred, EI->Checker,
397                       ProgramPoint::PostStmtKind, 0, CE);
398      bool evaluated = (*EI)(CE, C);
399      assert(!(evaluated && anyEvaluated)
400             && "There are more than one checkers evaluating the call");
401      if (evaluated) {
402        anyEvaluated = true;
403        Dst.insert(checkDst);
404#ifdef NDEBUG
405        break; // on release don't check that no other checker also evals.
406#endif
407      }
408    }
409
410    if (!anyEvaluated) {
411      if (defaultEval)
412        defaultEval->expandGraph(Dst, Pred);
413      else
414        Dst.insert(Pred);
415    }
416  }
417}
418
419/// \brief Run checkers for the entire Translation Unit.
420void CheckerManager::runCheckersOnEndOfTranslationUnit(
421                                                  const TranslationUnitDecl *TU,
422                                                  AnalysisManager &mgr,
423                                                  BugReporter &BR) {
424  for (unsigned i = 0, e = EndOfTranslationUnitCheckers.size(); i != e; ++i)
425    EndOfTranslationUnitCheckers[i](TU, mgr, BR);
426}
427
428//===----------------------------------------------------------------------===//
429// Internal registration functions for AST traversing.
430//===----------------------------------------------------------------------===//
431
432void CheckerManager::_registerForDecl(CheckDeclFunc checkfn,
433                                      HandlesDeclFunc isForDeclFn) {
434  DeclCheckerInfo info = { checkfn, isForDeclFn };
435  DeclCheckers.push_back(info);
436}
437
438void CheckerManager::_registerForBody(CheckDeclFunc checkfn) {
439  BodyCheckers.push_back(checkfn);
440}
441
442//===----------------------------------------------------------------------===//
443// Internal registration functions for path-sensitive checking.
444//===----------------------------------------------------------------------===//
445
446void CheckerManager::_registerForPreStmt(CheckStmtFunc checkfn,
447                                         HandlesStmtFunc isForStmtFn) {
448  StmtCheckerInfo info = { checkfn, isForStmtFn, /*IsPreVisit*/true };
449  StmtCheckers.push_back(info);
450}
451void CheckerManager::_registerForPostStmt(CheckStmtFunc checkfn,
452                                          HandlesStmtFunc isForStmtFn) {
453  StmtCheckerInfo info = { checkfn, isForStmtFn, /*IsPreVisit*/false };
454  StmtCheckers.push_back(info);
455}
456
457void CheckerManager::_registerForPreObjCMessage(CheckObjCMessageFunc checkfn) {
458  PreObjCMessageCheckers.push_back(checkfn);
459}
460void CheckerManager::_registerForPostObjCMessage(CheckObjCMessageFunc checkfn) {
461  PostObjCMessageCheckers.push_back(checkfn);
462}
463
464void CheckerManager::_registerForLocation(CheckLocationFunc checkfn) {
465  LocationCheckers.push_back(checkfn);
466}
467
468void CheckerManager::_registerForBind(CheckBindFunc checkfn) {
469  BindCheckers.push_back(checkfn);
470}
471
472void CheckerManager::_registerForEndAnalysis(CheckEndAnalysisFunc checkfn) {
473  EndAnalysisCheckers.push_back(checkfn);
474}
475
476void CheckerManager::_registerForEndPath(CheckEndPathFunc checkfn) {
477  EndPathCheckers.push_back(checkfn);
478}
479
480void CheckerManager::_registerForBranchCondition(
481                                             CheckBranchConditionFunc checkfn) {
482  BranchConditionCheckers.push_back(checkfn);
483}
484
485void CheckerManager::_registerForLiveSymbols(CheckLiveSymbolsFunc checkfn) {
486  LiveSymbolsCheckers.push_back(checkfn);
487}
488
489void CheckerManager::_registerForDeadSymbols(CheckDeadSymbolsFunc checkfn) {
490  DeadSymbolsCheckers.push_back(checkfn);
491}
492
493void CheckerManager::_registerForRegionChanges(CheckRegionChangesFunc checkfn,
494                                     WantsRegionChangeUpdateFunc wantUpdateFn) {
495  RegionChangesCheckerInfo info = {checkfn, wantUpdateFn};
496  RegionChangesCheckers.push_back(info);
497}
498
499void CheckerManager::_registerForEvalAssume(EvalAssumeFunc checkfn) {
500  EvalAssumeCheckers.push_back(checkfn);
501}
502
503void CheckerManager::_registerForEvalCall(EvalCallFunc checkfn) {
504  EvalCallCheckers.push_back(checkfn);
505}
506
507void CheckerManager::_registerForEndOfTranslationUnit(
508                                            CheckEndOfTranslationUnit checkfn) {
509  EndOfTranslationUnitCheckers.push_back(checkfn);
510}
511
512//===----------------------------------------------------------------------===//
513// Implementation details.
514//===----------------------------------------------------------------------===//
515
516CheckerManager::CachedStmtCheckers *
517CheckerManager::getCachedStmtCheckersFor(const Stmt *S, bool isPreVisit) {
518  assert(S);
519
520  CachedStmtCheckersKey key(S->getStmtClass(), isPreVisit);
521  CachedStmtCheckers *checkers = 0;
522  CachedStmtCheckersMapTy::iterator CCI = CachedStmtCheckersMap.find(key);
523  if (CCI != CachedStmtCheckersMap.end()) {
524    checkers = &(CCI->second);
525  } else {
526    // Find the checkers that should run for this Stmt and cache them.
527    checkers = &CachedStmtCheckersMap[key];
528    for (unsigned i = 0, e = StmtCheckers.size(); i != e; ++i) {
529      StmtCheckerInfo &info = StmtCheckers[i];
530      if (info.IsPreVisit == isPreVisit && info.IsForStmtFn(S))
531        checkers->push_back(info.CheckFn);
532    }
533  }
534
535  assert(checkers);
536  return checkers;
537}
538
539CheckerManager::~CheckerManager() {
540  for (unsigned i = 0, e = CheckerDtors.size(); i != e; ++i)
541    CheckerDtors[i]();
542}
543
544// Anchor for the vtable.
545CheckerProvider::~CheckerProvider() { }
546
547// Anchor for the vtable.
548GraphExpander::~GraphExpander() { }
549