1d7166b01df14173b7f26620c5a89f9934a968f85Alexander Kornienko//===--- tools/clang-check/ClangCheck.cpp - Clang check tool --------------===//
2cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek//
3cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek//                     The LLVM Compiler Infrastructure
4cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek//
5cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek// This file is distributed under the University of Illinois Open Source
6cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek// License. See LICENSE.TXT for details.
7cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek//
8cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek//===----------------------------------------------------------------------===//
9cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek//
105e5f726a90d234bd656a7cfd8ffd26472975f1b2Daniel Jasper//  This file implements a clang-check tool that runs clang based on the info
115e5f726a90d234bd656a7cfd8ffd26472975f1b2Daniel Jasper//  stored in a compilation database.
12cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek//
13dea8fba3c632745136017f3e8e9d9e0341d6feb9Alexander Kornienko//  This tool uses the Clang Tooling infrastructure, see
14dea8fba3c632745136017f3e8e9d9e0341d6feb9Alexander Kornienko//    http://clang.llvm.org/docs/HowToSetupToolingForLLVM.html
15dea8fba3c632745136017f3e8e9d9e0341d6feb9Alexander Kornienko//  for details on setting it up with LLVM source tree.
16dea8fba3c632745136017f3e8e9d9e0341d6feb9Alexander Kornienko//
17cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek//===----------------------------------------------------------------------===//
18cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek
194846470d20348f2e7b1f6cf6c68f81fc0657d129Alexander Kornienko#include "clang/AST/ASTConsumer.h"
204846470d20348f2e7b1f6cf6c68f81fc0657d129Alexander Kornienko#include "clang/Driver/Options.h"
214846470d20348f2e7b1f6cf6c68f81fc0657d129Alexander Kornienko#include "clang/Frontend/ASTConsumers.h"
225e5f726a90d234bd656a7cfd8ffd26472975f1b2Daniel Jasper#include "clang/Frontend/CompilerInstance.h"
235e5f726a90d234bd656a7cfd8ffd26472975f1b2Daniel Jasper#include "clang/Rewrite/Frontend/FixItRewriter.h"
245e5f726a90d234bd656a7cfd8ffd26472975f1b2Daniel Jasper#include "clang/Rewrite/Frontend/FrontendActions.h"
25651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines#include "clang/StaticAnalyzer/Frontend/FrontendActions.h"
26d7166b01df14173b7f26620c5a89f9934a968f85Alexander Kornienko#include "clang/Tooling/CommonOptionsParser.h"
27cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek#include "clang/Tooling/Tooling.h"
28651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines#include "llvm/Option/OptTable.h"
295e5f726a90d234bd656a7cfd8ffd26472975f1b2Daniel Jasper#include "llvm/Support/Path.h"
30b8238b6f20bf7b5a79f18dc84ab3e51db479faa7NAKAMURA Takumi#include "llvm/Support/Signals.h"
31cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek
324846470d20348f2e7b1f6cf6c68f81fc0657d129Alexander Kornienkousing namespace clang::driver;
33cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimekusing namespace clang::tooling;
34cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimekusing namespace llvm;
35cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek
366fbe982bb487931feb3f1ceb9eec8f7f1961393aAlexander Kornienkostatic cl::extrahelp CommonHelp(CommonOptionsParser::HelpMessage);
37d7166b01df14173b7f26620c5a89f9934a968f85Alexander Kornienkostatic cl::extrahelp MoreHelp(
38dea8fba3c632745136017f3e8e9d9e0341d6feb9Alexander Kornienko    "\tFor example, to run clang-check on all files in a subtree of the\n"
39dea8fba3c632745136017f3e8e9d9e0341d6feb9Alexander Kornienko    "\tsource tree, use:\n"
40140d5130434582aa2712a67b48f7db9c0563b34cAlexander Kornienko    "\n"
41dea8fba3c632745136017f3e8e9d9e0341d6feb9Alexander Kornienko    "\t  find path/in/subtree -name '*.cpp'|xargs clang-check\n"
42140d5130434582aa2712a67b48f7db9c0563b34cAlexander Kornienko    "\n"
43dea8fba3c632745136017f3e8e9d9e0341d6feb9Alexander Kornienko    "\tor using a specific build path:\n"
44140d5130434582aa2712a67b48f7db9c0563b34cAlexander Kornienko    "\n"
45dea8fba3c632745136017f3e8e9d9e0341d6feb9Alexander Kornienko    "\t  find path/in/subtree -name '*.cpp'|xargs clang-check -p build/path\n"
46140d5130434582aa2712a67b48f7db9c0563b34cAlexander Kornienko    "\n"
47dea8fba3c632745136017f3e8e9d9e0341d6feb9Alexander Kornienko    "\tNote, that path/in/subtree and current directory should follow the\n"
48dea8fba3c632745136017f3e8e9d9e0341d6feb9Alexander Kornienko    "\trules described above.\n"
49d7166b01df14173b7f26620c5a89f9934a968f85Alexander Kornienko    "\n"
50d7166b01df14173b7f26620c5a89f9934a968f85Alexander Kornienko);
51d7166b01df14173b7f26620c5a89f9934a968f85Alexander Kornienko
52651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesstatic cl::OptionCategory ClangCheckCategory("clang-check options");
53651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesstatic std::unique_ptr<opt::OptTable> Options(createDriverOptTable());
54651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesstatic cl::opt<bool>
55651f13cea278ec967336033dd032faef0e9fc2ecStephen HinesASTDump("ast-dump", cl::desc(Options->getOptionHelpText(options::OPT_ast_dump)),
56651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines        cl::cat(ClangCheckCategory));
57651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesstatic cl::opt<bool>
58651f13cea278ec967336033dd032faef0e9fc2ecStephen HinesASTList("ast-list", cl::desc(Options->getOptionHelpText(options::OPT_ast_list)),
59651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines        cl::cat(ClangCheckCategory));
60651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesstatic cl::opt<bool>
61651f13cea278ec967336033dd032faef0e9fc2ecStephen HinesASTPrint("ast-print",
62651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines         cl::desc(Options->getOptionHelpText(options::OPT_ast_print)),
63651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines         cl::cat(ClangCheckCategory));
64d7166b01df14173b7f26620c5a89f9934a968f85Alexander Kornienkostatic cl::opt<std::string> ASTDumpFilter(
65d7166b01df14173b7f26620c5a89f9934a968f85Alexander Kornienko    "ast-dump-filter",
66651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    cl::desc(Options->getOptionHelpText(options::OPT_ast_dump_filter)),
67651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    cl::cat(ClangCheckCategory));
68651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesstatic cl::opt<bool>
69651f13cea278ec967336033dd032faef0e9fc2ecStephen HinesAnalyze("analyze", cl::desc(Options->getOptionHelpText(options::OPT_analyze)),
70651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines        cl::cat(ClangCheckCategory));
71651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
72651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesstatic cl::opt<bool>
73651f13cea278ec967336033dd032faef0e9fc2ecStephen HinesFixit("fixit", cl::desc(Options->getOptionHelpText(options::OPT_fixit)),
74651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      cl::cat(ClangCheckCategory));
755e5f726a90d234bd656a7cfd8ffd26472975f1b2Daniel Jasperstatic cl::opt<bool> FixWhatYouCan(
765e5f726a90d234bd656a7cfd8ffd26472975f1b2Daniel Jasper    "fix-what-you-can",
77651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    cl::desc(Options->getOptionHelpText(options::OPT_fix_what_you_can)),
78651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    cl::cat(ClangCheckCategory));
79651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
80651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesstatic cl::list<std::string> ArgsAfter(
81651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    "extra-arg",
82651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    cl::desc("Additional argument to append to the compiler command line"),
83651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    cl::cat(ClangCheckCategory));
84651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesstatic cl::list<std::string> ArgsBefore(
85651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    "extra-arg-before",
86651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    cl::desc("Additional argument to prepend to the compiler command line"),
87651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    cl::cat(ClangCheckCategory));
8888c200473d133a4e40083af22c316da536bad755Pavel Labath
895e5f726a90d234bd656a7cfd8ffd26472975f1b2Daniel Jaspernamespace {
905e5f726a90d234bd656a7cfd8ffd26472975f1b2Daniel Jasper
915e5f726a90d234bd656a7cfd8ffd26472975f1b2Daniel Jasper// FIXME: Move FixItRewriteInPlace from lib/Rewrite/Frontend/FrontendActions.cpp
925e5f726a90d234bd656a7cfd8ffd26472975f1b2Daniel Jasper// into a header file and reuse that.
935e5f726a90d234bd656a7cfd8ffd26472975f1b2Daniel Jasperclass FixItOptions : public clang::FixItOptions {
945e5f726a90d234bd656a7cfd8ffd26472975f1b2Daniel Jasperpublic:
955e5f726a90d234bd656a7cfd8ffd26472975f1b2Daniel Jasper  FixItOptions() {
965e5f726a90d234bd656a7cfd8ffd26472975f1b2Daniel Jasper    FixWhatYouCan = ::FixWhatYouCan;
975e5f726a90d234bd656a7cfd8ffd26472975f1b2Daniel Jasper  }
985e5f726a90d234bd656a7cfd8ffd26472975f1b2Daniel Jasper
99651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  std::string RewriteFilename(const std::string& filename, int &fd) override {
1005e5f726a90d234bd656a7cfd8ffd26472975f1b2Daniel Jasper    assert(llvm::sys::path::is_absolute(filename) &&
1015e5f726a90d234bd656a7cfd8ffd26472975f1b2Daniel Jasper           "clang-fixit expects absolute paths only.");
1025e5f726a90d234bd656a7cfd8ffd26472975f1b2Daniel Jasper
1035e5f726a90d234bd656a7cfd8ffd26472975f1b2Daniel Jasper    // We don't need to do permission checking here since clang will diagnose
1045e5f726a90d234bd656a7cfd8ffd26472975f1b2Daniel Jasper    // any I/O errors itself.
1055e5f726a90d234bd656a7cfd8ffd26472975f1b2Daniel Jasper
1065e5f726a90d234bd656a7cfd8ffd26472975f1b2Daniel Jasper    fd = -1;  // No file descriptor for file.
1075e5f726a90d234bd656a7cfd8ffd26472975f1b2Daniel Jasper
1085e5f726a90d234bd656a7cfd8ffd26472975f1b2Daniel Jasper    return filename;
1095e5f726a90d234bd656a7cfd8ffd26472975f1b2Daniel Jasper  }
1105e5f726a90d234bd656a7cfd8ffd26472975f1b2Daniel Jasper};
1115e5f726a90d234bd656a7cfd8ffd26472975f1b2Daniel Jasper
1125e5f726a90d234bd656a7cfd8ffd26472975f1b2Daniel Jasper/// \brief Subclasses \c clang::FixItRewriter to not count fixed errors/warnings
1135e5f726a90d234bd656a7cfd8ffd26472975f1b2Daniel Jasper/// in the final error counts.
1145e5f726a90d234bd656a7cfd8ffd26472975f1b2Daniel Jasper///
1155e5f726a90d234bd656a7cfd8ffd26472975f1b2Daniel Jasper/// This has the side-effect that clang-check -fixit exits with code 0 on
1165e5f726a90d234bd656a7cfd8ffd26472975f1b2Daniel Jasper/// successfully fixing all errors.
1175e5f726a90d234bd656a7cfd8ffd26472975f1b2Daniel Jasperclass FixItRewriter : public clang::FixItRewriter {
1185e5f726a90d234bd656a7cfd8ffd26472975f1b2Daniel Jasperpublic:
1195e5f726a90d234bd656a7cfd8ffd26472975f1b2Daniel Jasper  FixItRewriter(clang::DiagnosticsEngine& Diags,
1205e5f726a90d234bd656a7cfd8ffd26472975f1b2Daniel Jasper                clang::SourceManager& SourceMgr,
1215e5f726a90d234bd656a7cfd8ffd26472975f1b2Daniel Jasper                const clang::LangOptions& LangOpts,
1225e5f726a90d234bd656a7cfd8ffd26472975f1b2Daniel Jasper                clang::FixItOptions* FixItOpts)
1235e5f726a90d234bd656a7cfd8ffd26472975f1b2Daniel Jasper      : clang::FixItRewriter(Diags, SourceMgr, LangOpts, FixItOpts) {
1245e5f726a90d234bd656a7cfd8ffd26472975f1b2Daniel Jasper  }
1255e5f726a90d234bd656a7cfd8ffd26472975f1b2Daniel Jasper
126651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  bool IncludeInDiagnosticCounts() const override { return false; }
1275e5f726a90d234bd656a7cfd8ffd26472975f1b2Daniel Jasper};
1285e5f726a90d234bd656a7cfd8ffd26472975f1b2Daniel Jasper
1295e5f726a90d234bd656a7cfd8ffd26472975f1b2Daniel Jasper/// \brief Subclasses \c clang::FixItAction so that we can install the custom
1305e5f726a90d234bd656a7cfd8ffd26472975f1b2Daniel Jasper/// \c FixItRewriter.
1315e5f726a90d234bd656a7cfd8ffd26472975f1b2Daniel Jasperclass FixItAction : public clang::FixItAction {
1325e5f726a90d234bd656a7cfd8ffd26472975f1b2Daniel Jasperpublic:
133651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  bool BeginSourceFileAction(clang::CompilerInstance& CI,
134651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                             StringRef Filename) override {
1355e5f726a90d234bd656a7cfd8ffd26472975f1b2Daniel Jasper    FixItOpts.reset(new FixItOptions);
1365e5f726a90d234bd656a7cfd8ffd26472975f1b2Daniel Jasper    Rewriter.reset(new FixItRewriter(CI.getDiagnostics(), CI.getSourceManager(),
1375e5f726a90d234bd656a7cfd8ffd26472975f1b2Daniel Jasper                                     CI.getLangOpts(), FixItOpts.get()));
1385e5f726a90d234bd656a7cfd8ffd26472975f1b2Daniel Jasper    return true;
1395e5f726a90d234bd656a7cfd8ffd26472975f1b2Daniel Jasper  }
1405e5f726a90d234bd656a7cfd8ffd26472975f1b2Daniel Jasper};
1415e5f726a90d234bd656a7cfd8ffd26472975f1b2Daniel Jasper
14288c200473d133a4e40083af22c316da536bad755Pavel Labathclass InsertAdjuster: public clang::tooling::ArgumentsAdjuster {
14388c200473d133a4e40083af22c316da536bad755Pavel Labathpublic:
14488c200473d133a4e40083af22c316da536bad755Pavel Labath  enum Position { BEGIN, END };
14588c200473d133a4e40083af22c316da536bad755Pavel Labath
14688c200473d133a4e40083af22c316da536bad755Pavel Labath  InsertAdjuster(const CommandLineArguments &Extra, Position Pos)
14788c200473d133a4e40083af22c316da536bad755Pavel Labath    : Extra(Extra), Pos(Pos) {
14888c200473d133a4e40083af22c316da536bad755Pavel Labath  }
14988c200473d133a4e40083af22c316da536bad755Pavel Labath
150373b807f36871de05a3b83bbc4ed4501317def5aPavel Labath  InsertAdjuster(const char *Extra, Position Pos)
151373b807f36871de05a3b83bbc4ed4501317def5aPavel Labath    : Extra(1, std::string(Extra)), Pos(Pos) {
152373b807f36871de05a3b83bbc4ed4501317def5aPavel Labath  }
153373b807f36871de05a3b83bbc4ed4501317def5aPavel Labath
15488c200473d133a4e40083af22c316da536bad755Pavel Labath  virtual CommandLineArguments
155651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  Adjust(const CommandLineArguments &Args) override {
15688c200473d133a4e40083af22c316da536bad755Pavel Labath    CommandLineArguments Return(Args);
15788c200473d133a4e40083af22c316da536bad755Pavel Labath
15888c200473d133a4e40083af22c316da536bad755Pavel Labath    CommandLineArguments::iterator I;
15988c200473d133a4e40083af22c316da536bad755Pavel Labath    if (Pos == END) {
16088c200473d133a4e40083af22c316da536bad755Pavel Labath      I = Return.end();
16188c200473d133a4e40083af22c316da536bad755Pavel Labath    } else {
16288c200473d133a4e40083af22c316da536bad755Pavel Labath      I = Return.begin();
16388c200473d133a4e40083af22c316da536bad755Pavel Labath      ++I; // To leave the program name in place
16488c200473d133a4e40083af22c316da536bad755Pavel Labath    }
16588c200473d133a4e40083af22c316da536bad755Pavel Labath
16688c200473d133a4e40083af22c316da536bad755Pavel Labath    Return.insert(I, Extra.begin(), Extra.end());
16788c200473d133a4e40083af22c316da536bad755Pavel Labath    return Return;
16888c200473d133a4e40083af22c316da536bad755Pavel Labath  }
16988c200473d133a4e40083af22c316da536bad755Pavel Labath
17088c200473d133a4e40083af22c316da536bad755Pavel Labathprivate:
17188c200473d133a4e40083af22c316da536bad755Pavel Labath  const CommandLineArguments Extra;
17288c200473d133a4e40083af22c316da536bad755Pavel Labath  const Position Pos;
17388c200473d133a4e40083af22c316da536bad755Pavel Labath};
17488c200473d133a4e40083af22c316da536bad755Pavel Labath
1755e5f726a90d234bd656a7cfd8ffd26472975f1b2Daniel Jasper} // namespace
1765e5f726a90d234bd656a7cfd8ffd26472975f1b2Daniel Jasper
17718857f7a1ff88469283b9e87384bdf5c8a274ca6Alexander Kornienko// Anonymous namespace here causes problems with gcc <= 4.4 on MacOS 10.6.
17818857f7a1ff88469283b9e87384bdf5c8a274ca6Alexander Kornienko// "Non-global symbol: ... can't be a weak_definition"
17918857f7a1ff88469283b9e87384bdf5c8a274ca6Alexander Kornienkonamespace clang_check {
18018857f7a1ff88469283b9e87384bdf5c8a274ca6Alexander Kornienkoclass ClangCheckActionFactory {
1814846470d20348f2e7b1f6cf6c68f81fc0657d129Alexander Kornienkopublic:
1824846470d20348f2e7b1f6cf6c68f81fc0657d129Alexander Kornienko  clang::ASTConsumer *newASTConsumer() {
1834846470d20348f2e7b1f6cf6c68f81fc0657d129Alexander Kornienko    if (ASTList)
1844846470d20348f2e7b1f6cf6c68f81fc0657d129Alexander Kornienko      return clang::CreateASTDeclNodeLister();
1854846470d20348f2e7b1f6cf6c68f81fc0657d129Alexander Kornienko    if (ASTDump)
1864846470d20348f2e7b1f6cf6c68f81fc0657d129Alexander Kornienko      return clang::CreateASTDumper(ASTDumpFilter);
1874846470d20348f2e7b1f6cf6c68f81fc0657d129Alexander Kornienko    if (ASTPrint)
1884846470d20348f2e7b1f6cf6c68f81fc0657d129Alexander Kornienko      return clang::CreateASTPrinter(&llvm::outs(), ASTDumpFilter);
1894846470d20348f2e7b1f6cf6c68f81fc0657d129Alexander Kornienko    return new clang::ASTConsumer();
1904846470d20348f2e7b1f6cf6c68f81fc0657d129Alexander Kornienko  }
1914846470d20348f2e7b1f6cf6c68f81fc0657d129Alexander Kornienko};
19218857f7a1ff88469283b9e87384bdf5c8a274ca6Alexander Kornienko}
1934846470d20348f2e7b1f6cf6c68f81fc0657d129Alexander Kornienko
19430318e6df9c8c24d080211dfb92ef8065fa7381cManuel Klimekint main(int argc, const char **argv) {
195b8238b6f20bf7b5a79f18dc84ab3e51db479faa7NAKAMURA Takumi  llvm::sys::PrintStackTraceOnErrorSignal();
196651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  CommonOptionsParser OptionsParser(argc, argv, ClangCheckCategory);
197b1f67dbbb12dec8304434c76c72e01336bf186e4Edwin Vane  ClangTool Tool(OptionsParser.getCompilations(),
198b1f67dbbb12dec8304434c76c72e01336bf186e4Edwin Vane                 OptionsParser.getSourcePathList());
19988c200473d133a4e40083af22c316da536bad755Pavel Labath
200373b807f36871de05a3b83bbc4ed4501317def5aPavel Labath  // Clear adjusters because -fsyntax-only is inserted by the default chain.
201373b807f36871de05a3b83bbc4ed4501317def5aPavel Labath  Tool.clearArgumentsAdjusters();
202373b807f36871de05a3b83bbc4ed4501317def5aPavel Labath  Tool.appendArgumentsAdjuster(new ClangStripOutputAdjuster());
203373b807f36871de05a3b83bbc4ed4501317def5aPavel Labath  if (ArgsAfter.size() > 0) {
204373b807f36871de05a3b83bbc4ed4501317def5aPavel Labath    Tool.appendArgumentsAdjuster(new InsertAdjuster(ArgsAfter,
205373b807f36871de05a3b83bbc4ed4501317def5aPavel Labath          InsertAdjuster::END));
206373b807f36871de05a3b83bbc4ed4501317def5aPavel Labath  }
207373b807f36871de05a3b83bbc4ed4501317def5aPavel Labath  if (ArgsBefore.size() > 0) {
208373b807f36871de05a3b83bbc4ed4501317def5aPavel Labath    Tool.appendArgumentsAdjuster(new InsertAdjuster(ArgsBefore,
209373b807f36871de05a3b83bbc4ed4501317def5aPavel Labath          InsertAdjuster::BEGIN));
210373b807f36871de05a3b83bbc4ed4501317def5aPavel Labath  }
211373b807f36871de05a3b83bbc4ed4501317def5aPavel Labath
212373b807f36871de05a3b83bbc4ed4501317def5aPavel Labath  // Running the analyzer requires --analyze. Other modes can work with the
213373b807f36871de05a3b83bbc4ed4501317def5aPavel Labath  // -fsyntax-only option.
214373b807f36871de05a3b83bbc4ed4501317def5aPavel Labath  Tool.appendArgumentsAdjuster(new InsertAdjuster(
215373b807f36871de05a3b83bbc4ed4501317def5aPavel Labath        Analyze ? "--analyze" : "-fsyntax-only", InsertAdjuster::BEGIN));
216373b807f36871de05a3b83bbc4ed4501317def5aPavel Labath
217373b807f36871de05a3b83bbc4ed4501317def5aPavel Labath  clang_check::ClangCheckActionFactory CheckFactory;
2186bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  std::unique_ptr<FrontendActionFactory> FrontendFactory;
219373b807f36871de05a3b83bbc4ed4501317def5aPavel Labath
220373b807f36871de05a3b83bbc4ed4501317def5aPavel Labath  // Choose the correct factory based on the selected mode.
221373b807f36871de05a3b83bbc4ed4501317def5aPavel Labath  if (Analyze)
222373b807f36871de05a3b83bbc4ed4501317def5aPavel Labath    FrontendFactory = newFrontendActionFactory<clang::ento::AnalysisAction>();
223373b807f36871de05a3b83bbc4ed4501317def5aPavel Labath  else if (Fixit)
224373b807f36871de05a3b83bbc4ed4501317def5aPavel Labath    FrontendFactory = newFrontendActionFactory<FixItAction>();
225373b807f36871de05a3b83bbc4ed4501317def5aPavel Labath  else
226373b807f36871de05a3b83bbc4ed4501317def5aPavel Labath    FrontendFactory = newFrontendActionFactory(&CheckFactory);
22788c200473d133a4e40083af22c316da536bad755Pavel Labath
2286bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  return Tool.run(FrontendFactory.get());
229cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek}
230