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