C++ iterator types are often templated, and sometimes declare `operator==` as a non-member templated function. In libc++, an example of this is `__wrap_iter` which is used as an iterator type for `std::vector` and `std::string`.
We don't currently import templated non-member operators into Swift, however, we still want to support common C++ iterator patterns.
This change adds logic to instantiate templated non-member `operator==` for types that define `iterator_category` and are therefore likely to be valid iterator types.
rdar://97915515
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.
If an operator is declared as a method of a templated class, we were failing to look it up during auto-conformance to `UnsafeCxxInputIterator`.
This fixes `Interop/Cxx/stdlib/use-std-map.swift` on Ubuntu.
rdar://102420290
This extends the existing auto-conformance mechanism to synthesize the conformances to `CxxConvertibleToCollection` protocol for C++ sequence types.
This means that the developer can now call `Array(myCxxSequence)` or `Set(myCxxSequence)` without adding any extensions manually.
Since we don't automatically conform C++ non-random-access collections to `Swift.Sequence` anymore for performance reasons, we need an alternative way to access the elements of a C++ sequence from Swift.
This allows explicitly converting a C++ sequence to a Swift Array/Set.
This became an issue in rebranch: multiple interop tests started failing (e.g. `Interop/Cxx/foreign-reference/pod.swift`).
The problem is not specific to rebranch though.
rdar://102151836
Iterating over a `CxxSequence` that is not a `CxxRandomAccessCollection` triggers a copy of the C++ collection. Let's disable the automatic conformances until we find a more efficient solution.
This means that for now developers won't be able to iterate over a `std::set` or `std::list` with a Swift for-in loop. I will submit a separate patch with an alternative solution for such types.
C++ random access collections, such as `std::vector` or `std::string`, are not affected.
This makes ClangImporter automatically conform C++ collection types to `Cxx.CxxRandomAccessCollection` protocol.
We consider a C++ sequence type to be a random access collection type its iterator conforms to `UnsafeCxxRandomAccessIterator`.
This fixes a couple cases of cases where a malformed C++ iterator type would trigger an assertion in ClangImporter: `Assertion failed: (Val && "isa<> used on a null pointer")`.
This makes ClangImporter automatically conform C++ sequence types to `Cxx.UnsafeCxxInputIterator` protocol.
We consider a C++ type to be a random access iterator type if conforms to `UnsafeCxxInputIterator`, and additionally defines `operator-` and `operator+=`.
This lifts the requirement for the user to explicitly add `import Cxx` in Swift code that relies on protocols from the `Cxx` module, such as `CxxSequence`.
This helps to bridge C++ random access collections, such as `std::vector` and `std::string`, to Swift by conforming them to `Swift.RandomAccessCollection`
To determine whether to conform a C++ type to `CxxSequence` protocol automatically, ClangImporter checks if the corresponding iterator type conforms to `UnsafeCxxInputIterator`.
This logic had false-positives, e.g. `Optional<OpaquePointer>` was treated as if it conforms to `UnsafeCxxInputIterator` while it actually doesn't. This happened because `lookupConformance` returned a conformance with a conditional requirement (`Wrapped : UnsafeCxxInputIterator`) that is not satisfied for `OpaquePointer`.
rdar://100265664
Previously the conversion mechanism called `std::string::c_str` and passed it to `String(cString:)` which accepts a null-terminated string. If the string contains a `\0` character, this failed to initialize the entire string properly.
This fixes an error that occurred when trying to use the subscript on an instance `std::map`:
```
error: cannot assign through subscript: 'map' is immutable
```
This was happening even with a mutable `std::map` instance.
`std::map::operator[]` has two overloads:
* `T& operator[]( const Key& key )`
* `T& operator[]( Key&& key )`
The second one is imported with an `inout` parameter, and we picked it as an implementation of the subscript getter because it was the last of the two overloads to get imported.
Swift does not allow subscripts with `inout` parameters. This is checked at the AST level, and those checks do not run for synthesized Swift code. This caused Swift to produce a surprising error which actually indicated that the argument of the subscript, not the instance itself, must be mutable.
rdar://100529571
This fixes a crash that happened when creating an instance of `std::string` from a `Swift.String` that contains non-ASCII characters.
When converted to a UTF-8 array, such characters might be represented by numbers that fall out of `CChar`'s boundaries if they have a sign bit set to 1. This is normal and shouldn't trigger a crash or an assertion failure.
C++ standard library module is called `std`. To make it more clear to a Swift developer that this module is a C++ stdlib, and not a Swift stdlib, let's rename it to `CxxStdlib`.
This is the first step in the module rename. We don't ban `std` in this patch to be able to build SwiftCompilerSources with hosttools until a new Swift compiler is shipped.
This makes ClangImporter automatically conform C++ sequence types to `Cxx.CxxSequence` protocol.
We consider a C++ type to be a sequence type if it defines `begin()` & `end()` methods that return iterators of the same type which conforms to `UnsafeCxxInputIterator`.
These errors were sometimes produced when synthesizing conformance to `UnsafeCxxInputIterator`:
```
<unknown>:0: error: circular reference
<unknown>:0: note: through reference here
<unknown>:0: note: through reference here
```
This happened because `NominalTypeDecl::lookupDirect` attempts to deserialize Swift extensions of the type, which might belong to the module which has a dependency to the module that is currently being imported, which leads to deserialization errors.
This change makes sure we don't call `NominalTypeDecl::lookupDirect` when synthesizing conformances for C++ types.
This allows `std::string` to be constructed implicitly from a String literal, which is convenient e.g. when calling C++ APIs that take `std::string` as a parameter.
Previosly we didn't detect `func ==` that was declared out-of-class when synthesizing conformaces to `UnsafeCxxInputIterator`. Now we do.
rdar://96235368
This teaches ClangImporter to synthesize conformances of C++ iterator types to `UnsafeCxxInputIterator` protocol from the `Cxx` module.
We consider a C++ type to be an iterator if it defines a subtype (usually a typedef or a using decl) called `iterator_category` that inherits from `std::input_iterator_tag`.
rdar://96235368
This allows projects that don't want to pull in the entire C++ standard library to use stdlib-independent C++ interop utilities like `CxxSequence`.
This also makes the utilities available on platforms where we don't currently have the `std` overlay available, e.g. Windows.
This change adds basic helper protocols and structs that are going to be used for making C++ sequences and collection safe and Swifty by adding conformances to `Swift.Sequence`, `Swift.Collection`, etc.
This is not meant to be a final design.