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