[clang][DependencyScanning] Relocate CompilerInstanceWithContext to DependencyScanningWorker.cpp (#211407)

This PR relocates all `CompilerInstanceWithContext` code to
`DependencyScanningWorker.cpp` and hides them as implementation details,
since no public APIs should use `CompilerInstanceWithContext` directly.

---

<sub>Stack created with <a
href="https://github.com/github/gh-stack">GitHub Stacks CLI</a> • <a
href="https://gh.io/stacks-feedback">Give Feedback 💬</a></sub>
This commit is contained in:
Qiongsi Wu 2026-07-31 08:54:14 -07:00 committed by GitHub
parent 5f4d725bca
commit 6109006676
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 276 additions and 287 deletions

View file

@ -28,10 +28,6 @@ namespace clang {
class DependencyOutputOptions;
namespace tooling {
class CompilerInstanceWithContext;
}
namespace dependencies {
class DependencyConsumer;
@ -64,6 +60,18 @@ public:
DiagnosticConsumer &DiagConsumer,
IntrusiveRefCntPtr<llvm::vfs::FileSystem> OverlayFS = nullptr);
/// By-name scanning over a single cc1 command line. Builds a scanning session
/// local to this call, then pulls module names from \p getNextName until it
/// returns std::nullopt. Results flow to \p DepConsumer (per-name status via
/// finishQuery); diagnostics flow to \p DiagConsumer.
/// \returns false if session setup failed, true otherwise.
bool computeDependenciesByName(
StringRef CWD, ArrayRef<std::string> CC1CommandLine,
IntrusiveRefCntPtr<llvm::vfs::FileSystem> OverlayFS,
DiagnosticConsumer &DiagConsumer, DependencyActionController &Controller,
llvm::function_ref<std::optional<std::string>()> getNextName,
DependencyConsumer &DepConsumer);
/// Creates the effective VFS that will be used for the scan.
///
/// If provided, OverlayFS will be overlaid on top of the Worker's dependency
@ -79,6 +87,15 @@ public:
return TracingFS.get();
}
// MaxNumOfByNameQueries is the upper limit of the number of names the by-name
// scanning API (computeDependenciesByName) can drain per call. At the time of
// this commit, the estimated number of total unique importable names is
// around 3000 from Apple's SDKs. We usually import them in parallel, so it is
// unlikely that all names are scanned by the same worker. Therefore the 64k
// (20x our estimate) size is sufficient to hold the unique source locations
// to report diagnostics per worker.
static const int32_t MaxNumOfByNameQueries = 1 << 16;
private:
/// The parent dependency scanning service.
DependencyScanningService &Service;
@ -89,7 +106,7 @@ private:
/// The tracing VFS overlaid on top of the base VFS.
IntrusiveRefCntPtr<llvm::vfs::TracingFileSystem> TracingFS;
friend tooling::CompilerInstanceWithContext;
friend class CompilerInstanceWithContext;
};
} // end namespace dependencies
} // end namespace clang

View file

