Checker.h revision 6bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89
183226976b532141b26ff3a40f381a5d08ce3259dreed@google.com//== Checker.h - Registration mechanism for checkers -------------*- C++ -*--=//
283226976b532141b26ff3a40f381a5d08ce3259dreed@google.com//
383226976b532141b26ff3a40f381a5d08ce3259dreed@google.com//                     The LLVM Compiler Infrastructure
483226976b532141b26ff3a40f381a5d08ce3259dreed@google.com//
583226976b532141b26ff3a40f381a5d08ce3259dreed@google.com// This file is distributed under the University of Illinois Open Source
683226976b532141b26ff3a40f381a5d08ce3259dreed@google.com// License. See LICENSE.TXT for details.
7e4fafb146e85cdfcf9d5418597b6818aa0754adatfarina@chromium.org//
81f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com//===----------------------------------------------------------------------===//
983226976b532141b26ff3a40f381a5d08ce3259dreed@google.com//
1083226976b532141b26ff3a40f381a5d08ce3259dreed@google.com//  This file defines Checker, used to create and register checkers.
1183226976b532141b26ff3a40f381a5d08ce3259dreed@google.com//
121f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com//===----------------------------------------------------------------------===//
131f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com
148f6884aab8aecd7657cf3f9cdbc682f0deca29c5tfarina@chromium.org#ifndef LLVM_CLANG_SA_CORE_CHECKER
1583226976b532141b26ff3a40f381a5d08ce3259dreed@google.com#define LLVM_CLANG_SA_CORE_CHECKER
1683226976b532141b26ff3a40f381a5d08ce3259dreed@google.com
1783226976b532141b26ff3a40f381a5d08ce3259dreed@google.com#include "clang/Analysis/ProgramPoint.h"
1883226976b532141b26ff3a40f381a5d08ce3259dreed@google.com#include "clang/StaticAnalyzer/Core/CheckerManager.h"
1983226976b532141b26ff3a40f381a5d08ce3259dreed@google.com#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
2083226976b532141b26ff3a40f381a5d08ce3259dreed@google.com#include "llvm/Support/Casting.h"
2183226976b532141b26ff3a40f381a5d08ce3259dreed@google.com
2283226976b532141b26ff3a40f381a5d08ce3259dreed@google.comnamespace clang {
2383226976b532141b26ff3a40f381a5d08ce3259dreed@google.comnamespace ento {
2483226976b532141b26ff3a40f381a5d08ce3259dreed@google.com  class BugReporter;
2583226976b532141b26ff3a40f381a5d08ce3259dreed@google.com
2683226976b532141b26ff3a40f381a5d08ce3259dreed@google.comnamespace check {
2783226976b532141b26ff3a40f381a5d08ce3259dreed@google.com
2883226976b532141b26ff3a40f381a5d08ce3259dreed@google.comstruct _VoidCheck {
2983226976b532141b26ff3a40f381a5d08ce3259dreed@google.com  static void _register(void *checker, CheckerManager &mgr) { }
3083226976b532141b26ff3a40f381a5d08ce3259dreed@google.com};
3183226976b532141b26ff3a40f381a5d08ce3259dreed@google.com
3283226976b532141b26ff3a40f381a5d08ce3259dreed@google.comtemplate <typename DECL>
3383226976b532141b26ff3a40f381a5d08ce3259dreed@google.comclass ASTDecl {
3483226976b532141b26ff3a40f381a5d08ce3259dreed@google.com  template <typename CHECKER>
3583226976b532141b26ff3a40f381a5d08ce3259dreed@google.com  static void _checkDecl(void *checker, const Decl *D, AnalysisManager& mgr,
3683226976b532141b26ff3a40f381a5d08ce3259dreed@google.com                         BugReporter &BR) {
3783226976b532141b26ff3a40f381a5d08ce3259dreed@google.com    ((const CHECKER *)checker)->checkASTDecl(cast<DECL>(D), mgr, BR);
3883226976b532141b26ff3a40f381a5d08ce3259dreed@google.com  }
3983226976b532141b26ff3a40f381a5d08ce3259dreed@google.com
4083226976b532141b26ff3a40f381a5d08ce3259dreed@google.com  static bool _handlesDecl(const Decl *D) {
4183226976b532141b26ff3a40f381a5d08ce3259dreed@google.com    return isa<DECL>(D);
4283226976b532141b26ff3a40f381a5d08ce3259dreed@google.com  }
4383226976b532141b26ff3a40f381a5d08ce3259dreed@google.compublic:
4483226976b532141b26ff3a40f381a5d08ce3259dreed@google.com  template <typename CHECKER>
45e0e385c1d4171e065348ba17c546b3463a0bd651sugoi@google.com  static void _register(CHECKER *checker, CheckerManager &mgr) {
4683226976b532141b26ff3a40f381a5d08ce3259dreed@google.com    mgr._registerForDecl(CheckerManager::CheckDeclFunc(checker,
4783226976b532141b26ff3a40f381a5d08ce3259dreed@google.com                                                       _checkDecl<CHECKER>),
4883226976b532141b26ff3a40f381a5d08ce3259dreed@google.com                         _handlesDecl);
4983226976b532141b26ff3a40f381a5d08ce3259dreed@google.com  }
5083226976b532141b26ff3a40f381a5d08ce3259dreed@google.com};
5183226976b532141b26ff3a40f381a5d08ce3259dreed@google.com
5283226976b532141b26ff3a40f381a5d08ce3259dreed@google.comclass ASTCodeBody {
5383226976b532141b26ff3a40f381a5d08ce3259dreed@google.com  template <typename CHECKER>
5483226976b532141b26ff3a40f381a5d08ce3259dreed@google.com  static void _checkBody(void *checker, const Decl *D, AnalysisManager& mgr,
5537ebe3fbf6c4a5728bc2c322cc0f626444f987bfrobertphillips@google.com                         BugReporter &BR) {
5683226976b532141b26ff3a40f381a5d08ce3259dreed@google.com    ((const CHECKER *)checker)->checkASTCodeBody(D, mgr, BR);
5783226976b532141b26ff3a40f381a5d08ce3259dreed@google.com  }
5883226976b532141b26ff3a40f381a5d08ce3259dreed@google.com
5983226976b532141b26ff3a40f381a5d08ce3259dreed@google.compublic:
6083226976b532141b26ff3a40f381a5d08ce3259dreed@google.com  template <typename CHECKER>
6183226976b532141b26ff3a40f381a5d08ce3259dreed@google.com  static void _register(CHECKER *checker, CheckerManager &mgr) {
6283226976b532141b26ff3a40f381a5d08ce3259dreed@google.com    mgr._registerForBody(CheckerManager::CheckDeclFunc(checker,
6383226976b532141b26ff3a40f381a5d08ce3259dreed@google.com                                                       _checkBody<CHECKER>));
6483226976b532141b26ff3a40f381a5d08ce3259dreed@google.com  }
6583226976b532141b26ff3a40f381a5d08ce3259dreed@google.com};
6683226976b532141b26ff3a40f381a5d08ce3259dreed@google.com
67d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.comclass EndOfTranslationUnit {
6883226976b532141b26ff3a40f381a5d08ce3259dreed@google.com  template <typename CHECKER>
6983226976b532141b26ff3a40f381a5d08ce3259dreed@google.com  static void _checkEndOfTranslationUnit(void *checker,
7083226976b532141b26ff3a40f381a5d08ce3259dreed@google.com                                         const TranslationUnitDecl *TU,
7183226976b532141b26ff3a40f381a5d08ce3259dreed@google.com                                         AnalysisManager& mgr,
7283226976b532141b26ff3a40f381a5d08ce3259dreed@google.com                                         BugReporter &BR) {
7383226976b532141b26ff3a40f381a5d08ce3259dreed@google.com    ((const CHECKER *)checker)->checkEndOfTranslationUnit(TU, mgr, BR);
7483226976b532141b26ff3a40f381a5d08ce3259dreed@google.com  }
7583226976b532141b26ff3a40f381a5d08ce3259dreed@google.com
7683226976b532141b26ff3a40f381a5d08ce3259dreed@google.compublic:
7783226976b532141b26ff3a40f381a5d08ce3259dreed@google.com  template <typename CHECKER>
7883226976b532141b26ff3a40f381a5d08ce3259dreed@google.com  static void _register(CHECKER *checker, CheckerManager &mgr){
7983226976b532141b26ff3a40f381a5d08ce3259dreed@google.com    mgr._registerForEndOfTranslationUnit(
80d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com                              CheckerManager::CheckEndOfTranslationUnit(checker,
8183226976b532141b26ff3a40f381a5d08ce3259dreed@google.com                                          _checkEndOfTranslationUnit<CHECKER>));
8283226976b532141b26ff3a40f381a5d08ce3259dreed@google.com  }
8383226976b532141b26ff3a40f381a5d08ce3259dreed@google.com};
8483226976b532141b26ff3a40f381a5d08ce3259dreed@google.com
8583226976b532141b26ff3a40f381a5d08ce3259dreed@google.comtemplate <typename STMT>
8683226976b532141b26ff3a40f381a5d08ce3259dreed@google.comclass PreStmt {
8783226976b532141b26ff3a40f381a5d08ce3259dreed@google.com  template <typename CHECKER>
8883226976b532141b26ff3a40f381a5d08ce3259dreed@google.com  static void _checkStmt(void *checker, const Stmt *S, CheckerContext &C) {
8983226976b532141b26ff3a40f381a5d08ce3259dreed@google.com    ((const CHECKER *)checker)->checkPreStmt(cast<STMT>(S), C);
9083226976b532141b26ff3a40f381a5d08ce3259dreed@google.com  }
9183226976b532141b26ff3a40f381a5d08ce3259dreed@google.com
9283226976b532141b26ff3a40f381a5d08ce3259dreed@google.com  static bool _handlesStmt(const Stmt *S) {
9383226976b532141b26ff3a40f381a5d08ce3259dreed@google.com    return isa<STMT>(S);
9483226976b532141b26ff3a40f381a5d08ce3259dreed@google.com  }
9583226976b532141b26ff3a40f381a5d08ce3259dreed@google.compublic:
96d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com  template <typename CHECKER>
9783226976b532141b26ff3a40f381a5d08ce3259dreed@google.com  static void _register(CHECKER *checker, CheckerManager &mgr) {
9883226976b532141b26ff3a40f381a5d08ce3259dreed@google.com    mgr._registerForPreStmt(CheckerManager::CheckStmtFunc(checker,
9983226976b532141b26ff3a40f381a5d08ce3259dreed@google.com                                                          _checkStmt<CHECKER>),
10083226976b532141b26ff3a40f381a5d08ce3259dreed@google.com                            _handlesStmt);
10183226976b532141b26ff3a40f381a5d08ce3259dreed@google.com  }
10283226976b532141b26ff3a40f381a5d08ce3259dreed@google.com};
10383226976b532141b26ff3a40f381a5d08ce3259dreed@google.com
10483226976b532141b26ff3a40f381a5d08ce3259dreed@google.comtemplate <typename STMT>
10583226976b532141b26ff3a40f381a5d08ce3259dreed@google.comclass PostStmt {
10683226976b532141b26ff3a40f381a5d08ce3259dreed@google.com  template <typename CHECKER>
10783226976b532141b26ff3a40f381a5d08ce3259dreed@google.com  static void _checkStmt(void *checker, const Stmt *S, CheckerContext &C) {
10883226976b532141b26ff3a40f381a5d08ce3259dreed@google.com    ((const CHECKER *)checker)->checkPostStmt(cast<STMT>(S), C);
109d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com  }
11083226976b532141b26ff3a40f381a5d08ce3259dreed@google.com
11183226976b532141b26ff3a40f381a5d08ce3259dreed@google.com  static bool _handlesStmt(const Stmt *S) {
11283226976b532141b26ff3a40f381a5d08ce3259dreed@google.com    return isa<STMT>(S);
11383226976b532141b26ff3a40f381a5d08ce3259dreed@google.com  }
11483226976b532141b26ff3a40f381a5d08ce3259dreed@google.compublic:
11583226976b532141b26ff3a40f381a5d08ce3259dreed@google.com  template <typename CHECKER>
11683226976b532141b26ff3a40f381a5d08ce3259dreed@google.com  static void _register(CHECKER *checker, CheckerManager &mgr) {
11783226976b532141b26ff3a40f381a5d08ce3259dreed@google.com    mgr._registerForPostStmt(CheckerManager::CheckStmtFunc(checker,
11883226976b532141b26ff3a40f381a5d08ce3259dreed@google.com                                                           _checkStmt<CHECKER>),
11983226976b532141b26ff3a40f381a5d08ce3259dreed@google.com                             _handlesStmt);
12083226976b532141b26ff3a40f381a5d08ce3259dreed@google.com  }
12183226976b532141b26ff3a40f381a5d08ce3259dreed@google.com};
12283226976b532141b26ff3a40f381a5d08ce3259dreed@google.com
12383226976b532141b26ff3a40f381a5d08ce3259dreed@google.comclass PreObjCMessage {
124d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com  template <typename CHECKER>
12583226976b532141b26ff3a40f381a5d08ce3259dreed@google.com  static void _checkObjCMessage(void *checker, const ObjCMethodCall &msg,
12683226976b532141b26ff3a40f381a5d08ce3259dreed@google.com                                CheckerContext &C) {
12783226976b532141b26ff3a40f381a5d08ce3259dreed@google.com    ((const CHECKER *)checker)->checkPreObjCMessage(msg, C);
12883226976b532141b26ff3a40f381a5d08ce3259dreed@google.com  }
12983226976b532141b26ff3a40f381a5d08ce3259dreed@google.com
13083226976b532141b26ff3a40f381a5d08ce3259dreed@google.compublic:
131e94b5e40c5fb0e36eebcae1abfe04b9bc33583f4junov@chromium.org  template <typename CHECKER>
132e0e385c1d4171e065348ba17c546b3463a0bd651sugoi@google.com  static void _register(CHECKER *checker, CheckerManager &mgr) {
133e94b5e40c5fb0e36eebcae1abfe04b9bc33583f4junov@chromium.org    mgr._registerForPreObjCMessage(
134e94b5e40c5fb0e36eebcae1abfe04b9bc33583f4junov@chromium.org     CheckerManager::CheckObjCMessageFunc(checker, _checkObjCMessage<CHECKER>));
135e94b5e40c5fb0e36eebcae1abfe04b9bc33583f4junov@chromium.org  }
136e94b5e40c5fb0e36eebcae1abfe04b9bc33583f4junov@chromium.org};
137e94b5e40c5fb0e36eebcae1abfe04b9bc33583f4junov@chromium.org
138e94b5e40c5fb0e36eebcae1abfe04b9bc33583f4junov@chromium.orgclass PostObjCMessage {
139e94b5e40c5fb0e36eebcae1abfe04b9bc33583f4junov@chromium.org  template <typename CHECKER>
140e94b5e40c5fb0e36eebcae1abfe04b9bc33583f4junov@chromium.org  static void _checkObjCMessage(void *checker, const ObjCMethodCall &msg,
141e94b5e40c5fb0e36eebcae1abfe04b9bc33583f4junov@chromium.org                                CheckerContext &C) {
142e94b5e40c5fb0e36eebcae1abfe04b9bc33583f4junov@chromium.org    ((const CHECKER *)checker)->checkPostObjCMessage(msg, C);
143e94b5e40c5fb0e36eebcae1abfe04b9bc33583f4junov@chromium.org  }
144e94b5e40c5fb0e36eebcae1abfe04b9bc33583f4junov@chromium.org
145deee496cd30070e52556dcb538c2e5eb39b66b81mike@reedtribe.orgpublic:
146e94b5e40c5fb0e36eebcae1abfe04b9bc33583f4junov@chromium.org  template <typename CHECKER>
147e94b5e40c5fb0e36eebcae1abfe04b9bc33583f4junov@chromium.org  static void _register(CHECKER *checker, CheckerManager &mgr) {
148deee496cd30070e52556dcb538c2e5eb39b66b81mike@reedtribe.org    mgr._registerForPostObjCMessage(
149e94b5e40c5fb0e36eebcae1abfe04b9bc33583f4junov@chromium.org     CheckerManager::CheckObjCMessageFunc(checker, _checkObjCMessage<CHECKER>));
150e94b5e40c5fb0e36eebcae1abfe04b9bc33583f4junov@chromium.org  }
151e94b5e40c5fb0e36eebcae1abfe04b9bc33583f4junov@chromium.org};
152e94b5e40c5fb0e36eebcae1abfe04b9bc33583f4junov@chromium.org
153e94b5e40c5fb0e36eebcae1abfe04b9bc33583f4junov@chromium.orgclass PreCall {
154e94b5e40c5fb0e36eebcae1abfe04b9bc33583f4junov@chromium.org  template <typename CHECKER>
155e94b5e40c5fb0e36eebcae1abfe04b9bc33583f4junov@chromium.org  static void _checkCall(void *checker, const CallEvent &msg,
156e94b5e40c5fb0e36eebcae1abfe04b9bc33583f4junov@chromium.org                         CheckerContext &C) {
157e94b5e40c5fb0e36eebcae1abfe04b9bc33583f4junov@chromium.org    ((const CHECKER *)checker)->checkPreCall(msg, C);
158e94b5e40c5fb0e36eebcae1abfe04b9bc33583f4junov@chromium.org  }
15983226976b532141b26ff3a40f381a5d08ce3259dreed@google.com
16083226976b532141b26ff3a40f381a5d08ce3259dreed@google.compublic:
161e94b5e40c5fb0e36eebcae1abfe04b9bc33583f4junov@chromium.org  template <typename CHECKER>
16283226976b532141b26ff3a40f381a5d08ce3259dreed@google.com  static void _register(CHECKER *checker, CheckerManager &mgr) {
16383226976b532141b26ff3a40f381a5d08ce3259dreed@google.com    mgr._registerForPreCall(
16483226976b532141b26ff3a40f381a5d08ce3259dreed@google.com     CheckerManager::CheckCallFunc(checker, _checkCall<CHECKER>));
16583226976b532141b26ff3a40f381a5d08ce3259dreed@google.com  }
16683226976b532141b26ff3a40f381a5d08ce3259dreed@google.com};
16783226976b532141b26ff3a40f381a5d08ce3259dreed@google.com
16883226976b532141b26ff3a40f381a5d08ce3259dreed@google.comclass PostCall {
16983226976b532141b26ff3a40f381a5d08ce3259dreed@google.com  template <typename CHECKER>
17083226976b532141b26ff3a40f381a5d08ce3259dreed@google.com  static void _checkCall(void *checker, const CallEvent &msg,
17183226976b532141b26ff3a40f381a5d08ce3259dreed@google.com                         CheckerContext &C) {
17283226976b532141b26ff3a40f381a5d08ce3259dreed@google.com    ((const CHECKER *)checker)->checkPostCall(msg, C);
17383226976b532141b26ff3a40f381a5d08ce3259dreed@google.com  }
17483226976b532141b26ff3a40f381a5d08ce3259dreed@google.com
17583226976b532141b26ff3a40f381a5d08ce3259dreed@google.compublic:
17683226976b532141b26ff3a40f381a5d08ce3259dreed@google.com  template <typename CHECKER>
17783226976b532141b26ff3a40f381a5d08ce3259dreed@google.com  static void _register(CHECKER *checker, CheckerManager &mgr) {
17883226976b532141b26ff3a40f381a5d08ce3259dreed@google.com    mgr._registerForPostCall(
17983226976b532141b26ff3a40f381a5d08ce3259dreed@google.com     CheckerManager::CheckCallFunc(checker, _checkCall<CHECKER>));
18083226976b532141b26ff3a40f381a5d08ce3259dreed@google.com  }
18183226976b532141b26ff3a40f381a5d08ce3259dreed@google.com};
18283226976b532141b26ff3a40f381a5d08ce3259dreed@google.com
18383226976b532141b26ff3a40f381a5d08ce3259dreed@google.comclass Location {
18483226976b532141b26ff3a40f381a5d08ce3259dreed@google.com  template <typename CHECKER>
18583226976b532141b26ff3a40f381a5d08ce3259dreed@google.com  static void _checkLocation(void *checker,
18683226976b532141b26ff3a40f381a5d08ce3259dreed@google.com                             const SVal &location, bool isLoad, const Stmt *S,
187d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com                             CheckerContext &C) {
18883226976b532141b26ff3a40f381a5d08ce3259dreed@google.com    ((const CHECKER *)checker)->checkLocation(location, isLoad, S, C);
18983226976b532141b26ff3a40f381a5d08ce3259dreed@google.com  }
19083226976b532141b26ff3a40f381a5d08ce3259dreed@google.com
19183226976b532141b26ff3a40f381a5d08ce3259dreed@google.compublic:
19283226976b532141b26ff3a40f381a5d08ce3259dreed@google.com  template <typename CHECKER>
193e4fafb146e85cdfcf9d5418597b6818aa0754adatfarina@chromium.org  static void _register(CHECKER *checker, CheckerManager &mgr) {
194e94b5e40c5fb0e36eebcae1abfe04b9bc33583f4junov@chromium.org    mgr._registerForLocation(
195e94b5e40c5fb0e36eebcae1abfe04b9bc33583f4junov@chromium.org           CheckerManager::CheckLocationFunc(checker, _checkLocation<CHECKER>));
196e94b5e40c5fb0e36eebcae1abfe04b9bc33583f4junov@chromium.org  }
197};
198
199class Bind {
200  template <typename CHECKER>
201  static void _checkBind(void *checker,
202                         const SVal &location, const SVal &val, const Stmt *S,
203                         CheckerContext &C) {
204    ((const CHECKER *)checker)->checkBind(location, val, S, C);
205  }
206
207public:
208  template <typename CHECKER>
209  static void _register(CHECKER *checker, CheckerManager &mgr) {
210    mgr._registerForBind(
211           CheckerManager::CheckBindFunc(checker, _checkBind<CHECKER>));
212  }
213};
214
215class EndAnalysis {
216  template <typename CHECKER>
217  static void _checkEndAnalysis(void *checker, ExplodedGraph &G,
218                                BugReporter &BR, ExprEngine &Eng) {
219    ((const CHECKER *)checker)->checkEndAnalysis(G, BR, Eng);
220  }
221
222public:
223  template <typename CHECKER>
224  static void _register(CHECKER *checker, CheckerManager &mgr) {
225    mgr._registerForEndAnalysis(
226     CheckerManager::CheckEndAnalysisFunc(checker, _checkEndAnalysis<CHECKER>));
227  }
228};
229
230class EndFunction {
231  template <typename CHECKER>
232  static void _checkEndFunction(void *checker,
233                                CheckerContext &C) {
234    ((const CHECKER *)checker)->checkEndFunction(C);
235  }
236
237public:
238  template <typename CHECKER>
239  static void _register(CHECKER *checker, CheckerManager &mgr) {
240    mgr._registerForEndFunction(
241     CheckerManager::CheckEndFunctionFunc(checker, _checkEndFunction<CHECKER>));
242  }
243};
244
245class BranchCondition {
246  template <typename CHECKER>
247  static void _checkBranchCondition(void *checker, const Stmt *Condition,
248                                    CheckerContext & C) {
249    ((const CHECKER *)checker)->checkBranchCondition(Condition, C);
250  }
251
252public:
253  template <typename CHECKER>
254  static void _register(CHECKER *checker, CheckerManager &mgr) {
255    mgr._registerForBranchCondition(
256      CheckerManager::CheckBranchConditionFunc(checker,
257                                               _checkBranchCondition<CHECKER>));
258  }
259};
260
261class LiveSymbols {
262  template <typename CHECKER>
263  static void _checkLiveSymbols(void *checker, ProgramStateRef state,
264                                SymbolReaper &SR) {
265    ((const CHECKER *)checker)->checkLiveSymbols(state, SR);
266  }
267
268public:
269  template <typename CHECKER>
270  static void _register(CHECKER *checker, CheckerManager &mgr) {
271    mgr._registerForLiveSymbols(
272     CheckerManager::CheckLiveSymbolsFunc(checker, _checkLiveSymbols<CHECKER>));
273  }
274};
275
276class DeadSymbols {
277  template <typename CHECKER>
278  static void _checkDeadSymbols(void *checker,
279                                SymbolReaper &SR, CheckerContext &C) {
280    ((const CHECKER *)checker)->checkDeadSymbols(SR, C);
281  }
282
283public:
284  template <typename CHECKER>
285  static void _register(CHECKER *checker, CheckerManager &mgr) {
286    mgr._registerForDeadSymbols(
287     CheckerManager::CheckDeadSymbolsFunc(checker, _checkDeadSymbols<CHECKER>));
288  }
289};
290
291class RegionChanges {
292  template <typename CHECKER>
293  static ProgramStateRef
294  _checkRegionChanges(void *checker,
295                      ProgramStateRef state,
296                      const InvalidatedSymbols *invalidated,
297                      ArrayRef<const MemRegion *> Explicits,
298                      ArrayRef<const MemRegion *> Regions,
299                      const CallEvent *Call) {
300    return ((const CHECKER *)checker)->checkRegionChanges(state, invalidated,
301                                                      Explicits, Regions, Call);
302  }
303  template <typename CHECKER>
304  static bool _wantsRegionChangeUpdate(void *checker,
305                                       ProgramStateRef state) {
306    return ((const CHECKER *)checker)->wantsRegionChangeUpdate(state);
307  }
308
309public:
310  template <typename CHECKER>
311  static void _register(CHECKER *checker, CheckerManager &mgr) {
312    mgr._registerForRegionChanges(
313          CheckerManager::CheckRegionChangesFunc(checker,
314                                                 _checkRegionChanges<CHECKER>),
315          CheckerManager::WantsRegionChangeUpdateFunc(checker,
316                                            _wantsRegionChangeUpdate<CHECKER>));
317  }
318};
319
320class PointerEscape {
321  template <typename CHECKER>
322  static ProgramStateRef
323  _checkPointerEscape(void *Checker,
324                     ProgramStateRef State,
325                     const InvalidatedSymbols &Escaped,
326                     const CallEvent *Call,
327                     PointerEscapeKind Kind,
328                     RegionAndSymbolInvalidationTraits *ETraits) {
329
330    if (!ETraits)
331      return ((const CHECKER *)Checker)->checkPointerEscape(State,
332                                                            Escaped,
333                                                            Call,
334                                                            Kind);
335
336    InvalidatedSymbols RegularEscape;
337    for (InvalidatedSymbols::const_iterator I = Escaped.begin(),
338                                            E = Escaped.end(); I != E; ++I)
339      if (!ETraits->hasTrait(*I,
340              RegionAndSymbolInvalidationTraits::TK_PreserveContents) &&
341          !ETraits->hasTrait(*I,
342              RegionAndSymbolInvalidationTraits::TK_SuppressEscape))
343        RegularEscape.insert(*I);
344
345    if (RegularEscape.empty())
346      return State;
347
348    return ((const CHECKER *)Checker)->checkPointerEscape(State,
349                                                          RegularEscape,
350                                                          Call,
351                                                          Kind);
352  }
353
354public:
355  template <typename CHECKER>
356  static void _register(CHECKER *checker, CheckerManager &mgr) {
357    mgr._registerForPointerEscape(
358          CheckerManager::CheckPointerEscapeFunc(checker,
359                                                _checkPointerEscape<CHECKER>));
360  }
361};
362
363class ConstPointerEscape {
364  template <typename CHECKER>
365  static ProgramStateRef
366  _checkConstPointerEscape(void *Checker,
367                      ProgramStateRef State,
368                      const InvalidatedSymbols &Escaped,
369                      const CallEvent *Call,
370                      PointerEscapeKind Kind,
371                      RegionAndSymbolInvalidationTraits *ETraits) {
372
373    if (!ETraits)
374      return State;
375
376    InvalidatedSymbols ConstEscape;
377    for (InvalidatedSymbols::const_iterator I = Escaped.begin(),
378                                            E = Escaped.end(); I != E; ++I)
379      if (ETraits->hasTrait(*I,
380              RegionAndSymbolInvalidationTraits::TK_PreserveContents) &&
381          !ETraits->hasTrait(*I,
382              RegionAndSymbolInvalidationTraits::TK_SuppressEscape))
383        ConstEscape.insert(*I);
384
385    if (ConstEscape.empty())
386      return State;
387
388    return ((const CHECKER *)Checker)->checkConstPointerEscape(State,
389                                                               ConstEscape,
390                                                               Call,
391                                                               Kind);
392  }
393
394public:
395  template <typename CHECKER>
396  static void _register(CHECKER *checker, CheckerManager &mgr) {
397    mgr._registerForPointerEscape(
398      CheckerManager::CheckPointerEscapeFunc(checker,
399                                            _checkConstPointerEscape<CHECKER>));
400  }
401};
402
403
404template <typename EVENT>
405class Event {
406  template <typename CHECKER>
407  static void _checkEvent(void *checker, const void *event) {
408    ((const CHECKER *)checker)->checkEvent(*(const EVENT *)event);
409  }
410public:
411  template <typename CHECKER>
412  static void _register(CHECKER *checker, CheckerManager &mgr) {
413    mgr._registerListenerForEvent<EVENT>(
414                 CheckerManager::CheckEventFunc(checker, _checkEvent<CHECKER>));
415  }
416};
417
418} // end check namespace
419
420namespace eval {
421
422class Assume {
423  template <typename CHECKER>
424  static ProgramStateRef _evalAssume(void *checker,
425                                         ProgramStateRef state,
426                                         const SVal &cond,
427                                         bool assumption) {
428    return ((const CHECKER *)checker)->evalAssume(state, cond, assumption);
429  }
430
431public:
432  template <typename CHECKER>
433  static void _register(CHECKER *checker, CheckerManager &mgr) {
434    mgr._registerForEvalAssume(
435                 CheckerManager::EvalAssumeFunc(checker, _evalAssume<CHECKER>));
436  }
437};
438
439class Call {
440  template <typename CHECKER>
441  static bool _evalCall(void *checker, const CallExpr *CE, CheckerContext &C) {
442    return ((const CHECKER *)checker)->evalCall(CE, C);
443  }
444
445public:
446  template <typename CHECKER>
447  static void _register(CHECKER *checker, CheckerManager &mgr) {
448    mgr._registerForEvalCall(
449                     CheckerManager::EvalCallFunc(checker, _evalCall<CHECKER>));
450  }
451};
452
453} // end eval namespace
454
455class CheckerBase : public ProgramPointTag {
456  CheckName Name;
457  friend class ::clang::ento::CheckerManager;
458
459public:
460  StringRef getTagDescription() const override;
461  CheckName getCheckName() const;
462
463  /// See CheckerManager::runCheckersForPrintState.
464  virtual void printState(raw_ostream &Out, ProgramStateRef State,
465                          const char *NL, const char *Sep) const { }
466};
467
468/// Dump checker name to stream.
469raw_ostream& operator<<(raw_ostream &Out, const CheckerBase &Checker);
470
471/// Tag that can use a checker name as a message provider
472/// (see SimpleProgramPointTag).
473class CheckerProgramPointTag : public SimpleProgramPointTag {
474public:
475  CheckerProgramPointTag(StringRef CheckerName, StringRef Msg);
476  CheckerProgramPointTag(const CheckerBase *Checker, StringRef Msg);
477};
478
479template <typename CHECK1, typename CHECK2=check::_VoidCheck,
480          typename CHECK3=check::_VoidCheck, typename CHECK4=check::_VoidCheck,
481          typename CHECK5=check::_VoidCheck, typename CHECK6=check::_VoidCheck,
482          typename CHECK7=check::_VoidCheck, typename CHECK8=check::_VoidCheck,
483          typename CHECK9=check::_VoidCheck, typename CHECK10=check::_VoidCheck,
484          typename CHECK11=check::_VoidCheck,typename CHECK12=check::_VoidCheck,
485          typename CHECK13=check::_VoidCheck,typename CHECK14=check::_VoidCheck,
486          typename CHECK15=check::_VoidCheck,typename CHECK16=check::_VoidCheck,
487          typename CHECK17=check::_VoidCheck,typename CHECK18=check::_VoidCheck,
488          typename CHECK19=check::_VoidCheck,typename CHECK20=check::_VoidCheck,
489          typename CHECK21=check::_VoidCheck,typename CHECK22=check::_VoidCheck,
490          typename CHECK23=check::_VoidCheck,typename CHECK24=check::_VoidCheck>
491class Checker;
492
493template <>
494class Checker<check::_VoidCheck>
495  : public CheckerBase
496{
497  virtual void anchor();
498public:
499  static void _register(void *checker, CheckerManager &mgr) { }
500};
501
502template <typename CHECK1, typename CHECK2, typename CHECK3, typename CHECK4,
503          typename CHECK5, typename CHECK6, typename CHECK7, typename CHECK8,
504          typename CHECK9, typename CHECK10,typename CHECK11,typename CHECK12,
505          typename CHECK13,typename CHECK14,typename CHECK15,typename CHECK16,
506          typename CHECK17,typename CHECK18,typename CHECK19,typename CHECK20,
507          typename CHECK21,typename CHECK22,typename CHECK23,typename CHECK24>
508class Checker
509    : public CHECK1,
510      public Checker<CHECK2, CHECK3, CHECK4, CHECK5, CHECK6, CHECK7,
511                     CHECK8, CHECK9, CHECK10,CHECK11,CHECK12,CHECK13,
512                     CHECK14,CHECK15,CHECK16,CHECK17,CHECK18,CHECK19,
513                     CHECK20,CHECK21,CHECK22,CHECK23,CHECK24> {
514public:
515  template <typename CHECKER>
516  static void _register(CHECKER *checker, CheckerManager &mgr) {
517    CHECK1::_register(checker, mgr);
518    Checker<CHECK2, CHECK3, CHECK4, CHECK5, CHECK6, CHECK7,
519            CHECK8, CHECK9, CHECK10,CHECK11,CHECK12,CHECK13,
520            CHECK14,CHECK15,CHECK16,CHECK17,CHECK18,CHECK19,
521            CHECK20,CHECK21,CHECK22,CHECK23,CHECK24>::_register(checker, mgr);
522  }
523};
524
525template <typename EVENT>
526class EventDispatcher {
527  CheckerManager *Mgr;
528public:
529  EventDispatcher() : Mgr(nullptr) { }
530
531  template <typename CHECKER>
532  static void _register(CHECKER *checker, CheckerManager &mgr) {
533    mgr._registerDispatcherForEvent<EVENT>();
534    static_cast<EventDispatcher<EVENT> *>(checker)->Mgr = &mgr;
535  }
536
537  void dispatchEvent(const EVENT &event) const {
538    Mgr->_dispatchEvent(event);
539  }
540};
541
542/// \brief We dereferenced a location that may be null.
543struct ImplicitNullDerefEvent {
544  SVal Location;
545  bool IsLoad;
546  ExplodedNode *SinkNode;
547  BugReporter *BR;
548};
549
550/// \brief A helper class which wraps a boolean value set to false by default.
551///
552/// This class should behave exactly like 'bool' except that it doesn't need to
553/// be explicitly initialized.
554struct DefaultBool {
555  bool val;
556  DefaultBool() : val(false) {}
557  /*implicit*/ operator bool&() { return val; }
558  /*implicit*/ operator const bool&() const { return val; }
559  DefaultBool &operator=(bool b) { val = b; return *this; }
560};
561
562} // end ento namespace
563
564} // end clang namespace
565
566#endif
567