Commit Graph

73 Commits

Author SHA1 Message Date
Egor Zhdan 338c8eafd8 [cxx-interop] Support static dispatch for virtual methods using super
This adds support for calling virtual methods of C++ foreign reference types with static dispatch.

In C++, one can do:
```cpp
this->Base::virtualMethod()
```

Swift doesn't allow calling a particular overload of an overridden method, however, it allows calling an overload from the superclass with `super`:
```swift
extension Derived {
  public func callSuper() {
    return super.foo()
  }
}
```

For inherited FRTs, the example above behaved in an unexpected way: the call would still be dispatched dynamically, despite using the syntax reserved for static dispatch. This change makes it behave similarly to pure-Swift classes.

rdar://177619427
2026-06-07 12:14:31 +01:00
Gabor Horvath f258c513f8 [cxx-interop] Never copy trivial move-only C++ types
We used unowned calling convention for all trivial C++ types, as a
result the move checker never diagnosed when an unintentional copy is
happened through a call. This PR changes move only types to use @owned
calling convention, matching what we do for native Swift types.

Now, we can no longer get away with these copies! Unfortunately, the fix
for now is turned off for types with the "destroy" attribute because the
synthesized code is triggering some errors. This can be fixed as a
follow-up.

rdar://135615824
2026-05-08 18:24:03 +01:00
John Hui 193ed25147 Merge pull request #87752 from j-hui/missing-returns-retained-diagnostics-boogaloo
[cxx-interop] [NFC] Clean up RETURNS_RETAINED diagnostics + add tests
2026-03-26 13:46:29 -07:00
Gabor Horvath 64fb3cb925 [cxx-interop] Fix a missing offset adjustment when calling FRTs
We already generate forwarding methods that can fix up the base offset
when we call base methods. Unfortunately, these forwarding methods were
not used when we emitted a call to a refcount operation of a foreign
reference type where the annotation is on the type itself but the
operation was inherited from a base.

rdar://173210238
2026-03-24 16:36:37 +00:00
John Hui 91f3dde9dd [cxx-interop] [NFC] Move Clang call diagnostics to ClangImporter
Moving this here gives us access to ClangImporter's internal APIs for
future improvements. It also keeps changes to interop-specific
diagnostics localized to the interop-specific part of the compiler.
2026-03-19 23:07:46 -07:00
Gabor Horvath 96ee6eaf18 [cxx-interop] Implicitly bridge annotated smart pointers to reference types
This PR introduces implicit bridging from annotated smart pointers to
reference counted objects to Swift foreign reference types. The bridging
only happens when these smart pointers are passed around by value. The
frontend only sees the Swift foreign reference types in the signature
and the actual bridging happens during SILGen when we look at the
original clang types and note that they differ significantly from the
native types.

The bridging of parameters did not quite fit into the existing structure
of bridging conversions as smart pointers are non-trivial types passed
around as addresses and existing bridging conversions were implemented
for types passed directly.

rdar://156521316
2026-01-28 12:34:21 +00:00
Gabor Horvath 6eb4d5b915 [cxx-interop] Fix crash deserializing some Clang function types
When a function type refers to a Swift declaration we get a crash during
deserialization. This patch prevents serializing the problematic clang
function types to avoid this crash.

rdar://166359524
2026-01-14 15:39:58 +00:00
John Hui d05a174233 [cxx-interop] [NFC] Make getClangOwningModule a free-standing function
Remove the ClangImporter::Implementation::getClangOwningModule() method,
and replaces all call sites with the static free-standing function it
calls, now exposed in the swift::importer namespace as an internal API.
This makes it easier to use in contexts where an Implementation instance
is not readily available.

Also, clone the documentation to the public ClangImporter API of the
same name.
2026-01-06 10:39:46 -08:00
Gabor Horvath 35bcc99f99 [cxx-interop] Fix miscompilation for inferred shared references
When a base class is annotated as shared reference we can occasionally
infer that the derived types also need to be shared references.
Unfortunately, we did not generate the correct code for some of those
scenarios. When the reference counted base is not at the offset zero we
need to do offset adjustments before we pass the pointer to the
reference counting functions. We did not do those offset calculations.

