Swift functions exposed to C++ return +1 (retained) values, but the
generated C++ thunks in the -Swift.h header lacked ownership
annotations. This prevented Clang's static analyzer from verifying
reference counts when C++ code calls into Swift.
Add NS_RETURNS_RETAINED, CF_RETURNS_RETAINED, and SWIFT_RETURNS_RETAINED
annotations to thunk signatures based on the return type:
- NS_RETURNS_RETAINED for ObjC classes (NSString, etc.) and existentials (id)
- CF_RETURNS_RETAINED for CF types (CFString, etc.)
- SWIFT_RETURNS_RETAINED for foreign reference types
rdar://165231653
Currently, move only types are never exposed in reverse interop because
the generated interop header does not support Swift's move semantics. On
the other hand, Clang types work out of the box with borrowing. This PR
enables exporting Swift functions that are borrowing or returning
move-only Clang types.
The consuming specifier does not work yet, that needs some changes to
the generated function bodies and can be done in a follow-up PR.
rdar://162361370
Instead of having a property-specific mechanism to detect duplicates,
let's use the generic facilities we have to detect problems with method
overloading. This both fixes an issue where we generated reverse interop
headers that would not compile when a user written method has the sanem
name as the getter we generate on the C++ side. But it also makes the
detection more flexible allowing for overloading when the parameter
types differ.
rdar://164465903
Previously, we never exported Swift functions that have pointers to C or
C++ structs in their signature. These pointers are always safe to pass,
we have declarations on the C/C++ side and we have no ABI issues.
rdar://172205792
Confusingly, isObjC on an existential does not check if the super class
is actually ObjC. Make the check stricter to avoid a crash down the
line.
rdar://169210092
Introduce a cache that helps cutting the recursion when we process a
type that we already visited before but did not finish processing yet.
Fixes#85361
rdar://164153038
This makes sure that whenever we emit `#if defined(__OBJC__)`, the matching `#endif` has a comment `// defined(__OBJC__)`.
This makes both testing and reading the header file easier.
This supports both built-in vector types and the SIMDX<T> Swift types
that are used through type aliases like float3. These SIMD types are
passed via compatibility structs (with their valued memcpy-d into the
ABI compatible struct) as they have special ABI rules. E.g., a float3 is
not passed as float3, but as float4 on the ABI level.
Previously, we did not expose simd types from Swift to C++ (unless the
SIMD types were impoted from clang).
rdar://153218744
These objects are behind typedefs and user code supposed to use the
typedef names. We already have some logic in place for Obj-C interop.
Reuse the same logic for C++ to use the correct names.
rdar://150453489
These types are passed around as reference counted pointers, so the
optional representation of them are nullable pointers. Previously, we
tried to wrap them in swift::Optional.
rdar://157667946
Functions or template instantiations with Obj-C types should always be
behind a macro to make sure the interop header compiles cleanly in C++.
rdar://152836730
The test for nested constructs used library evolution forcing all types
to be opaque. As a result some code paths for non-opaque types were not
updated to support nested types. This patch updates the rest of the code
making sure we use fully qualified names (so they also work in the
context of the nested classes), and generate correct names for the C
compatibility structs that cannot contain "::".
Fixes#80291
rdar://147882976
Print the type traits in reverse interop to enable the use of foreign
reference type in generics like Swift arrays. Also make sure optional
foreign reference types can be passed around as raw pointers.
rdar://108139769
In reverse interop, we create copies of values that will be consumed by
the Swift function. This is not necessary for pointers that are passed
as swift::Optional to Swift. These are layout compatible, and consuming
a pointer should not require us to do anything extra, hopefully ARC
would take care of all the details.
rdar://146855233
This is not supported, of course. But now, instead of an assertion
failure we properly mark the declaration as unavailable.
Fixes#78190.
rdar://141492654
This patch introduces handling of ObjC protocols similar to how ObjC
classes work. Since this only works in ObjC++, all declarations
containing ObjC protocols will be protected by the __OBJC__ macro.
This patch results in some `_bridgeObjC` methods being exposed, we might
end up hiding those in the future, but there is no harm having them in
the interop header for the interim period.
rdar://136757913
It is really involved to change how methods and classes are emitted into
the header so this patch introduces the impression of nested structs
through using statements and still emits the structs themselves as top
level structs. It emits them in their own namespace to avoid name
collisions. This patch also had to change some names to be fully
qualified to avoid some name lookup errors in case of nested structs.
Moreover, nesting level of 3 and above requires C++17 because it relies
on nested namespaces. Only nested structs are supported, not nested
classes.
Since this patch is already started to grow quite big, I decided to put
it out for reviews and plan to address some of the shortcomings in a
follow-up PR.
rdar://118793469
C++ only support multiparameter operator[] in C++23 and up. Change the
code to protect such overloaded operators with a C++ language mode
check.
rdar://133539699
Previously, when a Swift API referenced a C struct (that is not a C++
struct), we did not expose said API to C++. The reason was that we do
not have support yet for non-trivial structs (structs with ARC fields).
This patch introduces logic to determine if a C struct is trivial and
lets us expose trivial C structs from Swift to C++.
rdar://111812577
Previously the code got the declaration for types with generic
arguments and the printer used the declaration. This was a lossy
operation, we printed the type with generic parameters instead of the
arguments. This patch makes sure we print the type with the arguments.
Unfortunately, the code structure is not the most clear, type printing
is currently inherently part of the function signature printing. This
code path needs to be factored out in the future to make the code easier
to understand.
rdar://130679337
This feature worked prior 5.10 but the semantics was undefined. This PR
restores the behavior with the old semantics, and a separate PR will
update the documentation to describe the behavior.
Because imported enums are @objc, they were treated as unsupported in C++ and therefore ineligible to be printed in a C++ generated header. Narrow this logic so that only @objc *classes* are excluded, and update related printing logic to support enums correctly.
Fixes rdar://124262637.
Create two versions of the following functions:
isConsumedParameter
isGuaranteedParameter
SILParameterInfo::isConsumed
SILParameterInfo::isGuaranteed
SILArgumentConvention::isOwnedConvention
SILArgumentConvention::isGuaranteedConvention
These changes will be needed when we add a new convention for
non-trivial C++ types as the functions will return different answers
depending on whether they are called for the caller or the callee. This
commit doesn't change any functionality.
The clang nodes associated with Swift's Core Foundation types can already be
represented by a pointer. The interop code does not need to add an extra
layer of indirection in those cases.
rdar://119840281
The function responsible for printing signatures can return in the middle
of the printing process whenever it discovers an unsupported scenario.
To avoid creating a header that cannot be compiler, this function should
be transactional. It either has to succeed and write the signature to the
stream, or in case it failed, the stream should be untouched. This patch
introduces a temporary buffer that is flushed to the stream as the last
step for a successful execution. This should make the user experience
better whenever the user stumbles upon something that is unsupported.
In Swift, we can have enum elements and methods with the same name, they are overloaded.
Unfortunately, this feature is not supported by C++ interop at the moment. This patch
avoids emitting the methods with name collisions to make sure the resulting header
can be compiler. A proper fix should follow in a later PR.
rdar://128162252
Although I don't plan to bring over new assertions wholesale
into the current qualification branch, it's entirely possible
that various minor changes in main will use the new assertions;
having this basic support in the release branch will simplify that.
(This is why I'm adding the includes as a separate pass from
rewriting the individual assertions)
Extend the previous commit’s support for functions that return Never to also properly generate code for *throwing* Never functions. This is a little subtle because:
• At the SWIFT_CALL level, throwing Never functions are *not* noreturn
• At the thunk level, throwing Never functions are noreturn *only* if you’re using exceptions; if you’re using swift::Expected, they should throw
• In either case, the compiler cannot statically prove that thunks are noreturn except on the error path, so we need to add an abort() call on the success path
Swift-to-C++ thunk printing for functions didn’t really take into account Swift’s `Never` type. This type maps to `SWIFT_NORETURN`, but it also requires other tweaks to code generation, such as omitting the `return` keyword. (Removing that requires minor changes to many tests.)
Fixes rdar://124137073.
LLVM is presumably moving towards `std::string_view` -
`StringRef::startswith` is deprecated on tip. `SmallString::startswith`
was just renamed there (maybe with some small deprecation inbetween, but
if so, we've missed it).
The `SmallString::startswith` references were moved to
`.str().starts_with()`, rather than adding the `starts_with` on
`stable/20230725` as we only had a few of them. Open to switching that
over if anyone feels strongly though.
Noncopyable and nonescaping APIs in Swift can be expressed in C++ with
some downsides. Teach the AST printer to be more lenient, allowing
Swift APIs involving noncopyable and nonescapable types to be printed.