[ClangImporter] Prefer serialized bridging headers in LLDB.

Especially in an explicit modules project, LLDB might not know all the
search paths needed to imported the on disk header.

rdar://157063577
(cherry picked from commit a6678476d8)
This commit is contained in:
Adrian Prantl
2025-07-29 17:07:45 -07:00
parent 99a2db3392
commit 95ad22e799
3 changed files with 32 additions and 25 deletions

View File

@@ -1093,6 +1093,10 @@ namespace swift {
/// When set, don't enforce warnings with -Werror.
bool DebuggerSupport = false;
/// Prefer the serialized preprocessed header over the one on disk.
/// Used by LLDB.
bool PreferSerializedBridgingHeader = false;
/// When set, ClangImporter is disabled, and all requests go to the
/// DWARFImporter delegate.
bool DisableSourceImport = false;

View File

@@ -163,8 +163,7 @@ private:
bool requiresBuiltinHeadersInSystemModules = false;
ClangImporter(ASTContext &ctx,
DependencyTracker *tracker,
ClangImporter(ASTContext &ctx, DependencyTracker *tracker,
DWARFImporterDelegate *dwarfImporterDelegate);
/// Creates a clone of Clang importer's compiler instance that has been
@@ -196,8 +195,8 @@ public:
/// \returns a new Clang module importer, or null (with a diagnostic) if
/// an error occurred.
static std::unique_ptr<ClangImporter>
create(ASTContext &ctx,
std::string swiftPCHHash = "", DependencyTracker *tracker = nullptr,
create(ASTContext &ctx, std::string swiftPCHHash = "",
DependencyTracker *tracker = nullptr,
DWARFImporterDelegate *dwarfImporterDelegate = nullptr,
bool ignoreFileMapping = false);

View File

@@ -444,12 +444,10 @@ bool ClangImporter::Implementation::shouldIgnoreBridgeHeaderTopLevelDecl(
return importer::isForwardDeclOfType(D);
}
ClangImporter::ClangImporter(ASTContext &ctx,
DependencyTracker *tracker,
ClangImporter::ClangImporter(ASTContext &ctx, DependencyTracker *tracker,
DWARFImporterDelegate *dwarfImporterDelegate)
: ClangModuleLoader(tracker),
Impl(*new Implementation(ctx, tracker, dwarfImporterDelegate)) {
}
Impl(*new Implementation(ctx, tracker, dwarfImporterDelegate)) {}
ClangImporter::~ClangImporter() {
delete &Impl;
@@ -1298,11 +1296,9 @@ std::unique_ptr<clang::CompilerInvocation> ClangImporter::createClangInvocation(
return CI;
}
std::unique_ptr<ClangImporter>
ClangImporter::create(ASTContext &ctx,
std::string swiftPCHHash, DependencyTracker *tracker,
DWARFImporterDelegate *dwarfImporterDelegate,
bool ignoreFileMapping) {
std::unique_ptr<ClangImporter> ClangImporter::create(
ASTContext &ctx, std::string swiftPCHHash, DependencyTracker *tracker,
DWARFImporterDelegate *dwarfImporterDelegate, bool ignoreFileMapping) {
std::unique_ptr<ClangImporter> importer{
new ClangImporter(ctx, tracker, dwarfImporterDelegate)};
auto &importerOpts = ctx.ClangImporterOpts;
@@ -1788,15 +1784,24 @@ bool ClangImporter::importHeader(StringRef header, ModuleDecl *adapter,
off_t expectedSize, time_t expectedModTime,
StringRef cachedContents, SourceLoc diagLoc) {
clang::FileManager &fileManager = Impl.Instance->getFileManager();
auto headerFile = fileManager.getFile(header, /*OpenFile=*/true);
// Prefer importing the header directly if the header content matches by
// checking size and mod time. This allows correct import if some no-modular
// headers are already imported into clang importer. If mod time is zero, then
// the module should be built from CAS and there is no mod time to verify.
if (headerFile && (*headerFile)->getSize() == expectedSize &&
(expectedModTime == 0 ||
(*headerFile)->getModificationTime() == expectedModTime)) {
return importBridgingHeader(header, adapter, diagLoc, false, true);
// Especially in an explicit modules project, LLDB might not know all the
// search paths needed to imported the on disk header, so prefer the
// serialized preprocessed contents when debugger support is on.
if (!Impl.SwiftContext.ClangImporterOpts.PreferSerializedBridgingHeader ||
cachedContents.empty()) {
auto headerFile = fileManager.getFile(header, /*OpenFile=*/true);
// Prefer importing the header directly if the header content matches by
// checking size and mod time. This allows correct import if some no-modular
// headers are already imported into clang importer. If mod time is zero,
// then the module should be built from CAS and there is no mod time to
// verify. LLDB prefers the serialized bridging header because, in an
// explicit modules project, LLDB might not know all the search paths needed
// to imported the on disk header.
if (headerFile && (*headerFile)->getSize() == expectedSize &&
(expectedModTime == 0 ||
(*headerFile)->getModificationTime() == expectedModTime)) {
return importBridgingHeader(header, adapter, diagLoc, false, true);
}
}
// If we've made it to here, this is some header other than the bridging
@@ -1806,9 +1811,8 @@ bool ClangImporter::importHeader(StringRef header, ModuleDecl *adapter,
if (!cachedContents.empty() && cachedContents.back() == '\0')
cachedContents = cachedContents.drop_back();
std::unique_ptr<llvm::MemoryBuffer> sourceBuffer{
llvm::MemoryBuffer::getMemBuffer(cachedContents, header)
};
std::unique_ptr<llvm::MemoryBuffer> sourceBuffer =
llvm::MemoryBuffer::getMemBufferCopy(cachedContents, header);
return Impl.importHeader(adapter, header, diagLoc, /*trackParsedSymbols=*/false,
std::move(sourceBuffer), true);
}