|
31 | 31 | #include "llvm/ADT/StringMap.h" |
32 | 32 | #include "llvm/ADT/StringRef.h" |
33 | 33 | #include "llvm/ADT/StringSet.h" |
| 34 | +#include "llvm/Support/CommandLine.h" |
34 | 35 | #include "llvm/Support/FileSystem.h" |
35 | 36 | #include "llvm/Support/StringSaver.h" |
36 | 37 | #include "llvm/Support/YAMLTraits.h" |
@@ -626,7 +627,6 @@ static bool diagnoseCycle(CompilerInstance &instance, |
626 | 627 |
|
627 | 628 | static bool scanModuleDependencies(CompilerInstance &instance, |
628 | 629 | StringRef moduleName, |
629 | | - StringRef arguments, |
630 | 630 | bool isClang, |
631 | 631 | StringRef outputPath) { |
632 | 632 | ASTContext &ctx = instance.getASTContext(); |
@@ -685,25 +685,58 @@ static bool scanModuleDependencies(CompilerInstance &instance, |
685 | 685 | bool swift::scanClangDependencies(CompilerInstance &instance) { |
686 | 686 | return scanModuleDependencies(instance, |
687 | 687 | instance.getMainModule()->getNameStr(), |
688 | | - StringRef(), |
689 | 688 | /*isClang*/true, |
690 | 689 | instance.getInvocation().getFrontendOptions() |
691 | 690 | .InputsAndOutputs.getSingleOutputFilename()); |
692 | 691 | } |
693 | 692 |
|
694 | | -bool swift::batchScanModuleDependencies(CompilerInstance &instance, |
695 | | - llvm::StringRef batchInputFile) { |
| 693 | +bool swift::batchScanModuleDependencies(CompilerInvocation &invok, |
| 694 | + CompilerInstance &instance, |
| 695 | + llvm::StringRef batchInputFile) { |
696 | 696 | (void)instance.getMainModule(); |
697 | 697 | llvm::BumpPtrAllocator alloc; |
698 | 698 | llvm::StringSaver saver(alloc); |
699 | 699 | auto results = parseBatchScanInputFile(instance.getASTContext(), |
700 | 700 | batchInputFile, saver); |
701 | 701 | if (!results.hasValue()) |
702 | 702 | return true; |
| 703 | + auto &diags = instance.getDiags(); |
| 704 | + ForwardingDiagnosticConsumer FDC(diags); |
| 705 | + // Keep track of all compiler instances we have created. |
| 706 | + llvm::StringMap<std::unique_ptr<CompilerInstance>> subInstanceMap; |
703 | 707 | for (auto &entry: *results) { |
704 | | - if (scanModuleDependencies(instance, entry.moduleName, entry.arguments, |
705 | | - !entry.isSwift, entry.outputPath)) |
| 708 | + CompilerInstance *pInstance = nullptr; |
| 709 | + if (entry.arguments.empty()) { |
| 710 | + // Use the compiler's instance if no arguments are specified. |
| 711 | + pInstance = &instance; |
| 712 | + } else if (subInstanceMap.count(entry.arguments)) { |
| 713 | + // Use the previously created instance if we've seen the arguments before. |
| 714 | + pInstance = subInstanceMap[entry.arguments].get(); |
| 715 | + } else { |
| 716 | + // Create a new instance by the arguments and save it in the map. |
| 717 | + pInstance = subInstanceMap.insert({entry.arguments, |
| 718 | + std::make_unique<CompilerInstance>()}).first->getValue().get(); |
| 719 | + SmallVector<const char*, 4> args; |
| 720 | + llvm::cl::TokenizeGNUCommandLine(entry.arguments, saver, args); |
| 721 | + CompilerInvocation subInvok = invok; |
| 722 | + pInstance->addDiagnosticConsumer(&FDC); |
| 723 | + if (subInvok.parseArgs(args, diags)) { |
| 724 | + instance.getDiags().diagnose(SourceLoc(), diag::scanner_arguments_invalid, |
| 725 | + entry.arguments); |
| 726 | + return true; |
| 727 | + } |
| 728 | + if (pInstance->setup(subInvok)) { |
| 729 | + instance.getDiags().diagnose(SourceLoc(), diag::scanner_arguments_invalid, |
| 730 | + entry.arguments); |
| 731 | + return true; |
| 732 | + } |
| 733 | + } |
| 734 | + assert(pInstance); |
| 735 | + // Scan using the chosen compiler instance. |
| 736 | + if (scanModuleDependencies(*pInstance, entry.moduleName, !entry.isSwift, |
| 737 | + entry.outputPath)) { |
706 | 738 | return true; |
| 739 | + } |
707 | 740 | } |
708 | 741 | return false; |
709 | 742 | } |
|
0 commit comments