I looked into implementing the codegen for the offset calculation
directly in Swift but it needed significantly more work than I
anticipated. We need to invoke the frontend to get the path to the base
class and we also need to deal with virtual inheritance, alignment and
some other considerations.

This PR ends up generating a Clang shim instead and the derived to base
conversion happens in this shim. As a result, we piggy-back on Clang
making all the correct offset calculations. This patch also had to
change how certain aspects of shared references are implemented to be
compatible with this approach:
* Instead of always looking at the base classes to querry the
  retain/release operations we now propagate the corresponding
  annotations once per types. This also has the beneficial effects that
  we traverse the inheritance hierarchy less often.
* To generate the correct diagnostics, I reuse the result of the
  refcount operation query.
* We do not want these generated functions to be inherited, so added a
  set to exempt them from cloning.
* Tweaked the lookup logic for retain/release a bit as these generated
  clang methods are not found by lookup. We rely on looking up the
  imported methods instead.

rdar://166227787
rdar://165635002
2025-12-18 18:02:38 +00:00
Egor Zhdan 7fc815e383 [cxx-interop] Allow initializing std::function from Swift capturing closures
This introduces support for converting a Swift closure that captures variables from its surrounding context into an instance of `std::function`, which is useful for working with C++ APIs that use callbacks.

Each instantiation of `std::function` gets a synthesized Swift constructor that takes a Swift closure. Unlike the previous implementation, the closure is _not_ marked as `@convention(c)`. The body of the constructor is created lazily.

Under the hood, the closure is bitcast to a pair of a function pointer and a context pointer, which are then wrapped in a C++ object, `__SwiftFunctionWrapper`, that manages the lifetime of the context object via calls to `swift_retain`/`swift_release` from the copy constructor and the destructor. The `__SwiftFunctionWrapper` class is templated, and is instantiated by ClangImporter.

rdar://133777029
2025-12-05 15:41:59 +00:00
Egor Zhdan dc6ec456d4 [cxx-interop] Assign correct owning module to class template specializations
When importing C++ class template specializations into Swift, we were assigning the owning module to the imported Swift structs inconsistently. For specializations that had a typedef (or a using-decl), we assumed the module that declares the typedef to be the owning module for the specialization. For specializations that do not have a typedef, we assumed the module that declares the class template itself to be the owning module. This changes the behavior to always assume the latter.

rdar://158589803
2025-10-14 18:21:23 +01:00
Allan Shortlidge 3d722e1919 ClangImporter: Generate and call custom availability domain predicates.
When importing custom availability domains with dynamic predicates from Clang
modules, synthesize predicate functions for `if #available` queries and call
them when generating SIL.

Resolves rdar://138441312.
2025-07-10 08:15:01 -07:00
Gabor Horvath 4de92656dd [cxx-interop] Fix unqualified name lookup failure
When MemberImportVisibility is enabled we failed to find certain base
methods from the extensions when said base methods are imported from
C++.

rdar://154887575
2025-07-08 12:41:01 +01:00
susmonteiro 79227e7a09 [cxx-interop] Fix ambiguous methods in long chains of inheritance 2025-06-02 16:51:58 +01:00
Dylan Sturgeon 2c8e337f25 Merge pull request #80074 from dylansturg/objc_enum_refs
The Error enum synthesized declarations, e.g. the struct and its static accessors, should generally appear to be identical to the underlying Clang definitions. There are some specific use cases where the synthesized declarations are necessary though.

I've added an option for USR generation to override the Clang node and emit the USR of the synthesized Swift declaration. This is used by SwiftDocSupport so that the USRs of the synthesized declarations are emitted.

