xref: /minix3/external/bsd/llvm/dist/clang/lib/Tooling/Tooling.cpp (revision f4a2713ac843a11c696ec80c0a5e3e5d80b4d338)
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