14a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project//===--- CompilationDatabase.cpp - ----------------------------------------===//
24a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project//
34a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project//                     The LLVM Compiler Infrastructure
44a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project//
54a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project// This file is distributed under the University of Illinois Open Source
64a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project// License. See LICENSE.TXT for details.
74a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project//
84a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project//===----------------------------------------------------------------------===//
94a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project//
104a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project//  This file contains implementations of the CompilationDatabase base class
114a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project//  and the FixedCompilationDatabase.
124a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project//
134a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project//===----------------------------------------------------------------------===//
144a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
154a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#include "clang/Tooling/CompilationDatabase.h"
164a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#include "clang/Basic/Diagnostic.h"
174a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#include "clang/Basic/DiagnosticOptions.h"
184a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#include "clang/Driver/Action.h"
194a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#include "clang/Driver/Compilation.h"
204a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#include "clang/Driver/Driver.h"
214a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#include "clang/Driver/DriverDiagnostic.h"
224a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#include "clang/Driver/Job.h"
234a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#include "clang/Frontend/TextDiagnosticPrinter.h"
244a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#include "clang/Tooling/CompilationDatabasePluginRegistry.h"
254a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#include "clang/Tooling/Tooling.h"
264a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#include "llvm/ADT/SmallString.h"
274a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#include "llvm/Option/Arg.h"
284a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#include "llvm/Support/Host.h"
294a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#include "llvm/Support/Path.h"
304a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#include <sstream>
314a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#include <system_error>
324a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
334a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectnamespace clang {
344a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectnamespace tooling {
354a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
364a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source ProjectCompilationDatabase::~CompilationDatabase() {}
374a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
384a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source ProjectCompilationDatabase *
394a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source ProjectCompilationDatabase::loadFromDirectory(StringRef BuildDirectory,
404a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project                                       std::string &ErrorMessage) {
4115fc15883c8aee2b736e8cc9a31eef071908e4a0Sean McNeil  std::stringstream ErrorStream;
424a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  for (CompilationDatabasePluginRegistry::iterator
434a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project       It = CompilationDatabasePluginRegistry::begin(),
444a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project       Ie = CompilationDatabasePluginRegistry::end();
454a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project       It != Ie; ++It) {
464a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    std::string DatabaseErrorMessage;
474a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    std::unique_ptr<CompilationDatabasePlugin> Plugin(It->instantiate());
484a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    if (CompilationDatabase *DB =
494a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        Plugin->loadFromDirectory(BuildDirectory, DatabaseErrorMessage))
504a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      return DB;
514a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    else
524a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      ErrorStream << It->getName() << ": " << DatabaseErrorMessage << "\n";
534a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
544a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  ErrorMessage = ErrorStream.str();
554a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  return nullptr;
564a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project}
574a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
584a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectstatic CompilationDatabase *
594a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source ProjectfindCompilationDatabaseFromDirectory(StringRef Directory,
604a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project                                     std::string &ErrorMessage) {
614a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  std::stringstream ErrorStream;
624a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  bool HasErrorMessage = false;
634a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  while (!Directory.empty()) {
644a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    std::string LoadErrorMessage;
654a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
664a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    if (CompilationDatabase *DB =
674a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project           CompilationDatabase::loadFromDirectory(Directory, LoadErrorMessage))
684a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      return DB;
694a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
704a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    if (!HasErrorMessage) {
714a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      ErrorStream << "No compilation database found in " << Directory.str()
724a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project                  << " or any parent directory\n" << LoadErrorMessage;
734a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      HasErrorMessage = true;
744a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    }
754a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
764a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    Directory = llvm::sys::path::parent_path(Directory);
774a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
784a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  ErrorMessage = ErrorStream.str();
794a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  return nullptr;
804a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project}
814a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
824a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source ProjectCompilationDatabase *
834a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source ProjectCompilationDatabase::autoDetectFromSource(StringRef SourceFile,
844a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project                                          std::string &ErrorMessage) {
854a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  SmallString<1024> AbsolutePath(getAbsolutePath(SourceFile));
864a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  StringRef Directory = llvm::sys::path::parent_path(AbsolutePath);
874a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
884a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  CompilationDatabase *DB = findCompilationDatabaseFromDirectory(Directory,
894a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project                                                                 ErrorMessage);
904a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
914a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if (!DB)
924a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    ErrorMessage = ("Could not auto-detect compilation database for file \"" +
934a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project                   SourceFile + "\"\n" + ErrorMessage).str();
944a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  return DB;
954a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project}
964a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
974a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source ProjectCompilationDatabase *
984a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source ProjectCompilationDatabase::autoDetectFromDirectory(StringRef SourceDir,
994a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project                                             std::string &ErrorMessage) {
1004a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  SmallString<1024> AbsolutePath(getAbsolutePath(SourceDir));
1014a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
1024a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  CompilationDatabase *DB = findCompilationDatabaseFromDirectory(AbsolutePath,
1034a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project                                                                 ErrorMessage);
1044a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
1054a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if (!DB)
1064a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    ErrorMessage = ("Could not auto-detect compilation database from directory \"" +
1074a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project                   SourceDir + "\"\n" + ErrorMessage).str();
1084a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  return DB;
1094a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project}
1104a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
1114a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source ProjectCompilationDatabasePlugin::~CompilationDatabasePlugin() {}
1124a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
1134a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project// Helper for recursively searching through a chain of actions and collecting
1144a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project// all inputs, direct and indirect, of compile jobs.
1154a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectstruct CompileJobAnalyzer {
1164a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  void run(const driver::Action *A) {
1174a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    runImpl(A, false);
1184a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
1194a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
1204a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  SmallVector<std::string, 2> Inputs;
1214a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
1224a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectprivate:
1234a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
1244a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  void runImpl(const driver::Action *A, bool Collect) {
1254a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    bool CollectChildren = Collect;
1264a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    switch (A->getKind()) {
1274a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    case driver::Action::CompileJobClass:
1284a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      CollectChildren = true;
1294a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      break;
1304a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
1314a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    case driver::Action::InputClass: {
1324a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      if (Collect) {
1334a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        const driver::InputAction *IA = cast<driver::InputAction>(A);
1344a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        Inputs.push_back(IA->getInputArg().getSpelling());
1354a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      }
1364a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    } break;
1374a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
1384a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    default:
1394a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      // Don't care about others
1404a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      ;
1414a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    }
1424a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
1434a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    for (driver::ActionList::const_iterator I = A->begin(), E = A->end();
1444a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project         I != E; ++I)
1454a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      runImpl(*I, CollectChildren);
1464a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
1474a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project};
1484a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
1494a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project// Special DiagnosticConsumer that looks for warn_drv_input_file_unused
1504a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project// diagnostics from the driver and collects the option strings for those unused
1514a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project// options.
1524a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectclass UnusedInputDiagConsumer : public DiagnosticConsumer {
1534a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectpublic:
1544a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  UnusedInputDiagConsumer() : Other(nullptr) {}
1554a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
1564a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  // Useful for debugging, chain diagnostics to another consumer after
1574a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  // recording for our own purposes.
1584a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  UnusedInputDiagConsumer(DiagnosticConsumer *Other) : Other(Other) {}
1594a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
1604a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  virtual void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
1614a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project                                const Diagnostic &Info) override {
1624a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    if (Info.getID() == clang::diag::warn_drv_input_file_unused) {
1634a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      // Arg 1 for this diagnostic is the option that didn't get used.
1644a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      UnusedInputs.push_back(Info.getArgStdStr(0));
1654a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    }
1664a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    if (Other)
1674a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      Other->HandleDiagnostic(DiagLevel, Info);
1684a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
1694a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
1704a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  DiagnosticConsumer *Other;
1714a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  SmallVector<std::string, 2> UnusedInputs;
1724a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project};
1734a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
1744a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project// Unary functor for asking "Given a StringRef S1, does there exist a string
1754a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project// S2 in Arr where S1 == S2?"
1764a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectstruct MatchesAny {
1774a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  MatchesAny(ArrayRef<std::string> Arr) : Arr(Arr) {}
1784a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  bool operator() (StringRef S) {
1794a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    for (const std::string *I = Arr.begin(), *E = Arr.end(); I != E; ++I)
1804a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      if (*I == S)
1814a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        return true;
1824a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    return false;
1834a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
1844a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectprivate:
1854a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  ArrayRef<std::string> Arr;
1864a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project};
1874a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
1884a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project/// \brief Strips any positional args and possible argv[0] from a command-line
1894a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project/// provided by the user to construct a FixedCompilationDatabase.
1904a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project///
1914a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project/// FixedCompilationDatabase requires a command line to be in this format as it
1924a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project/// constructs the command line for each file by appending the name of the file
1934a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project/// to be compiled. FixedCompilationDatabase also adds its own argv[0] to the
1944a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project/// start of the command line although its value is not important as it's just
1954a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project/// ignored by the Driver invoked by the ClangTool using the
1964a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project/// FixedCompilationDatabase.
1974a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project///
1984a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project/// FIXME: This functionality should probably be made available by
1994a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project/// clang::driver::Driver although what the interface should look like is not
2004a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project/// clear.
2014a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project///
2024a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project/// \param[in] Args Args as provided by the user.
2034a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project/// \return Resulting stripped command line.
2044a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project///          \li true if successful.
2054a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project///          \li false if \c Args cannot be used for compilation jobs (e.g.
2064a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project///          contains an option like -E or -version).
2074a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectstatic bool stripPositionalArgs(std::vector<const char *> Args,
2084a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project                                std::vector<std::string> &Result) {
2094a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts = new DiagnosticOptions();
2104a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  UnusedInputDiagConsumer DiagClient;
2114a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  DiagnosticsEngine Diagnostics(
2124a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      IntrusiveRefCntPtr<clang::DiagnosticIDs>(new DiagnosticIDs()),
2134a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      &*DiagOpts, &DiagClient, false);
2144a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
2154a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  // The clang executable path isn't required since the jobs the driver builds
2164a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  // will not be executed.
2174a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  std::unique_ptr<driver::Driver> NewDriver(new driver::Driver(
2184a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      /* ClangExecutable= */ "", llvm::sys::getDefaultTargetTriple(),
2194a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      Diagnostics));
2204a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  NewDriver->setCheckInputsExist(false);
2214a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
2224a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  // This becomes the new argv[0]. The value is actually not important as it
2234a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  // isn't used for invoking Tools.
2244a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  Args.insert(Args.begin(), "clang-tool");
2254a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
2264a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  // By adding -c, we force the driver to treat compilation as the last phase.
2274a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  // It will then issue warnings via Diagnostics about un-used options that
2284a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  // would have been used for linking. If the user provided a compiler name as
2294a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  // the original argv[0], this will be treated as a linker input thanks to
2304a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  // insertng a new argv[0] above. All un-used options get collected by
2314a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  // UnusedInputdiagConsumer and get stripped out later.
2324a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  Args.push_back("-c");
2334a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
2344a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  // Put a dummy C++ file on to ensure there's at least one compile job for the
2354a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  // driver to construct. If the user specified some other argument that
2364a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  // prevents compilation, e.g. -E or something like -version, we may still end
2374a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  // up with no jobs but then this is the user's fault.
2384a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  Args.push_back("placeholder.cpp");
2394a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
2404a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  // Remove -no-integrated-as; it's not used for syntax checking,
2414a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  // and it confuses targets which don't support this option.
2424a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  Args.erase(std::remove_if(Args.begin(), Args.end(),
2434a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project                            MatchesAny(std::string("-no-integrated-as"))),
2444a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project             Args.end());
2454a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
2464a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  const std::unique_ptr<driver::Compilation> Compilation(
2474a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      NewDriver->BuildCompilation(Args));
2484a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
2494a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  const driver::JobList &Jobs = Compilation->getJobs();
2504a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
2514a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  CompileJobAnalyzer CompileAnalyzer;
2524a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
2534a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  for (driver::JobList::const_iterator I = Jobs.begin(), E = Jobs.end(); I != E;
2544a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project       ++I) {
2554a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    if ((*I)->getKind() == driver::Job::CommandClass) {
2564a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      const driver::Command *Cmd = cast<driver::Command>(*I);
2574a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      // Collect only for Assemble jobs. If we do all jobs we get duplicates
2584a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      // since Link jobs point to Assemble jobs as inputs.
2594a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      if (Cmd->getSource().getKind() == driver::Action::AssembleJobClass)
2604a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        CompileAnalyzer.run(&Cmd->getSource());
2614a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    }
2624a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
2634a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
2644a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if (CompileAnalyzer.Inputs.empty()) {
2654a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    // No compile jobs found.
2664a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    // FIXME: Emit a warning of some kind?
2674a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    return false;
2684a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
2694a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
2704a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  // Remove all compilation input files from the command line. This is
2714a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  // necessary so that getCompileCommands() can construct a command line for
2724a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  // each file.
2734a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  std::vector<const char *>::iterator End = std::remove_if(
2744a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      Args.begin(), Args.end(), MatchesAny(CompileAnalyzer.Inputs));
2754a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
2764a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  // Remove all inputs deemed unused for compilation.
2774a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  End = std::remove_if(Args.begin(), End, MatchesAny(DiagClient.UnusedInputs));
2784a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
2794a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  // Remove the -c add above as well. It will be at the end right now.
2804a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  assert(strcmp(*(End - 1), "-c") == 0);
2814a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  --End;
2824a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
2834a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  Result = std::vector<std::string>(Args.begin() + 1, End);
2844a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  return true;
2854a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project}
2864a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
2874a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source ProjectFixedCompilationDatabase *
2884a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source ProjectFixedCompilationDatabase::loadFromCommandLine(int &Argc,
2894a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project                                              const char **Argv,
2904a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project                                              Twine Directory) {
2914a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  const char **DoubleDash = std::find(Argv, Argv + Argc, StringRef("--"));
2924a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if (DoubleDash == Argv + Argc)
2934a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    return nullptr;
2944a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  std::vector<const char *> CommandLine(DoubleDash + 1, Argv + Argc);
2954a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  Argc = DoubleDash - Argv;
2964a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
2974a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  std::vector<std::string> StrippedArgs;
2984a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if (!stripPositionalArgs(CommandLine, StrippedArgs))
2994a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    return nullptr;
3004a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  return new FixedCompilationDatabase(Directory, StrippedArgs);
3014a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project}
3024a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
3034a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source ProjectFixedCompilationDatabase::
3044a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source ProjectFixedCompilationDatabase(Twine Directory, ArrayRef<std::string> CommandLine) {
3054a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  std::vector<std::string> ToolCommandLine(1, "clang-tool");
3064a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  ToolCommandLine.insert(ToolCommandLine.end(),
3074a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project                         CommandLine.begin(), CommandLine.end());
3084a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  CompileCommands.push_back(
3094a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      CompileCommand(Directory, std::move(ToolCommandLine)));
3104a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project}
3114a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
3124a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectstd::vector<CompileCommand>
3134a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source ProjectFixedCompilationDatabase::getCompileCommands(StringRef FilePath) const {
3144a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  std::vector<CompileCommand> Result(CompileCommands);
3154a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  Result[0].CommandLine.push_back(FilePath);
3164a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  return Result;
3174a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project}
3184a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
3194a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectstd::vector<std::string>
3204a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source ProjectFixedCompilationDatabase::getAllFiles() const {
3214a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  return std::vector<std::string>();
3224a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project}
3234a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
3244a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectstd::vector<CompileCommand>
3254a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source ProjectFixedCompilationDatabase::getAllCompileCommands() const {
3264a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  return std::vector<CompileCommand>();
3274a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project}
3284a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
3294a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project// This anchor is used to force the linker to link in the generated object file
3304a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project// and thus register the JSONCompilationDatabasePlugin.
3314a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectextern volatile int JSONAnchorSource;
3324a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectstatic int JSONAnchorDest = JSONAnchorSource;
3334a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
3344a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project} // end namespace tooling
3354a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project} // end namespace clang
3364a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project