@ -124,8 +124,6 @@ public:
private:
dependencies::DependencyScanningWorker Worker;
friend class CompilerInstanceWithContext;
};
/// Run the dependency scanning worker for the given driver or frontend
@ -146,79 +144,6 @@ bool computeDependencies(
dependencies::DependencyActionController &Controller,
DiagnosticConsumer &DiagConsumer,
IntrusiveRefCntPtr<llvm::vfs::FileSystem> OverlayFS = nullptr);
class CompilerInstanceWithContext {
// Context
dependencies::DependencyScanningWorker &Worker;
llvm::StringRef CWD;
std::vector<std::string> CommandLine;
// Context - Diagnostics engine.
DiagnosticConsumer *DiagConsumer = nullptr;
std::unique_ptr<dependencies::DiagnosticsEngineWithDiagOpts>
DiagEngineWithCmdAndOpts;
// Context - compiler invocation
std::unique_ptr<CompilerInvocation> OriginalInvocation;
// Context - output options
std::unique_ptr<DependencyOutputOptions> OutputOpts;
// Context - stable directory handling
llvm::SmallVector<StringRef> StableDirs;
dependencies::PrebuiltModulesAttrsMap PrebuiltModuleASTMap;
// Compiler Instance
std::unique_ptr<CompilerInstance> CIPtr;
// Source location offset.
int32_t SrcLocOffset = 0;
CompilerInstanceWithContext(dependencies::DependencyScanningWorker &Worker,
StringRef CWD, ArrayRef<std::string> CMD)
: Worker(Worker), CWD(CWD), CommandLine(CMD.begin(), CMD.end()) {}
bool initialize(dependencies::DependencyActionController &Controller,
std::unique_ptr<dependencies::DiagnosticsEngineWithDiagOpts>
DiagEngineWithDiagOpts,
IntrusiveRefCntPtr<llvm::vfs::FileSystem> OverlayFS);
public:
/// @brief Initialize the compiler instance from an already-lowered cc1
/// commandline (driver-free).
/// @param Worker The dependency scanning worker to initialize the compiler
/// instance.
/// @param CWD The current working directory.
/// @param CC1CommandLine A cc1 command.
/// @param DiagEngineWithDiagOpts The diagnostic engine used during scan.
/// @param OverlayFS An overlay FS containing the input file, which may be
/// from an in-memory buffer.
/// @param Controller A dependency action controller to gather some results.
static std::optional<CompilerInstanceWithContext>
initializeFromCC1Commandline(
dependencies::DependencyScanningWorker &Worker, StringRef CWD,
ArrayRef<std::string> CC1CommandLine,
std::unique_ptr<dependencies::DiagnosticsEngineWithDiagOpts>
DiagEngineWithDiagOpts,
IntrusiveRefCntPtr<llvm::vfs::FileSystem> OverlayFS,
dependencies::DependencyActionController &Controller);
bool
computeDependencies(StringRef ModuleName,
dependencies::DependencyConsumer &Consumer,
dependencies::DependencyActionController &Controller);
// MaxNumOfQueries is the upper limit of the number of names the by-name
// scanning API (computeDependencies) can support after a
// CompilerInstanceWithContext is initialized. At the time of this commit, the
// estimated number of total unique importable names is around 3000 from
// Apple's SDKs. We usually import them in parallel, so it is unlikely that
// all names are all scanned by the same dependency scanning worker. Therefore
// the 64k (20x bigger than our estimate) size is sufficient to hold the
// unique source locations to report diagnostics per worker.
static const int32_t MaxNumOfQueries = 1 << 16;
};
} // end namespace tooling
} // end namespace clang

View file

