comparison clang/lib/Tooling/Tooling.cpp @ 207:2e18cbf3894f

LLVM12
author Shinji KONO <kono@ie.u-ryukyu.ac.jp>
date Tue, 08 Jun 2021 06:07:14 +0900
parents 0572611fdcc8
children c4bab56944e8
comparison
equal deleted inserted replaced
173:0572611fdcc8 207:2e18cbf3894f
76 static driver::Driver * 76 static driver::Driver *
77 newDriver(DiagnosticsEngine *Diagnostics, const char *BinaryName, 77 newDriver(DiagnosticsEngine *Diagnostics, const char *BinaryName,
78 IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS) { 78 IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS) {
79 driver::Driver *CompilerDriver = 79 driver::Driver *CompilerDriver =
80 new driver::Driver(BinaryName, llvm::sys::getDefaultTargetTriple(), 80 new driver::Driver(BinaryName, llvm::sys::getDefaultTargetTriple(),
81 *Diagnostics, std::move(VFS)); 81 *Diagnostics, "clang LLVM compiler", std::move(VFS));
82 CompilerDriver->setTitle("clang_based_tool"); 82 CompilerDriver->setTitle("clang_based_tool");
83 return CompilerDriver; 83 return CompilerDriver;
84 } 84 }
85 85
86 /// Retrieves the clang CC1 specific flags out of the compilation's jobs. 86 /// Retrieves the clang CC1 specific flags out of the compilation's jobs.
139 139
140 namespace clang { 140 namespace clang {
141 namespace tooling { 141 namespace tooling {
142 142
143 /// Returns a clang build invocation initialized from the CC1 flags. 143 /// Returns a clang build invocation initialized from the CC1 flags.
144 CompilerInvocation *newInvocation( 144 CompilerInvocation *newInvocation(DiagnosticsEngine *Diagnostics,
145 DiagnosticsEngine *Diagnostics, const llvm::opt::ArgStringList &CC1Args) { 145 const llvm::opt::ArgStringList &CC1Args,
146 const char *const BinaryName) {
146 assert(!CC1Args.empty() && "Must at least contain the program name!"); 147 assert(!CC1Args.empty() && "Must at least contain the program name!");
147 CompilerInvocation *Invocation = new CompilerInvocation; 148 CompilerInvocation *Invocation = new CompilerInvocation;
148 CompilerInvocation::CreateFromArgs(*Invocation, CC1Args, *Diagnostics); 149 CompilerInvocation::CreateFromArgs(*Invocation, CC1Args, *Diagnostics,
150 BinaryName);
149 Invocation->getFrontendOpts().DisableFree = false; 151 Invocation->getFrontendOpts().DisableFree = false;
150 Invocation->getCodeGenOpts().DisableFree = false; 152 Invocation->getCodeGenOpts().DisableFree = false;
151 return Invocation; 153 return Invocation;
152 } 154 }
153 155
241 return llvm::cantFail(getAbsolutePath(*llvm::vfs::getRealFileSystem(), File)); 243 return llvm::cantFail(getAbsolutePath(*llvm::vfs::getRealFileSystem(), File));
242 } 244 }
243 245
244 void addTargetAndModeForProgramName(std::vector<std::string> &CommandLine, 246 void addTargetAndModeForProgramName(std::vector<std::string> &CommandLine,
245 StringRef InvokedAs) { 247 StringRef InvokedAs) {
246 if (!CommandLine.empty() && !InvokedAs.empty()) { 248 if (CommandLine.empty() || InvokedAs.empty())
247 bool AlreadyHasTarget = false; 249 return;
248 bool AlreadyHasMode = false; 250 const auto &Table = driver::getDriverOptTable();
249 // Skip CommandLine[0]. 251 // --target=X
250 for (auto Token = ++CommandLine.begin(); Token != CommandLine.end(); 252 const std::string TargetOPT =
251 ++Token) { 253 Table.getOption(driver::options::OPT_target).getPrefixedName();
252 StringRef TokenRef(*Token); 254 // -target X
253 AlreadyHasTarget |= 255 const std::string TargetOPTLegacy =
254 (TokenRef == "-target" || TokenRef.startswith("-target=")); 256 Table.getOption(driver::options::OPT_target_legacy_spelling)
255 AlreadyHasMode |= (TokenRef == "--driver-mode" || 257 .getPrefixedName();
256 TokenRef.startswith("--driver-mode=")); 258 // --driver-mode=X
257 } 259 const std::string DriverModeOPT =
258 auto TargetMode = 260 Table.getOption(driver::options::OPT_driver_mode).getPrefixedName();
259 driver::ToolChain::getTargetAndModeFromProgramName(InvokedAs); 261 auto TargetMode =
260 if (!AlreadyHasMode && TargetMode.DriverMode) { 262 driver::ToolChain::getTargetAndModeFromProgramName(InvokedAs);
261 CommandLine.insert(++CommandLine.begin(), TargetMode.DriverMode); 263 // No need to search for target args if we don't have a target/mode to insert.
262 } 264 bool ShouldAddTarget = TargetMode.TargetIsValid;
263 if (!AlreadyHasTarget && TargetMode.TargetIsValid) { 265 bool ShouldAddMode = TargetMode.DriverMode != nullptr;
264 CommandLine.insert(++CommandLine.begin(), {"-target", 266 // Skip CommandLine[0].
265 TargetMode.TargetPrefix}); 267 for (auto Token = ++CommandLine.begin(); Token != CommandLine.end();
266 } 268 ++Token) {
269 StringRef TokenRef(*Token);
270 ShouldAddTarget = ShouldAddTarget && !TokenRef.startswith(TargetOPT) &&
271 !TokenRef.equals(TargetOPTLegacy);
272 ShouldAddMode = ShouldAddMode && !TokenRef.startswith(DriverModeOPT);
273 }
274 if (ShouldAddMode) {
275 CommandLine.insert(++CommandLine.begin(), TargetMode.DriverMode);
276 }
277 if (ShouldAddTarget) {
278 CommandLine.insert(++CommandLine.begin(),
279 TargetOPT + TargetMode.TargetPrefix);
267 } 280 }
268 } 281 }
269 282
270 } // namespace tooling 283 } // namespace tooling
271 } // namespace clang 284 } // namespace clang
302 PCHContainerOps(std::move(PCHContainerOps)) {} 315 PCHContainerOps(std::move(PCHContainerOps)) {}
303 316
304 ToolInvocation::~ToolInvocation() { 317 ToolInvocation::~ToolInvocation() {
305 if (OwnsAction) 318 if (OwnsAction)
306 delete Action; 319 delete Action;
307 }
308
309 void ToolInvocation::mapVirtualFile(StringRef FilePath, StringRef Content) {
310 SmallString<1024> PathStorage;
311 llvm::sys::path::native(FilePath, PathStorage);
312 MappedFileContents[PathStorage] = Content;
313 } 320 }
314 321
315 bool ToolInvocation::run() { 322 bool ToolInvocation::run() {
316 std::vector<const char*> Argv; 323 std::vector<const char*> Argv;
317 for (const std::string &Str : CommandLine) 324 for (const std::string &Str : CommandLine)
325 TextDiagnosticPrinter DiagnosticPrinter( 332 TextDiagnosticPrinter DiagnosticPrinter(
326 llvm::errs(), &*DiagOpts); 333 llvm::errs(), &*DiagOpts);
327 DiagnosticsEngine Diagnostics( 334 DiagnosticsEngine Diagnostics(
328 IntrusiveRefCntPtr<DiagnosticIDs>(new DiagnosticIDs()), &*DiagOpts, 335 IntrusiveRefCntPtr<DiagnosticIDs>(new DiagnosticIDs()), &*DiagOpts,
329 DiagConsumer ? DiagConsumer : &DiagnosticPrinter, false); 336 DiagConsumer ? DiagConsumer : &DiagnosticPrinter, false);
337 // Although `Diagnostics` are used only for command-line parsing, the custom
338 // `DiagConsumer` might expect a `SourceManager` to be present.
339 SourceManager SrcMgr(Diagnostics, *Files);
340 Diagnostics.setSourceManager(&SrcMgr);
330 341
331 const std::unique_ptr<driver::Driver> Driver( 342 const std::unique_ptr<driver::Driver> Driver(
332 newDriver(&Diagnostics, BinaryName, &Files->getVirtualFileSystem())); 343 newDriver(&Diagnostics, BinaryName, &Files->getVirtualFileSystem()));
333 // The "input file not found" diagnostics from the driver are useful. 344 // The "input file not found" diagnostics from the driver are useful.
334 // The driver is only aware of the VFS working directory, but some clients 345 // The driver is only aware of the VFS working directory, but some clients
343 const llvm::opt::ArgStringList *const CC1Args = getCC1Arguments( 354 const llvm::opt::ArgStringList *const CC1Args = getCC1Arguments(
344 &Diagnostics, Compilation.get()); 355 &Diagnostics, Compilation.get());
345 if (!CC1Args) 356 if (!CC1Args)
346 return false; 357 return false;
347 std::unique_ptr<CompilerInvocation> Invocation( 358 std::unique_ptr<CompilerInvocation> Invocation(
348 newInvocation(&Diagnostics, *CC1Args)); 359 newInvocation(&Diagnostics, *CC1Args, BinaryName));
349 // FIXME: remove this when all users have migrated!
350 for (const auto &It : MappedFileContents) {
351 // Inject the code as the given file name into the preprocessor options.
352 std::unique_ptr<llvm::MemoryBuffer> Input =
353 llvm::MemoryBuffer::getMemBuffer(It.getValue());
354 Invocation->getPreprocessorOpts().addRemappedFile(It.getKey(),
355 Input.release());
356 }
357 return runInvocation(BinaryName, Compilation.get(), std::move(Invocation), 360 return runInvocation(BinaryName, Compilation.get(), std::move(Invocation),
358 std::move(PCHContainerOps)); 361 std::move(PCHContainerOps));
359 } 362 }
360 363
361 bool ToolInvocation::runInvocation( 364 bool ToolInvocation::runInvocation(
439 for (StringRef Arg : Args) 442 for (StringRef Arg : Args)
440 if (Arg.startswith("-resource-dir")) 443 if (Arg.startswith("-resource-dir"))
441 return; 444 return;
442 445
443 // If there's no override in place add our resource dir. 446 // If there's no override in place add our resource dir.
444 Args.push_back("-resource-dir=" + 447 Args = getInsertArgumentAdjuster(
445 CompilerInvocation::GetResourcesPath(Argv0, MainAddr)); 448 ("-resource-dir=" + CompilerInvocation::GetResourcesPath(Argv0, MainAddr))
449 .c_str())(Args, "");
446 } 450 }
447 451
448 int ClangTool::run(ToolAction *Action) { 452 int ClangTool::run(ToolAction *Action) {
449 // Exists solely for the purpose of lookup of the resource path. 453 // Exists solely for the purpose of lookup of the resource path.
450 // This just needs to be some symbol in the binary. 454 // This just needs to be some symbol in the binary.
644 llvm::MemoryBuffer::getMemBuffer(FilenameWithContent.second)); 648 llvm::MemoryBuffer::getMemBuffer(FilenameWithContent.second));
645 } 649 }
646 650
647 if (!Invocation.run()) 651 if (!Invocation.run())
648 return nullptr; 652 return nullptr;
649 653
650 assert(ASTs.size() == 1); 654 assert(ASTs.size() == 1);
651 return std::move(ASTs[0]); 655 return std::move(ASTs[0]);
652 } 656 }
653 657
654 } // namespace tooling 658 } // namespace tooling