apple/swift
ClangImporter
Active contributors: jrose-apple, zoecarver, gribozavr, hborla
Purpose
ClangImporter embeds a Clang instance inside the Swift compiler. When Swift imports a C, Objective-C, or C++ module, ClangImporter parses the headers and translates the resulting Clang AST into Swift declarations on the fly. Without it, none of Foundation, Darwin, the C++ standard library, or any system framework would be visible to Swift.
It is one of the most active areas of the codebase -- the C++ interop project drives constant churn in lib/ClangImporter/ and test/Interop/.
Directory layout
lib/ClangImporter/ (46 files)
├── ClangImporter.cpp # 9,287 lines — top-level entry point
├── ImportDecl.cpp # 11,222 lines — translate Clang Decl → Swift Decl
├── ImportType.cpp # translate Clang QualType → swift::Type
├── ImportName.cpp # apply Swift naming rules ("omit needless words")
├── ImportEnumInfo.cpp
├── ImportMacro.cpp # promote some C macros to Swift constants
├── CFTypeInfo.cpp # CoreFoundation bridge
├── SwiftLookupTable.cpp # the imported-module's name lookup
├── ClangSwiftTypeCorrespondence.cpp # numeric / pointer mapping
├── DWARFImporter.cpp # import C decls from DWARF (LLDB)
└── ...
include/swift/ClangImporter/
└── ClangImporter.hKey abstractions
| Type | File | Description |
|---|---|---|
swift::ClangImporter |
include/swift/ClangImporter/ClangImporter.h |
The public API; subclass of ClangModuleLoader. |
swift::ClangImporter::Implementation |
lib/ClangImporter/ImporterImpl.h |
The PIMPL holding all state (Clang invocation, lookup tables, caches). |
swift::ClangModuleUnit |
include/swift/ClangImporter/ClangModule.h |
A FileUnit that wraps a Clang module. |
swift::SwiftLookupTable |
lib/ClangImporter/SwiftLookupTable.h |
On-disk hash table of imported names. |
swift::ImportTypeKind |
lib/ClangImporter/ImportType.cpp |
Steers how a C type lowers (parameter vs result vs property, etc.). |
How it works
graph TD
Source["import Foundation"] --> Sema
Sema --> Importer[ClangImporter]
Importer -->|build invocation| Clang[Clang]
Clang -->|parse modulemap + headers| ClangAST[Clang AST]
Importer --> Walk[walk Clang Decls]
Walk -->|"per Decl"| ImportDecl
ImportDecl --> Swift[Swift Decl]
Importer --> ApplyNames[Apply naming rules]
ApplyNames --> Swift
Swift --> ClangModuleUnit[ClangModuleUnit added to ASTContext]Setup
When the compiler starts up, ClangImporter::create builds a Clang CompilerInvocation matching the host platform and the user's -I/-Xcc flags. The invocation is configured for module-mode parsing using module.modulemap files (or the new C++ interop modulemaps under apinotes/).
Per-import lookup
When Sema asks for import Foundation:
- ClangImporter resolves the Clang module by name.
- It builds (and caches) a
ClangModuleUnitrepresenting the module's contents to Swift. - As Swift code references
NSString,NSArray, etc., ClangImporter walks the corresponding ClangDecls and produces SwiftDecls on demand. Imported names are cached.
Naming rules
The imported name is not the C name. ClangImporter applies the omit needless words algorithm (ImportName.cpp, see docs/CToSwiftNameTranslation-OmitNeedlessWords.md) to drop redundant prefixes (NSStringFromBlah → string(from:)), align with Swift API guidelines, and apply per-API hints from API notes files (apinotes/).
API notes
apinotes/*.apinotes are YAML-style annotations that override or augment imported declarations -- e.g., to mark something nullable, rename a method, or attach @available. They are how Apple supplements imports of system headers without modifying the C source.
CoreFoundation bridging
CF types like CFStringRef get special handling (CFTypeInfo.cpp). The runtime treats them as bridged (stdlib/public/runtime/SwiftValue.mm); the importer marks them as toll-free with NSString/NSArray/etc.
Objective-C interop
For Objective-C, ClangImporter translates classes, protocols, methods, properties, blocks, and id types. Selectors are split into Swift labeled-argument calls. Subclasses of NSObject get full ABI-compatible support.
C++ interop
C++ interop is the active development front. ClangImporter learns to import:
- C++ classes and structs (with member functions, operators).
- C++ template specializations.
- C++ standard library types via the
Cxxoverlay (stdlib/public/Cxx/). - Reference types vs value types (the
SWIFT_*_REFERENCE_TYPEannotations).
The user-facing documentation lives in docs/CppInteroperability/.
Integration points
- Sema uses ClangImporter to resolve
importdirectives; imported decls go into theASTContext. - The runtime has separate hooks for Objective-C bridging (
stdlib/public/runtime/Casting.cpp,SwiftValue.mm). - Serialization -- imported decls referenced by Swift code are recorded in the
.swiftmoduleso deserialization can re-resolve them. - PrintAsClang -- the inverse direction; emits a
.hheader for Swift declarations marked@objcor@_cdecl(seelib/PrintAsClang/). - DWARFImporter -- LLDB uses
lib/ClangImporter/DWARFImporter.cppto import C decls from debug info when source headers are unavailable.
Entry points for modification
- Importing a new kind of C++ construct: extend
ImportDecl.cppandImportType.cpp. Most new logic lives behindswift::ImportTypeKindswitches. - Changing the Swift-naming rules: edit
ImportName.cppand the data tables it consumes. - Adding API notes for a SDK: drop a
.apinotesfile underapinotes/(or in the SDK). - Investigating "why was this declaration imported with that name?": run
swift -frontend -emit-imported-modules -dump-clang-diagnostics file.swift.
Related pages
- Sema -- requests imports from ClangImporter.
- Standard library / C++ interop -- the Swift-side overlay.
- Serialization -- how imported decls survive across modules.
Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.