@ -9,8 +9,11 @@
#include "clang/DependencyScanning/DependencyScanningWorker.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/DiagnosticFrontend.h"
#include "clang/DependencyScanning/DependencyActionController.h"
#include "clang/DependencyScanning/DependencyConsumer.h"
#include "clang/DependencyScanning/DependencyScannerImpl.h"
#include "clang/Frontend/FrontendActions.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Serialization/ObjectFilePCHContainerReader.h"
#include "llvm/ADT/IntrusiveRefCntPtr.h"
#include "llvm/ADT/ScopeExit.h"
@ -19,6 +22,227 @@
using namespace clang;
using namespace dependencies;
namespace clang {
namespace dependencies {
class CompilerInstanceWithContext {
// Context
DependencyScanningWorker &Worker;
llvm::StringRef CWD;
std::vector<std::string> CommandLine;
// Context - Diagnostics engine.
DiagnosticConsumer *DiagConsumer = nullptr;
std::unique_ptr<DiagnosticsEngineWithDiagOpts> DiagEngineWithCmdAndOpts;
// Context - compiler invocation
std::unique_ptr<CompilerInvocation> OriginalInvocation;
// Context - output options
std::unique_ptr<DependencyOutputOptions> OutputOpts;
// Context - stable directory handling
llvm::SmallVector<StringRef> StableDirs;
PrebuiltModulesAttrsMap PrebuiltModuleASTMap;
// Compiler Instance
std::unique_ptr<CompilerInstance> CIPtr;
// Source location offset.
int32_t SrcLocOffset = 0;
CompilerInstanceWithContext(DependencyScanningWorker &Worker, StringRef CWD,
ArrayRef<std::string> CMD)
: Worker(Worker), CWD(CWD), CommandLine(CMD.begin(), CMD.end()) {}
bool initialize(
DependencyActionController &Controller,
std::unique_ptr<DiagnosticsEngineWithDiagOpts> DiagEngineWithDiagOpts,
IntrusiveRefCntPtr<llvm::vfs::FileSystem> OverlayFS) {
{
auto LogLine = Worker.Service.getLogger().log();
LogLine.logArray("init_compiler_instance_with_context:", " ",
CommandLine);
}
assert(DiagEngineWithDiagOpts && "Valid diagnostics engine required!");
DiagEngineWithCmdAndOpts = std::move(DiagEngineWithDiagOpts);
DiagConsumer = DiagEngineWithCmdAndOpts->DiagEngine->getClient();
assert(OverlayFS && "OverlayFS required!");
auto FS = Worker.makeEffectiveVFS(CWD, std::move(OverlayFS));
OriginalInvocation = createCompilerInvocation(
CommandLine, *DiagEngineWithCmdAndOpts->DiagEngine);
if (!OriginalInvocation) {
DiagEngineWithCmdAndOpts->DiagEngine->Report(
diag::err_fe_expected_compiler_job)
<< llvm::join(CommandLine, " ");
return false;
}
if (any(Worker.Service.getOpts().OptimizeArgs &
ScanningOptimizations::Macros))
canonicalizeDefines(OriginalInvocation->getPreprocessorOpts());
// Create the CompilerInstance.
std::shared_ptr<ModuleCache> ModCache = makeInProcessModuleCache(
Worker.Service.getModuleCacheEntries(), Worker.Service.getLogger());
CIPtr = std::make_unique<CompilerInstance>(
createScanCompilerInvocation(*OriginalInvocation, Worker.Service,
Controller),
Worker.PCHContainerOps, std::move(ModCache));
auto &CI = *CIPtr;
initializeScanCompilerInstance(
CI, std::move(FS), DiagEngineWithCmdAndOpts->DiagEngine->getClient(),
Worker.Service, Worker.DepFS);
StableDirs = getInitialStableDirs(CI);
auto MaybePrebuiltModulesASTMap =
computePrebuiltModulesASTMap(CI, StableDirs);
if (!MaybePrebuiltModulesASTMap)
return false;
PrebuiltModuleASTMap = std::move(*MaybePrebuiltModulesASTMap);
OutputOpts = createDependencyOutputOptions(*OriginalInvocation);
// We do not create the target in initializeScanCompilerInstance because
// setting it here is unique for by-name lookups. We create the target only
// once here, and the information is reused for all computeDependencies
// calls. We do not need to call createTarget explicitly if we go through
// CompilerInstance::ExecuteAction to perform scanning.
return CI.createTarget();
}
public:
static std::optional<CompilerInstanceWithContext>
initializeFromCC1Commandline(
DependencyScanningWorker &Worker, StringRef CWD,
ArrayRef<std::string> CC1CommandLine,
std::unique_ptr<DiagnosticsEngineWithDiagOpts> DiagEngineWithDiagOpts,
IntrusiveRefCntPtr<llvm::vfs::FileSystem> OverlayFS,
DependencyActionController &Controller) {
CompilerInstanceWithContext CIWC(Worker, CWD, CC1CommandLine);
if (!CIWC.initialize(Controller, std::move(DiagEngineWithDiagOpts),
std::move(OverlayFS)))
return std::nullopt;
return std::move(CIWC);
}
bool computeDependencies(StringRef ModuleName, DependencyConsumer &Consumer,
DependencyActionController &Controller) {
Worker.Service.getLogger().log() << "start scan_by_name: " << ModuleName;
llvm::scope_exit ExitLogging([&] {
Worker.Service.getLogger().log() << "finish scan_by_name: " << ModuleName;
});
if (SrcLocOffset >= DependencyScanningWorker::MaxNumOfByNameQueries)
llvm::report_fatal_error("exceeded maximum by-name scans for worker");
assert(CIPtr && "CIPtr must be initialized before calling this method");
auto &CI = *CIPtr;
// We need to reset the diagnostics, so that the diagnostics issued
// during a previous computeDependencies call do not affect the current
// call. If we do not reset, we may inherit fatal errors from a previous
// call.
CI.getDiagnostics().Reset();
// We create this cleanup object because computeDependencies may exit
// early with errors.
llvm::scope_exit CleanUp([&]() {
CI.clearDependencyCollectors();
// The preprocessor may not be created at the entry of this method,
// but it must have been created when this method returns, whether
// there are errors during scanning or not.
CI.getPreprocessor().removePPCallbacks();
});
auto MDC = initializeScanInstanceDependencyCollector(
CI, std::make_unique<DependencyOutputOptions>(*OutputOpts),
Worker.Service,
/* The MDC's constructor makes a copy of the OriginalInvocation, so
we can pass it in without worrying that it might be changed across
invocations of computeDependencies. */
*OriginalInvocation, Controller, PrebuiltModuleASTMap, StableDirs);
CompilerInvocation ModuleInvocation(*OriginalInvocation);
if (!Controller.initialize(CI, ModuleInvocation))
return false;
if (!SrcLocOffset) {
// When SrcLocOffset is zero, we are at the beginning of the fake source
// file. In this case, we call BeginSourceFile to initialize.
std::unique_ptr<FrontendAction> Action =
std::make_unique<PreprocessOnlyAction>();
auto *InputFile = CI.getFrontendOpts().Inputs.begin();
bool ActionBeginSucceeded = Action->BeginSourceFile(CI, *InputFile);
assert(ActionBeginSucceeded && "Action BeginSourceFile must succeed");
(void)ActionBeginSucceeded;
}
Preprocessor &PP = CI.getPreprocessor();
SourceManager &SM = PP.getSourceManager();
FileID MainFileID = SM.getMainFileID();
SourceLocation FileStart = SM.getLocForStartOfFile(MainFileID);
SourceLocation IDLocation = FileStart.getLocWithOffset(SrcLocOffset);
PPCallbacks *CB = nullptr;
if (!SrcLocOffset) {
// We need to call EnterSourceFile when SrcLocOffset is zero to initialize
// the preprocessor.
bool PPFailed = PP.EnterSourceFile(MainFileID, nullptr, SourceLocation());
assert(!PPFailed && "Preprocess must be able to enter the main file.");
(void)PPFailed;
CB = MDC->getPPCallbacks();
} else {
// When SrcLocOffset is non-zero, the preprocessor has already been
// initialized through a previous call of computeDependencies. We want to
// preserve the PP's state, hence we do not call EnterSourceFile again.
MDC->attachToPreprocessor(PP);
CB = MDC->getPPCallbacks();
FileID PrevFID;
SrcMgr::CharacteristicKind FileType =
SM.getFileCharacteristic(IDLocation);
CB->LexedFileChanged(MainFileID,
PPChainedCallbacks::LexedFileChangeReason::EnterFile,
FileType, PrevFID, IDLocation);
}
// FIXME: Scan modules asynchronously here as well.
SrcLocOffset++;
SmallVector<IdentifierLoc, 2> Path;
IdentifierInfo *ModuleID = PP.getIdentifierInfo(ModuleName);
Path.emplace_back(IDLocation, ModuleID);
auto ModResult = CI.loadModule(IDLocation, Path, Module::Hidden, false);
assert(CB && "Must have PPCallbacks after module loading");
CB->moduleImport(SourceLocation(), Path, ModResult);
if (!ModResult)
return false;
if (CI.getDiagnostics().hasErrorOccurred())
return false;
MDC->run(Consumer);
MDC->applyDiscoveredDependencies(ModuleInvocation);
bool Success = ModuleInvocation.withCowRef<bool>(
[&](CowCompilerInvocation &CowModuleInvocation) {
return Controller.finalize(CI, CowModuleInvocation);
});
if (!Success)
return false;
Consumer.handleBuildCommand(
{CommandLine[0], ModuleInvocation.getCC1CommandLine()});
return true;
}
};
} // namespace dependencies
} // namespace clang
DependencyScanningWorker::DependencyScanningWorker(
DependencyScanningService &Service)
: Service(Service) {
@ -108,3 +332,29 @@ bool DependencyScanningWorker::computeDependencies(
return Success && Action.hasScanned();
}
bool DependencyScanningWorker::computeDependenciesByName(
StringRef CWD, ArrayRef<std::string> CC1CommandLine,
IntrusiveRefCntPtr<llvm::vfs::FileSystem> OverlayFS,
DiagnosticConsumer &DiagConsumer, DependencyActionController &Controller,
llvm::function_ref<std::optional<std::string>()> getNextName,
DependencyConsumer &DepConsumer) {
auto FS = makeEffectiveVFS(CWD, OverlayFS);
auto DiagEngine = std::make_unique<DiagnosticsEngineWithDiagOpts>(
CC1CommandLine, FS, DiagConsumer);
std::optional<CompilerInstanceWithContext> CIWC =
CompilerInstanceWithContext::initializeFromCC1Commandline(
*this, CWD, CC1CommandLine, std::move(DiagEngine),
std::move(OverlayFS), Controller);
if (!CIWC)
return false;
bool AllScansSucceeded = true;
while (std::optional<std::string> NextName = getNextName()) {
bool Success =
CIWC->computeDependencies(*NextName, DepConsumer, Controller);
DepConsumer.finishQuery(*NextName, Success);
AllScansSucceeded = AllScansSucceeded && Success;
}
return AllScansSucceeded;
}

View file

@ -13,10 +13,7 @@
#include "clang/Driver/Compilation.h"
#include "clang/Driver/Driver.h"
#include "clang/Driver/Tool.h"
#include "clang/Frontend/FrontendActions.h"
#include "clang/Frontend/Utils.h"
#include "clang/Lex/Preprocessor.h"
#include "llvm/ADT/ScopeExit.h"
#include "llvm/ADT/SmallVectorExtras.h"
#include "llvm/ADT/iterator.h"
#include "llvm/TargetParser/Host.h"
@ -280,7 +277,7 @@ initVFSForByNameScanning(ArrayRef<std::string> CommandLine) {
// locations for the diagnostics. Therefore, sharing this global buffer across
// threads is ok.
static const std::string FakeInput(
CompilerInstanceWithContext::MaxNumOfQueries, ' ');
DependencyScanningWorker::MaxNumOfByNameQueries, ' ');
StringRef InputPath =
llvm::sys::path::is_style_windows(llvm::sys::path::Style::native)
@ -367,207 +364,7 @@ bool DependencyScanningTool::getByNameDependencies(
CC1CommandLine.assign(MaybeFirstCC1->begin(), MaybeFirstCC1->end());
}
// Build one scanning session (a CIWC reused across all input names) and pull
// names until getNextName is exhausted.
auto DiagEngineWithOpts = std::make_unique<DiagnosticsEngineWithDiagOpts>(
CC1CommandLine, FS, DiagConsumer);
std::optional<CompilerInstanceWithContext> CIWC =
CompilerInstanceWithContext::initializeFromCC1Commandline(
Worker, CWD, CC1CommandLine, std::move(DiagEngineWithOpts),
std::move(OverlayFS), Controller);
if (!CIWC)
return false;
bool AllScansSucceeded = true;
while (std::optional<std::string> NextName = getNextName()) {
bool Success =
CIWC->computeDependencies(*NextName, DepConsumer, Controller);
DepConsumer.finishQuery(*NextName, Success);
AllScansSucceeded = AllScansSucceeded && Success;
}
return AllScansSucceeded;
}
std::optional<CompilerInstanceWithContext>
CompilerInstanceWithContext::initializeFromCC1Commandline(
DependencyScanningWorker &Worker, StringRef CWD,
ArrayRef<std::string> CC1CommandLine,
std::unique_ptr<dependencies::DiagnosticsEngineWithDiagOpts>
DiagEngineWithDiagOpts,
IntrusiveRefCntPtr<llvm::vfs::FileSystem> OverlayFS,
DependencyActionController &Controller) {
CompilerInstanceWithContext CIWC(Worker, CWD, CC1CommandLine);
if (!CIWC.initialize(Controller, std::move(DiagEngineWithDiagOpts),
std::move(OverlayFS)))
return std::nullopt;
return std::move(CIWC);
}
bool CompilerInstanceWithContext::initialize(
DependencyActionController &Controller,
std::unique_ptr<DiagnosticsEngineWithDiagOpts> DiagEngineWithDiagOpts,
IntrusiveRefCntPtr<llvm::vfs::FileSystem> OverlayFS) {
{
auto LogLine = Worker.Service.getLogger().log();
LogLine.logArray("init_compiler_instance_with_context:", " ", CommandLine);
}
assert(DiagEngineWithDiagOpts && "Valid diagnostics engine required!");
DiagEngineWithCmdAndOpts = std::move(DiagEngineWithDiagOpts);
DiagConsumer = DiagEngineWithCmdAndOpts->DiagEngine->getClient();
assert(OverlayFS && "OverlayFS required!");
auto FS = Worker.makeEffectiveVFS(CWD, std::move(OverlayFS));
OriginalInvocation = createCompilerInvocation(
CommandLine, *DiagEngineWithCmdAndOpts->DiagEngine);
if (!OriginalInvocation) {
DiagEngineWithCmdAndOpts->DiagEngine->Report(
diag::err_fe_expected_compiler_job)
<< llvm::join(CommandLine, " ");
return false;
}
if (any(Worker.Service.getOpts().OptimizeArgs &
ScanningOptimizations::Macros))
canonicalizeDefines(OriginalInvocation->getPreprocessorOpts());
// Create the CompilerInstance.
std::shared_ptr<ModuleCache> ModCache = makeInProcessModuleCache(
Worker.Service.getModuleCacheEntries(), Worker.Service.getLogger());
CIPtr = std::make_unique<CompilerInstance>(
createScanCompilerInvocation(*OriginalInvocation, Worker.Service,
Controller),
Worker.PCHContainerOps, std::move(ModCache));
auto &CI = *CIPtr;
initializeScanCompilerInstance(
CI, std::move(FS), DiagEngineWithCmdAndOpts->DiagEngine->getClient(),
Worker.Service, Worker.DepFS);
StableDirs = getInitialStableDirs(CI);
auto MaybePrebuiltModulesASTMap =
computePrebuiltModulesASTMap(CI, StableDirs);
if (!MaybePrebuiltModulesASTMap)
return false;
PrebuiltModuleASTMap = std::move(*MaybePrebuiltModulesASTMap);
OutputOpts = createDependencyOutputOptions(*OriginalInvocation);
// We do not create the target in initializeScanCompilerInstance because
// setting it here is unique for by-name lookups. We create the target only
// once here, and the information is reused for all computeDependencies calls.
// We do not need to call createTarget explicitly if we go through
// CompilerInstance::ExecuteAction to perform scanning.
return CI.createTarget();
}
bool CompilerInstanceWithContext::computeDependencies(
StringRef ModuleName, DependencyConsumer &Consumer,
DependencyActionController &Controller) {
Worker.Service.getLogger().log() << "start scan_by_name: " << ModuleName;
llvm::scope_exit ExitLogging([&] {
Worker.Service.getLogger().log() << "finish scan_by_name: " << ModuleName;
});
if (SrcLocOffset >= MaxNumOfQueries)
llvm::report_fatal_error("exceeded maximum by-name scans for worker");
assert(CIPtr && "CIPtr must be initialized before calling this method");
auto &CI = *CIPtr;
// We need to reset the diagnostics, so that the diagnostics issued
// during a previous computeDependencies call do not affect the current call.
// If we do not reset, we may inherit fatal errors from a previous call.
CI.getDiagnostics().Reset();
// We create this cleanup object because computeDependencies may exit
// early with errors.
llvm::scope_exit CleanUp([&]() {
CI.clearDependencyCollectors();
// The preprocessor may not be created at the entry of this method,
// but it must have been created when this method returns, whether
// there are errors during scanning or not.
CI.getPreprocessor().removePPCallbacks();
});
auto MDC = initializeScanInstanceDependencyCollector(
CI, std::make_unique<DependencyOutputOptions>(*OutputOpts),
Worker.Service,
/* The MDC's constructor makes a copy of the OriginalInvocation, so
we can pass it in without worrying that it might be changed across
invocations of computeDependencies. */
*OriginalInvocation, Controller, PrebuiltModuleASTMap, StableDirs);
CompilerInvocation ModuleInvocation(*OriginalInvocation);
if (!Controller.initialize(CI, ModuleInvocation))
return false;
if (!SrcLocOffset) {
// When SrcLocOffset is zero, we are at the beginning of the fake source
// file. In this case, we call BeginSourceFile to initialize.
std::unique_ptr<FrontendAction> Action =
std::make_unique<PreprocessOnlyAction>();
auto *InputFile = CI.getFrontendOpts().Inputs.begin();
bool ActionBeginSucceeded = Action->BeginSourceFile(CI, *InputFile);
assert(ActionBeginSucceeded && "Action BeginSourceFile must succeed");
(void)ActionBeginSucceeded;
}
Preprocessor &PP = CI.getPreprocessor();
SourceManager &SM = PP.getSourceManager();
FileID MainFileID = SM.getMainFileID();
SourceLocation FileStart = SM.getLocForStartOfFile(MainFileID);
SourceLocation IDLocation = FileStart.getLocWithOffset(SrcLocOffset);
PPCallbacks *CB = nullptr;
if (!SrcLocOffset) {
// We need to call EnterSourceFile when SrcLocOffset is zero to initialize
// the preprocessor.
bool PPFailed = PP.EnterSourceFile(MainFileID, nullptr, SourceLocation());
assert(!PPFailed && "Preprocess must be able to enter the main file.");
(void)PPFailed;
CB = MDC->getPPCallbacks();
} else {
// When SrcLocOffset is non-zero, the preprocessor has already been
// initialized through a previous call of computeDependencies. We want to
// preserve the PP's state, hence we do not call EnterSourceFile again.
MDC->attachToPreprocessor(PP);
CB = MDC->getPPCallbacks();
FileID PrevFID;
SrcMgr::CharacteristicKind FileType = SM.getFileCharacteristic(IDLocation);
CB->LexedFileChanged(MainFileID,
PPChainedCallbacks::LexedFileChangeReason::EnterFile,
FileType, PrevFID, IDLocation);
}
// FIXME: Scan modules asynchronously here as well.
SrcLocOffset++;
SmallVector<IdentifierLoc, 2> Path;
IdentifierInfo *ModuleID = PP.getIdentifierInfo(ModuleName);
Path.emplace_back(IDLocation, ModuleID);
auto ModResult = CI.loadModule(IDLocation, Path, Module::Hidden, false);
assert(CB && "Must have PPCallbacks after module loading");
CB->moduleImport(SourceLocation(), Path, ModResult);
if (!ModResult)
return false;
if (CI.getDiagnostics().hasErrorOccurred())
return false;
MDC->run(Consumer);
MDC->applyDiscoveredDependencies(ModuleInvocation);
bool Success = ModuleInvocation.withCowRef<bool>(
[&](CowCompilerInvocation &CowModuleInvocation) {
return Controller.finalize(CI, CowModuleInvocation);
});
if (!Success)
return false;
Consumer.handleBuildCommand(
{CommandLine[0], ModuleInvocation.getCC1CommandLine()});
return true;
return Worker.computeDependenciesByName(CWD, CC1CommandLine,
std::move(OverlayFS), DiagConsumer,
Controller, getNextName, DepConsumer);
}