blob: 6f62228ffa8a8a8097386b74efb17eed2dfaaae3 [file] [log] [blame]
Alexander Kornienkod7166b02012-08-22 20:52:52 +00001//===--- tools/clang-check/ClangCheck.cpp - Clang check tool --------------===//
Manuel Klimekcb971c62012-04-04 12:07:46 +00002//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
Daniel Jasper5e5f7262012-10-03 13:28:43 +000010// This file implements a clang-check tool that runs clang based on the info
11// stored in a compilation database.
Manuel Klimekcb971c62012-04-04 12:07:46 +000012//
Alexander Kornienkodea8fba2012-07-16 12:46:48 +000013// This tool uses the Clang Tooling infrastructure, see
14// http://clang.llvm.org/docs/HowToSetupToolingForLLVM.html
15// for details on setting it up with LLVM source tree.
16//
Manuel Klimekcb971c62012-04-04 12:07:46 +000017//===----------------------------------------------------------------------===//
18
Alexander Kornienko48464702012-08-13 10:50:08 +000019#include "clang/AST/ASTConsumer.h"
20#include "clang/Driver/OptTable.h"
21#include "clang/Driver/Options.h"
22#include "clang/Frontend/ASTConsumers.h"
Daniel Jasper5e5f7262012-10-03 13:28:43 +000023#include "clang/Frontend/CompilerInstance.h"
24#include "clang/Rewrite/Frontend/FixItRewriter.h"
25#include "clang/Rewrite/Frontend/FrontendActions.h"
Alexander Kornienkod7166b02012-08-22 20:52:52 +000026#include "clang/Tooling/CommonOptionsParser.h"
Manuel Klimekcb971c62012-04-04 12:07:46 +000027#include "clang/Tooling/Tooling.h"
Alexander Kornienkod7166b02012-08-22 20:52:52 +000028#include "llvm/Support/CommandLine.h"
Daniel Jasper5e5f7262012-10-03 13:28:43 +000029#include "llvm/Support/Path.h"
Manuel Klimekcb971c62012-04-04 12:07:46 +000030
Alexander Kornienko48464702012-08-13 10:50:08 +000031using namespace clang::driver;
Manuel Klimekcb971c62012-04-04 12:07:46 +000032using namespace clang::tooling;
33using namespace llvm;
34
Alexander Kornienko6fbe9822012-08-24 00:39:14 +000035static cl::extrahelp CommonHelp(CommonOptionsParser::HelpMessage);
Alexander Kornienkod7166b02012-08-22 20:52:52 +000036static cl::extrahelp MoreHelp(
Alexander Kornienkodea8fba2012-07-16 12:46:48 +000037 "\tFor example, to run clang-check on all files in a subtree of the\n"
38 "\tsource tree, use:\n"
Alexander Kornienko140d5132012-07-12 14:34:23 +000039 "\n"
Alexander Kornienkodea8fba2012-07-16 12:46:48 +000040 "\t find path/in/subtree -name '*.cpp'|xargs clang-check\n"
Alexander Kornienko140d5132012-07-12 14:34:23 +000041 "\n"
Alexander Kornienkodea8fba2012-07-16 12:46:48 +000042 "\tor using a specific build path:\n"
Alexander Kornienko140d5132012-07-12 14:34:23 +000043 "\n"
Alexander Kornienkodea8fba2012-07-16 12:46:48 +000044 "\t find path/in/subtree -name '*.cpp'|xargs clang-check -p build/path\n"
Alexander Kornienko140d5132012-07-12 14:34:23 +000045 "\n"
Alexander Kornienkodea8fba2012-07-16 12:46:48 +000046 "\tNote, that path/in/subtree and current directory should follow the\n"
47 "\trules described above.\n"
Alexander Kornienkod7166b02012-08-22 20:52:52 +000048 "\n"
49);
50
51static OwningPtr<OptTable> Options(createDriverOptTable());
52static cl::opt<bool> ASTDump(
53 "ast-dump",
54 cl::desc(Options->getOptionHelpText(options::OPT_ast_dump)));
55static cl::opt<bool> ASTList(
56 "ast-list",
57 cl::desc(Options->getOptionHelpText(options::OPT_ast_list)));
58static cl::opt<bool> ASTPrint(
59 "ast-print",
60 cl::desc(Options->getOptionHelpText(options::OPT_ast_print)));
61static cl::opt<std::string> ASTDumpFilter(
62 "ast-dump-filter",
63 cl::desc(Options->getOptionHelpText(options::OPT_ast_dump_filter)));
Alexander Kornienko140d5132012-07-12 14:34:23 +000064
Daniel Jasper5e5f7262012-10-03 13:28:43 +000065static cl::opt<bool> Fixit(
66 "fixit",
67 cl::desc(Options->getOptionHelpText(options::OPT_fixit)));
68static cl::opt<bool> FixWhatYouCan(
69 "fix-what-you-can",
70 cl::desc(Options->getOptionHelpText(options::OPT_fix_what_you_can)));
71
72namespace {
73
74// FIXME: Move FixItRewriteInPlace from lib/Rewrite/Frontend/FrontendActions.cpp
75// into a header file and reuse that.
76class FixItOptions : public clang::FixItOptions {
77public:
78 FixItOptions() {
79 FixWhatYouCan = ::FixWhatYouCan;
80 }
81
82 std::string RewriteFilename(const std::string& filename, int &fd) {
83 assert(llvm::sys::path::is_absolute(filename) &&
84 "clang-fixit expects absolute paths only.");
85
86 // We don't need to do permission checking here since clang will diagnose
87 // any I/O errors itself.
88
89 fd = -1; // No file descriptor for file.
90
91 return filename;
92 }
93};
94
95/// \brief Subclasses \c clang::FixItRewriter to not count fixed errors/warnings
96/// in the final error counts.
97///
98/// This has the side-effect that clang-check -fixit exits with code 0 on
99/// successfully fixing all errors.
100class FixItRewriter : public clang::FixItRewriter {
101public:
102 FixItRewriter(clang::DiagnosticsEngine& Diags,
103 clang::SourceManager& SourceMgr,
104 const clang::LangOptions& LangOpts,
105 clang::FixItOptions* FixItOpts)
106 : clang::FixItRewriter(Diags, SourceMgr, LangOpts, FixItOpts) {
107 }
108
109 virtual bool IncludeInDiagnosticCounts() const { return false; }
110};
111
112/// \brief Subclasses \c clang::FixItAction so that we can install the custom
113/// \c FixItRewriter.
114class FixItAction : public clang::FixItAction {
115public:
116 virtual bool BeginSourceFileAction(clang::CompilerInstance& CI,
117 StringRef Filename) {
118 FixItOpts.reset(new FixItOptions);
119 Rewriter.reset(new FixItRewriter(CI.getDiagnostics(), CI.getSourceManager(),
120 CI.getLangOpts(), FixItOpts.get()));
121 return true;
122 }
123};
124
125} // namespace
126
Alexander Kornienko18857f72012-09-10 14:54:38 +0000127// Anonymous namespace here causes problems with gcc <= 4.4 on MacOS 10.6.
128// "Non-global symbol: ... can't be a weak_definition"
129namespace clang_check {
130class ClangCheckActionFactory {
Alexander Kornienko48464702012-08-13 10:50:08 +0000131public:
Alexander Kornienko48464702012-08-13 10:50:08 +0000132 clang::ASTConsumer *newASTConsumer() {
133 if (ASTList)
134 return clang::CreateASTDeclNodeLister();
135 if (ASTDump)
136 return clang::CreateASTDumper(ASTDumpFilter);
137 if (ASTPrint)
138 return clang::CreateASTPrinter(&llvm::outs(), ASTDumpFilter);
139 return new clang::ASTConsumer();
140 }
Alexander Kornienko48464702012-08-13 10:50:08 +0000141};
Alexander Kornienko18857f72012-09-10 14:54:38 +0000142}
Alexander Kornienko48464702012-08-13 10:50:08 +0000143
Manuel Klimek30318e62012-04-18 07:41:50 +0000144int main(int argc, const char **argv) {
Alexander Kornienkod7166b02012-08-22 20:52:52 +0000145 CommonOptionsParser OptionsParser(argc, argv);
Edwin Vaneb1f67db2012-12-14 18:58:25 +0000146 ClangTool Tool(OptionsParser.getCompilations(),
147 OptionsParser.getSourcePathList());
Daniel Jasper5e5f7262012-10-03 13:28:43 +0000148 if (Fixit)
149 return Tool.run(newFrontendActionFactory<FixItAction>());
150 clang_check::ClangCheckActionFactory Factory;
Alexander Kornienko48464702012-08-13 10:50:08 +0000151 return Tool.run(newFrontendActionFactory(&Factory));
Manuel Klimekcb971c62012-04-04 12:07:46 +0000152}