CheckerRegistration.cpp revision 5705a40c7ec62f1a903bf26e1e6a7f91b5b98ba3
118a1444b4f1e6a0948fd38fa0de382d86cfe04deBernhard Rosenkränzer//===--- CheckerRegistration.cpp - Registration for the Analyzer Checkers -===//
218a1444b4f1e6a0948fd38fa0de382d86cfe04deBernhard Rosenkränzer//
318a1444b4f1e6a0948fd38fa0de382d86cfe04deBernhard Rosenkränzer//                     The LLVM Compiler Infrastructure
418a1444b4f1e6a0948fd38fa0de382d86cfe04deBernhard Rosenkränzer//
518a1444b4f1e6a0948fd38fa0de382d86cfe04deBernhard Rosenkränzer// This file is distributed under the University of Illinois Open Source
618a1444b4f1e6a0948fd38fa0de382d86cfe04deBernhard Rosenkränzer// License. See LICENSE.TXT for details.
718a1444b4f1e6a0948fd38fa0de382d86cfe04deBernhard Rosenkränzer//
8e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall//===----------------------------------------------------------------------===//
9e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall//
1018a1444b4f1e6a0948fd38fa0de382d86cfe04deBernhard Rosenkränzer// Defines the registration function for the analyzer checkers.
11e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall//
12e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall//===----------------------------------------------------------------------===//
13e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall
14e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#include "clang/StaticAnalyzer/Frontend/CheckerRegistration.h"
15e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#include "clang/StaticAnalyzer/Frontend/FrontendActions.h"
16e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#include "clang/StaticAnalyzer/Checkers/ClangCheckers.h"
17e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#include "clang/StaticAnalyzer/Core/CheckerManager.h"
18e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#include "clang/StaticAnalyzer/Core/CheckerOptInfo.h"
19e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#include "clang/StaticAnalyzer/Core/CheckerRegistry.h"
20e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#include "clang/StaticAnalyzer/AnalyzerOptions.h"
21e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#include "clang/Frontend/FrontendDiagnostic.h"
22e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#include "clang/Basic/Diagnostic.h"
23e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#include "llvm/Support/DynamicLibrary.h"
24e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#include "llvm/Support/Path.h"
25e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#include "llvm/Support/raw_ostream.h"
26e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#include "llvm/ADT/OwningPtr.h"
27e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#include "llvm/ADT/SmallVector.h"
28e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall
29e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallusing namespace clang;
30e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallusing namespace ento;
31e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallusing llvm::sys::DynamicLibrary;
32e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall
33e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallnamespace {
34e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallclass ClangCheckerRegistry : public CheckerRegistry {
35e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall  typedef void (*RegisterCheckersFn)(CheckerRegistry &);
36e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall
37e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall  static bool isCompatibleAPIVersion(const char *versionString);
38e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall  static void warnIncompatible(DiagnosticsEngine *diags, StringRef pluginPath,
39e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall                               const char *pluginAPIVersion);
40e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall
41e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallpublic:
42e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall  ClangCheckerRegistry(ArrayRef<std::string> plugins,
43e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall                       DiagnosticsEngine *diags = 0);
44e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall};
45e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall
46e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall} // end anonymous namespace
47e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall
48e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP AbgrallClangCheckerRegistry::ClangCheckerRegistry(ArrayRef<std::string> plugins,
49e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall                                           DiagnosticsEngine *diags) {
50e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall  registerBuiltinCheckers(*this);
51e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall
52e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall  for (ArrayRef<std::string>::iterator i = plugins.begin(), e = plugins.end();
53e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall       i != e; ++i) {
54e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall    // Get access to the plugin.
55e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall    DynamicLibrary lib = DynamicLibrary::getPermanentLibrary(i->c_str());
56e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall
57e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall    // See if it's compatible with this build of clang.
58e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall    const char *pluginAPIVersion =
59e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall      (const char *) lib.getAddressOfSymbol("clang_analyzerAPIVersionString");
60e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall    if (!isCompatibleAPIVersion(pluginAPIVersion)) {
61e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall      warnIncompatible(diags, *i, pluginAPIVersion);
62e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall      continue;
63e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall    }
64e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall
65e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall    // Register its checkers.
66e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall    RegisterCheckersFn registerPluginCheckers =
67e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall      (RegisterCheckersFn) (intptr_t) lib.getAddressOfSymbol(
68e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall                                                      "clang_registerCheckers");
69e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall    if (registerPluginCheckers)
70e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall      registerPluginCheckers(*this);
71e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall  }
72e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall}
73e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall
74e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallbool ClangCheckerRegistry::isCompatibleAPIVersion(const char *versionString) {
75e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall  // If the version string is null, it's not an analyzer plugin.
76e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall  if (versionString == 0)
77e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall    return false;
78e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall
79e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall  // For now, none of the static analyzer API is considered stable.
80e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall  // Versions must match exactly.
81e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall  if (strcmp(versionString, CLANG_ANALYZER_API_VERSION_STRING) == 0)
82e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall    return true;
83e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall
84e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall  return false;
85e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall}
86e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall
87e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallvoid ClangCheckerRegistry::warnIncompatible(DiagnosticsEngine *diags,
88e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall                                            StringRef pluginPath,
89e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall                                            const char *pluginAPIVersion) {
90e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall  if (!diags)
91e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall    return;
92e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall  if (!pluginAPIVersion)
93e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall    return;
94e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall
95e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall  diags->Report(diag::warn_incompatible_analyzer_plugin_api)
96e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall      << llvm::sys::path::filename(pluginPath);
97e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall  diags->Report(diag::note_incompatible_analyzer_plugin_api)
98e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall      << CLANG_ANALYZER_API_VERSION_STRING
99e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall      << pluginAPIVersion;
100e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall}
101e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall
102e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall
103e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP AbgrallCheckerManager *ento::createCheckerManager(const AnalyzerOptions &opts,
104e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall                                           const LangOptions &langOpts,
105e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall                                           ArrayRef<std::string> plugins,
106e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall                                           DiagnosticsEngine &diags) {
107e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall  OwningPtr<CheckerManager> checkerMgr(new CheckerManager(langOpts));
108e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall
109e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall  SmallVector<CheckerOptInfo, 8> checkerOpts;
110e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall  for (unsigned i = 0, e = opts.CheckersControlList.size(); i != e; ++i) {
111e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall    const std::pair<std::string, bool> &opt = opts.CheckersControlList[i];
112e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall    checkerOpts.push_back(CheckerOptInfo(opt.first.c_str(), opt.second));
113e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall  }
114e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall
115e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall  ClangCheckerRegistry allCheckers(plugins, &diags);
116e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall  allCheckers.initializeManager(*checkerMgr, checkerOpts);
117e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall  checkerMgr->finishedCheckerRegistration();
118e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall
119e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall  for (unsigned i = 0, e = checkerOpts.size(); i != e; ++i) {
120e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall    if (checkerOpts[i].isUnclaimed())
121e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall      diags.Report(diag::err_unknown_analyzer_checker)
122e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall          << checkerOpts[i].getName();
123e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall  }
124e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall
125e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall  return checkerMgr.take();
126e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall}
127e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall
128e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallvoid ento::printCheckerHelp(raw_ostream &out, ArrayRef<std::string> plugins) {
129e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall  out << "OVERVIEW: Clang Static Analyzer Checkers List\n\n";
130e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall  out << "USAGE: -analyzer-checker <CHECKER or PACKAGE,...>\n\n";
131e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall
132e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall  ClangCheckerRegistry(plugins).printHelp(out);
133e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall}
134e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall