Commit Graph

127 Commits

Author SHA1 Message Date
Egor Zhdan
b16816b4ee [cxx-interop] Disable test with an older runtime
848fad00 introduced support for printing foreign reference types. It changes both the compiler and the runtime, and having the runtime change applied is required for the test to pass. Let's not try to run it with an old runtime.

This change also splits up a test for printing of value types from a test for printing of foreign reference types, since we don't have any runtime restrictions for value types.

rdar://153205860
(cherry picked from commit 62d56067c8)
2025-06-23 18:16:24 +01:00
susmonteiro
862efcf3a0 [cxx-interop] Support for printing C++ foreign references
Adds support for printing a C++ foreign reference in Swift.

Also skips metadata of private fields in C++ records imported as Swift classes, following up on #81035

(cherry-picked from 848fad0021)
2025-06-11 17:13:01 +01:00
Egor Zhdan
ee5f7ad262 [cxx-interop] Do not crash when emitting layout of std::string
If a `[[no_unique_address]]` field has zero size according to Clang, and field has a type that isn't representable in Swift, Swift would previously try to add an opaque field of size 1 for it.

This is wrong and was causing crashes for `std::string` while emitting a padding field:
```
_LIBCPP_NO_UNIQUE_ADDRESS ::std::__compressed_pair_padding<T1> _LIBCPP_CONCAT3(__padding1_, __LINE__, _);
```

rdar://151941799
(cherry picked from commit a7c174431f)
2025-05-30 17:33:31 +01:00
susmonteiro
d81d6547ba [cxx-interop] Fix metadata mismatch regarding fields of structs
In https://github.com/swiftlang/swift/pull/78467 and https://github.com/swiftlang/swift/pull/78961, we stopped emitting metadata for private C++ fields. However, this created a mismatch between the fields emitted and the number of fields + their offsets in the StructDescriptor.

rdar://147263490
(cherry picked from commit 72b13b3b48)
2025-05-23 11:16:09 +01:00
John Hui
f6f5adb5f4 [cxx-interop] Avoid querying layout of dependent types during symbolic import
In #80786, we started importing certain padded fields as opaque blobs.
Part of this logic involved querying those fields' ASTRecordLayout.
However, dependent types (which are imported symbolically) do not have
an ASTRecordLayout, so calling Clang's getASTRecordLayout() would lead
to an assertion error for class templates where a no_unique_address
field is some kind of dependent C++ record type.

This patch avoids the field padding check during symbolic import mode
because that check is only relevant for codegen anyway.

