
If you were around the analyzer for a while now, you must've seen a lot of patches that awkwardly puts code from one library to the other: * D75360 moves the constructors of CheckerManager, which lies in the Core library, to the Frontend library. Most the patch itself was a struggle along the library lines. * D78126 had to be reverted because dependency information would be utilized in the Core library, but the actual data lied in the frontend. D78126#inline-751477 touches on this issue as well. This stems from the often mentioned problem: the Frontend library depends on Core and Checkers, Checkers depends on Core. The checker registry functions (`registerMallocChecker`, etc) lie in the Checkers library in order to keep each checker its own module. What this implies is that checker registration cannot take place in the Core, but the Core might still want to use the data that results from it (which checker/package is enabled, dependencies, etc). D54436 was the patch that initiated this. Back in the days when CheckerRegistry was super dumb and buggy, it implemented a non-documented solution to this problem by keeping the data in the Core, and leaving the logic in the Frontend. At the time when the patch landed, the merger to the Frontend made sense, because the data hadn't been utilized anywhere, and the whole workaround without any documentation made little sense to me. So, lets put the data back where it belongs, in the Core library. This patch introduces `CheckerRegistryData`, and turns `CheckerRegistry` into a short lived wrapper around this data that implements the logic of checker registration. The data is tied to CheckerManager because it is required to parse it. Side note: I can't help but cringe at the fact how ridiculously awkward the library lines are. I feel like I'm thinking too much inside the box, but I guess this is just the price of keeping the checkers so modularized. Differential Revision: https://reviews.llvm.org/D82585
116 lines
5.0 KiB
C++
116 lines
5.0 KiB
C++
//===--- CheckerRegistration.cpp - Registration for the Analyzer Checkers -===//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// Defines the registration function for the analyzer checkers.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "clang/StaticAnalyzer/Frontend/AnalyzerHelpFlags.h"
|
|
#include "clang/Basic/Diagnostic.h"
|
|
#include "clang/Frontend/CompilerInstance.h"
|
|
#include "clang/Frontend/FrontendDiagnostic.h"
|
|
#include "clang/StaticAnalyzer/Core/AnalyzerOptions.h"
|
|
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
|
|
#include "clang/StaticAnalyzer/Frontend/CheckerRegistry.h"
|
|
#include "clang/StaticAnalyzer/Frontend/FrontendActions.h"
|
|
#include "llvm/ADT/SmallVector.h"
|
|
#include "llvm/Support/raw_ostream.h"
|
|
#include <memory>
|
|
|
|
using namespace clang;
|
|
using namespace ento;
|
|
|
|
void ento::printCheckerHelp(raw_ostream &out, CompilerInstance &CI) {
|
|
out << "OVERVIEW: Clang Static Analyzer Checkers List\n\n";
|
|
out << "USAGE: -analyzer-checker <CHECKER or PACKAGE,...>\n\n";
|
|
|
|
auto CheckerMgr = std::make_unique<CheckerManager>(
|
|
*CI.getAnalyzerOpts(), CI.getLangOpts(), CI.getDiagnostics(),
|
|
CI.getFrontendOpts().Plugins);
|
|
|
|
CheckerMgr->getCheckerRegistryData().printCheckerWithDescList(
|
|
*CI.getAnalyzerOpts(), out);
|
|
}
|
|
|
|
void ento::printEnabledCheckerList(raw_ostream &out, CompilerInstance &CI) {
|
|
out << "OVERVIEW: Clang Static Analyzer Enabled Checkers List\n\n";
|
|
|
|
auto CheckerMgr = std::make_unique<CheckerManager>(
|
|
*CI.getAnalyzerOpts(), CI.getLangOpts(), CI.getDiagnostics(),
|
|
CI.getFrontendOpts().Plugins);
|
|
|
|
CheckerMgr->getCheckerRegistryData().printEnabledCheckerList(out);
|
|
}
|
|
|
|
void ento::printCheckerConfigList(raw_ostream &out, CompilerInstance &CI) {
|
|
|
|
auto CheckerMgr = std::make_unique<CheckerManager>(
|
|
*CI.getAnalyzerOpts(), CI.getLangOpts(), CI.getDiagnostics(),
|
|
CI.getFrontendOpts().Plugins);
|
|
|
|
CheckerMgr->getCheckerRegistryData().printCheckerOptionList(
|
|
*CI.getAnalyzerOpts(), out);
|
|
}
|
|
|
|
void ento::printAnalyzerConfigList(raw_ostream &out) {
|
|
// FIXME: This message sounds scary, should be scary, but incorrectly states
|
|
// that all configs are super dangerous. In reality, many of them should be
|
|
// accessible to the user. We should create a user-facing subset of config
|
|
// options under a different frontend flag.
|
|
out << R"(
|
|
OVERVIEW: Clang Static Analyzer -analyzer-config Option List
|
|
|
|
The following list of configurations are meant for development purposes only, as
|
|
some of the variables they define are set to result in the most optimal
|
|
analysis. Setting them to other values may drastically change how the analyzer
|
|
behaves, and may even result in instabilities, crashes!
|
|
|
|
USAGE: -analyzer-config <OPTION1=VALUE,OPTION2=VALUE,...>
|
|
-analyzer-config OPTION1=VALUE, -analyzer-config OPTION2=VALUE, ...
|
|
OPTIONS:
|
|
)";
|
|
|
|
using OptionAndDescriptionTy = std::pair<StringRef, std::string>;
|
|
OptionAndDescriptionTy PrintableOptions[] = {
|
|
#define ANALYZER_OPTION(TYPE, NAME, CMDFLAG, DESC, DEFAULT_VAL) \
|
|
{ \
|
|
CMDFLAG, \
|
|
llvm::Twine(llvm::Twine() + "(" + \
|
|
(StringRef(#TYPE) == "StringRef" ? "string" : #TYPE ) + \
|
|
") " DESC \
|
|
" (default: " #DEFAULT_VAL ")").str() \
|
|
},
|
|
|
|
#define ANALYZER_OPTION_DEPENDS_ON_USER_MODE(TYPE, NAME, CMDFLAG, DESC, \
|
|
SHALLOW_VAL, DEEP_VAL) \
|
|
{ \
|
|
CMDFLAG, \
|
|
llvm::Twine(llvm::Twine() + "(" + \
|
|
(StringRef(#TYPE) == "StringRef" ? "string" : #TYPE ) + \
|
|
") " DESC \
|
|
" (default: " #SHALLOW_VAL " in shallow mode, " #DEEP_VAL \
|
|
" in deep mode)").str() \
|
|
},
|
|
#include "clang/StaticAnalyzer/Core/AnalyzerOptions.def"
|
|
#undef ANALYZER_OPTION
|
|
#undef ANALYZER_OPTION_DEPENDS_ON_USER_MODE
|
|
};
|
|
|
|
llvm::sort(PrintableOptions, [](const OptionAndDescriptionTy &LHS,
|
|
const OptionAndDescriptionTy &RHS) {
|
|
return LHS.first < RHS.first;
|
|
});
|
|
|
|
for (const auto &Pair : PrintableOptions) {
|
|
AnalyzerOptions::printFormattedEntry(out, Pair, /*InitialPad*/ 2,
|
|
/*EntryWidth*/ 30,
|
|
/*MinLineWidth*/ 70);
|
|
out << "\n\n";
|
|
}
|
|
}
|