Clang Project

clang_source_code/tools/clang-check/ClangCheck.cpp
1//===--- tools/clang-check/ClangCheck.cpp - Clang check tool --------------===//
2//
3// 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
6//
7//===----------------------------------------------------------------------===//
8//
9//  This file implements a clang-check tool that runs clang based on the info
10//  stored in a compilation database.
11//
12//  This tool uses the Clang Tooling infrastructure, see
13//    http://clang.llvm.org/docs/HowToSetupToolingForLLVM.html
14//  for details on setting it up with LLVM source tree.
15//
16//===----------------------------------------------------------------------===//
17
18#include "clang/AST/ASTConsumer.h"
19#include "clang/CodeGen/ObjectFilePCHContainerOperations.h"
20#include "clang/Driver/Options.h"
21#include "clang/Frontend/ASTConsumers.h"
22#include "clang/Frontend/CompilerInstance.h"
23#include "clang/Rewrite/Frontend/FixItRewriter.h"
24#include "clang/Rewrite/Frontend/FrontendActions.h"
25#include "clang/StaticAnalyzer/Frontend/FrontendActions.h"
26#include "clang/Tooling/CommonOptionsParser.h"
27#include "clang/Tooling/Tooling.h"
28#include "llvm/ADT/STLExtras.h"
29#include "llvm/Option/OptTable.h"
30#include "llvm/Support/Path.h"
31#include "llvm/Support/Signals.h"
32#include "llvm/Support/TargetSelect.h"
33
34using namespace clang::driver;
35using namespace clang::tooling;
36using namespace llvm;
37
38static cl::extrahelp CommonHelp(CommonOptionsParser::HelpMessage);
39static cl::extrahelp MoreHelp(
40    "\tFor example, to run clang-check on all files in a subtree of the\n"
41    "\tsource tree, use:\n"
42    "\n"
43    "\t  find path/in/subtree -name '*.cpp'|xargs clang-check\n"
44    "\n"
45    "\tor using a specific build path:\n"
46    "\n"
47    "\t  find path/in/subtree -name '*.cpp'|xargs clang-check -p build/path\n"
48    "\n"
49    "\tNote, that path/in/subtree and current directory should follow the\n"
50    "\trules described above.\n"
51    "\n"
52);
53
54static cl::OptionCategory ClangCheckCategory("clang-check options");
55static std::unique_ptr<opt::OptTableOptions(createDriverOptTable());
56static cl::opt<bool>
57ASTDump("ast-dump", cl::desc(Options->getOptionHelpText(options::OPT_ast_dump)),
58        cl::cat(ClangCheckCategory));
59static cl::opt<bool>
60ASTList("ast-list", cl::desc(Options->getOptionHelpText(options::OPT_ast_list)),
61        cl::cat(ClangCheckCategory));
62static cl::opt<bool>
63ASTPrint("ast-print",
64         cl::desc(Options->getOptionHelpText(options::OPT_ast_print)),
65         cl::cat(ClangCheckCategory));
66static cl::opt<std::string> ASTDumpFilter(
67    "ast-dump-filter",
68    cl::desc(Options->getOptionHelpText(options::OPT_ast_dump_filter)),
69    cl::cat(ClangCheckCategory));
70static cl::opt<bool>
71Analyze("analyze", cl::desc(Options->getOptionHelpText(options::OPT_analyze)),
72        cl::cat(ClangCheckCategory));
73
74static cl::opt<bool>
75Fixit("fixit", cl::desc(Options->getOptionHelpText(options::OPT_fixit)),
76      cl::cat(ClangCheckCategory));
77static cl::opt<boolFixWhatYouCan(
78    "fix-what-you-can",
79    cl::desc(Options->getOptionHelpText(options::OPT_fix_what_you_can)),
80    cl::cat(ClangCheckCategory));
81
82namespace {
83
84// FIXME: Move FixItRewriteInPlace from lib/Rewrite/Frontend/FrontendActions.cpp
85// into a header file and reuse that.
86class FixItOptions : public clang::FixItOptions {
87public:
88  FixItOptions() {
89    FixWhatYouCan = ::FixWhatYouCan;
90  }
91
92  std::string RewriteFilename(const std::stringfilenameint &fd) override {
93     (0) . __assert_fail ("llvm..sys..path..is_absolute(filename) && \"clang-fixit expects absolute paths only.\"", "/home/seafit/code_projects/clang_source/clang/tools/clang-check/ClangCheck.cpp", 94, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(llvm::sys::path::is_absolute(filename) &&
94 (0) . __assert_fail ("llvm..sys..path..is_absolute(filename) && \"clang-fixit expects absolute paths only.\"", "/home/seafit/code_projects/clang_source/clang/tools/clang-check/ClangCheck.cpp", 94, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">           "clang-fixit expects absolute paths only.");
95
96    // We don't need to do permission checking here since clang will diagnose
97    // any I/O errors itself.
98
99    fd = -1;  // No file descriptor for file.
100
101    return filename;
102  }
103};
104
105/// Subclasses \c clang::FixItRewriter to not count fixed errors/warnings
106/// in the final error counts.
107///
108/// This has the side-effect that clang-check -fixit exits with code 0 on
109/// successfully fixing all errors.
110class FixItRewriter : public clang::FixItRewriter {
111public:
112  FixItRewriter(clang::DiagnosticsEngineDiags,
113                clang::SourceManagerSourceMgr,
114                const clang::LangOptionsLangOpts,
115                clang::FixItOptionsFixItOpts)
116      : clang::FixItRewriter(DiagsSourceMgrLangOptsFixItOpts) {
117  }
118
119  bool IncludeInDiagnosticCounts() const override { return false; }
120};
121
122/// Subclasses \c clang::FixItAction so that we can install the custom
123/// \c FixItRewriter.
124class ClangCheckFixItAction : public clang::FixItAction {
125public:
126  bool BeginSourceFileAction(clang::CompilerInstanceCI) override {
127    FixItOpts.reset(new FixItOptions);
128    Rewriter.reset(new FixItRewriter(CI.getDiagnostics(), CI.getSourceManager(),
129                                     CI.getLangOpts(), FixItOpts.get()));
130    return true;
131  }
132};
133
134class ClangCheckActionFactory {
135public:
136  std::unique_ptr<clang::ASTConsumernewASTConsumer() {
137    if (ASTList)
138      return clang::CreateASTDeclNodeLister();
139    if (ASTDump)
140      return clang::CreateASTDumper(nullptr /*Dump to stdout.*/,
141                                    ASTDumpFilter,
142                                    /*DumpDecls=*/true,
143                                    /*Deserialize=*/false,
144                                    /*DumpLookups=*/false);
145    if (ASTPrint)
146      return clang::CreateASTPrinter(nullptr, ASTDumpFilter);
147    return llvm::make_unique<clang::ASTConsumer>();
148  }
149};
150
151// namespace
152
153int main(int argcconst char **argv) {
154  llvm::sys::PrintStackTraceOnErrorSignal(argv[0]);
155
156  // Initialize targets for clang module support.
157  llvm::InitializeAllTargets();
158  llvm::InitializeAllTargetMCs();
159  llvm::InitializeAllAsmPrinters();
160  llvm::InitializeAllAsmParsers();
161
162  CommonOptionsParser OptionsParser(argc, argv, ClangCheckCategory);
163  ClangTool Tool(OptionsParser.getCompilations(),
164                 OptionsParser.getSourcePathList());
165
166  // Clear adjusters because -fsyntax-only is inserted by the default chain.
167  Tool.clearArgumentsAdjusters();
168  Tool.appendArgumentsAdjuster(getClangStripOutputAdjuster());
169  Tool.appendArgumentsAdjuster(getClangStripDependencyFileAdjuster());
170
171  // Running the analyzer requires --analyze. Other modes can work with the
172  // -fsyntax-only option.
173  Tool.appendArgumentsAdjuster(getInsertArgumentAdjuster(
174      Analyze ? "--analyze" : "-fsyntax-only", ArgumentInsertPosition::BEGIN));
175
176  ClangCheckActionFactory CheckFactory;
177  std::unique_ptr<FrontendActionFactoryFrontendFactory;
178
179  // Choose the correct factory based on the selected mode.
180  if (Analyze)
181    FrontendFactory = newFrontendActionFactory<clang::ento::AnalysisAction>();
182  else if (Fixit)
183    FrontendFactory = newFrontendActionFactory<ClangCheckFixItAction>();
184  else
185    FrontendFactory = newFrontendActionFactory(&CheckFactory);
186
187  return Tool.run(FrontendFactory.get());
188}
189