rdar://150067288
(cherry picked from commit 1fdb239cea)
2025-05-01 10:10:56 -07:00
John Hui
a2c5cff6a1 [NFC] Add test where the padding of a [[no_unique_address]] field with a custom type is reused
(cherry picked from commit 5fdbb44041)
2025-05-01 10:10:56 -07:00
John Hui
e5038f1f18 [NFC] Rename types to mention optional
(cherry picked from commit 9b0ab9095e)
2025-05-01 10:10:56 -07:00
Gábor Horváth
7f0d24b810 Merge pull request #81100 from swiftlang/gaborh/unique-address-padding-on-6.2 2025-04-25 14:03:27 -07:00
Gabor Horvath
291a63fd80 [6.2][cxx-interop] Fix a crash with [[no_unique_address]]
Explanation: Swift does not support storing fields in the padding of the previous
fields just yet, so let's not import fields like that from C++.
Represent them as opaque blobs instead.
Issue: rdar://149072458
Risk: Low, the fix is targeted at a scenario that was crashing before.
Testing: Regression test added.
Original PR: #80786
Reviewer:
2025-04-25 12:51:13 +01:00
Gábor Horváth
c3a7203221 [6.2][cxx-interop] Fix runtime crash passing FRTs as const FRT*
Explanation: There was an inconsistency between non-const and const FRT
pointers. The former used Direct_Unowned the latter used Indirect
calling convention. We want to use Direct_Unowned for both cases. The
crash was the result of a calling convention mismatch between the
SILFunctionType of a Swift closure and the SILFunctionType of the C++
function's formal parameter that is taking a function pointer. The
compiler tried to insert a conversion between the two function types
that does not exist and caused an assertion in debug compilers and
miscompilation in production compilers.
Issue: rdar://149398905
Risk: Low, the fix is targeted and we change to a well-tested behavior
with non-const FRT pointers.
Testing: Regression test added.
Original PR: #81070
Reviewer: @j-hui
2025-04-25 10:59:45 +01:00
fahadnayyar
5cab57439f [cxx-interop] Import parameterized public ctors of C++ foreign ref types as Swift Initializer (#80449)
Extends PR #79986 by adding support for calling parameterized C++ initializers from Swift. This patch synthesizes static factory methods corresponding to C++ parameterized constructors, allowing Swift to call them as Swift initializers (e.g., init(_:), init(_:_:), etc.). This patch also aded tests and logic to make sure that we emit no additional diagnostics when a C++ foreign ref type is just referred from Swift and its initializer is not explicitly called.

rdar://148285251
2025-04-10 05:55:05 -07:00
fahadnayyar
9694cc8d70 [cxx-interop] Import default public ctor of C++ foreign ref types as Swift Initializer (#79986)
Building on top of PR #79288, this update synthesizes a static factory method using the default new operator, with a call to the default constructor expression for C++ foreign reference types, and imports them as Swift initializers.

rdar://147529406
2025-03-31 20:33:53 -07:00
Gabor Horvath
14d92ff7a1 [cxx-interop] Test static factory backed initializers with value types
We can use swift_name to import a static factory function as a Swift
initializer. This was tested with foreign reference types but not with
value types. This PR adds a test case for the latter.

rdar://117531428
2025-03-11 17:36:54 +00:00
susmonteiro
51357a952c [cxx-interop] Prevent usage in Swift of C++ move constructor with default args 2025-03-07 16:02:38 +00:00
Susana Monteiro
593f320460 Merge pull request #79325 from swiftlang/susmonteiro/copy-constructor-default-args
[cxx-interop] Prevent usage in Swift of C++ copy constructor with default args
2025-03-04 15:40:22 +00:00
susmonteiro
bc6573ec32 [cxx-interop] Prevent usage in Swift of C++ copy constructor with default args 2025-03-03 13:22:11 +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
Gábor Horváth
40deafb285 Merge pull request #79076 from swiftlang/gaborh/zero-sized-field-import
[cxx-interop] Do not codegen zero-sized fields
2025-02-03 17:22:00 +00:00
Gabor Horvath
998591e9f9 [cxx-interop] Do not import zero-sized fields
Zero sized fields are messing up the offset calculations when we import
C++ fields to Swift. We assume that the size of the field is determined
by the type of the field. This is not true for fields marked with
no_unique_address. Those fields can have 0 size while the
sizeof(decltype(field)) is still 1.

rdar://143907490
2025-02-03 11:55:54 +00:00
John Hui
be73254cdc [cxx-interop] Import private members (#78942)
This commit removes the guardrails in ImportDecl.cpp:SwiftDeclConverter
that prevent it from importing non-public C++ members. It also
accordingly adjusts all code that assumes generated Swift decls should
be public. This commit does not import non-public inherited members;
that needs its own follow-up patch.

Note that Swift enforces stricter invariants about access levels than C++.
For instance, public typealiases cannot be assigned private underlying types,
and public functions cannot take or return private types. Meanwhile,
both of these patterns are supported in C++, where exposing private types
from a class's public interface is considered feature. As far as I am aware,
Swift was already importing such private-containing public decls from C++
already, but I added a test suite, access inversion, that checks and
documents this scenario, to ensure that it doesn't trip any assertions.
2025-01-30 14:50:15 -08:00
Egor Zhdan
738c8fb6c6 [cxx-interop] Skip type metadata for C++ types that are only used in private C++ fields
This fixes compiler errors for C++ types that use pimpl idiom:
```
invalid application of 'sizeof' to an incomplete type
```

rdar://141960396
2025-01-13 12:03:35 +00:00
Egor Zhdan
aa584bf876 [cxx-interop] Check the presence of copy constructor correctly
This reverts commit 3066bd6919.

This re-lands a change after it got reverted because of a regression in the build of SwiftCompilerSources.

rdar://136838485
2024-11-15 15:21:55 +00:00
Egor Zhdan
3066bd6919 Revert "[cxx-interop] Check the presence of copy constructor correctly"
This reverts commit fbbec48c

The change was causing regressions in certain build configs that need to be investigated.

rdar://139723218
2024-11-14 16:31:27 +00:00
Egor Zhdan
6943986c71 [cxx-interop] Import private fields of C++ structs
While private and protected fields coming from C++ cannot be accessed from Swift, they can affect Swift typechecking.

For instance, the Swift typechecker mechanism that adds implicit `Sendable` conformances works by iterating over all of the struct's fields and checking whether all of them are `Sendable`. This logic was broken for C++ types with private fields, since they were never accounted for. This resulted in erroneous implicit `Sendable` confromances being added.

Same applies for `BitwiseCopyable`.

In addition to this, ClangImporter used to mistakenly mark all C++ structs that have private fields as types with unreferenceable storage, which hampered optimizations.

As a side effect of this change, we now also provide a better diagnostic when someone tries to access a private C++ field from Swift.

rdar://134430857
2024-11-12 12:47:26 +00:00
Akira Hatanaka
f73c2e51bd Revert "[SILGen] Fix the type of closure thunks that are passed const reference structs (#76903)" (#77309)
This reverts commit 9c44b79189.

The commit caused swift's deserialization code to crash.

rdar://138726860
2024-10-31 15:16:00 -07:00
Egor Zhdan
fbbec48c76 [cxx-interop] Check the presence of copy constructor correctly
This removes a longstanding workaround in the import logic for C++ structs:
Swift assumed that if a C++ struct has no copy constructor that is explicitly deleted, then the struct is copyable. This is not actually correct. This replaces the workaround with a proper check for the presence of a C++ copy constructor.

rdar://136838485
2024-10-28 20:05:57 +00:00
Akira Hatanaka
9c44b79189 [SILGen] Fix the type of closure thunks that are passed const reference structs (#76903)
The thunk's parameter needs the @in_guaranteed convention if it's a
const reference parameter. However, that convention wasn't being used
because clang importer was removing the const reference from the
type and SILGen was computing the type of the parameter based on the
type without const reference.

This commit fixes the bug by passing the clang function type to
SILDeclRef so that it can be used to compute the correct thunk type.

This fixes a crash when a closure is passed to a C function taking a
pointer to a function that has a const reference struct parameter.

This recommits e074426 with fixes to
serialization/deserialization of function types. The fixes prevent clang
types of functions from being dropped during serialization.

rdar://131321096
2024-10-08 23:44:49 -07:00
Akira Hatanaka
90e4a98a46 [cxx-interop] Use the name of the typedef when an unnamed class is used as a template argument (#76844)
This fixes a bug where IRGen would try to use the same name for two
different protocol witness methods.

rdar://134149098
2024-10-03 08:58:29 -07:00
Slava Pestov
9632979879 Revert "[SILGen] Fix the type of closure thunks that are passed const referen…"
This reverts commit e074426058.
2024-09-29 22:32:04 -04:00
Akira Hatanaka
e074426058 [SILGen] Fix the type of closure thunks that are passed const reference structs (#75491)
The thunk's parameter needs the @in_guaranteed convention if it's a
const reference parameter. However, that convention wasn't being used
because clang importer was removing the const reference from the
type and SILGen was computing the type of the parameter based on the
type without const reference.

This commit fixes the bug by passing the clang function type to
SILDeclRef so that it can be used to compute the correct thunk type.

This fixes a crash when a closure is passed to a C function taking a
pointer to a function that has a const reference struct parameter.

rdar://131321096
2024-09-27 07:04:47 -07:00
Egor Zhdan
34c796d100 [cxx-interop] Add a test for instantiation of a default destructor
This is a follow-up to f56fa41.

rdar://124061505
2024-07-04 17:35:01 +01:00
Akira Hatanaka
42bc49d3fe Add a new parameter convention @in_cxx for non-trivial C++ classes that are passed indirectly and destructed by the caller (#73019)
This corresponds to the parameter-passing convention of the Itanium C++
ABI, in which the argument is passed indirectly and possibly modified,
but not destroyed, by the callee.

@in_cxx is handled the same way as @in in callers and @in_guaranteed in
callees. OwnershipModelEliminator emits the call to destroy_addr that is
needed to destroy the argument in the caller.

rdar://122707697
2024-06-27 09:44:04 -07:00
Akira Hatanaka
11696cd452 [SILGen] Fix assertion failure when opaque value is enabled (#74676)
emitManagedParameter assumes the passed value has an address type and
calls forBorrowedAddressRValue when the parameter convention is
Indirect_In_Guaranteed.

Call forBorrowedObjectRValue instead when the type isn't an address
type.

rdar://130456931
2024-06-25 11:49:34 -07:00
Akira Hatanaka
1b0df4eefe [SILGen] Fix a crash when a closure is converted to a pointer to a function returning a non-trivial C++ type (#73561)
When emitting a native-to-foreign thunk, pass the thunk's result address parameter to the native function if both the thunk and the native function return their results indirectly and the thunk is not for an async function.

Also, remove an outdated assertion.

rdar://124501345
2024-06-18 15:03:44 -07:00
Alex Lorenz
2039b8d254 [cxx-interop] import static operator call from C++23 as member callAsFunction functions in Swift to preserve source compatibility 2024-06-12 09:11:15 -07:00
Akira Hatanaka
b5cc5615bd [SILGen] Fix a crash when a closure is converted to a block returning a value indirectly (#73520) 2024-05-23 21:22:32 -07:00
Akira Hatanaka
428fe21855 [SILGen] Fix a bug where the wrong convention was being used for computing the type of a closure thunk (#73299)
The ObjC selector family convention was being used instead of the C
function type convention.

rdar://127090209
2024-04-29 18:03:59 -07:00
Egor Zhdan
cfe27287da Merge pull request #72903 from apple/egorzhdan/zero-init
[cxx-interop] Zero-initialize C++ structs when calling their default constructors
2024-04-17 13:39:21 +01:00
Akira Hatanaka
d76dbb1a64 [SILGen] Fix a bug where the wrong convention was being used for lowering a closure to a C++ function pointer (#73039)
Use the C function pointer convention instead of the block convention.

rdar://122977380
2024-04-16 15:18:50 -07:00
Egor Zhdan
bac5d0e9a1 [cxx-interop] Zero-initialize C++ structs when calling their default constructors
When Swift imports C structs, it synthesizes an initializer that takes no arguments and zero-initializes the C struct.

When C++ interop is enabled, Clang treats all C structs as if they were C++ structs. This means that some of the C structs will get a default constructor implicitly generated by Clang. This implicit default constructor will not zero-initialize trivial fields of the struct.

This is a common source of confusion and subtle bugs for developers who try to enable C++ interop in existing projects that use C interop and rely on zero-initialization of C structs.

rdar://115909532
2024-04-16 13:42:02 +01:00
Egor Zhdan
802f20ec00 [cxx-interop][IRGen] Assign Clang function types to copy constructors
This fixes an assertion failure when building certain projects for arm64e with `-use-clang-function-types` Swift compiler flag:
```
Expected non-null Clang type for @convention(c)/@convention(block) function but found nullptr
```

rdar://121227452
2024-04-03 19:26:32 +01:00
Egor Zhdan
d494632e98 [cxx-interop] Refactor: move swift/bridging source elsewhere for better testability
rdar://123334601
2024-03-08 20:13:27 +00:00
Egor Zhdan
8ead7224b7 [cxx-interop] Overhaul virtual method support
This adds a new implementation of virtual method dispatch that handles reference types correctly.

Previously, for all C++ types an invocation of a virtual method would actually get dispatched statically. For value types this is expected and matches what C++ does because of slicing. For reference types, however, this is incorrect, we should do dynamic dispatch.

rdar://123852577
2024-03-01 19:45:58 +00:00
Egor Zhdan
6ecaaa41c5 Merge pull request #70304 from apple/egorzhdan/conforms-to-derived-class
[cxx-interop] Propagate `CONFORMS_TO` attribute to derived classes
2023-12-07 22:00:44 +01:00
Egor Zhdan
45b22542d5 [cxx-interop] Propagate CONFORMS_TO attribute to derived classes
If `struct Base` is a public base class of `struct Derived`, and `Base` is annotated with `__attribute__((swift_attr("conforms_to:MyModule.MyProto")))`, `Derived` will now also get a conformance to `MyProto`.

rdar://113971944
2023-12-07 18:11:37 +00:00
Alex Lorenz
b7158ea486 [cxx-interop] add SWIFT_NONCOPYABLE annotation 2023-11-29 18:13:31 -08:00
Egor Zhdan
efc008a2ca [cxx-interop] Import using decls that expose methods from private base classes
If a C++ type `Derived` inherits from `Base` privately, the public methods from `Base` should not be callable on an instance of `Derived`. However, C++ supports exposing such methods via a using declaration: `using MyPrivateBase::myPublicMethod;`.

MSVC started using this feature for `std::optional` which means Swift doesn't correctly import `var pointee: Pointee` for instantiations of `std::optional` on Windows. This prevents the automatic conformance to `CxxOptional` from being synthesized.

 rdar://114282353 / resolves https://github.com/apple/swift/issues/68068
2023-11-14 00:30:54 +00:00
Egor Zhdan
9c22a7a530 [cxx-interop] Memberwise init is not synthesized for C++ type with templated using decl
When Swift fails to import a member of a struct, it checks to see if this member could affect the memory layout of the struct, and if it can, Swift doesn't synthesize the memberwise initializer for this struct. This logic was overly restrictive and treated templated using-decls as potentially affecting the memory layout of the struct.

rdar://113044949
2023-07-28 19:53:59 +01:00
Alex Lorenz
15a0345857 Merge pull request #67268 from hyp/eng/windows-method-oh-no
[cxx-interop] windows methods fixes
2023-07-21 06:57:01 -07:00
Alex Lorenz
96806f4d44 [cxx-interop] Windows: unify address-only logic and mark non-trivial loadable C++ types as unavailable
Windows logic for determining address-only type layout for a C++ type is now unified with other platforms.
However, this means that on Windows, a C++ type with a custom destructor, but a default copy constructor
is now loadable, even though it's non-trivial. Since Swift does not support such type operations at the
moment (it can't be yet destroyed), mark such type as unavailable in Swift instead, when building for
the Windows target.

This fixes the Windows miscompilation related to such types when they were passed indirectly to C++
functions even though they're actually passed directly.
2023-07-20 14:58:02 -07:00