Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[BridgingHeader] Fix auto-chaining when only dependency has bridging header #79301

Merged
merged 1 commit into from
Feb 13, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion include/swift/Frontend/FrontendOptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -286,7 +286,7 @@ class FrontendOptions {

/// If set, the header provided in ImplicitObjCHeaderPath will be rewritten
/// by the Clang importer as part of semantic analysis.
bool SerializeBridgingHeader = false;
bool ModuleHasBridgingHeader = false;

/// Indicates whether or not the frontend should print statistics upon
/// termination.
Expand Down
2 changes: 1 addition & 1 deletion lib/Frontend/ArgsToFrontendOptionsConverter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -901,7 +901,7 @@ void ArgsToFrontendOptionsConverter::computeImportObjCHeaderOptions() {
Opts.ImplicitObjCHeaderPath = A->getValue();
// If `-import-object-header` is used, it means the module has a direct
// bridging header dependency and it can be serialized into binary module.
Opts.SerializeBridgingHeader |= true;
Opts.ModuleHasBridgingHeader |= true;
}
if (const Arg *A = Args.getLastArgNoClaim(OPT_import_pch))
Opts.ImplicitObjCPCHPath = A->getValue();
Expand Down
12 changes: 7 additions & 5 deletions lib/Frontend/Frontend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,7 @@ SerializationOptions CompilerInvocation::computeSerializationOptions(
serializationOpts.DocOutputPath = outs.ModuleDocOutputPath;
serializationOpts.SourceInfoOutputPath = outs.ModuleSourceInfoOutputPath;
serializationOpts.GroupInfoPath = opts.GroupInfoPath.c_str();
if (opts.SerializeBridgingHeader && !outs.ModuleOutputPath.empty())
if (opts.ModuleHasBridgingHeader && !outs.ModuleOutputPath.empty())
serializationOpts.SerializeBridgingHeader = true;
// For batch mode, emit empty header path as placeholder.
if (serializationOpts.SerializeBridgingHeader &&
Expand Down Expand Up @@ -1302,10 +1302,12 @@ ImplicitImportInfo CompilerInstance::getImplicitImportInfo() const {
}

imports.ShouldImportUnderlyingModule = frontendOpts.ImportUnderlyingModule;
if (frontendOpts.ImplicitObjCPCHPath.empty())
imports.BridgingHeaderPath = frontendOpts.ImplicitObjCHeaderPath;
else
imports.BridgingHeaderPath = frontendOpts.ImplicitObjCPCHPath;
if (frontendOpts.ModuleHasBridgingHeader) {
if (frontendOpts.ImplicitObjCPCHPath.empty())
imports.BridgingHeaderPath = frontendOpts.ImplicitObjCHeaderPath;
else
imports.BridgingHeaderPath = frontendOpts.ImplicitObjCPCHPath;
}
return imports;
}

Expand Down
13 changes: 8 additions & 5 deletions test/ScanDependencies/bridging-header-autochaining.swift
Original file line number Diff line number Diff line change
Expand Up @@ -43,18 +43,18 @@
// RUN: %target-swift-frontend -module-name Test -O @%t/MyApp.cmd %t/test.swift \
// RUN: -emit-module -o %t/Test.swiftmodule

/// Importing binary module with bridging header built from CAS from a regluar build.
/// Importing binary module with bridging header from a module that also has bridging header using implicit build method.
/// This should succeed even it is also importing a bridging header that shares same header dependencies (with proper header guard).
// RUN: %target-swift-frontend -typecheck -module-name User \
// RUN: -disable-implicit-string-processing-module-import -disable-implicit-concurrency-module-import \
// RUN: -Xcc -fmodule-map-file=%t/a.modulemap -Xcc -fmodule-map-file=%t/b.modulemap \
// RUN: -I %t %t/user2.swift -import-objc-header %t/Bridging2.h

/// Importing binary module with bridging header built from CAS from a cached build. This should work without additional bridging header deps.
/// Importing binary module with bridging header from a module that has no bridging header.
// RUN: %target-swift-frontend -scan-dependencies -module-name User -module-cache-path %t/clang-module-cache -O \
// RUN: -disable-implicit-string-processing-module-import -disable-implicit-concurrency-module-import \
// RUN: %t/user.swift -o %t/deps2.json -auto-bridging-header-chaining -scanner-output-dir %t -scanner-debug-write-output \
// RUN: -Xcc -fmodule-map-file=%t/a.modulemap -Xcc -fmodule-map-file=%t/b.modulemap -I %t
// RUN: -Xcc -fmodule-map-file=%t/a.modulemap -Xcc -fmodule-map-file=%t/b.modulemap -I %t -enable-library-evolution

// RUN: %swift-scan-test -action get_chained_bridging_header -- %target-swift-frontend -emit-module \
// RUN: -module-name User -module-cache-path %t/clang-module-cache -O \
Expand All @@ -74,12 +74,15 @@
// RUN: -disable-implicit-string-processing-module-import -disable-implicit-concurrency-module-import -disable-implicit-swift-modules \
// RUN: -import-pch %t/bridging1.pch \
// RUN: -explicit-swift-module-map-file %t/map2.json @%t/User.cmd %t/user.swift \
// RUN: -emit-module -o %t/User.swiftmodule
// RUN: -emit-module -o %t/User.swiftmodule -emit-module-interface-path %t/User.swiftinterface -enable-library-evolution

/// Make sure the emitted content is compatible with original. The embedded header path needs to be original header and no bridging header module leaking into interface.
// RUN: llvm-bcanalyzer -dump %t/User.swiftmodule | %FileCheck %s --check-prefix CHECK-NO-HEADER
// CHECK-NO-HEADER-NOT: <IMPORTED_HEADER
// RUN: %FileCheck %s --check-prefix NO-OBJC-LEAKING --input-file=%t/User.swiftinterface
// NO-OBJC-LEAKING-NOT: import __ObjC

/// Importing binary module with bridging header for a cached build while also importing a bridging header.
/// Importing binary module with bridging header from a module with bridging header using explicit build method with header chaining.
// RUN: %target-swift-frontend -scan-dependencies -module-name User -O \
// RUN: -disable-implicit-string-processing-module-import -disable-implicit-concurrency-module-import \
// RUN: -Xcc -fmodule-map-file=%t/a.modulemap -Xcc -fmodule-map-file=%t/b.modulemap \
Expand Down
3 changes: 3 additions & 0 deletions tools/swift-ide-test/swift-ide-test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4524,6 +4524,9 @@ int main(int argc, char *argv[]) {
options::ImportObjCHeader;
InitInvok.getClangImporterOptions().BridgingHeader =
options::ImportObjCHeader;
if (!options::ImportObjCHeader.empty())
InitInvok.getFrontendOptions().ModuleHasBridgingHeader = true;

InitInvok.getLangOptions().EnableAccessControl =
!options::DisableAccessControl;
InitInvok.getLangOptions().EnableDeserializationSafety =
Expand Down