Fixes 79912
2025-03-25 11:21:21 +00:00
John Hui 66c2e2c52b [cxx-interop] Import non-public inherited members (#79348)
This patch is follow-up work from #78942 and imports non-public members,
which were previously not being imported. Those members can be accessed
in a Swift file blessed by the SWIFT_PRIVATE_FILEID annotation.

As a consequence of this patch, we are also now importing inherited members
that are inaccessible from the derived classes, because they were declared
private, or because they were inherited via nested private inheritance. We
import them anyway but mark them unavailable, for better diagnostics and to
(somewhat) simplify the import logic for inheritance.

Because non-public base class members are now imported too, this patch
inflames an existing issue where a 'using' declaration on an inherited member
with a synthesized name (e.g., operators) produces duplicate members, leading
to miscompilation (resulting in a runtime crash). This was not previously noticed
because a 'using' declaration on a public inherited member is not usually
necessary, but is a common way to expose otherwise non-public members.
This patch puts in a workaround to prevent this from affecting the behavior
of MSVC's std::optional implementation, which uses this pattern of 'using'
a private inherited member. That will be fixed in a follow-up patch.

Follow-up work is also needed to correctly diagnose ambiguous overloads
in cases of multiple inheritance, and to account for virtual inheritance.

rdar://137764620
2025-02-25 01:03:16 -08:00
Allan Shortlidge 07b84fccfb AST: Introduce ModuleDecl::isClangHeaderImportModule() convenience. 2024-09-27 12:00:03 -07:00
Becca Royal-Gordon fd9ae4c8ac Merge pull request #72023 from beccadax/lazy-objc-workaround
Add workaround flag for lazy import-as-member
2024-03-05 16:12:32 -08:00
Becca Royal-Gordon 1a97803c8c Add flag for dumping ClangImporter lookup tables
ClangImporter’s SwiftLookupTables map Swift names to their corresponding Clang declarations. These tables are built into a module’s clang .pcm file and missing or inaccurate entries can cause name lookup to fail to find an imported declaration.

Swift has always included a helper function that would dump these tables, and swift-ide-test has a command-line switch that would invoke it, but these tools are clumsy to use in many debugging scenarios. Add a frontend flag that dumps the tables at the end of the frontend job, making it a lot easier to get at this information in the context of a specific compilation.
2024-02-29 17:51:00 -08:00
Ben Barham ef8825bfe6 Migrate llvm::Optional to std::optional
LLVM has removed llvm::Optional, move over to std::optional. Also
clang-format to fix up all the renamed #includes.
2024-02-21 11:20:06 -08:00
Egor Zhdan 494474b021 [cxx-interop] Support C++ default arguments
This allows calling a C++ function with default arguments from Swift without having to explicitly specify the values of all arguments.

rdar://103975014
2024-01-10 16:37:42 +00:00
Alex Lorenz 59f86d71f2 Revert "[cxx-interop] Refactor: do not rely on Clang module importer being available"
This reverts commit 6a2f10a388.
2023-09-28 18:47:12 -07:00
Egor Zhdan 6a2f10a388 [cxx-interop] Refactor: do not rely on Clang module importer being available
This makes sure that we can emit a pch from a C++ header that uses `CF_OPTIONS`.

rdar://112225263
2023-09-18 21:54:11 +01:00
Alex Lorenz 4d084100ce [cxx-interop] Mark C++ functions with unavailable return type as unavailable
This prevents users from calling functions with unsupported or unavailable return types. This ensures that users don't for example call a function that returns a non-copyable and non-movable type

Fixes https://github.com/apple/swift/issues/64401
2023-07-11 16:40:57 -07:00
Artem Chikin f2cf55a472 [Explicit Module Builds] Ensure IRGen uses Swift compiler's target triple when '-clang-target' is set.
The Clang importer's Clang instance may be configured with a different (higher)
OS version than the compilation target itself in order to be able to load
pre-compiled Clang modules that are aligned with the broader SDK, and match the
SDK deployment target against which Swift modules are also built. In this case,
we must use the Swift compiler's OS version triple in order to generate the
binary as-requested.

This change makes 'ClangImporter' 'Implementation' keep track of a distinct
'TargetInfo' and 'CodeGenOpts' containers that are meant to be used by clients
in IRGen. When '-clang-target' is not set, they are defined to be copies of the
'ClangImporter's built-in module-loading Clang instance. When '-clang-target' is
set, they are configured with the Swift compilation's target triple and OS
version (but otherwise identical) instead. To distinguish IRGen clients from
module loading clients, 'getModuleAvailabilityTarget' is added for module
loading clients of 'ClangImporter'.

The notion of using a different triple for loading Clang modules arises for the
following reason:
- Swift is able to load Swift modules built against a different target triple
  than the source module that is being compiled. Swift relies on availability
  annotations on the API within the loaded modules to ensure that compilation
  for the current target only uses appropriately-available API from its
  dependencies.
- Clang, in contrast, requires that compilation only ever load modules (.pcm)
  that are precisely aligned to the current source compilation. Because the
  target triple (OS version in particular) between Swift source compilation and
  Swift dependency module compilation may differ, this would otherwise result in
  builtin multiple copies of the same Clang module, against different OS
  versions, once for each different triple in the build graph.
Instead, with Explicitly-Built Modules, Swift sets a '-clang-target' argument
that ensures that all Clang modules participating in the build are built against
the SDK deployment target, matching the Swift modules in the SDK, which allows
them to expose a maximally-available API surface as required by
potentially-depending Swift modules' target OS version.
--------------------------------------------
For example:
Suppose we are building a source module 'Foo', targeting 'macosx10.0', using an
SDK with a deployment target of 'macosx12.0'. Swift modules in said SDK will be
built for 'macosx12.0' (as hard-coded in their textual interfaces), meaning they
may reference symbols expected to be present in dependency Clang modules at that
target OS version.

Suppose the source module 'Foo' depends on Swift module 'Bar', which then
depends on Clang module `Baz`. 'Bar' must be built targeting 'macosx12.0'
(SDK-matching deployment target is hard-coded into its textual interface). Which
means that 'Bar' expects 'Baz' to expose symbols that may only be available when
targeting at least 'macosx12.0'. e.g. 'Baz' may have symbols guarded with
'__MAC_OS_X_VERSION_MIN_REQUIRED >= __MAC_12_0'. For this reason, we use
'-clang-target' to ensure 'Baz' is built targeting 'macosx12.0', and can be
loaded by both 'Foo' and 'Bar'.

As a result, we cannot direclty use the Clang instance's target triple here and
must check if we need to instead use the triple of the Swift compiler instance.

Resolves rdar://109228963
2023-05-16 09:42:30 -07:00
Zoe Carver e93e7d1b7a Merge pull request #64513 from zoecarver/revert-75dc69a81da07647bda2d1ccc3b82ce6e68b44a7
Revert 75dc69a81d
2023-03-23 09:58:10 -07:00
zoecarver 4c73369366 Revert "[cxx-interop] Add debug dump when we hit The Flakey Issue™."
This reverts commit 75dc69a81d.
2023-03-21 13:27:17 -07:00
zoecarver ebc492a368 [cxx-interop] Add fix-its to apply 'safe_to_import' and 'self_contained'. 2023-03-20 16:14:42 -07:00
Egor Zhdan 55a08bb2e5 Merge pull request #64453 from apple/egorzhdan/cxx-completion-unsafe
[cxx-interop] Do not auto-complete unsafe underscored methods, part 2
2023-03-17 22:05:39 +00:00
Egor Zhdan 9247d53082 [cxx-interop] Do not auto-complete unsafe underscored methods, part 2
Previous patch removed unsafe C++ methods from the module interface, but not from auto-completion results.

rdar://103252957
2023-03-17 18:04:22 +00:00
Nuri Amari fe2f85765e Merge pull request #64043 from apple/ns-option-linkage-conflict
Fix ASTMangler mangling NS_OPTION differently in C++ mode
2023-03-17 09:33:47 -07:00
zoecarver 75dc69a81d [cxx-interop] Add debug dump when we hit The Flakey Issue™.
This commit should be reverted in a week or two. Sorry.
2023-03-15 12:46:53 -07:00
Nuri Amari 709321b69f Fix ASTMangler mangling NS_OPTION differently in C++ mode
CF_OPTIONS is defined differently in the SDK based on
a __cplusplus preprocessor branch. As a result, declarations
referencing CF_OPTIONS are mangled differently depending
on if C++ interop is enabled.

This meant a module compiled with cxx interop on could
not be linked with a module compiled without and vice versa.
This patch modifies the mangler such that the mangled names
are consistent. This is achieved by feeding the mangler a modified
AST node that looks like the Objective-C definition of CF_OPTIONS,
even when we have cxx interop enabled.
2023-03-09 09:30:05 -08:00
zoecarver f0d5cb9a84 [cxx-interop] Lazily instanciate var types and compute their type. 2022-09-09 17:26:22 -07:00
Egor Zhdan 51a1176d90 [cxx-interop] Clang member lookup should not look into Swift extensions
Calling `NominalTypeDecl::lookupDirect` triggers deserialization of Swift extensions for the type. `ClangRecordMemberLookup` shouldn't assume it is allowed to deserialize Swift extensions for the given C++ type: there might be extensions which reference the module that is currently being imported, which causes circular request dependency errors.
2022-08-08 17:05:25 +01:00
zoecarver 680d5d2cc8 [nfc] [cxx-interop] Move function template specialization logic into clang-module-loader. 2022-03-02 10:58:14 -08:00
zoecarver bb00e8dcfe [cxx-interop] Rudimentary support for importing base classes.
This commit adds very basic support for importing and calling base class methods, getting and setting base class fields, and using types inside of base classes.
2022-02-18 15:59:52 -08:00
Nuri Amari 3762ca1fa7 Attach Lazy ClangImporter Diagnostics as Notes
Clang importer diagnostics that are produced as a result of a reference
in Swift code are attached to as notes to the Sema produced diagnostic
that indicates the declaration is unavailable.

Ex: Notes about why a C function import failed are attached to
the error explaining that the symbol could not be found in scope.
2022-01-29 14:32:42 -05:00
Nuri Amari 130f2de7fd Improve ClangImporter failure diagnostics
This patch introduces new diagnostics to the ClangImporter to help
explain why certain C, Objective-C or C++ declarations fail to import
into Swift. This patch includes new diagnostics for the following entities:

- C functions
- C struct fields
- Macros
- Objective-C properties
- Objective-C methods

In particular, notes are attached to indicate when any of the above
entities fail to import as a result of refering an incomplete (only
forward declared) type.

The new diangostics are hidden behind two new flags, -enable-experimental-clang-importer-diagnostics
and -enable-experimental-eager-clang-module-diagnostics. The first flag emits diagnostics lazily,
while the second eagerly imports all declarations visible from loaded Clang modules. The first
flag is intended for day to day swiftc use, the second for module linting or debugging the importer.
2022-01-02 12:43:59 -05:00
zoecarver d13f43c31b [cxx-interop] Add three utilities to the ClangModuleLoader.
This adds `importDeclDirectly`, `findLookupTable`, `importName`, and `getEffectiveClangContext`. These are all needed for #38675.
2021-09-23 16:51:03 -07:00
zoecarver 6e9bf50996 [cxx-interop] Lazily load the result of imported functions.
Note: we only lazily load the result if it's a record, because otherwise it's trivial to load when importing the function. Also, we still eagerly import operator's results types.
2021-09-08 17:48:39 -07:00
Egor Zhdan a8f126f7cd C++ Interop: import const methods as non-mutating
This change makes ClangImporter import some C++ member functions as non-mutating, given that they satisfy two requirements:
* the function itself is marked as `const`
* the parent struct doesn't contain any `mutable` members

`get` accessors of subscript operators are now also imported as non-mutating if the C++ `operator[]` satisfies the requirements above.

Fixes SR-12795.
2021-07-25 15:18:33 +03:00
Marcel Hlopko 4f5c75a236 [cxx-interop] Instantiate C++ class templates from Swift (#33284)
This PR makes it possible to instantiate C++ class templates from Swift. Given a C++ header:

```c++
// C++ module `ClassTemplates`
template<class T>
struct MagicWrapper {
  T t;
};

struct MagicNumber {};
```

it is now possible to write in Swift:

```swift
import ClassTemplates

func x() -> MagicWrapper<MagicNumber> {
  return MagicWrapper<MagicNumber>()
}
```

This is achieved by importing C++ class templates as generic structs, and then when Swift type checker calls `applyGenericArguments` we detect when the generic struct is backed by the C++ class template and call Clang to instantiate the template. In order to make it possible to put class instantiations such as `MagicWrapper<MagicNumber>` into Swift signatures, we have created a new field in `StructDecl` named `TemplateInstantiationType` where the typechecker stores the `BoundGenericType` which we serialize. Deserializer then notices that the `BoundGenericType` is actually a C++ class template and performs the instantiation logic.

Depends on https://github.com/apple/swift/pull/33420.
Progress towards https://bugs.swift.org/browse/SR-13261.
Fixes https://bugs.swift.org/browse/SR-13775.

Co-authored-by: Dmitri Gribenko <gribozavr@gmail.com>
Co-authored-by: Rosica Dejanovska <rosica@google.com>
2021-01-27 13:01:20 +01:00
zoecarver c4da4975ed [NFC] Cleanup function templates implementation. Address post-commmit review comments from #33053.
Addresses the post-commit review comments from #33053. Just re-naming,
commenting, and some other small cleanups, nothing functionally
different.
2021-01-19 12:02:15 -08:00
Zoe Carver f0f2246793 [cxx-interop] Support C++ function templates in Swift. (#33053)
This patch adds rudimentary support for C++ template functions in swift.
2020-10-21 20:42:25 -07:00
David Zarzycki 1e940c2c7e [NFC] Fix -Wsuggest-override warnings
LLVM, as of 77e0e9e17daf0865620abcd41f692ab0642367c4, now builds with
-Wsuggest-override. Let's clean up the swift sources rather than disable
the warning locally.
2020-08-13 16:17:46 -04:00
Brent Royal-Gordon 121fa9a058 Ignore transitive ObjC imports when cross-importing
This behavior change reduces the chance of unexpected and unwanted cross-imports being performed.

Fixes rdar://problem/60554019.
2020-04-05 19:06:59 -07:00
Hamish Knight d9182af63d [AST] Introduce ModuleDecl::getTopLevelModule
This can be used to retrieve the Swift module
wrapper for a Clang submodule's top-level module.
2020-02-24 20:10:13 -08:00
John McCall faee21b626 Implement Swift serialization and deserialization of Clang types.
As part of this, we have to change the type export rules to
prevent `@convention(c)` function types from being used in
exported interfaces if they aren't serializable.  This is a
more conservative version of the original rule I had, which
was to import such function-pointer types as opaque pointers.
That rule would've completely prevented importing function-pointer
types defined in bridging headers and so simply doesn't work,
so we're left trying to catch the unsupportable cases
retroactively.  This has the unfortunate consequence that we
can't necessarily serialize the internal state of the compiler,
but that was already true due to normal type uses of aggregate
types from bridging headers; if we can teach the compiler to
reliably serialize such types, we should be able to use the
same mechanisms for function types.

This PR doesn't flip the switch to use Clang function types
by default, so many of the clang-function-type-serialization
FIXMEs are still in place.
2020-02-06 22:09:00 -05:00
Varun Gandhi afc6ccdeb5 Re-land parsing and printing for Clang function types.
This reverts commit e805fe486e, which reverted
the change earlier. The problem was caused due to a simultaneous change to some
code by the PR with parsing and printing for Clang function types (#28737)
and the PR which introduced Located<T> (#28643).

This commit also includes a small change to make sure the intersecting region
is fixed: the change is limited to using the fields of Located<T> in the
`tryParseClangType` lambda.
2020-01-07 15:58:32 -08:00