1cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek//===--- CompilationDatabase.cpp - ----------------------------------------===//
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//
107fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper//  This file contains implementations of the CompilationDatabase base class
117fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper//  and the FixedCompilationDatabase.
12cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek//
13cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek//===----------------------------------------------------------------------===//
14cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek
15cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek#include "clang/Tooling/CompilationDatabase.h"
16c8f03423e23d4e093d8149fd924e6fef26a15e94Edwin Vane#include "clang/Basic/Diagnostic.h"
176bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines#include "clang/Basic/DiagnosticOptions.h"
18c8f03423e23d4e093d8149fd924e6fef26a15e94Edwin Vane#include "clang/Driver/Action.h"
19651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines#include "clang/Driver/Compilation.h"
20c8f03423e23d4e093d8149fd924e6fef26a15e94Edwin Vane#include "clang/Driver/Driver.h"
21c8f03423e23d4e093d8149fd924e6fef26a15e94Edwin Vane#include "clang/Driver/DriverDiagnostic.h"
22c8f03423e23d4e093d8149fd924e6fef26a15e94Edwin Vane#include "clang/Driver/Job.h"
23c8f03423e23d4e093d8149fd924e6fef26a15e94Edwin Vane#include "clang/Frontend/TextDiagnosticPrinter.h"
24651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines#include "clang/Tooling/CompilationDatabasePluginRegistry.h"
25651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines#include "clang/Tooling/Tooling.h"
26651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines#include "llvm/ADT/SmallString.h"
27c8f03423e23d4e093d8149fd924e6fef26a15e94Edwin Vane#include "llvm/Option/Arg.h"
28651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines#include "llvm/Support/Host.h"
29651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines#include "llvm/Support/Path.h"
30651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines#include <sstream>
31ef8225444452a1486bd721f3285301fe84643b00Stephen Hines#include <system_error>
32c8f03423e23d4e093d8149fd924e6fef26a15e94Edwin Vane
33cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimeknamespace clang {
34cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimeknamespace tooling {
35cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek
36cb971c6726d16e12ecd2a340941d7f5c06698332Manuel KlimekCompilationDatabase::~CompilationDatabase() {}
37cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek
38cb971c6726d16e12ecd2a340941d7f5c06698332Manuel KlimekCompilationDatabase *
39cb971c6726d16e12ecd2a340941d7f5c06698332Manuel KlimekCompilationDatabase::loadFromDirectory(StringRef BuildDirectory,
40cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek                                       std::string &ErrorMessage) {
417fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper  std::stringstream ErrorStream;
427fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper  for (CompilationDatabasePluginRegistry::iterator
437fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper       It = CompilationDatabasePluginRegistry::begin(),
447fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper       Ie = CompilationDatabasePluginRegistry::end();
457fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper       It != Ie; ++It) {
467fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper    std::string DatabaseErrorMessage;
47651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    std::unique_ptr<CompilationDatabasePlugin> Plugin(It->instantiate());
487fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper    if (CompilationDatabase *DB =
497fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper        Plugin->loadFromDirectory(BuildDirectory, DatabaseErrorMessage))
507fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper      return DB;
517fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper    else
527fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper      ErrorStream << It->getName() << ": " << DatabaseErrorMessage << "\n";
53cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek  }
547fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper  ErrorMessage = ErrorStream.str();
556bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  return nullptr;
56cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek}
57cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek
584187df5f7bdda66d2fbe64a3f2660ee3977f0d12Arnaud A. de Grandmaisonstatic CompilationDatabase *
597fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel JasperfindCompilationDatabaseFromDirectory(StringRef Directory,
607fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper                                     std::string &ErrorMessage) {
617fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper  std::stringstream ErrorStream;
623d21078935d0376c1fc93af662a93e79d82e6f4bDaniel Jasper  bool HasErrorMessage = false;
638fa2fb859a4cb8e67d9763225281d9b0aa9cb59fManuel Klimek  while (!Directory.empty()) {
648fa2fb859a4cb8e67d9763225281d9b0aa9cb59fManuel Klimek    std::string LoadErrorMessage;
654187df5f7bdda66d2fbe64a3f2660ee3977f0d12Arnaud A. de Grandmaison
664187df5f7bdda66d2fbe64a3f2660ee3977f0d12Arnaud A. de Grandmaison    if (CompilationDatabase *DB =
674187df5f7bdda66d2fbe64a3f2660ee3977f0d12Arnaud A. de Grandmaison           CompilationDatabase::loadFromDirectory(Directory, LoadErrorMessage))
688fa2fb859a4cb8e67d9763225281d9b0aa9cb59fManuel Klimek      return DB;
693d21078935d0376c1fc93af662a93e79d82e6f4bDaniel Jasper
703d21078935d0376c1fc93af662a93e79d82e6f4bDaniel Jasper    if (!HasErrorMessage) {
713d21078935d0376c1fc93af662a93e79d82e6f4bDaniel Jasper      ErrorStream << "No compilation database found in " << Directory.str()
723d21078935d0376c1fc93af662a93e79d82e6f4bDaniel Jasper                  << " or any parent directory\n" << LoadErrorMessage;
733d21078935d0376c1fc93af662a93e79d82e6f4bDaniel Jasper      HasErrorMessage = true;
743d21078935d0376c1fc93af662a93e79d82e6f4bDaniel Jasper    }
754187df5f7bdda66d2fbe64a3f2660ee3977f0d12Arnaud A. de Grandmaison
768fa2fb859a4cb8e67d9763225281d9b0aa9cb59fManuel Klimek    Directory = llvm::sys::path::parent_path(Directory);
778fa2fb859a4cb8e67d9763225281d9b0aa9cb59fManuel Klimek  }
787fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper  ErrorMessage = ErrorStream.str();
796bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  return nullptr;
808fa2fb859a4cb8e67d9763225281d9b0aa9cb59fManuel Klimek}
818fa2fb859a4cb8e67d9763225281d9b0aa9cb59fManuel Klimek
824187df5f7bdda66d2fbe64a3f2660ee3977f0d12Arnaud A. de GrandmaisonCompilationDatabase *
834187df5f7bdda66d2fbe64a3f2660ee3977f0d12Arnaud A. de GrandmaisonCompilationDatabase::autoDetectFromSource(StringRef SourceFile,
844187df5f7bdda66d2fbe64a3f2660ee3977f0d12Arnaud A. de Grandmaison                                          std::string &ErrorMessage) {
85cfa88f893915ceb8ae4ce2f17c46c24a4d67502fDmitri Gribenko  SmallString<1024> AbsolutePath(getAbsolutePath(SourceFile));
864187df5f7bdda66d2fbe64a3f2660ee3977f0d12Arnaud A. de Grandmaison  StringRef Directory = llvm::sys::path::parent_path(AbsolutePath);
874187df5f7bdda66d2fbe64a3f2660ee3977f0d12Arnaud A. de Grandmaison
887fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper  CompilationDatabase *DB = findCompilationDatabaseFromDirectory(Directory,
897fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper                                                                 ErrorMessage);
904187df5f7bdda66d2fbe64a3f2660ee3977f0d12Arnaud A. de Grandmaison
914187df5f7bdda66d2fbe64a3f2660ee3977f0d12Arnaud A. de Grandmaison  if (!DB)
924187df5f7bdda66d2fbe64a3f2660ee3977f0d12Arnaud A. de Grandmaison    ErrorMessage = ("Could not auto-detect compilation database for file \"" +
937fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper                   SourceFile + "\"\n" + ErrorMessage).str();
944187df5f7bdda66d2fbe64a3f2660ee3977f0d12Arnaud A. de Grandmaison  return DB;
954187df5f7bdda66d2fbe64a3f2660ee3977f0d12Arnaud A. de Grandmaison}
964187df5f7bdda66d2fbe64a3f2660ee3977f0d12Arnaud A. de Grandmaison
974187df5f7bdda66d2fbe64a3f2660ee3977f0d12Arnaud A. de GrandmaisonCompilationDatabase *
984187df5f7bdda66d2fbe64a3f2660ee3977f0d12Arnaud A. de GrandmaisonCompilationDatabase::autoDetectFromDirectory(StringRef SourceDir,
994187df5f7bdda66d2fbe64a3f2660ee3977f0d12Arnaud A. de Grandmaison                                             std::string &ErrorMessage) {
100cfa88f893915ceb8ae4ce2f17c46c24a4d67502fDmitri Gribenko  SmallString<1024> AbsolutePath(getAbsolutePath(SourceDir));
1014187df5f7bdda66d2fbe64a3f2660ee3977f0d12Arnaud A. de Grandmaison
1027fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper  CompilationDatabase *DB = findCompilationDatabaseFromDirectory(AbsolutePath,
1037fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper                                                                 ErrorMessage);
1044187df5f7bdda66d2fbe64a3f2660ee3977f0d12Arnaud A. de Grandmaison
1054187df5f7bdda66d2fbe64a3f2660ee3977f0d12Arnaud A. de Grandmaison  if (!DB)
1064187df5f7bdda66d2fbe64a3f2660ee3977f0d12Arnaud A. de Grandmaison    ErrorMessage = ("Could not auto-detect compilation database from directory \"" +
1077fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper                   SourceDir + "\"\n" + ErrorMessage).str();
1084187df5f7bdda66d2fbe64a3f2660ee3977f0d12Arnaud A. de Grandmaison  return DB;
1094187df5f7bdda66d2fbe64a3f2660ee3977f0d12Arnaud A. de Grandmaison}
1104187df5f7bdda66d2fbe64a3f2660ee3977f0d12Arnaud A. de Grandmaison
1117fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel JasperCompilationDatabasePlugin::~CompilationDatabasePlugin() {}
1127fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper
113c8f03423e23d4e093d8149fd924e6fef26a15e94Edwin Vane// Helper for recursively searching through a chain of actions and collecting
114c8f03423e23d4e093d8149fd924e6fef26a15e94Edwin Vane// all inputs, direct and indirect, of compile jobs.
115c8f03423e23d4e093d8149fd924e6fef26a15e94Edwin Vanestruct CompileJobAnalyzer {
116c8f03423e23d4e093d8149fd924e6fef26a15e94Edwin Vane  void run(const driver::Action *A) {
117c8f03423e23d4e093d8149fd924e6fef26a15e94Edwin Vane    runImpl(A, false);
118c8f03423e23d4e093d8149fd924e6fef26a15e94Edwin Vane  }
119c8f03423e23d4e093d8149fd924e6fef26a15e94Edwin Vane
120c8f03423e23d4e093d8149fd924e6fef26a15e94Edwin Vane  SmallVector<std::string, 2> Inputs;
121c8f03423e23d4e093d8149fd924e6fef26a15e94Edwin Vane
122c8f03423e23d4e093d8149fd924e6fef26a15e94Edwin Vaneprivate:
123c8f03423e23d4e093d8149fd924e6fef26a15e94Edwin Vane
124c8f03423e23d4e093d8149fd924e6fef26a15e94Edwin Vane  void runImpl(const driver::Action *A, bool Collect) {
125c8f03423e23d4e093d8149fd924e6fef26a15e94Edwin Vane    bool CollectChildren = Collect;
126c8f03423e23d4e093d8149fd924e6fef26a15e94Edwin Vane    switch (A->getKind()) {
127c8f03423e23d4e093d8149fd924e6fef26a15e94Edwin Vane    case driver::Action::CompileJobClass:
128c8f03423e23d4e093d8149fd924e6fef26a15e94Edwin Vane      CollectChildren = true;
129c8f03423e23d4e093d8149fd924e6fef26a15e94Edwin Vane      break;
130c8f03423e23d4e093d8149fd924e6fef26a15e94Edwin Vane
131c8f03423e23d4e093d8149fd924e6fef26a15e94Edwin Vane    case driver::Action::InputClass: {
132c8f03423e23d4e093d8149fd924e6fef26a15e94Edwin Vane      if (Collect) {
133c8f03423e23d4e093d8149fd924e6fef26a15e94Edwin Vane        const driver::InputAction *IA = cast<driver::InputAction>(A);
134c8f03423e23d4e093d8149fd924e6fef26a15e94Edwin Vane        Inputs.push_back(IA->getInputArg().getSpelling());
135c8f03423e23d4e093d8149fd924e6fef26a15e94Edwin Vane      }
136c8f03423e23d4e093d8149fd924e6fef26a15e94Edwin Vane    } break;
137c8f03423e23d4e093d8149fd924e6fef26a15e94Edwin Vane
138c8f03423e23d4e093d8149fd924e6fef26a15e94Edwin Vane    default:
139c8f03423e23d4e093d8149fd924e6fef26a15e94Edwin Vane      // Don't care about others
140c8f03423e23d4e093d8149fd924e6fef26a15e94Edwin Vane      ;
141c8f03423e23d4e093d8149fd924e6fef26a15e94Edwin Vane    }
142c8f03423e23d4e093d8149fd924e6fef26a15e94Edwin Vane
143c8f03423e23d4e093d8149fd924e6fef26a15e94Edwin Vane    for (driver::ActionList::const_iterator I = A->begin(), E = A->end();
144c8f03423e23d4e093d8149fd924e6fef26a15e94Edwin Vane         I != E; ++I)
145c8f03423e23d4e093d8149fd924e6fef26a15e94Edwin Vane      runImpl(*I, CollectChildren);
146c8f03423e23d4e093d8149fd924e6fef26a15e94Edwin Vane  }
147c8f03423e23d4e093d8149fd924e6fef26a15e94Edwin Vane};
148c8f03423e23d4e093d8149fd924e6fef26a15e94Edwin Vane
149c8f03423e23d4e093d8149fd924e6fef26a15e94Edwin Vane// Special DiagnosticConsumer that looks for warn_drv_input_file_unused
150c8f03423e23d4e093d8149fd924e6fef26a15e94Edwin Vane// diagnostics from the driver and collects the option strings for those unused
151c8f03423e23d4e093d8149fd924e6fef26a15e94Edwin Vane// options.
152c8f03423e23d4e093d8149fd924e6fef26a15e94Edwin Vaneclass UnusedInputDiagConsumer : public DiagnosticConsumer {
153c8f03423e23d4e093d8149fd924e6fef26a15e94Edwin Vanepublic:
1546bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  UnusedInputDiagConsumer() : Other(nullptr) {}
155c8f03423e23d4e093d8149fd924e6fef26a15e94Edwin Vane
156c8f03423e23d4e093d8149fd924e6fef26a15e94Edwin Vane  // Useful for debugging, chain diagnostics to another consumer after
157c8f03423e23d4e093d8149fd924e6fef26a15e94Edwin Vane  // recording for our own purposes.
158c8f03423e23d4e093d8149fd924e6fef26a15e94Edwin Vane  UnusedInputDiagConsumer(DiagnosticConsumer *Other) : Other(Other) {}
159c8f03423e23d4e093d8149fd924e6fef26a15e94Edwin Vane
160c8f03423e23d4e093d8149fd924e6fef26a15e94Edwin Vane  virtual void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
161651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                                const Diagnostic &Info) override {
162c8f03423e23d4e093d8149fd924e6fef26a15e94Edwin Vane    if (Info.getID() == clang::diag::warn_drv_input_file_unused) {
163c8f03423e23d4e093d8149fd924e6fef26a15e94Edwin Vane      // Arg 1 for this diagnostic is the option that didn't get used.
164c8f03423e23d4e093d8149fd924e6fef26a15e94Edwin Vane      UnusedInputs.push_back(Info.getArgStdStr(0));
165c8f03423e23d4e093d8149fd924e6fef26a15e94Edwin Vane    }
166c8f03423e23d4e093d8149fd924e6fef26a15e94Edwin Vane    if (Other)
167c8f03423e23d4e093d8149fd924e6fef26a15e94Edwin Vane      Other->HandleDiagnostic(DiagLevel, Info);
168c8f03423e23d4e093d8149fd924e6fef26a15e94Edwin Vane  }
169c8f03423e23d4e093d8149fd924e6fef26a15e94Edwin Vane
170c8f03423e23d4e093d8149fd924e6fef26a15e94Edwin Vane  DiagnosticConsumer *Other;
171c8f03423e23d4e093d8149fd924e6fef26a15e94Edwin Vane  SmallVector<std::string, 2> UnusedInputs;
172c8f03423e23d4e093d8149fd924e6fef26a15e94Edwin Vane};
173c8f03423e23d4e093d8149fd924e6fef26a15e94Edwin Vane
174c8f03423e23d4e093d8149fd924e6fef26a15e94Edwin Vane// Unary functor for asking "Given a StringRef S1, does there exist a string
175c8f03423e23d4e093d8149fd924e6fef26a15e94Edwin Vane// S2 in Arr where S1 == S2?"
176c8f03423e23d4e093d8149fd924e6fef26a15e94Edwin Vanestruct MatchesAny {
177c8f03423e23d4e093d8149fd924e6fef26a15e94Edwin Vane  MatchesAny(ArrayRef<std::string> Arr) : Arr(Arr) {}
178c8f03423e23d4e093d8149fd924e6fef26a15e94Edwin Vane  bool operator() (StringRef S) {
179c8f03423e23d4e093d8149fd924e6fef26a15e94Edwin Vane    for (const std::string *I = Arr.begin(), *E = Arr.end(); I != E; ++I)
180c8f03423e23d4e093d8149fd924e6fef26a15e94Edwin Vane      if (*I == S)
181c8f03423e23d4e093d8149fd924e6fef26a15e94Edwin Vane        return true;
182c8f03423e23d4e093d8149fd924e6fef26a15e94Edwin Vane    return false;
183c8f03423e23d4e093d8149fd924e6fef26a15e94Edwin Vane  }
184c8f03423e23d4e093d8149fd924e6fef26a15e94Edwin Vaneprivate:
185c8f03423e23d4e093d8149fd924e6fef26a15e94Edwin Vane  ArrayRef<std::string> Arr;
186c8f03423e23d4e093d8149fd924e6fef26a15e94Edwin Vane};
187c8f03423e23d4e093d8149fd924e6fef26a15e94Edwin Vane
188c8f03423e23d4e093d8149fd924e6fef26a15e94Edwin Vane/// \brief Strips any positional args and possible argv[0] from a command-line
189c8f03423e23d4e093d8149fd924e6fef26a15e94Edwin Vane/// provided by the user to construct a FixedCompilationDatabase.
190c8f03423e23d4e093d8149fd924e6fef26a15e94Edwin Vane///
191c8f03423e23d4e093d8149fd924e6fef26a15e94Edwin Vane/// FixedCompilationDatabase requires a command line to be in this format as it
192c8f03423e23d4e093d8149fd924e6fef26a15e94Edwin Vane/// constructs the command line for each file by appending the name of the file
193c8f03423e23d4e093d8149fd924e6fef26a15e94Edwin Vane/// to be compiled. FixedCompilationDatabase also adds its own argv[0] to the
194c8f03423e23d4e093d8149fd924e6fef26a15e94Edwin Vane/// start of the command line although its value is not important as it's just
195c8f03423e23d4e093d8149fd924e6fef26a15e94Edwin Vane/// ignored by the Driver invoked by the ClangTool using the
196c8f03423e23d4e093d8149fd924e6fef26a15e94Edwin Vane/// FixedCompilationDatabase.
197c8f03423e23d4e093d8149fd924e6fef26a15e94Edwin Vane///
198c8f03423e23d4e093d8149fd924e6fef26a15e94Edwin Vane/// FIXME: This functionality should probably be made available by
199c8f03423e23d4e093d8149fd924e6fef26a15e94Edwin Vane/// clang::driver::Driver although what the interface should look like is not
200c8f03423e23d4e093d8149fd924e6fef26a15e94Edwin Vane/// clear.
201c8f03423e23d4e093d8149fd924e6fef26a15e94Edwin Vane///
202c8f03423e23d4e093d8149fd924e6fef26a15e94Edwin Vane/// \param[in] Args Args as provided by the user.
203f2e479edc8156e1d8d17c5289b41113d7408ac35NAKAMURA Takumi/// \return Resulting stripped command line.
204f2e479edc8156e1d8d17c5289b41113d7408ac35NAKAMURA Takumi///          \li true if successful.
205c8f03423e23d4e093d8149fd924e6fef26a15e94Edwin Vane///          \li false if \c Args cannot be used for compilation jobs (e.g.
206c8f03423e23d4e093d8149fd924e6fef26a15e94Edwin Vane///          contains an option like -E or -version).
207651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesstatic bool stripPositionalArgs(std::vector<const char *> Args,
208651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                                std::vector<std::string> &Result) {
209c8f03423e23d4e093d8149fd924e6fef26a15e94Edwin Vane  IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts = new DiagnosticOptions();
210c8f03423e23d4e093d8149fd924e6fef26a15e94Edwin Vane  UnusedInputDiagConsumer DiagClient;
211c8f03423e23d4e093d8149fd924e6fef26a15e94Edwin Vane  DiagnosticsEngine Diagnostics(
212c8f03423e23d4e093d8149fd924e6fef26a15e94Edwin Vane      IntrusiveRefCntPtr<clang::DiagnosticIDs>(new DiagnosticIDs()),
213c8f03423e23d4e093d8149fd924e6fef26a15e94Edwin Vane      &*DiagOpts, &DiagClient, false);
214c8f03423e23d4e093d8149fd924e6fef26a15e94Edwin Vane
2156bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  // The clang executable path isn't required since the jobs the driver builds
2166bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  // will not be executed.
217651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  std::unique_ptr<driver::Driver> NewDriver(new driver::Driver(
218c8f03423e23d4e093d8149fd924e6fef26a15e94Edwin Vane      /* ClangExecutable= */ "", llvm::sys::getDefaultTargetTriple(),
2196bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      Diagnostics));
220c8f03423e23d4e093d8149fd924e6fef26a15e94Edwin Vane  NewDriver->setCheckInputsExist(false);
221c8f03423e23d4e093d8149fd924e6fef26a15e94Edwin Vane
222c8f03423e23d4e093d8149fd924e6fef26a15e94Edwin Vane  // This becomes the new argv[0]. The value is actually not important as it
223c8f03423e23d4e093d8149fd924e6fef26a15e94Edwin Vane  // isn't used for invoking Tools.
224c8f03423e23d4e093d8149fd924e6fef26a15e94Edwin Vane  Args.insert(Args.begin(), "clang-tool");
225c8f03423e23d4e093d8149fd924e6fef26a15e94Edwin Vane
226c8f03423e23d4e093d8149fd924e6fef26a15e94Edwin Vane  // By adding -c, we force the driver to treat compilation as the last phase.
227c8f03423e23d4e093d8149fd924e6fef26a15e94Edwin Vane  // It will then issue warnings via Diagnostics about un-used options that
228c8f03423e23d4e093d8149fd924e6fef26a15e94Edwin Vane  // would have been used for linking. If the user provided a compiler name as
229c8f03423e23d4e093d8149fd924e6fef26a15e94Edwin Vane  // the original argv[0], this will be treated as a linker input thanks to
230c8f03423e23d4e093d8149fd924e6fef26a15e94Edwin Vane  // insertng a new argv[0] above. All un-used options get collected by
231c8f03423e23d4e093d8149fd924e6fef26a15e94Edwin Vane  // UnusedInputdiagConsumer and get stripped out later.
232c8f03423e23d4e093d8149fd924e6fef26a15e94Edwin Vane  Args.push_back("-c");
233c8f03423e23d4e093d8149fd924e6fef26a15e94Edwin Vane
234c8f03423e23d4e093d8149fd924e6fef26a15e94Edwin Vane  // Put a dummy C++ file on to ensure there's at least one compile job for the
235c8f03423e23d4e093d8149fd924e6fef26a15e94Edwin Vane  // driver to construct. If the user specified some other argument that
236c8f03423e23d4e093d8149fd924e6fef26a15e94Edwin Vane  // prevents compilation, e.g. -E or something like -version, we may still end
237c8f03423e23d4e093d8149fd924e6fef26a15e94Edwin Vane  // up with no jobs but then this is the user's fault.
238c8f03423e23d4e093d8149fd924e6fef26a15e94Edwin Vane  Args.push_back("placeholder.cpp");
239c8f03423e23d4e093d8149fd924e6fef26a15e94Edwin Vane
240651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  // Remove -no-integrated-as; it's not used for syntax checking,
241651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  // and it confuses targets which don't support this option.
2426bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  Args.erase(std::remove_if(Args.begin(), Args.end(),
2436bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines                            MatchesAny(std::string("-no-integrated-as"))),
2446bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines             Args.end());
245651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
246651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  const std::unique_ptr<driver::Compilation> Compilation(
247c8f03423e23d4e093d8149fd924e6fef26a15e94Edwin Vane      NewDriver->BuildCompilation(Args));
248c8f03423e23d4e093d8149fd924e6fef26a15e94Edwin Vane
249c8f03423e23d4e093d8149fd924e6fef26a15e94Edwin Vane  const driver::JobList &Jobs = Compilation->getJobs();
250c8f03423e23d4e093d8149fd924e6fef26a15e94Edwin Vane
251c8f03423e23d4e093d8149fd924e6fef26a15e94Edwin Vane  CompileJobAnalyzer CompileAnalyzer;
252c8f03423e23d4e093d8149fd924e6fef26a15e94Edwin Vane
253c8f03423e23d4e093d8149fd924e6fef26a15e94Edwin Vane  for (driver::JobList::const_iterator I = Jobs.begin(), E = Jobs.end(); I != E;
254c8f03423e23d4e093d8149fd924e6fef26a15e94Edwin Vane       ++I) {
255c8f03423e23d4e093d8149fd924e6fef26a15e94Edwin Vane    if ((*I)->getKind() == driver::Job::CommandClass) {
256c8f03423e23d4e093d8149fd924e6fef26a15e94Edwin Vane      const driver::Command *Cmd = cast<driver::Command>(*I);
257c8f03423e23d4e093d8149fd924e6fef26a15e94Edwin Vane      // Collect only for Assemble jobs. If we do all jobs we get duplicates
258c8f03423e23d4e093d8149fd924e6fef26a15e94Edwin Vane      // since Link jobs point to Assemble jobs as inputs.
259c8f03423e23d4e093d8149fd924e6fef26a15e94Edwin Vane      if (Cmd->getSource().getKind() == driver::Action::AssembleJobClass)
260c8f03423e23d4e093d8149fd924e6fef26a15e94Edwin Vane        CompileAnalyzer.run(&Cmd->getSource());
261c8f03423e23d4e093d8149fd924e6fef26a15e94Edwin Vane    }
262c8f03423e23d4e093d8149fd924e6fef26a15e94Edwin Vane  }
263c8f03423e23d4e093d8149fd924e6fef26a15e94Edwin Vane
264c8f03423e23d4e093d8149fd924e6fef26a15e94Edwin Vane  if (CompileAnalyzer.Inputs.empty()) {
265c8f03423e23d4e093d8149fd924e6fef26a15e94Edwin Vane    // No compile jobs found.
266c8f03423e23d4e093d8149fd924e6fef26a15e94Edwin Vane    // FIXME: Emit a warning of some kind?
267c8f03423e23d4e093d8149fd924e6fef26a15e94Edwin Vane    return false;
268c8f03423e23d4e093d8149fd924e6fef26a15e94Edwin Vane  }
269c8f03423e23d4e093d8149fd924e6fef26a15e94Edwin Vane
270c8f03423e23d4e093d8149fd924e6fef26a15e94Edwin Vane  // Remove all compilation input files from the command line. This is
271c8f03423e23d4e093d8149fd924e6fef26a15e94Edwin Vane  // necessary so that getCompileCommands() can construct a command line for
272c8f03423e23d4e093d8149fd924e6fef26a15e94Edwin Vane  // each file.
273c8f03423e23d4e093d8149fd924e6fef26a15e94Edwin Vane  std::vector<const char *>::iterator End = std::remove_if(
274c8f03423e23d4e093d8149fd924e6fef26a15e94Edwin Vane      Args.begin(), Args.end(), MatchesAny(CompileAnalyzer.Inputs));
275c8f03423e23d4e093d8149fd924e6fef26a15e94Edwin Vane
276c8f03423e23d4e093d8149fd924e6fef26a15e94Edwin Vane  // Remove all inputs deemed unused for compilation.
277c8f03423e23d4e093d8149fd924e6fef26a15e94Edwin Vane  End = std::remove_if(Args.begin(), End, MatchesAny(DiagClient.UnusedInputs));
278c8f03423e23d4e093d8149fd924e6fef26a15e94Edwin Vane
279c8f03423e23d4e093d8149fd924e6fef26a15e94Edwin Vane  // Remove the -c add above as well. It will be at the end right now.
280651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  assert(strcmp(*(End - 1), "-c") == 0);
281c8f03423e23d4e093d8149fd924e6fef26a15e94Edwin Vane  --End;
282c8f03423e23d4e093d8149fd924e6fef26a15e94Edwin Vane
283c8f03423e23d4e093d8149fd924e6fef26a15e94Edwin Vane  Result = std::vector<std::string>(Args.begin() + 1, End);
284c8f03423e23d4e093d8149fd924e6fef26a15e94Edwin Vane  return true;
285c8f03423e23d4e093d8149fd924e6fef26a15e94Edwin Vane}
286c8f03423e23d4e093d8149fd924e6fef26a15e94Edwin Vane
28730318e6df9c8c24d080211dfb92ef8065fa7381cManuel KlimekFixedCompilationDatabase *
28830318e6df9c8c24d080211dfb92ef8065fa7381cManuel KlimekFixedCompilationDatabase::loadFromCommandLine(int &Argc,
28930318e6df9c8c24d080211dfb92ef8065fa7381cManuel Klimek                                              const char **Argv,
29030318e6df9c8c24d080211dfb92ef8065fa7381cManuel Klimek                                              Twine Directory) {
29130318e6df9c8c24d080211dfb92ef8065fa7381cManuel Klimek  const char **DoubleDash = std::find(Argv, Argv + Argc, StringRef("--"));
29230318e6df9c8c24d080211dfb92ef8065fa7381cManuel Klimek  if (DoubleDash == Argv + Argc)
2936bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    return nullptr;
294c8f03423e23d4e093d8149fd924e6fef26a15e94Edwin Vane  std::vector<const char *> CommandLine(DoubleDash + 1, Argv + Argc);
29530318e6df9c8c24d080211dfb92ef8065fa7381cManuel Klimek  Argc = DoubleDash - Argv;
296c8f03423e23d4e093d8149fd924e6fef26a15e94Edwin Vane
297c8f03423e23d4e093d8149fd924e6fef26a15e94Edwin Vane  std::vector<std::string> StrippedArgs;
298c8f03423e23d4e093d8149fd924e6fef26a15e94Edwin Vane  if (!stripPositionalArgs(CommandLine, StrippedArgs))
2996bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    return nullptr;
300c8f03423e23d4e093d8149fd924e6fef26a15e94Edwin Vane  return new FixedCompilationDatabase(Directory, StrippedArgs);
30130318e6df9c8c24d080211dfb92ef8065fa7381cManuel Klimek}
30230318e6df9c8c24d080211dfb92ef8065fa7381cManuel Klimek
30330318e6df9c8c24d080211dfb92ef8065fa7381cManuel KlimekFixedCompilationDatabase::
30430318e6df9c8c24d080211dfb92ef8065fa7381cManuel KlimekFixedCompilationDatabase(Twine Directory, ArrayRef<std::string> CommandLine) {
30530318e6df9c8c24d080211dfb92ef8065fa7381cManuel Klimek  std::vector<std::string> ToolCommandLine(1, "clang-tool");
30630318e6df9c8c24d080211dfb92ef8065fa7381cManuel Klimek  ToolCommandLine.insert(ToolCommandLine.end(),
30730318e6df9c8c24d080211dfb92ef8065fa7381cManuel Klimek                         CommandLine.begin(), CommandLine.end());
308651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  CompileCommands.push_back(
309651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      CompileCommand(Directory, std::move(ToolCommandLine)));
31030318e6df9c8c24d080211dfb92ef8065fa7381cManuel Klimek}
31130318e6df9c8c24d080211dfb92ef8065fa7381cManuel Klimek
31230318e6df9c8c24d080211dfb92ef8065fa7381cManuel Klimekstd::vector<CompileCommand>
31330318e6df9c8c24d080211dfb92ef8065fa7381cManuel KlimekFixedCompilationDatabase::getCompileCommands(StringRef FilePath) const {
31430318e6df9c8c24d080211dfb92ef8065fa7381cManuel Klimek  std::vector<CompileCommand> Result(CompileCommands);
31530318e6df9c8c24d080211dfb92ef8065fa7381cManuel Klimek  Result[0].CommandLine.push_back(FilePath);
31630318e6df9c8c24d080211dfb92ef8065fa7381cManuel Klimek  return Result;
31730318e6df9c8c24d080211dfb92ef8065fa7381cManuel Klimek}
31830318e6df9c8c24d080211dfb92ef8065fa7381cManuel Klimek
319a3c70966babdd6c63623470fbba9bb4ec37de4a5Manuel Klimekstd::vector<std::string>
320a3c70966babdd6c63623470fbba9bb4ec37de4a5Manuel KlimekFixedCompilationDatabase::getAllFiles() const {
321a3c70966babdd6c63623470fbba9bb4ec37de4a5Manuel Klimek  return std::vector<std::string>();
322a3c70966babdd6c63623470fbba9bb4ec37de4a5Manuel Klimek}
323a3c70966babdd6c63623470fbba9bb4ec37de4a5Manuel Klimek
3247e96bfb4d507700a122f270a11ce3fc0e8e36c85Argyrios Kyrtzidisstd::vector<CompileCommand>
3257e96bfb4d507700a122f270a11ce3fc0e8e36c85Argyrios KyrtzidisFixedCompilationDatabase::getAllCompileCommands() const {
3267e96bfb4d507700a122f270a11ce3fc0e8e36c85Argyrios Kyrtzidis  return std::vector<CompileCommand>();
3277e96bfb4d507700a122f270a11ce3fc0e8e36c85Argyrios Kyrtzidis}
3287e96bfb4d507700a122f270a11ce3fc0e8e36c85Argyrios Kyrtzidis
3297fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper// This anchor is used to force the linker to link in the generated object file
3307fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper// and thus register the JSONCompilationDatabasePlugin.
3317fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasperextern volatile int JSONAnchorSource;
3327fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasperstatic int JSONAnchorDest = JSONAnchorSource;
333cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek
334cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek} // end namespace tooling
335cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek} // end namespace clang
336