[clang][deps] Make the service provide the VFS (#181424)
This PR makes it so that the base VFS used during a scan is provided to
the top-level service, not to each worker/tool individually. This
enables resolving a FIXME in the async-scan-modules mode of the scanner,
will clean up [downstream
code](0eb56baa1d/clang/tools/libclang/CDependencies.cpp (L619-L622)),
and will make it more difficult to have mismatching VFSs across workers,
which may cause non-deterministic poisoning of
`DependencyScanningFilesystemSharedCache`.
This commit is contained in:
parent
8f6866c9e9
commit
e7bad4ac4f
@ -35,8 +35,9 @@ public:
|
||||
ModuleDependencyScanner(
|
||||
std::shared_ptr<const clang::tooling::CompilationDatabase> CDB,
|
||||
const ThreadsafeFS &TFS)
|
||||
: CDB(CDB), TFS(TFS), Service([] {
|
||||
: CDB(CDB), Service([&TFS] {
|
||||
dependencies::DependencyScanningServiceOptions Opts;
|
||||
Opts.MakeVFS = [&] { return TFS.view(std::nullopt); };
|
||||
Opts.Mode = dependencies::ScanningMode::CanonicalPreprocessing;
|
||||
Opts.Format = dependencies::ScanningOutputFormat::P1689;
|
||||
return Opts;
|
||||
@ -79,7 +80,6 @@ public:
|
||||
|
||||
private:
|
||||
std::shared_ptr<const clang::tooling::CompilationDatabase> CDB;
|
||||
const ThreadsafeFS &TFS;
|
||||
|
||||
// Whether the scanner has scanned the project globally.
|
||||
bool GlobalScanned = false;
|
||||
@ -109,9 +109,7 @@ ModuleDependencyScanner::scan(PathRef FilePath,
|
||||
|
||||
using namespace clang::tooling;
|
||||
|
||||
llvm::SmallString<128> FilePathDir(FilePath);
|
||||
llvm::sys::path::remove_filename(FilePathDir);
|
||||
DependencyScanningTool ScanningTool(Service, TFS.view(FilePathDir));
|
||||
DependencyScanningTool ScanningTool(Service);
|
||||
|
||||
std::string S;
|
||||
llvm::raw_string_ostream OS(S);
|
||||
|
||||
@ -80,6 +80,11 @@ enum class ScanningOptimizations {
|
||||
struct DependencyScanningServiceOptions {
|
||||
DependencyScanningServiceOptions();
|
||||
|
||||
/// The function invoked to create each worker's VFS. This function and the
|
||||
/// VFS itself must be thread-safe whenever using multiple workers
|
||||
/// concurrently or whenever \c AsyncScanModules is true.
|
||||
std::function<IntrusiveRefCntPtr<llvm::vfs::FileSystem>()>
|
||||
MakeVFS; // = [] { return llvm::vfs::createPhysicalFileSystem(); }
|
||||
/// Whether to use optimized dependency directive scan or full preprocessing.
|
||||
ScanningMode Mode = ScanningMode::DependencyDirectivesScan;
|
||||
/// What output format are we expected to produce.
|
||||
|
||||
@ -87,9 +87,7 @@ public:
|
||||
/// Construct a dependency scanning worker.
|
||||
///
|
||||
/// @param Service The parent service. Must outlive the worker.
|
||||
/// @param BaseFS The filesystem for the worker to use.
|
||||
DependencyScanningWorker(DependencyScanningService &Service,
|
||||
IntrusiveRefCntPtr<llvm::vfs::FileSystem> BaseFS);
|
||||
DependencyScanningWorker(DependencyScanningService &Service);
|
||||
|
||||
~DependencyScanningWorker();
|
||||
|
||||
|
||||
@ -36,10 +36,8 @@ public:
|
||||
/// Construct a dependency scanning tool.
|
||||
///
|
||||
/// @param Service The parent service. Must outlive the tool.
|
||||
/// @param FS The filesystem for the tool to use. Defaults to the physical FS.
|
||||
DependencyScanningTool(dependencies::DependencyScanningService &Service,
|
||||
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS =
|
||||
llvm::vfs::createPhysicalFileSystem());
|
||||
DependencyScanningTool(dependencies::DependencyScanningService &Service)
|
||||
: Worker(Service) {}
|
||||
|
||||
/// Print out the dependency information into a string using the dependency
|
||||
/// file format that is specified in the options (-MD is the default) and
|
||||
|
||||
@ -620,10 +620,9 @@ struct AsyncModuleCompile : PPCallbacks {
|
||||
if (!LockErr && !Owned)
|
||||
return;
|
||||
// We should build the PCM.
|
||||
// FIXME: Pass the correct BaseFS to the worker FS.
|
||||
IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS =
|
||||
llvm::makeIntrusiveRefCnt<DependencyScanningWorkerFilesystem>(
|
||||
Service.getSharedCache(), llvm::vfs::getRealFileSystem());
|
||||
Service.getSharedCache(), Service.getOpts().MakeVFS());
|
||||
VFS = createVFSFromCompilerInvocation(CI.getInvocation(),
|
||||
CI.getDiagnostics(), std::move(VFS));
|
||||
auto DC = std::make_unique<DiagnosticConsumer>();
|
||||
|
||||
@ -14,5 +14,6 @@ using namespace clang;
|
||||
using namespace dependencies;
|
||||
|
||||
DependencyScanningServiceOptions::DependencyScanningServiceOptions()
|
||||
: BuildSessionTimestamp(
|
||||
: MakeVFS([] { return llvm::vfs::createPhysicalFileSystem(); }),
|
||||
BuildSessionTimestamp(
|
||||
llvm::sys::toTimeT(std::chrono::system_clock::now())) {}
|
||||
|
||||
@ -20,8 +20,7 @@ using namespace clang;
|
||||
using namespace dependencies;
|
||||
|
||||
DependencyScanningWorker::DependencyScanningWorker(
|
||||
DependencyScanningService &Service,
|
||||
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> BaseFS)
|
||||
DependencyScanningService &Service)
|
||||
: Service(Service) {
|
||||
PCHContainerOps = std::make_shared<PCHContainerOperations>();
|
||||
// We need to read object files from PCH built outside the scanner.
|
||||
@ -30,6 +29,8 @@ DependencyScanningWorker::DependencyScanningWorker(
|
||||
// The scanner itself writes only raw ast files.
|
||||
PCHContainerOps->registerWriter(std::make_unique<RawPCHContainerWriter>());
|
||||
|
||||
auto BaseFS = Service.getOpts().MakeVFS();
|
||||
|
||||
if (Service.getOpts().TraceVFS)
|
||||
BaseFS = llvm::makeIntrusiveRefCnt<llvm::vfs::TracingFileSystem>(
|
||||
std::move(BaseFS));
|
||||
|
||||
@ -14,7 +14,6 @@
|
||||
#include "clang/Frontend/Utils.h"
|
||||
#include "llvm/ADT/SmallVectorExtras.h"
|
||||
#include "llvm/ADT/iterator.h"
|
||||
#include "llvm/Support/VirtualFileSystem.h"
|
||||
#include "llvm/TargetParser/Host.h"
|
||||
#include <optional>
|
||||
|
||||
@ -22,11 +21,6 @@ using namespace clang;
|
||||
using namespace tooling;
|
||||
using namespace dependencies;
|
||||
|
||||
DependencyScanningTool::DependencyScanningTool(
|
||||
DependencyScanningService &Service,
|
||||
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS)
|
||||
: Worker(Service, std::move(FS)) {}
|
||||
|
||||
namespace {
|
||||
/// Prints out all of the gathered dependencies into a string.
|
||||
class MakeDependencyPrinterConsumer : public DependencyConsumer {
|
||||
|
||||
@ -32,9 +32,10 @@ TEST(DependencyScanner, ScanDepsWithDiagConsumer) {
|
||||
VFS->addFile(AsmPath, 0, llvm::MemoryBuffer::getMemBuffer(""));
|
||||
|
||||
DependencyScanningServiceOptions Opts;
|
||||
Opts.MakeVFS = [&] { return VFS; };
|
||||
Opts.Format = ScanningOutputFormat::Make;
|
||||
DependencyScanningService Service(std::move(Opts));
|
||||
DependencyScanningWorker Worker(Service, VFS);
|
||||
DependencyScanningWorker Worker(Service);
|
||||
|
||||
llvm::DenseSet<ModuleID> AlreadySeen;
|
||||
FullDependencyConsumer DC(AlreadySeen);
|
||||
|
||||
@ -229,9 +229,10 @@ TEST(DependencyScanner, ScanDepsWithFS) {
|
||||
llvm::MemoryBuffer::getMemBuffer("#include \"header.h\"\n"));
|
||||
|
||||
DependencyScanningServiceOptions Opts;
|
||||
Opts.MakeVFS = [&] { return VFS; };
|
||||
Opts.Format = ScanningOutputFormat::Make;
|
||||
DependencyScanningService Service(std::move(Opts));
|
||||
DependencyScanningTool ScanTool(Service, VFS);
|
||||
DependencyScanningTool ScanTool(Service);
|
||||
|
||||
TextDiagnosticBuffer DiagConsumer;
|
||||
std::optional<std::string> DepFile =
|
||||
@ -287,9 +288,10 @@ TEST(DependencyScanner, ScanDepsWithModuleLookup) {
|
||||
auto InterceptFS = llvm::makeIntrusiveRefCnt<InterceptorFS>(VFS);
|
||||
|
||||
DependencyScanningServiceOptions Opts;
|
||||
Opts.MakeVFS = [&] { return InterceptFS; };
|
||||
Opts.Format = ScanningOutputFormat::Make;
|
||||
DependencyScanningService Service(std::move(Opts));
|
||||
DependencyScanningTool ScanTool(Service, InterceptFS);
|
||||
DependencyScanningTool ScanTool(Service);
|
||||
|
||||
// This will fail with "fatal error: module 'Foo' not found" but it doesn't
|
||||
// matter, the point of the test is to check that files are not read
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user