If two different C++ structs have methods with the same name, both annotated with `SWIFT_COMPUTED_PROPERTY`, ClangImporter previously confused them when one of the structs referenced the other struct.
rdar://108990490 / resolves https://github.com/apple/swift/issues/65675
A record that's non trivia for purpose of calls, as defined in Itanium ABI is allowed to have non-trivial copy/move assignment operators, but it most not have non-trivial constructors or destructors. This change ensures that a C++ record with a non-trivial copy assignment operator but trivial other members can be passed/returned directly by value, so that the compiler can accept the returned value correctly when calling a C++ function.
Calling getImportedModules requires to list the desired kind of imports.
With the new kind of imports this has become cumbersome. Let's simplify
it by offering common sets of imports. Advanced call sites can still
list the desired imports explicitly.
This modifies the ClangImporter to introduce an opaque placeholder
representation for forward declared Objective-C interfaces and
protocols when imported into Swift.
In the compiler, the new functionality is hidden behind a frontend
flag -enable-import-objc-forward-declarations, and is on by default
for language mode >6.
The feature is disabled entirely in LLDB expression evaluation / Swift
REPL, regardless of language version.
This adds a protocol to the C++ standard library overlay which will improve the ergonomics of `std::optional` when used from Swift code.
As of now, the overlay adds an initializer of `Swift.Optional` that takes an instance of `CxxOptional` as a parameter.
At the call sites of `findAnonymousEnumForTypedef` we often wish to
import the returned enum declaration and return the type the declaration
creates.
Prior to this patch, we assumed that the enum declaration would be
imported as a `NominalTypeDecl`. This is not always the case. For
whatever reason, sometimes in typechecking we import a declaration
for various different naming versions. If the Swift name for an imported
enum differs between the canonical name version, and currently
requested name version, we import the enum as a `TypeAliasDecl` instead.
Prior to this patch, this meant we would hit asserts importing some
components of UIKit.
This patch relaxes the assumption that the import is a `NominalTypeDecl`
to just a `TypeDecl`, which as of yet, seems to be true.
If a C++ struct defines multiple overloads of `operator*`, avoid synthesizing multiple `var pointee: Pointee` properties, since that would introduce name resolution ambiguity. Instead, pick one of the const overloads and synthesize a single `pointee` property.
This is required for `std::optional` support.
This adds a protocol to the C++ standard library overlay which will improve the ergonomics of `std::map` and `std::unordered_map` when used from Swift code.
As of now, `CxxDictionary` adds a subscript with an optional return type that mimics the subscript of `Swift.Dictionary`.
Similar to https://github.com/apple/swift/pull/63244.
This adds a protocol to the C++ standard library overlay which will improve the ergonomics of `std::set`, `std::unordered_set` and `std::multiset` when used from Swift code.
As of now, `CxxSet` adds a `contains` function to C++ sets.
C++ stdlib set types are automatically conformed to `CxxSet`: `std::set`, `unordered_set`, `std::multiset`. Custom user types are not conformed to `CxxSet` automatically: while a custom type might have an interface similar to `std::set`, the semantics might differ, and adding a conformance would cause confusion.
Trying to use members of C++ private base classes from Swift causes an assertion failure in ClangImporter:
```
<build dir>/swift/lib/swift/macosx/arm64/libcxxshim.h:2:66: error: cannot cast 'A' to its private base class 'B'
To __swift_interopStaticCast(From from) { return static_cast<To>(from); }
^
```
Such members should not be exposed.
rdar://103871000
If a templated C++ class declares an operator as a member function, and is instantiated using a typedef or a using-decl on the C++ side, it previously could not be conformed to a Swift protocol that requires the operator function despite matching signatures.
This was due to a Swift name lookup issue: operators, unlike regular member functions, are found by doing an unqualified lookup. Since C++ class template specializations and their members are not added to `SwiftLookupTable`, when doing qualified lookup members are searched by looking at all of the members of the specialization and choosing the ones with matching names. With unqualified lookup, we cannot rely on knowing the right specialization and need to search for all the operators in a given module.
This change adds synthesized operator thunks to `SwiftLookupTable` to make them discoverable by unqualified lookup.
If a non-member operator is declared in a C++ namespace, we previously imported it as a static member of the enum that represents the C++ namespace.
This is not always correct under Swift rules for operators. In pure Swift, this code is valid:
```
public protocol UnsafeCxxRandomAccessIterator {
static func +=(lhs: inout Self, rhs: Int)
}
enum std {
public struct A : UnsafeCxxRandomAccessIterator {
public static func += (lhs: inout A, rhs: Int) {
}
}
}
```
but this is not valid:
```
public protocol UnsafeCxxRandomAccessIterator {
static func +=(lhs: inout Self, rhs: Int)
}
enum std {
public struct A : UnsafeCxxRandomAccessIterator {}
public static func += (lhs: inout A, rhs: Int) {}
}
// error: Member operator '+=' must have at least one argument of type 'std'
```
This caused assertion failures in SILGen when conforming C++ iterator types to `UnsafeCxxRandomAccessIterator`.
When importing a C++ struct that contains two methods that only differ in const-ness, we append `Mutating` to the name of the non-const method to make it possible to call from Swift unambiguously.
Unfortunately that logic was dependent on the order in which we import methods of a class: the `Mutating` suffix was added when another method with the same name was already imported.
This caused lookup failures, and the behavior was incorrect when the pair of methods return instances of an unsafe type: the const overload was renamed as `Unsafe` properly, but the non-const overload was not renamed.