1*f4a2713aSLionel Sambuc //===--- Tooling.cpp - Running clang standalone tools ---------------------===// 2*f4a2713aSLionel Sambuc // 3*f4a2713aSLionel Sambuc // The LLVM Compiler Infrastructure 4*f4a2713aSLionel Sambuc // 5*f4a2713aSLionel Sambuc // This file is distributed under the University of Illinois Open Source 6*f4a2713aSLionel Sambuc // License. See LICENSE.TXT for details. 7*f4a2713aSLionel Sambuc // 8*f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===// 9*f4a2713aSLionel Sambuc // 10*f4a2713aSLionel Sambuc // This file implements functions to run clang tools standalone instead 11*f4a2713aSLionel Sambuc // of running them as a plugin. 12*f4a2713aSLionel Sambuc // 13*f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===// 14*f4a2713aSLionel Sambuc 15*f4a2713aSLionel Sambuc #include "clang/Tooling/Tooling.h" 16*f4a2713aSLionel Sambuc #include "clang/AST/ASTConsumer.h" 17*f4a2713aSLionel Sambuc #include "clang/Driver/Compilation.h" 18*f4a2713aSLionel Sambuc #include "clang/Driver/Driver.h" 19*f4a2713aSLionel Sambuc #include "clang/Driver/Tool.h" 20*f4a2713aSLionel Sambuc #include "clang/Frontend/ASTUnit.h" 21*f4a2713aSLionel Sambuc #include "clang/Frontend/CompilerInstance.h" 22*f4a2713aSLionel Sambuc #include "clang/Frontend/FrontendDiagnostic.h" 23*f4a2713aSLionel Sambuc #include "clang/Frontend/TextDiagnosticPrinter.h" 24*f4a2713aSLionel Sambuc #include "clang/Tooling/ArgumentsAdjusters.h" 25*f4a2713aSLionel Sambuc #include "clang/Tooling/CompilationDatabase.h" 26*f4a2713aSLionel Sambuc #include "llvm/ADT/STLExtras.h" 27*f4a2713aSLionel Sambuc #include "llvm/Option/Option.h" 28*f4a2713aSLionel Sambuc #include "llvm/Support/Debug.h" 29*f4a2713aSLionel Sambuc #include "llvm/Support/FileSystem.h" 30*f4a2713aSLionel Sambuc #include "llvm/Support/Host.h" 31*f4a2713aSLionel Sambuc #include "llvm/Support/raw_ostream.h" 32*f4a2713aSLionel Sambuc 33*f4a2713aSLionel Sambuc // For chdir, see the comment in ClangTool::run for more information. 34*f4a2713aSLionel Sambuc #ifdef _WIN32 35*f4a2713aSLionel Sambuc # include <direct.h> 36*f4a2713aSLionel Sambuc #else 37*f4a2713aSLionel Sambuc # include <unistd.h> 38*f4a2713aSLionel Sambuc #endif 39*f4a2713aSLionel Sambuc 40*f4a2713aSLionel Sambuc namespace clang { 41*f4a2713aSLionel Sambuc namespace tooling { 42*f4a2713aSLionel Sambuc 43*f4a2713aSLionel Sambuc ToolAction::~ToolAction() {} 44*f4a2713aSLionel Sambuc 45*f4a2713aSLionel Sambuc FrontendActionFactory::~FrontendActionFactory() {} 46*f4a2713aSLionel Sambuc 47*f4a2713aSLionel Sambuc // FIXME: This file contains structural duplication with other parts of the 48*f4a2713aSLionel Sambuc // code that sets up a compiler to run tools on it, and we should refactor 49*f4a2713aSLionel Sambuc // it to be based on the same framework. 50*f4a2713aSLionel Sambuc 51*f4a2713aSLionel Sambuc /// \brief Builds a clang driver initialized for running clang tools. 52*f4a2713aSLionel Sambuc static clang::driver::Driver *newDriver(clang::DiagnosticsEngine *Diagnostics, 53*f4a2713aSLionel Sambuc const char *BinaryName) { 54*f4a2713aSLionel Sambuc const std::string DefaultOutputName = "a.out"; 55*f4a2713aSLionel Sambuc clang::driver::Driver *CompilerDriver = new clang::driver::Driver( 56*f4a2713aSLionel Sambuc BinaryName, llvm::sys::getDefaultTargetTriple(), 57*f4a2713aSLionel Sambuc DefaultOutputName, *Diagnostics); 58*f4a2713aSLionel Sambuc CompilerDriver->setTitle("clang_based_tool"); 59*f4a2713aSLionel Sambuc return CompilerDriver; 60*f4a2713aSLionel Sambuc } 61*f4a2713aSLionel Sambuc 62*f4a2713aSLionel Sambuc /// \brief Retrieves the clang CC1 specific flags out of the compilation's jobs. 63*f4a2713aSLionel Sambuc /// 64*f4a2713aSLionel Sambuc /// Returns NULL on error. 65*f4a2713aSLionel Sambuc static const llvm::opt::ArgStringList *getCC1Arguments( 66*f4a2713aSLionel Sambuc clang::DiagnosticsEngine *Diagnostics, 67*f4a2713aSLionel Sambuc clang::driver::Compilation *Compilation) { 68*f4a2713aSLionel Sambuc // We expect to get back exactly one Command job, if we didn't something 69*f4a2713aSLionel Sambuc // failed. Extract that job from the Compilation. 70*f4a2713aSLionel Sambuc const clang::driver::JobList &Jobs = Compilation->getJobs(); 71*f4a2713aSLionel Sambuc if (Jobs.size() != 1 || !isa<clang::driver::Command>(*Jobs.begin())) { 72*f4a2713aSLionel Sambuc SmallString<256> error_msg; 73*f4a2713aSLionel Sambuc llvm::raw_svector_ostream error_stream(error_msg); 74*f4a2713aSLionel Sambuc Jobs.Print(error_stream, "; ", true); 75*f4a2713aSLionel Sambuc Diagnostics->Report(clang::diag::err_fe_expected_compiler_job) 76*f4a2713aSLionel Sambuc << error_stream.str(); 77*f4a2713aSLionel Sambuc return NULL; 78*f4a2713aSLionel Sambuc } 79*f4a2713aSLionel Sambuc 80*f4a2713aSLionel Sambuc // The one job we find should be to invoke clang again. 81*f4a2713aSLionel Sambuc const clang::driver::Command *Cmd = 82*f4a2713aSLionel Sambuc cast<clang::driver::Command>(*Jobs.begin()); 83*f4a2713aSLionel Sambuc if (StringRef(Cmd->getCreator().getName()) != "clang") { 84*f4a2713aSLionel Sambuc Diagnostics->Report(clang::diag::err_fe_expected_clang_command); 85*f4a2713aSLionel Sambuc return NULL; 86*f4a2713aSLionel Sambuc } 87*f4a2713aSLionel Sambuc 88*f4a2713aSLionel Sambuc return &Cmd->getArguments(); 89*f4a2713aSLionel Sambuc } 90*f4a2713aSLionel Sambuc 91*f4a2713aSLionel Sambuc /// \brief Returns a clang build invocation initialized from the CC1 flags. 92*f4a2713aSLionel Sambuc static clang::CompilerInvocation *newInvocation( 93*f4a2713aSLionel Sambuc clang::DiagnosticsEngine *Diagnostics, 94*f4a2713aSLionel Sambuc const llvm::opt::ArgStringList &CC1Args) { 95*f4a2713aSLionel Sambuc assert(!CC1Args.empty() && "Must at least contain the program name!"); 96*f4a2713aSLionel Sambuc clang::CompilerInvocation *Invocation = new clang::CompilerInvocation; 97*f4a2713aSLionel Sambuc clang::CompilerInvocation::CreateFromArgs( 98*f4a2713aSLionel Sambuc *Invocation, CC1Args.data() + 1, CC1Args.data() + CC1Args.size(), 99*f4a2713aSLionel Sambuc *Diagnostics); 100*f4a2713aSLionel Sambuc Invocation->getFrontendOpts().DisableFree = false; 101*f4a2713aSLionel Sambuc Invocation->getCodeGenOpts().DisableFree = false; 102*f4a2713aSLionel Sambuc return Invocation; 103*f4a2713aSLionel Sambuc } 104*f4a2713aSLionel Sambuc 105*f4a2713aSLionel Sambuc bool runToolOnCode(clang::FrontendAction *ToolAction, const Twine &Code, 106*f4a2713aSLionel Sambuc const Twine &FileName) { 107*f4a2713aSLionel Sambuc return runToolOnCodeWithArgs( 108*f4a2713aSLionel Sambuc ToolAction, Code, std::vector<std::string>(), FileName); 109*f4a2713aSLionel Sambuc } 110*f4a2713aSLionel Sambuc 111*f4a2713aSLionel Sambuc static std::vector<std::string> 112*f4a2713aSLionel Sambuc getSyntaxOnlyToolArgs(const std::vector<std::string> &ExtraArgs, 113*f4a2713aSLionel Sambuc StringRef FileName) { 114*f4a2713aSLionel Sambuc std::vector<std::string> Args; 115*f4a2713aSLionel Sambuc Args.push_back("clang-tool"); 116*f4a2713aSLionel Sambuc Args.push_back("-fsyntax-only"); 117*f4a2713aSLionel Sambuc Args.insert(Args.end(), ExtraArgs.begin(), ExtraArgs.end()); 118*f4a2713aSLionel Sambuc Args.push_back(FileName.str()); 119*f4a2713aSLionel Sambuc return Args; 120*f4a2713aSLionel Sambuc } 121*f4a2713aSLionel Sambuc 122*f4a2713aSLionel Sambuc bool runToolOnCodeWithArgs(clang::FrontendAction *ToolAction, const Twine &Code, 123*f4a2713aSLionel Sambuc const std::vector<std::string> &Args, 124*f4a2713aSLionel Sambuc const Twine &FileName) { 125*f4a2713aSLionel Sambuc SmallString<16> FileNameStorage; 126*f4a2713aSLionel Sambuc StringRef FileNameRef = FileName.toNullTerminatedStringRef(FileNameStorage); 127*f4a2713aSLionel Sambuc llvm::IntrusiveRefCntPtr<FileManager> Files( 128*f4a2713aSLionel Sambuc new FileManager(FileSystemOptions())); 129*f4a2713aSLionel Sambuc ToolInvocation Invocation(getSyntaxOnlyToolArgs(Args, FileNameRef), ToolAction, 130*f4a2713aSLionel Sambuc Files.getPtr()); 131*f4a2713aSLionel Sambuc 132*f4a2713aSLionel Sambuc SmallString<1024> CodeStorage; 133*f4a2713aSLionel Sambuc Invocation.mapVirtualFile(FileNameRef, 134*f4a2713aSLionel Sambuc Code.toNullTerminatedStringRef(CodeStorage)); 135*f4a2713aSLionel Sambuc return Invocation.run(); 136*f4a2713aSLionel Sambuc } 137*f4a2713aSLionel Sambuc 138*f4a2713aSLionel Sambuc std::string getAbsolutePath(StringRef File) { 139*f4a2713aSLionel Sambuc StringRef RelativePath(File); 140*f4a2713aSLionel Sambuc // FIXME: Should '.\\' be accepted on Win32? 141*f4a2713aSLionel Sambuc if (RelativePath.startswith("./")) { 142*f4a2713aSLionel Sambuc RelativePath = RelativePath.substr(strlen("./")); 143*f4a2713aSLionel Sambuc } 144*f4a2713aSLionel Sambuc 145*f4a2713aSLionel Sambuc SmallString<1024> AbsolutePath = RelativePath; 146*f4a2713aSLionel Sambuc llvm::error_code EC = llvm::sys::fs::make_absolute(AbsolutePath); 147*f4a2713aSLionel Sambuc assert(!EC); 148*f4a2713aSLionel Sambuc (void)EC; 149*f4a2713aSLionel Sambuc llvm::sys::path::native(AbsolutePath); 150*f4a2713aSLionel Sambuc return AbsolutePath.str(); 151*f4a2713aSLionel Sambuc } 152*f4a2713aSLionel Sambuc 153*f4a2713aSLionel Sambuc namespace { 154*f4a2713aSLionel Sambuc 155*f4a2713aSLionel Sambuc class SingleFrontendActionFactory : public FrontendActionFactory { 156*f4a2713aSLionel Sambuc FrontendAction *Action; 157*f4a2713aSLionel Sambuc 158*f4a2713aSLionel Sambuc public: 159*f4a2713aSLionel Sambuc SingleFrontendActionFactory(FrontendAction *Action) : Action(Action) {} 160*f4a2713aSLionel Sambuc 161*f4a2713aSLionel Sambuc FrontendAction *create() { return Action; } 162*f4a2713aSLionel Sambuc }; 163*f4a2713aSLionel Sambuc 164*f4a2713aSLionel Sambuc } 165*f4a2713aSLionel Sambuc 166*f4a2713aSLionel Sambuc ToolInvocation::ToolInvocation(ArrayRef<std::string> CommandLine, 167*f4a2713aSLionel Sambuc ToolAction *Action, FileManager *Files) 168*f4a2713aSLionel Sambuc : CommandLine(CommandLine.vec()), 169*f4a2713aSLionel Sambuc Action(Action), 170*f4a2713aSLionel Sambuc OwnsAction(false), 171*f4a2713aSLionel Sambuc Files(Files), 172*f4a2713aSLionel Sambuc DiagConsumer(NULL) {} 173*f4a2713aSLionel Sambuc 174*f4a2713aSLionel Sambuc ToolInvocation::ToolInvocation(ArrayRef<std::string> CommandLine, 175*f4a2713aSLionel Sambuc FrontendAction *FAction, FileManager *Files) 176*f4a2713aSLionel Sambuc : CommandLine(CommandLine.vec()), 177*f4a2713aSLionel Sambuc Action(new SingleFrontendActionFactory(FAction)), 178*f4a2713aSLionel Sambuc OwnsAction(true), 179*f4a2713aSLionel Sambuc Files(Files), 180*f4a2713aSLionel Sambuc DiagConsumer(NULL) {} 181*f4a2713aSLionel Sambuc 182*f4a2713aSLionel Sambuc ToolInvocation::~ToolInvocation() { 183*f4a2713aSLionel Sambuc if (OwnsAction) 184*f4a2713aSLionel Sambuc delete Action; 185*f4a2713aSLionel Sambuc } 186*f4a2713aSLionel Sambuc 187*f4a2713aSLionel Sambuc void ToolInvocation::setDiagnosticConsumer(DiagnosticConsumer *D) { 188*f4a2713aSLionel Sambuc DiagConsumer = D; 189*f4a2713aSLionel Sambuc } 190*f4a2713aSLionel Sambuc 191*f4a2713aSLionel Sambuc void ToolInvocation::mapVirtualFile(StringRef FilePath, StringRef Content) { 192*f4a2713aSLionel Sambuc SmallString<1024> PathStorage; 193*f4a2713aSLionel Sambuc llvm::sys::path::native(FilePath, PathStorage); 194*f4a2713aSLionel Sambuc MappedFileContents[PathStorage] = Content; 195*f4a2713aSLionel Sambuc } 196*f4a2713aSLionel Sambuc 197*f4a2713aSLionel Sambuc bool ToolInvocation::run() { 198*f4a2713aSLionel Sambuc std::vector<const char*> Argv; 199*f4a2713aSLionel Sambuc for (int I = 0, E = CommandLine.size(); I != E; ++I) 200*f4a2713aSLionel Sambuc Argv.push_back(CommandLine[I].c_str()); 201*f4a2713aSLionel Sambuc const char *const BinaryName = Argv[0]; 202*f4a2713aSLionel Sambuc IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts = new DiagnosticOptions(); 203*f4a2713aSLionel Sambuc TextDiagnosticPrinter DiagnosticPrinter( 204*f4a2713aSLionel Sambuc llvm::errs(), &*DiagOpts); 205*f4a2713aSLionel Sambuc DiagnosticsEngine Diagnostics( 206*f4a2713aSLionel Sambuc IntrusiveRefCntPtr<clang::DiagnosticIDs>(new DiagnosticIDs()), &*DiagOpts, 207*f4a2713aSLionel Sambuc DiagConsumer ? DiagConsumer : &DiagnosticPrinter, false); 208*f4a2713aSLionel Sambuc 209*f4a2713aSLionel Sambuc const OwningPtr<clang::driver::Driver> Driver( 210*f4a2713aSLionel Sambuc newDriver(&Diagnostics, BinaryName)); 211*f4a2713aSLionel Sambuc // Since the input might only be virtual, don't check whether it exists. 212*f4a2713aSLionel Sambuc Driver->setCheckInputsExist(false); 213*f4a2713aSLionel Sambuc const OwningPtr<clang::driver::Compilation> Compilation( 214*f4a2713aSLionel Sambuc Driver->BuildCompilation(llvm::makeArrayRef(Argv))); 215*f4a2713aSLionel Sambuc const llvm::opt::ArgStringList *const CC1Args = getCC1Arguments( 216*f4a2713aSLionel Sambuc &Diagnostics, Compilation.get()); 217*f4a2713aSLionel Sambuc if (CC1Args == NULL) { 218*f4a2713aSLionel Sambuc return false; 219*f4a2713aSLionel Sambuc } 220*f4a2713aSLionel Sambuc OwningPtr<clang::CompilerInvocation> Invocation( 221*f4a2713aSLionel Sambuc newInvocation(&Diagnostics, *CC1Args)); 222*f4a2713aSLionel Sambuc for (llvm::StringMap<StringRef>::const_iterator 223*f4a2713aSLionel Sambuc It = MappedFileContents.begin(), End = MappedFileContents.end(); 224*f4a2713aSLionel Sambuc It != End; ++It) { 225*f4a2713aSLionel Sambuc // Inject the code as the given file name into the preprocessor options. 226*f4a2713aSLionel Sambuc const llvm::MemoryBuffer *Input = 227*f4a2713aSLionel Sambuc llvm::MemoryBuffer::getMemBuffer(It->getValue()); 228*f4a2713aSLionel Sambuc Invocation->getPreprocessorOpts().addRemappedFile(It->getKey(), Input); 229*f4a2713aSLionel Sambuc } 230*f4a2713aSLionel Sambuc return runInvocation(BinaryName, Compilation.get(), Invocation.take()); 231*f4a2713aSLionel Sambuc } 232*f4a2713aSLionel Sambuc 233*f4a2713aSLionel Sambuc bool ToolInvocation::runInvocation( 234*f4a2713aSLionel Sambuc const char *BinaryName, 235*f4a2713aSLionel Sambuc clang::driver::Compilation *Compilation, 236*f4a2713aSLionel Sambuc clang::CompilerInvocation *Invocation) { 237*f4a2713aSLionel Sambuc // Show the invocation, with -v. 238*f4a2713aSLionel Sambuc if (Invocation->getHeaderSearchOpts().Verbose) { 239*f4a2713aSLionel Sambuc llvm::errs() << "clang Invocation:\n"; 240*f4a2713aSLionel Sambuc Compilation->getJobs().Print(llvm::errs(), "\n", true); 241*f4a2713aSLionel Sambuc llvm::errs() << "\n"; 242*f4a2713aSLionel Sambuc } 243*f4a2713aSLionel Sambuc 244*f4a2713aSLionel Sambuc return Action->runInvocation(Invocation, Files, DiagConsumer); 245*f4a2713aSLionel Sambuc } 246*f4a2713aSLionel Sambuc 247*f4a2713aSLionel Sambuc bool FrontendActionFactory::runInvocation(CompilerInvocation *Invocation, 248*f4a2713aSLionel Sambuc FileManager *Files, 249*f4a2713aSLionel Sambuc DiagnosticConsumer *DiagConsumer) { 250*f4a2713aSLionel Sambuc // Create a compiler instance to handle the actual work. 251*f4a2713aSLionel Sambuc clang::CompilerInstance Compiler; 252*f4a2713aSLionel Sambuc Compiler.setInvocation(Invocation); 253*f4a2713aSLionel Sambuc Compiler.setFileManager(Files); 254*f4a2713aSLionel Sambuc 255*f4a2713aSLionel Sambuc // The FrontendAction can have lifetime requirements for Compiler or its 256*f4a2713aSLionel Sambuc // members, and we need to ensure it's deleted earlier than Compiler. So we 257*f4a2713aSLionel Sambuc // pass it to an OwningPtr declared after the Compiler variable. 258*f4a2713aSLionel Sambuc OwningPtr<FrontendAction> ScopedToolAction(create()); 259*f4a2713aSLionel Sambuc 260*f4a2713aSLionel Sambuc // Create the compilers actual diagnostics engine. 261*f4a2713aSLionel Sambuc Compiler.createDiagnostics(DiagConsumer, /*ShouldOwnClient=*/false); 262*f4a2713aSLionel Sambuc if (!Compiler.hasDiagnostics()) 263*f4a2713aSLionel Sambuc return false; 264*f4a2713aSLionel Sambuc 265*f4a2713aSLionel Sambuc Compiler.createSourceManager(*Files); 266*f4a2713aSLionel Sambuc 267*f4a2713aSLionel Sambuc const bool Success = Compiler.ExecuteAction(*ScopedToolAction); 268*f4a2713aSLionel Sambuc 269*f4a2713aSLionel Sambuc Files->clearStatCaches(); 270*f4a2713aSLionel Sambuc return Success; 271*f4a2713aSLionel Sambuc } 272*f4a2713aSLionel Sambuc 273*f4a2713aSLionel Sambuc ClangTool::ClangTool(const CompilationDatabase &Compilations, 274*f4a2713aSLionel Sambuc ArrayRef<std::string> SourcePaths) 275*f4a2713aSLionel Sambuc : Files(new FileManager(FileSystemOptions())), DiagConsumer(NULL) { 276*f4a2713aSLionel Sambuc ArgsAdjusters.push_back(new ClangStripOutputAdjuster()); 277*f4a2713aSLionel Sambuc ArgsAdjusters.push_back(new ClangSyntaxOnlyAdjuster()); 278*f4a2713aSLionel Sambuc for (unsigned I = 0, E = SourcePaths.size(); I != E; ++I) { 279*f4a2713aSLionel Sambuc SmallString<1024> File(getAbsolutePath(SourcePaths[I])); 280*f4a2713aSLionel Sambuc 281*f4a2713aSLionel Sambuc std::vector<CompileCommand> CompileCommandsForFile = 282*f4a2713aSLionel Sambuc Compilations.getCompileCommands(File.str()); 283*f4a2713aSLionel Sambuc if (!CompileCommandsForFile.empty()) { 284*f4a2713aSLionel Sambuc for (int I = 0, E = CompileCommandsForFile.size(); I != E; ++I) { 285*f4a2713aSLionel Sambuc CompileCommands.push_back(std::make_pair(File.str(), 286*f4a2713aSLionel Sambuc CompileCommandsForFile[I])); 287*f4a2713aSLionel Sambuc } 288*f4a2713aSLionel Sambuc } else { 289*f4a2713aSLionel Sambuc // FIXME: There are two use cases here: doing a fuzzy 290*f4a2713aSLionel Sambuc // "find . -name '*.cc' |xargs tool" match, where as a user I don't care 291*f4a2713aSLionel Sambuc // about the .cc files that were not found, and the use case where I 292*f4a2713aSLionel Sambuc // specify all files I want to run over explicitly, where this should 293*f4a2713aSLionel Sambuc // be an error. We'll want to add an option for this. 294*f4a2713aSLionel Sambuc llvm::outs() << "Skipping " << File << ". Command line not found.\n"; 295*f4a2713aSLionel Sambuc } 296*f4a2713aSLionel Sambuc } 297*f4a2713aSLionel Sambuc } 298*f4a2713aSLionel Sambuc 299*f4a2713aSLionel Sambuc void ClangTool::setDiagnosticConsumer(DiagnosticConsumer *D) { 300*f4a2713aSLionel Sambuc DiagConsumer = D; 301*f4a2713aSLionel Sambuc } 302*f4a2713aSLionel Sambuc 303*f4a2713aSLionel Sambuc void ClangTool::mapVirtualFile(StringRef FilePath, StringRef Content) { 304*f4a2713aSLionel Sambuc MappedFileContents.push_back(std::make_pair(FilePath, Content)); 305*f4a2713aSLionel Sambuc } 306*f4a2713aSLionel Sambuc 307*f4a2713aSLionel Sambuc void ClangTool::setArgumentsAdjuster(ArgumentsAdjuster *Adjuster) { 308*f4a2713aSLionel Sambuc clearArgumentsAdjusters(); 309*f4a2713aSLionel Sambuc appendArgumentsAdjuster(Adjuster); 310*f4a2713aSLionel Sambuc } 311*f4a2713aSLionel Sambuc 312*f4a2713aSLionel Sambuc void ClangTool::appendArgumentsAdjuster(ArgumentsAdjuster *Adjuster) { 313*f4a2713aSLionel Sambuc ArgsAdjusters.push_back(Adjuster); 314*f4a2713aSLionel Sambuc } 315*f4a2713aSLionel Sambuc 316*f4a2713aSLionel Sambuc void ClangTool::clearArgumentsAdjusters() { 317*f4a2713aSLionel Sambuc for (unsigned I = 0, E = ArgsAdjusters.size(); I != E; ++I) 318*f4a2713aSLionel Sambuc delete ArgsAdjusters[I]; 319*f4a2713aSLionel Sambuc ArgsAdjusters.clear(); 320*f4a2713aSLionel Sambuc } 321*f4a2713aSLionel Sambuc 322*f4a2713aSLionel Sambuc int ClangTool::run(ToolAction *Action) { 323*f4a2713aSLionel Sambuc // Exists solely for the purpose of lookup of the resource path. 324*f4a2713aSLionel Sambuc // This just needs to be some symbol in the binary. 325*f4a2713aSLionel Sambuc static int StaticSymbol; 326*f4a2713aSLionel Sambuc // The driver detects the builtin header path based on the path of the 327*f4a2713aSLionel Sambuc // executable. 328*f4a2713aSLionel Sambuc // FIXME: On linux, GetMainExecutable is independent of the value of the 329*f4a2713aSLionel Sambuc // first argument, thus allowing ClangTool and runToolOnCode to just 330*f4a2713aSLionel Sambuc // pass in made-up names here. Make sure this works on other platforms. 331*f4a2713aSLionel Sambuc std::string MainExecutable = 332*f4a2713aSLionel Sambuc llvm::sys::fs::getMainExecutable("clang_tool", &StaticSymbol); 333*f4a2713aSLionel Sambuc 334*f4a2713aSLionel Sambuc bool ProcessingFailed = false; 335*f4a2713aSLionel Sambuc for (unsigned I = 0; I < CompileCommands.size(); ++I) { 336*f4a2713aSLionel Sambuc std::string File = CompileCommands[I].first; 337*f4a2713aSLionel Sambuc // FIXME: chdir is thread hostile; on the other hand, creating the same 338*f4a2713aSLionel Sambuc // behavior as chdir is complex: chdir resolves the path once, thus 339*f4a2713aSLionel Sambuc // guaranteeing that all subsequent relative path operations work 340*f4a2713aSLionel Sambuc // on the same path the original chdir resulted in. This makes a difference 341*f4a2713aSLionel Sambuc // for example on network filesystems, where symlinks might be switched 342*f4a2713aSLionel Sambuc // during runtime of the tool. Fixing this depends on having a file system 343*f4a2713aSLionel Sambuc // abstraction that allows openat() style interactions. 344*f4a2713aSLionel Sambuc if (chdir(CompileCommands[I].second.Directory.c_str())) 345*f4a2713aSLionel Sambuc llvm::report_fatal_error("Cannot chdir into \"" + 346*f4a2713aSLionel Sambuc CompileCommands[I].second.Directory + "\n!"); 347*f4a2713aSLionel Sambuc std::vector<std::string> CommandLine = CompileCommands[I].second.CommandLine; 348*f4a2713aSLionel Sambuc for (unsigned I = 0, E = ArgsAdjusters.size(); I != E; ++I) 349*f4a2713aSLionel Sambuc CommandLine = ArgsAdjusters[I]->Adjust(CommandLine); 350*f4a2713aSLionel Sambuc assert(!CommandLine.empty()); 351*f4a2713aSLionel Sambuc CommandLine[0] = MainExecutable; 352*f4a2713aSLionel Sambuc // FIXME: We need a callback mechanism for the tool writer to output a 353*f4a2713aSLionel Sambuc // customized message for each file. 354*f4a2713aSLionel Sambuc DEBUG({ 355*f4a2713aSLionel Sambuc llvm::dbgs() << "Processing: " << File << ".\n"; 356*f4a2713aSLionel Sambuc }); 357*f4a2713aSLionel Sambuc ToolInvocation Invocation(CommandLine, Action, Files.getPtr()); 358*f4a2713aSLionel Sambuc Invocation.setDiagnosticConsumer(DiagConsumer); 359*f4a2713aSLionel Sambuc for (int I = 0, E = MappedFileContents.size(); I != E; ++I) { 360*f4a2713aSLionel Sambuc Invocation.mapVirtualFile(MappedFileContents[I].first, 361*f4a2713aSLionel Sambuc MappedFileContents[I].second); 362*f4a2713aSLionel Sambuc } 363*f4a2713aSLionel Sambuc if (!Invocation.run()) { 364*f4a2713aSLionel Sambuc // FIXME: Diagnostics should be used instead. 365*f4a2713aSLionel Sambuc llvm::errs() << "Error while processing " << File << ".\n"; 366*f4a2713aSLionel Sambuc ProcessingFailed = true; 367*f4a2713aSLionel Sambuc } 368*f4a2713aSLionel Sambuc } 369*f4a2713aSLionel Sambuc return ProcessingFailed ? 1 : 0; 370*f4a2713aSLionel Sambuc } 371*f4a2713aSLionel Sambuc 372*f4a2713aSLionel Sambuc namespace { 373*f4a2713aSLionel Sambuc 374*f4a2713aSLionel Sambuc class ASTBuilderAction : public ToolAction { 375*f4a2713aSLionel Sambuc std::vector<ASTUnit *> &ASTs; 376*f4a2713aSLionel Sambuc 377*f4a2713aSLionel Sambuc public: 378*f4a2713aSLionel Sambuc ASTBuilderAction(std::vector<ASTUnit *> &ASTs) : ASTs(ASTs) {} 379*f4a2713aSLionel Sambuc 380*f4a2713aSLionel Sambuc bool runInvocation(CompilerInvocation *Invocation, FileManager *Files, 381*f4a2713aSLionel Sambuc DiagnosticConsumer *DiagConsumer) { 382*f4a2713aSLionel Sambuc // FIXME: This should use the provided FileManager. 383*f4a2713aSLionel Sambuc ASTUnit *AST = ASTUnit::LoadFromCompilerInvocation( 384*f4a2713aSLionel Sambuc Invocation, CompilerInstance::createDiagnostics( 385*f4a2713aSLionel Sambuc &Invocation->getDiagnosticOpts(), DiagConsumer, 386*f4a2713aSLionel Sambuc /*ShouldOwnClient=*/false)); 387*f4a2713aSLionel Sambuc if (!AST) 388*f4a2713aSLionel Sambuc return false; 389*f4a2713aSLionel Sambuc 390*f4a2713aSLionel Sambuc ASTs.push_back(AST); 391*f4a2713aSLionel Sambuc return true; 392*f4a2713aSLionel Sambuc } 393*f4a2713aSLionel Sambuc }; 394*f4a2713aSLionel Sambuc 395*f4a2713aSLionel Sambuc } 396*f4a2713aSLionel Sambuc 397*f4a2713aSLionel Sambuc int ClangTool::buildASTs(std::vector<ASTUnit *> &ASTs) { 398*f4a2713aSLionel Sambuc ASTBuilderAction Action(ASTs); 399*f4a2713aSLionel Sambuc return run(&Action); 400*f4a2713aSLionel Sambuc } 401*f4a2713aSLionel Sambuc 402*f4a2713aSLionel Sambuc ASTUnit *buildASTFromCode(const Twine &Code, const Twine &FileName) { 403*f4a2713aSLionel Sambuc return buildASTFromCodeWithArgs(Code, std::vector<std::string>(), FileName); 404*f4a2713aSLionel Sambuc } 405*f4a2713aSLionel Sambuc 406*f4a2713aSLionel Sambuc ASTUnit *buildASTFromCodeWithArgs(const Twine &Code, 407*f4a2713aSLionel Sambuc const std::vector<std::string> &Args, 408*f4a2713aSLionel Sambuc const Twine &FileName) { 409*f4a2713aSLionel Sambuc SmallString<16> FileNameStorage; 410*f4a2713aSLionel Sambuc StringRef FileNameRef = FileName.toNullTerminatedStringRef(FileNameStorage); 411*f4a2713aSLionel Sambuc 412*f4a2713aSLionel Sambuc std::vector<ASTUnit *> ASTs; 413*f4a2713aSLionel Sambuc ASTBuilderAction Action(ASTs); 414*f4a2713aSLionel Sambuc ToolInvocation Invocation(getSyntaxOnlyToolArgs(Args, FileNameRef), &Action, 0); 415*f4a2713aSLionel Sambuc 416*f4a2713aSLionel Sambuc SmallString<1024> CodeStorage; 417*f4a2713aSLionel Sambuc Invocation.mapVirtualFile(FileNameRef, 418*f4a2713aSLionel Sambuc Code.toNullTerminatedStringRef(CodeStorage)); 419*f4a2713aSLionel Sambuc if (!Invocation.run()) 420*f4a2713aSLionel Sambuc return 0; 421*f4a2713aSLionel Sambuc 422*f4a2713aSLionel Sambuc assert(ASTs.size() == 1); 423*f4a2713aSLionel Sambuc return ASTs[0]; 424*f4a2713aSLionel Sambuc } 425*f4a2713aSLionel Sambuc 426*f4a2713aSLionel Sambuc } // end namespace tooling 427*f4a2713aSLionel Sambuc } // end namespace clang 428