Introduction
I did a poor investigation of SR-15586: import Foundation
hides declarations (derived from C) in other modules on Linux for these few months.
I finally found that it is a bug caused by ClangImporter
which is due to how it imports C declarations. Furthermore, the issue would occur on any platforms, even on macOS. (Filed as SR-15822: Existence of modulemap disables declarations in simple C headers in some cases.)
How the bug is produced
ClangImporter
(ClangImporter::Implementation
) holds the instances of ClangModuleUnit
which wraps a clang module. On the other hand, it also holds BridgingHeaderLookupTable
that contains C declarations derived from bridging headers, for example, from headers imported with -import-objc-header
.
The problem here is that ClangImporter::Implementation
has only one unique instance of clang::CompilerInstance
(created in ClangImporter::create
[1]). It also uses one unique instance of clang::Preprocessor
which holds a unique instance of clang::HeaderSearch
. (The status quo of Swift's implementation)
ClangImporter::Implementation::loadModuleClang
calls the instance of clang::HeaderSearch
to load a clang module[2]. At the time of it, #include guards in the headers required by the module are being enabled.
That does matter when ClangImporter::Implementation
tries to import bridging headers.
ClangImporter::Implementation::importHeader
uses the instance of clang::Preprocessor
to parse the bridging header such as #include "c.h"
[3] which is generated in ClangImporter::importBridgingHeader
[4].
However, if the bridging header wants to include some headers already imported by some other clang modules, #include guards block to include the same headers.
Then, no declarations in those headers are added to BridgingHeaderLookupTable
.
As a result, for example, LookupByName::doLocalLookup
fails to look up some types, because it doesn't try to look up the type in other (clang) modules.
I think this feature of Clang::Importer
causes some bugs such as SR-15822, SR-15586, SR-15532, and SR-15462.
The error messages don't imply the nature of the problem, but the compiler would be confused by such feature.
Question
Why does ClangImporter
import separately clang modules and bridging C headers?
-
https://github.com/apple/swift/blob/b26a575e1cc8d746ec7b96525d59983a031ba641/lib/ClangImporter/ClangImporter.cpp#L1143-L1144 ↩︎
-
https://github.com/apple/swift/blob/b26a575e1cc8d746ec7b96525d59983a031ba641/lib/ClangImporter/ClangImporter.cpp#L1920-L1925 ↩︎
-
https://github.com/apple/swift/blob/b26a575e1cc8d746ec7b96525d59983a031ba641/lib/ClangImporter/ClangImporter.cpp#L1394-L1397 ↩︎
-
https://github.com/apple/swift/blob/b26a575e1cc8d746ec7b96525d59983a031ba641/lib/ClangImporter/ClangImporter.cpp#L1530-L1537 ↩︎