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