[clang] [clang][Dependency Scanning] Refactor Scanning Compiler Instance Initialization (PR #161300)
Jan Svoboda via cfe-commits
cfe-commits at lists.llvm.org
Tue Sep 30 12:59:19 PDT 2025
================
@@ -356,43 +369,131 @@ void clang::tooling::dependencies::sanitizeDiagOpts(
});
}
-bool DependencyScanningAction::runInvocation(
- std::shared_ptr<CompilerInvocation> Invocation,
- IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS,
- std::shared_ptr<PCHContainerOperations> PCHContainerOps,
- DiagnosticConsumer *DiagConsumer) {
- // Making sure that we canonicalize the defines before we create the deep
- // copy to avoid unnecessary variants in the scanner and in the resulting
- // explicit command lines.
- if (any(Service.getOptimizeArgs() & ScanningOptimizations::Macros))
- canonicalizeDefines(Invocation->getPreprocessorOpts());
+std::pair<std::unique_ptr<driver::Driver>, std::unique_ptr<driver::Compilation>>
+clang::tooling::dependencies::buildCompilation(
+ ArrayRef<std::string> ArgStrs, DiagnosticsEngine &Diags,
+ IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS) {
+ SmallVector<const char *, 256> Argv;
+ Argv.reserve(ArgStrs.size());
+ for (const std::string &Arg : ArgStrs)
+ Argv.push_back(Arg.c_str());
+
+ std::unique_ptr<driver::Driver> Driver = std::make_unique<driver::Driver>(
+ Argv[0], llvm::sys::getDefaultTargetTriple(), Diags,
+ "clang LLVM compiler", FS);
+ Driver->setTitle("clang_based_tool");
+
+ llvm::BumpPtrAllocator Alloc;
+ bool CLMode = driver::IsClangCL(
+ driver::getDriverMode(Argv[0], ArrayRef(Argv).slice(1)));
+
+ if (llvm::Error E =
+ driver::expandResponseFiles(Argv, CLMode, Alloc, FS.get())) {
+ Diags.Report(diag::err_drv_expand_response_file)
+ << llvm::toString(std::move(E));
+ return std::make_pair(nullptr, nullptr);
+ }
- // Make a deep copy of the original Clang invocation.
- CompilerInvocation OriginalInvocation(*Invocation);
+ std::unique_ptr<driver::Compilation> Compilation(
+ Driver->BuildCompilation(llvm::ArrayRef(Argv)));
+ if (!Compilation)
+ return std::make_pair(nullptr, nullptr);
- if (Scanned) {
- // Scanning runs once for the first -cc1 invocation in a chain of driver
- // jobs. For any dependent jobs, reuse the scanning result and just
- // update the LastCC1Arguments to correspond to the new invocation.
- // FIXME: to support multi-arch builds, each arch requires a separate scan
- setLastCC1Arguments(std::move(OriginalInvocation));
- return true;
+ if (Compilation->containsError())
+ return std::make_pair(nullptr, nullptr);
+
+ return std::make_pair(std::move(Driver), std::move(Compilation));
+}
+
+llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem>
+clang::tooling::dependencies::initVFSForTUBufferScanning(
+ llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> BaseFS,
+ std::optional<std::vector<std::string>> &ModifiedCommandLine,
+ const std::vector<std::string> &CommandLine, StringRef WorkingDirectory,
+ std::optional<llvm::MemoryBufferRef> TUBuffer) {
+ // Reset what might have been modified in the previous worker invocation.
+ BaseFS->setCurrentWorkingDirectory(WorkingDirectory);
+
+ llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> ModifiedFS;
+ if (TUBuffer) {
+ auto OverlayFS =
+ llvm::makeIntrusiveRefCnt<llvm::vfs::OverlayFileSystem>(BaseFS);
+ auto InMemoryFS =
+ llvm::makeIntrusiveRefCnt<llvm::vfs::InMemoryFileSystem>();
+ InMemoryFS->setCurrentWorkingDirectory(WorkingDirectory);
+ auto InputPath = TUBuffer->getBufferIdentifier();
+ InMemoryFS->addFile(
+ InputPath, 0,
+ llvm::MemoryBuffer::getMemBufferCopy(TUBuffer->getBuffer()));
+ llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> InMemoryOverlay =
+ InMemoryFS;
+
+ OverlayFS->pushOverlay(InMemoryOverlay);
+ ModifiedFS = OverlayFS;
+ ModifiedCommandLine = CommandLine;
+ ModifiedCommandLine->emplace_back(InputPath);
+
+ return ModifiedFS;
}
- Scanned = true;
+ return BaseFS;
+}
- // Create a compiler instance to handle the actual work.
- auto ModCache = makeInProcessModuleCache(Service.getModuleCacheEntries());
- ScanInstanceStorage.emplace(std::move(Invocation), std::move(PCHContainerOps),
- ModCache.get());
- CompilerInstance &ScanInstance = *ScanInstanceStorage;
+llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem>
+clang::tooling::dependencies::initVFSForByNameScanning(
+ llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> BaseFS,
+ std::vector<std::string> &CommandLine, StringRef WorkingDirectory,
+ StringRef FakeFileNamePrefix) {
+ // Reset what might have been modified in the previous worker invocation.
+ BaseFS->setCurrentWorkingDirectory(WorkingDirectory);
+
+ // If we're scanning based on a module name alone, we don't expect the client
+ // to provide us with an input file. However, the driver really wants to have
+ // one. Let's just make it up to make the driver happy.
+ auto OverlayFS =
+ llvm::makeIntrusiveRefCnt<llvm::vfs::OverlayFileSystem>(BaseFS);
+ auto InMemoryFS = llvm::makeIntrusiveRefCnt<llvm::vfs::InMemoryFileSystem>();
+ InMemoryFS->setCurrentWorkingDirectory(WorkingDirectory);
+ SmallString<128> FakeInputPath;
+ // TODO: We should retry the creation if the path already exists.
+ llvm::sys::fs::createUniquePath(FakeFileNamePrefix + "-%%%%%%%%.input",
+ FakeInputPath,
+ /*MakeAbsolute=*/false);
+ InMemoryFS->addFile(FakeInputPath, 0, llvm::MemoryBuffer::getMemBuffer(""));
+ llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> InMemoryOverlay = InMemoryFS;
+ OverlayFS->pushOverlay(InMemoryOverlay);
+
+ CommandLine.emplace_back(FakeInputPath);
+
+ return OverlayFS;
+}
+
+std::unique_ptr<CompilerInvocation>
+clang::tooling::dependencies::createCompilerInvocation(
+ const std::vector<std::string> &CommandLine, DiagnosticsEngine &Diags) {
+ llvm::opt::ArgStringList Argv;
+ for (const std::string &Str : ArrayRef(CommandLine).drop_front())
+ Argv.push_back(Str.c_str());
+
+ auto Invocation = std::make_unique<CompilerInvocation>();
+ if (!CompilerInvocation::CreateFromArgs(*Invocation, Argv, Diags)) {
+ // FIXME: Should we just go on like cc1_main does?
+ return nullptr;
+ }
+ return Invocation;
+}
+
+bool clang::tooling::dependencies::initializeScanCompilerInstance(
+ CompilerInstance &ScanInstance,
+ IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS,
+ DiagnosticConsumer *DiagConsumer, DependencyScanningService &Service,
+ llvm::IntrusiveRefCntPtr<DependencyScanningWorkerFilesystem> DepFS) {
ScanInstance.setBuildingModule(false);
ScanInstance.createVirtualFileSystem(FS, DiagConsumer);
// Create the compiler's actual diagnostics engine.
sanitizeDiagOpts(ScanInstance.getDiagnosticOpts());
- assert(!DiagConsumerFinished && "attempt to reuse finished consumer");
----------------
jansvoboda11 wrote:
Did we drop this assert?
https://github.com/llvm/llvm-project/pull/161300
More information about the cfe-commits
mailing list