[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
This commit is contained in:
Adrian Prantl
2025-07-29 17:07:45 -07:00
parent 0597fd927f
commit a6678476d8
3 changed files with 32 additions and 25 deletions

View File

@@ -1106,6 +1106,10 @@ namespace swift {
/// When set, don't enforce warnings with -Werror. /// When set, don't enforce warnings with -Werror.
bool DebuggerSupport = false; 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 /// When set, ClangImporter is disabled, and all requests go to the
/// DWARFImporter delegate. /// DWARFImporter delegate.
bool DisableSourceImport = false; bool DisableSourceImport = false;

View File

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

View File

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