Skip to content

Commit b90f524

Browse files
committed
[Bridging PCH] Warn on non-redundant implicit bridging-header imports.
We're trying to get rid of implicit bridging-header imports, as a feature. These are IMPORTED_HEADER blocks left in modules built with bridging headers, that trigger re-importing the bridging header into any client that imports the module. As a half-way measure to deprecating them, we add a warning here that triggers when an implicit bridging-header import occurs that is _not_ suppressed as redundant by clang.
1 parent 2d398b6 commit b90f524

File tree

7 files changed

+42
-10
lines changed

7 files changed

+42
-10
lines changed

include/swift/AST/DiagnosticsClangImporter.def

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,11 @@ WARNING(unresolvable_clang_decl,none,
7979
"imported declaration '%0' could not be mapped to '%1'",
8080
(StringRef, StringRef))
8181

82+
WARNING(implicit_bridging_header_imported_from_module,none,
83+
"implicit import of bridging header '%0' via module %1 "
84+
"is deprecated and will be removed in a later version of Swift",
85+
(StringRef, Identifier))
86+
8287
#ifndef DIAG_NO_UNDEF
8388
# if defined(DIAG)
8489
# undef DIAG

include/swift/ClangImporter/ClangImporter.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -201,13 +201,16 @@ class ClangImporter final : public ClangModuleLoader {
201201
/// \param diagLoc A location to attach any diagnostics to if import fails.
202202
/// \param trackParsedSymbols If true, tracks decls and macros that were
203203
/// parsed from the bridging header.
204+
/// \param implicitImport If true, indicates that this import was implicit
205+
/// from a reference in a module file (deprecated behaviour).
204206
///
205207
/// \returns true if there was an error importing the header.
206208
///
207209
/// \sa getImportedHeaderModule
208210
bool importBridgingHeader(StringRef header, ModuleDecl *adapter,
209211
SourceLoc diagLoc = {},
210-
bool trackParsedSymbols = false);
212+
bool trackParsedSymbols = false,
213+
bool implicitImport = false);
211214

212215
/// Returns the module that contains imports and declarations from all loaded
213216
/// Objective-C header files.

lib/ClangImporter/ClangImporter.cpp

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -865,7 +865,8 @@ bool ClangImporter::addSearchPath(StringRef newSearchPath, bool isFramework) {
865865
bool ClangImporter::Implementation::importHeader(
866866
Module *adapter, StringRef headerName, SourceLoc diagLoc,
867867
bool trackParsedSymbols,
868-
std::unique_ptr<llvm::MemoryBuffer> sourceBuffer) {
868+
std::unique_ptr<llvm::MemoryBuffer> sourceBuffer,
869+
bool implicitImport) {
869870
// Don't even try to load the bridging header if the Clang AST is in a bad
870871
// state. It could cause a crash.
871872
auto &clangDiags = getClangASTContext().getDiagnostics();
@@ -917,6 +918,27 @@ bool ClangImporter::Implementation::importHeader(
917918
consumer.reset();
918919
}
919920

921+
// We're trying to discourage (and eventually deprecate) the use of implicit
922+
// bridging-header imports triggered by IMPORTED_HEADER blocks in
923+
// modules. There are two sub-cases to consider:
924+
//
925+
// #1 The implicit import actually occurred.
926+
//
927+
// #2 The user explicitly -import-objc-header'ed some header or PCH that
928+
// makes the implicit import redundant.
929+
//
930+
// It's not obvious how to exactly differentiate these cases given the
931+
// interface clang gives us, but we only want to warn on case #1, and the
932+
// non-emptiness of allParsedDecls is a _definite_ sign that we're in case
933+
// #1. So we treat that as an approximation of the condition we're after, and
934+
// accept that we might fail to warn in the odd case where "the import
935+
// occurred" but didn't introduce any new decls.
936+
if (implicitImport && !allParsedDecls.empty()) {
937+
SwiftContext.Diags.diagnose(
938+
diagLoc, diag::implicit_bridging_header_imported_from_module,
939+
llvm::sys::path::filename(headerName), adapter->getName());
940+
}
941+
920942
// We can't do this as we're parsing because we may want to resolve naming
921943
// conflicts between the things we've parsed.
922944
for (auto group : allParsedDecls)
@@ -959,7 +981,7 @@ bool ClangImporter::importHeader(StringRef header, Module *adapter,
959981
/*OpenFile=*/true);
960982
if (headerFile && headerFile->getSize() == expectedSize &&
961983
headerFile->getModificationTime() == expectedModTime) {
962-
return importBridgingHeader(header, adapter, diagLoc);
984+
return importBridgingHeader(header, adapter, diagLoc, false, true);
963985
}
964986

965987
if (!cachedContents.empty() && cachedContents.back() == '\0')
@@ -968,12 +990,13 @@ bool ClangImporter::importHeader(StringRef header, Module *adapter,
968990
llvm::MemoryBuffer::getMemBuffer(cachedContents, header)
969991
};
970992
return Impl.importHeader(adapter, header, diagLoc, /*trackParsedSymbols=*/false,
971-
std::move(sourceBuffer));
993+
std::move(sourceBuffer), true);
972994
}
973995

