blob: b753ec36504daf56f612d09b792fd6e5ef6e80ea [file] [log] [blame]
Argyrios Kyrtzidis556c45e2011-02-14 18:13:31 +00001//===--- CheckerRegistration.cpp - Registration for the Analyzer Checkers -===//
2//
Chandler Carruth2946cd72019-01-19 08:50:56 +00003// 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
Argyrios Kyrtzidis556c45e2011-02-14 18:13:31 +00006//
7//===----------------------------------------------------------------------===//
8//
9// Defines the registration function for the analyzer checkers.
10//
11//===----------------------------------------------------------------------===//
12
Argyrios Kyrtzidis6fa0d202011-02-15 16:54:12 +000013#include "clang/StaticAnalyzer/Frontend/CheckerRegistration.h"
Chandler Carruth3a022472012-12-04 09:13:33 +000014#include "clang/Basic/Diagnostic.h"
15#include "clang/Frontend/FrontendDiagnostic.h"
Chandler Carruth3a022472012-12-04 09:13:33 +000016#include "clang/StaticAnalyzer/Core/AnalyzerOptions.h"
Argyrios Kyrtzidis556c45e2011-02-14 18:13:31 +000017#include "clang/StaticAnalyzer/Core/CheckerManager.h"
Kristof Umann76a21502018-12-15 16:23:51 +000018#include "clang/StaticAnalyzer/Frontend/CheckerRegistry.h"
Chandler Carruth3a022472012-12-04 09:13:33 +000019#include "clang/StaticAnalyzer/Frontend/FrontendActions.h"
Chandler Carruth3a022472012-12-04 09:13:33 +000020#include "llvm/ADT/SmallVector.h"
Kristof Umannf1f351c2018-11-02 15:59:37 +000021#include "llvm/Support/FormattedStream.h"
Argyrios Kyrtzidis17bee3e2011-02-25 00:09:51 +000022#include "llvm/Support/raw_ostream.h"
Ahmed Charlesdfca6f92014-03-09 11:36:40 +000023#include <memory>
Argyrios Kyrtzidis556c45e2011-02-14 18:13:31 +000024
25using namespace clang;
26using namespace ento;
Jordy Rose075d73b2011-08-17 04:56:03 +000027
Alexander Kornienkod00ed8e2018-06-27 14:56:12 +000028std::unique_ptr<CheckerManager> ento::createCheckerManager(
George Karpenkov4ece68a2018-08-06 23:09:07 +000029 ASTContext &context,
30 AnalyzerOptions &opts,
Alexander Kornienkod00ed8e2018-06-27 14:56:12 +000031 ArrayRef<std::string> plugins,
32 ArrayRef<std::function<void(CheckerRegistry &)>> checkerRegistrationFns,
33 DiagnosticsEngine &diags) {
George Karpenkov4ece68a2018-08-06 23:09:07 +000034 auto checkerMgr = llvm::make_unique<CheckerManager>(context, opts);
Argyrios Kyrtzidis556c45e2011-02-14 18:13:31 +000035
Kristof Umann058a7a42019-01-26 14:23:08 +000036 CheckerRegistry allCheckers(plugins, diags, context.getLangOpts());
Alexander Kornienkod00ed8e2018-06-27 14:56:12 +000037
38 for (const auto &Fn : checkerRegistrationFns)
39 Fn(allCheckers);
40
Kristof Umannb0be2ab2018-12-15 18:11:49 +000041 allCheckers.initializeManager(*checkerMgr, opts);
42 allCheckers.validateCheckerOptions(opts);
Argyrios Kyrtzidisa15dfec2011-02-28 17:36:09 +000043 checkerMgr->finishedCheckerRegistration();
44
Richard Trieud4b05ce2015-01-17 00:46:55 +000045 return checkerMgr;
Argyrios Kyrtzidis556c45e2011-02-14 18:13:31 +000046}
Argyrios Kyrtzidis17bee3e2011-02-25 00:09:51 +000047
Kristof Umannb0be2ab2018-12-15 18:11:49 +000048void ento::printCheckerHelp(raw_ostream &out, ArrayRef<std::string> plugins,
Kristof Umann058a7a42019-01-26 14:23:08 +000049 DiagnosticsEngine &diags,
50 const LangOptions &langOpts) {
Jordy Rose59cce712011-08-16 21:24:21 +000051 out << "OVERVIEW: Clang Static Analyzer Checkers List\n\n";
52 out << "USAGE: -analyzer-checker <CHECKER or PACKAGE,...>\n\n";
Argyrios Kyrtzidis17bee3e2011-02-25 00:09:51 +000053
Kristof Umann058a7a42019-01-26 14:23:08 +000054 CheckerRegistry(plugins, diags, langOpts).printHelp(out);
Argyrios Kyrtzidis17bee3e2011-02-25 00:09:51 +000055}
Gabor Horvathc4309902016-08-08 13:41:04 +000056
57void ento::printEnabledCheckerList(raw_ostream &out,
58 ArrayRef<std::string> plugins,
Kristof Umannf282d272018-12-15 15:44:05 +000059 const AnalyzerOptions &opts,
Kristof Umann058a7a42019-01-26 14:23:08 +000060 DiagnosticsEngine &diags,
61 const LangOptions &langOpts) {
Gabor Horvathc4309902016-08-08 13:41:04 +000062 out << "OVERVIEW: Clang Static Analyzer Enabled Checkers List\n\n";
63
Kristof Umann058a7a42019-01-26 14:23:08 +000064 CheckerRegistry(plugins, diags, langOpts).printList(out, opts);
Gabor Horvathc4309902016-08-08 13:41:04 +000065}
Kristof Umannf1f351c2018-11-02 15:59:37 +000066
67void ento::printAnalyzerConfigList(raw_ostream &out) {
68 out << "OVERVIEW: Clang Static Analyzer -analyzer-config Option List\n\n";
69 out << "USAGE: clang -cc1 [CLANG_OPTIONS] -analyzer-config "
70 "<OPTION1=VALUE,OPTION2=VALUE,...>\n\n";
71 out << " clang -cc1 [CLANG_OPTIONS] -analyzer-config OPTION1=VALUE, "
72 "-analyzer-config OPTION2=VALUE, ...\n\n";
73 out << " clang [CLANG_OPTIONS] -Xclang -analyzer-config -Xclang"
74 "<OPTION1=VALUE,OPTION2=VALUE,...>\n\n";
75 out << " clang [CLANG_OPTIONS] -Xclang -analyzer-config -Xclang "
76 "OPTION1=VALUE, -Xclang -analyzer-config -Xclang "
77 "OPTION2=VALUE, ...\n\n";
78 out << "OPTIONS:\n\n";
79
80 using OptionAndDescriptionTy = std::pair<StringRef, std::string>;
81 OptionAndDescriptionTy PrintableOptions[] = {
82#define ANALYZER_OPTION(TYPE, NAME, CMDFLAG, DESC, DEFAULT_VAL) \
83 { \
84 CMDFLAG, \
85 llvm::Twine(llvm::Twine() + "(" + \
Kristof Umann37829b52018-11-02 19:48:56 +000086 (StringRef(#TYPE) == "StringRef" ? "string" : #TYPE ) + \
87 ") " DESC \
Kristof Umannf1f351c2018-11-02 15:59:37 +000088 " (default: " #DEFAULT_VAL ")").str() \
89 },
90
91#define ANALYZER_OPTION_DEPENDS_ON_USER_MODE(TYPE, NAME, CMDFLAG, DESC, \
92 SHALLOW_VAL, DEEP_VAL) \
93 { \
94 CMDFLAG, \
95 llvm::Twine(llvm::Twine() + "(" + \
Kristof Umann37829b52018-11-02 19:48:56 +000096 (StringRef(#TYPE) == "StringRef" ? "string" : #TYPE ) + \
97 ") " DESC \
Kristof Umannf1f351c2018-11-02 15:59:37 +000098 " (default: " #SHALLOW_VAL " in shallow mode, " #DEEP_VAL \
99 " in deep mode)").str() \
100 },
101#include "clang/StaticAnalyzer/Core/AnalyzerOptions.def"
102#undef ANALYZER_OPTION
103#undef ANALYZER_OPTION_DEPENDS_ON_USER_MODE
104 };
105
106 llvm::sort(PrintableOptions, [](const OptionAndDescriptionTy &LHS,
107 const OptionAndDescriptionTy &RHS) {
108 return LHS.first < RHS.first;
109 });
110
111 constexpr size_t MinLineWidth = 70;
112 constexpr size_t PadForOpt = 2;
113 constexpr size_t OptionWidth = 30;
114 constexpr size_t PadForDesc = PadForOpt + OptionWidth;
115 static_assert(MinLineWidth > PadForDesc, "MinLineWidth must be greater!");
116
117 llvm::formatted_raw_ostream FOut(out);
118
119 for (const auto &Pair : PrintableOptions) {
120 FOut.PadToColumn(PadForOpt) << Pair.first;
121
122 // If the buffer's length is greater then PadForDesc, print a newline.
123 if (FOut.getColumn() > PadForDesc)
124 FOut << '\n';
125
126 FOut.PadToColumn(PadForDesc);
127
128 for (char C : Pair.second) {
129 if (FOut.getColumn() > MinLineWidth && C == ' ') {
130 FOut << '\n';
131 FOut.PadToColumn(PadForDesc);
132 continue;
133 }
134 FOut << C;
135 }
136 FOut << "\n\n";
137 }
138}