18 #include "../ClangTidy.h"
19 #include "clang/Tooling/CommonOptionsParser.h"
20 #include "llvm/Support/Process.h"
22 using namespace clang::ast_matchers;
23 using namespace clang::driver;
24 using namespace clang::tooling;
29 static cl::extrahelp
CommonHelp(CommonOptionsParser::HelpMessage);
32 clang-tidy attempts to read configuration for each source file from a
33 .clang-tidy file located in the closest parent directory of the source
34 file. If any configuration options have a corresponding command-line
35 option, command-line option takes precedence. The effective
36 configuration can be inspected using -dump-config:
38 $ clang-tidy -dump-config - --
40 Checks: '-*,some-check'
43 AnalyzeTemporaryDtors: false
46 - key: some-check.SomeOption
56 static cl::opt<std::string>
Checks(
"checks", cl::desc(R
"(
57 Comma-separated list of globs with optional '-'
58 prefix. Globs are processed in order of
59 appearance in the list. Globs without '-'
60 prefix add checks with matching names to the
61 set, globs with the '-' prefix remove checks
62 with matching names from the set of enabled
63 checks. This option's value is appended to the
64 value of the 'Checks' option in .clang-tidy
69 static cl::opt<std::string>
WarningsAsErrors(
"warnings-as-errors", cl::desc(R
"(
70 Upgrades warnings to errors. Same format as
72 This option's value is appended to the value of
73 the 'WarningsAsErrors' option in .clang-tidy
79 static cl::opt<std::string>
HeaderFilter(
"header-filter", cl::desc(R
"(
80 Regular expression matching the names of the
81 headers to output diagnostics from. Diagnostics
82 from the main file of each translation unit are
84 Can be used together with -line-filter.
85 This option overrides the 'HeaderFilter' option
86 in .clang-tidy file, if any.
93 cl::desc(
"Display the errors from system headers."),
95 static cl::opt<std::string>
LineFilter(
"line-filter", cl::desc(R
"(
96 List of files with line ranges to filter the
97 warnings. Can be used together with
98 -header-filter. The format of the list is a
99 JSON array of objects:
101 {"name":"file1.cpp","lines":[[1,3],[5,7]]},
108 static cl::opt<bool>
Fix(
"fix", cl::desc(R
"(
109 Apply suggested fixes. Without -fix-errors
110 clang-tidy will bail out if any compilation
115 static cl::opt<bool>
FixErrors(
"fix-errors", cl::desc(R
"(
116 Apply suggested fixes even if compilation
117 errors were found. If compiler errors have
118 attached fix-its, clang-tidy will apply them as
123 static cl::opt<std::string>
FormatStyle(
"style", cl::desc(R
"(
124 Fallback style for reformatting after inserting fixes
125 if there is no clang-format config file found.
130 static cl::opt<bool>
ListChecks(
"list-checks", cl::desc(R
"(
131 List all enabled checks and exit. Use with
132 -checks=* to list all available checks.
136 static cl::opt<bool>
ExplainConfig(
"explain-config", cl::desc(R
"(
137 For each enabled check explains, where it is
138 enabled, i.e. in clang-tidy binary, command
139 line or a specific configuration file.
143 static cl::opt<std::string>
Config(
"config", cl::desc(R
"(
144 Specifies a configuration in YAML/JSON format:
145 -config="{Checks: '*',
146 CheckOptions: [{key: x,
148 When the value is empty, clang-tidy will
149 attempt to find a file named .clang-tidy for
150 each source file in its parent directories.
154 static cl::opt<bool>
DumpConfig(
"dump-config", cl::desc(R
"(
155 Dumps configuration in the YAML format to
156 stdout. This option can be used along with a
157 file name (and '--' if the file is outside of a
158 project with configured compilation database).
159 The configuration used for this file will be
161 Use along with -checks=* to include
162 configuration of all checks.
167 Enable per-check timing profiles, and print a
175 Enable temporary destructor-aware analysis in
176 clang-analyzer- checks.
177 This option overrides the value read from a
183 static cl::opt<std::string>
ExportFixes(
"export-fixes", cl::desc(R
"(
184 YAML file to store suggested fixes in. The
185 stored fixes can be applied to the input source
186 code with clang-apply-replacements.
188 cl::value_desc("filename"),
196 llvm::errs() <<
"Suppressed " << Stats.
errorsIgnored() <<
" warnings (";
197 StringRef Separator =
"";
204 <<
" due to line filter";
213 <<
" with check filters";
214 llvm::errs() <<
").\n";
216 llvm::errs() <<
"Use -header-filter=.* to display errors from all "
217 "non-system headers. Use -system-headers to display "
218 "errors from system headers as well.\n";
223 llvm::raw_ostream &OS) {
225 std::vector<std::pair<llvm::TimeRecord, StringRef>> Timers;
228 for (
const auto &P : Profile.Records) {
229 Timers.emplace_back(P.getValue(), P.getKey());
230 Total += P.getValue();
233 std::sort(Timers.begin(), Timers.end());
235 std::string
Line =
"===" + std::string(73,
'-') +
"===\n";
238 if (Total.getUserTime())
239 OS <<
" ---User Time---";
240 if (Total.getSystemTime())
241 OS <<
" --System Time--";
242 if (Total.getProcessTime())
243 OS <<
" --User+System--";
244 OS <<
" ---Wall Time---";
245 if (Total.getMemUsed())
247 OS <<
" --- Name ---\n";
250 for (
auto I = Timers.rbegin(), E = Timers.rend(); I != E; ++I) {
251 I->first.print(Total, OS);
252 OS << I->second <<
'\n';
255 Total.print(Total, OS);
262 ClangTidyGlobalOptions GlobalOptions;
264 llvm::errs() <<
"Invalid LineFilter: " << Err.message() <<
"\n\nUsage:\n";
265 llvm::cl::PrintHelpMessage(
false,
true);
269 ClangTidyOptions DefaultOptions;
271 DefaultOptions.WarningsAsErrors =
"";
275 DefaultOptions.User = llvm::sys::Process::GetEnv(
"USER");
277 if (!DefaultOptions.User)
278 DefaultOptions.User = llvm::sys::Process::GetEnv(
"USERNAME");
280 ClangTidyOptions OverrideOptions;
281 if (
Checks.getNumOccurrences() > 0)
282 OverrideOptions.Checks =
Checks;
293 if (llvm::ErrorOr<ClangTidyOptions> ParsedConfig =
295 return llvm::make_unique<ConfigOptionsProvider>(
297 ClangTidyOptions::getDefaults().mergeWith(DefaultOptions),
298 *ParsedConfig, OverrideOptions);
300 llvm::errs() <<
"Error: invalid configuration specified.\n"
301 << ParsedConfig.getError().message() <<
"\n";
305 return llvm::make_unique<FileOptionsProvider>(GlobalOptions, DefaultOptions,
314 if (!OptionsProvider)
317 StringRef FileName(
"dummy");
318 auto PathList = OptionsParser.getSourcePathList();
319 if (!PathList.empty()) {
320 FileName = PathList.front();
323 SmallString<256> FilePath(FileName);
324 if (std::error_code EC = llvm::sys::fs::make_absolute(FilePath)) {
325 llvm::errs() <<
"Can't make absolute path from " << FileName <<
": "
326 << EC.message() <<
"\n";
328 ClangTidyOptions EffectiveOptions = OptionsProvider->getOptions(FilePath);
333 std::vector<clang::tidy::ClangTidyOptionsProvider::OptionsSource>
334 RawOptions = OptionsProvider->getRawOptions(FilePath);
335 for (
const std::string &
Check : EnabledChecks) {
336 for (
auto It = RawOptions.rbegin(); It != RawOptions.rend(); ++It) {
338 llvm::outs() <<
"'" <<
Check <<
"' is enabled in the " << It->second
348 if (EnabledChecks.empty()) {
349 llvm::errs() <<
"No checks enabled.\n";
352 llvm::outs() <<
"Enabled checks:";
353 for (
const auto &CheckName : EnabledChecks)
354 llvm::outs() <<
"\n " << CheckName;
355 llvm::outs() <<
"\n\n";
362 ClangTidyOptions::getDefaults().mergeWith(
368 if (EnabledChecks.empty()) {
369 llvm::errs() <<
"Error: no checks enabled.\n";
370 llvm::cl::PrintHelpMessage(
false,
true);
374 if (PathList.empty()) {
375 llvm::errs() <<
"Error: no input files specified.\n";
376 llvm::cl::PrintHelpMessage(
false,
true);
382 std::vector<ClangTidyError> Errors;
383 ClangTidyStats Stats =
384 runClangTidy(std::move(OptionsProvider), OptionsParser.getCompilations(),
387 std::find_if(Errors.begin(), Errors.end(), [](
const ClangTidyError &E) {
388 return E.DiagLevel == ClangTidyError::Error;
391 const bool DisableFixes =
Fix && FoundErrors && !
FixErrors;
393 unsigned WErrorCount = 0;
401 llvm::raw_fd_ostream OS(
ExportFixes, EC, llvm::sys::fs::F_None);
403 llvm::errs() <<
"Error opening output file: " << EC.message() <<
'\n';
412 <<
"Found compiler errors, but -fix-errors was not specified.\n"
413 "Fixes have NOT been applied.\n\n";
419 StringRef Plural = WErrorCount == 1 ?
"" :
"s";
420 llvm::errs() << WErrorCount <<
" warning" << Plural <<
" treated as error"
481 int main(
int argc,
const char **argv) {
volatile int GoogleModuleAnchorSource
static void printStats(const ClangTidyStats &Stats)
static cl::extrahelp ClangTidyHelp(R"(
Configuration files:
clang-tidy attempts to read configuration for each source file from a
.clang-tidy file located in the closest parent directory of the source
file. If any configuration options have a corresponding command-line
option, command-line option takes precedence. The effective
configuration can be inspected using -dump-config:
$ clang-tidy -dump-config - --
---
Checks: '-*,some-check'
WarningsAsErrors: ''
HeaderFilterRegex: ''
AnalyzeTemporaryDtors: false
User: user
CheckOptions:
- key: some-check.SomeOption
value: 'some value'
...
)")
static cl::opt< bool > SystemHeaders("system-headers", cl::desc("Display the errors from system headers."), cl::init(false), cl::cat(ClangTidyCategory))
Read-only set of strings represented as a list of positive and negative globs.
volatile int ReadabilityModuleAnchorSource
static cl::opt< bool > FixErrors("fix-errors", cl::desc(R"(
Apply suggested fixes even if compilation
errors were found. If compiler errors have
attached fix-its, clang-tidy will apply them as
well.
)"), cl::init(false), cl::cat(ClangTidyCategory))
static cl::opt< std::string > HeaderFilter("header-filter", cl::desc(R"(
Regular expression matching the names of the
headers to output diagnostics from. Diagnostics
from the main file of each translation unit are
always displayed.
Can be used together with -line-filter.
This option overrides the 'HeaderFilter' option
in .clang-tidy file, if any.
)"), cl::init(""), cl::cat(ClangTidyCategory))
bool contains(StringRef S)
Returns true if the pattern matches S.
static cl::opt< bool > DumpConfig("dump-config", cl::desc(R"(
Dumps configuration in the YAML format to
stdout. This option can be used along with a
file name (and '--' if the file is outside of a
project with configured compilation database).
The configuration used for this file will be
printed.
Use along with -checks=* to include
configuration of all checks.
)"), cl::init(false), cl::cat(ClangTidyCategory))
static cl::opt< bool > ExplainConfig("explain-config", cl::desc(R"(
For each enabled check explains, where it is
enabled, i.e. in clang-tidy binary, command
line or a specific configuration file.
)"), cl::init(false), cl::cat(ClangTidyCategory))
ClangTidyOptions::OptionMap getCheckOptions(const ClangTidyOptions &Options)
Returns the effective check-specific options.
static int LLVM_ATTRIBUTE_UNUSED LLVMModuleAnchorDestination
unsigned ErrorsIgnoredCheckFilter
std::error_code parseLineFilter(StringRef LineFilter, clang::tidy::ClangTidyGlobalOptions &Options)
Parses -line-filter option and stores it to the Options.
static cl::opt< bool > AnalyzeTemporaryDtors("analyze-temporary-dtors", cl::desc(R"(
Enable temporary destructor-aware analysis in
clang-analyzer- checks.
This option overrides the value read from a
.clang-tidy file.
)"), cl::init(false), cl::cat(ClangTidyCategory))
llvm::ErrorOr< ClangTidyOptions > parseConfiguration(StringRef Config)
unsigned ErrorsIgnoredNOLINT
static cl::opt< bool > ListChecks("list-checks", cl::desc(R"(
List all enabled checks and exit. Use with
-checks=* to list all available checks.
)"), cl::init(false), cl::cat(ClangTidyCategory))
volatile int LLVMModuleAnchorSource
volatile int PerformanceModuleAnchorSource
volatile int CppCoreGuidelinesModuleAnchorSource
static int LLVM_ATTRIBUTE_UNUSED ReadabilityModuleAnchorDestination
static cl::opt< std::string > LineFilter("line-filter", cl::desc(R"(
List of files with line ranges to filter the
warnings. Can be used together with
-header-filter. The format of the list is a
JSON array of objects:
[
{"name":"file1.cpp","lines":[[1,3],[5,7]]},
{"name":"file2.h"}
]
)"), cl::init(""), cl::cat(ClangTidyCategory))
unsigned ErrorsIgnoredNonUserCode
volatile int MPIModuleAnchorSource
std::string configurationAsText(const ClangTidyOptions &Options)
Serializes configuration to a YAML-encoded string.
volatile int CERTModuleAnchorSource
ClangTidyStats runClangTidy(std::unique_ptr< ClangTidyOptionsProvider > OptionsProvider, const CompilationDatabase &Compilations, ArrayRef< std::string > InputFiles, std::vector< ClangTidyError > *Errors, ProfileData *Profile)
static cl::OptionCategory ClangTidyCategory("clang-tidy options")
static cl::opt< std::string > WarningsAsErrors("warnings-as-errors", cl::desc(R"(
Upgrades warnings to errors. Same format as
'-checks'.
This option's value is appended to the value of
the 'WarningsAsErrors' option in .clang-tidy
file, if any.
)"), cl::init(""), cl::cat(ClangTidyCategory))
static int LLVM_ATTRIBUTE_UNUSED GoogleModuleAnchorDestination
std::vector< std::string > getCheckNames(const ClangTidyOptions &Options)
Fills the list of check names that are enabled when the provided filters are applied.
static cl::opt< std::string > Config("config", cl::desc(R"(
Specifies a configuration in YAML/JSON format:
-config="{Checks: '*', CheckOptions:[{key:x, value:y}]}"
When the value is empty, clang-tidy will
attempt to find a file named .clang-tidy for
each source file in its parent directories.
)"), cl::init(""), cl::cat(ClangTidyCategory))
unsigned ErrorsIgnoredLineFilter
static cl::opt< bool > EnableCheckProfile("enable-check-profile", cl::desc(R"(
Enable per-check timing profiles, and print a
report to stderr.
)"), cl::init(false), cl::cat(ClangTidyCategory))
static cl::extrahelp CommonHelp(CommonOptionsParser::HelpMessage)
static void printProfileData(const ProfileData &Profile, llvm::raw_ostream &OS)
volatile int BoostModuleAnchorSource
static cl::opt< std::string > ExportFixes("export-fixes", cl::desc(R"(
YAML file to store suggested fixes in. The
stored fixes can be applied to the input source
code with clang-apply-replacements.
)"), cl::value_desc("filename"), cl::cat(ClangTidyCategory))
volatile int MiscModuleAnchorSource
static int LLVM_ATTRIBUTE_UNUSED PerformanceModuleAnchorDestination
static int clangTidyMain(int argc, const char **argv)
static int LLVM_ATTRIBUTE_UNUSED MiscModuleAnchorDestination
static int LLVM_ATTRIBUTE_UNUSED CppCoreGuidelinesModuleAnchorDestination
static int LLVM_ATTRIBUTE_UNUSED ModernizeModuleAnchorDestination
void exportReplacements(const llvm::StringRef MainFilePath, const std::vector< ClangTidyError > &Errors, raw_ostream &OS)
unsigned errorsIgnored() const
const char DefaultChecks[]
static std::unique_ptr< ClangTidyOptionsProvider > createOptionsProvider()
int main(int argc, const char **argv)
Contains displayed and ignored diagnostic counters for a ClangTidy run.
volatile int ModernizeModuleAnchorSource
static int LLVM_ATTRIBUTE_UNUSED MPIModuleAnchorDestination
static int LLVM_ATTRIBUTE_UNUSED CERTModuleAnchorDestination
static cl::opt< std::string > Checks("checks", cl::desc(R"(
Comma-separated list of globs with optional '-'
prefix. Globs are processed in order of
appearance in the list. Globs without '-'
prefix add checks with matching names to the
set, globs with the '-' prefix remove checks
with matching names from the set of enabled
checks. This option's value is appended to the
value of the 'Checks' option in .clang-tidy
file, if any.
)"), cl::init(""), cl::cat(ClangTidyCategory))
static cl::opt< bool > Fix("fix", cl::desc(R"(
Apply suggested fixes. Without -fix-errors
clang-tidy will bail out if any compilation
errors were found.
)"), cl::init(false), cl::cat(ClangTidyCategory))
static int LLVM_ATTRIBUTE_UNUSED BoostModuleAnchorDestination
static cl::opt< std::string > FormatStyle("style", cl::desc(R"(
Fallback style for reformatting after inserting fixes
if there is no clang-format config file found.
)"), cl::init("llvm"), cl::cat(ClangTidyCategory))
void handleErrors(const std::vector< ClangTidyError > &Errors, bool Fix, StringRef FormatStyle, unsigned &WarningsAsErrorsCount)
Displays the found Errors to the users.