974996
bool ClangImporter::importBridgingHeader(StringRef header, Module *adapter,
975997
SourceLoc diagLoc,
976-
bool trackParsedSymbols) {
998+
bool trackParsedSymbols,
999+
bool implicitImport) {
9771000
if (llvm::sys::path::extension(header).endswith(PCH_EXTENSION)) {
9781001
// We already imported this with -include-pch above, so we should have
9791002
// collected a bunch of PCH-encoded module imports that we need to
@@ -1006,7 +1029,7 @@ bool ClangImporter::importBridgingHeader(StringRef header, Module *adapter,
10061029
};
10071030

10081031
return Impl.importHeader(adapter, header, diagLoc, trackParsedSymbols,
1009-
std::move(sourceBuffer));
1032+
std::move(sourceBuffer), implicitImport);
10101033
}
10111034

10121035
std::string ClangImporter::getBridgingHeaderContents(StringRef headerPath,

lib/ClangImporter/ImporterImpl.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -599,7 +599,8 @@ class LLVM_LIBRARY_VISIBILITY ClangImporter::Implementation
599599
/// Imports the given header contents into the Clang context.
600600
bool importHeader(Module *adapter, StringRef headerName, SourceLoc diagLoc,
601601
bool trackParsedSymbols,
602-
std::unique_ptr<llvm::MemoryBuffer> contents);
602+
std::unique_ptr<llvm::MemoryBuffer> contents,
603+
bool implicitImport);
603604

604605
/// \brief Retrieve the imported module that should contain the given
605606
/// Clang decl.

test/ClangImporter/MixedSource/broken-bridging-header.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919

2020
// REQUIRES: objc_interop
2121

22-
import HasBridgingHeader // expected-error {{failed to import bridging header}} expected-error {{failed to load module 'HasBridgingHeader'}}
22+
import HasBridgingHeader // expected-error {{failed to import bridging header}} expected-error {{failed to load module 'HasBridgingHeader'}} expected-warning {{implicit import of bridging header}}
2323

2424
// MISSING-HEADER: error: bridging header '{{.*}}/fake.h' does not exist
2525
// MISSING-HEADER-NOT: error:

test/ClangImporter/MixedSource/import-mixed-with-header-twice.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
// USE-SERIALIZED-HEADER: redefinition of 'Point2D'
1414
// USE-SERIALIZED-HEADER: previous definition is here
1515

16-
import MixedWithHeaderAgain
16+
import MixedWithHeaderAgain // expected-warning {{implicit import of bridging header 'header-again.h' via module 'MixedWithHeaderAgain' is deprecated and will be removed in a later version of Swift}}
1717

1818
func testLine(line: Line) {
1919
testLineImpl(line)

test/ClangImporter/MixedSource/import-mixed-with-header.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414

1515
// XFAIL: linux
1616

17-
import MixedWithHeader
17+
import MixedWithHeader // expected-warning {{implicit import of bridging header 'header.h' via module 'MixedWithHeader' is deprecated and will be removed in a later version of Swift}}
1818

1919
func testReexportedClangModules(_ foo : FooProto) {
2020
_ = foo.bar as CInt

0 commit comments

Comments
 (0)