ClangImporter has logic that infers default arguments of certain C/C++ types, such as the types declared via `CF_OPTIONS`/`NS_OPTIONS` macros.
There were some workarounds in place which triggered for C++ interop mode specifically. The workarounds were applying a heuristic based on the name of the type, which tried to match the behavior to non-C++ interop mode for certain types from the OS SDK. That was not working well for user-defined types, causing source compatibility breakages when enabling C++ interop.
This change replaces the name-based heuristic with a more robust criteria.
See also 3791ccb6.
rdar://142961112
This removes a workaround from the module interface loader, which was forcing AppKit and UIKit to be rebuilt from their textual interfaces with C++ interop disabled, even if the current compilation explicitly enables it.
The workaround was previously put in place because of a compiler error:
```
error: type 'AttributeScopes.AppKitAttributes.StrikethroughStyleAttribute' does not conform to protocol 'AttributedStringKey'
note: possibly intended match 'AttributeScopes.AppKitAttributes.StrikethroughStyleAttribute.Value' (aka 'NSUnderlineStyle') does not conform to 'Hashable'
```
`NSUnderlineStyle` is a C/C++ type from AppKit that is declared using `NS_OPTIONS` macro. `NS_OPTIONS`/`CF_OPTIONS` macros have different expansions in C vs C++ language modes. The C++ expansions weren't handled correctly by ClangImporter, resulting in two distinct Swift types being created: a `typealias NSUnderlineStyle` which was marked as unavailable in Swift, and `enum NSUnderlineStyle`. This mostly worked fine, since the lookup logic was picking the enum during regular name lookup. However, this silently broke down when rebuilding the explicit conformance from `AppKit.swiftinterface`:
```
extension AppKit.NSUnderlineStyle : Swift.Hashable {}
```
Swift was picking the (unavailable) typealias when rebuilding this extension, which means the (available) enum wasn't getting the conformance.
This is verified by an existing test (`test/Interop/Cxx/objc-correctness/appkit-uikit.swift`).
rdar://142961112
Interop is injecting escapability annotations for the STL and doing a
limited inference for aggregates. Let's reuse the same facilities in the
AST when we calculate the safety of the foreign types.
Initializers should always have Swift names that have the special `DeclBaseName::createConstructor()` base name. Although there is an assertion to this effect in the constructor for ConstructorDecl, ClangImporter did not actually reject custom Swift names for initializers that violated this rule. This meant that asserts compilers would crash if they encountered code with an invalid `swift_name` attribute, while release compilers would silently accept them (while excluding these decls from certain checks since lookups that were supposed to find all initializers didn’t find them).
Modify ClangImporter to diagnose this condition and ignore the custom Swift name.
Unfortunately, importing them as is results in ambiguous call sites.
E.g., std::vector::push_back has overloads for lvalue reference and
rvalue reference and we have no way to distinguish them at the call site
in Swift. To overcome this issue, functions with rvalue reference
parameters are imported with 'consuming:' argument labels.
Note that, in general, move only types and consuming is not properly
supported in Swift yet. We do not invoke the dtor for the moved-from
objects. This is a preexisting problem that can be observed with move
only types before this PR, so the fix will be done in a separate PR.
Fortunately, for most types, the moved-from objects do not require
additional cleanups.
rdar://125816354
C++ swift::Parser is going to be replaced with SwiftParser+ASTGen.
Direct dependencies to it should be removed. Before that, remove
unnecessary '#include "swift/Parse/Parser.h"' to clarify what actually
depends on 'swift::Parser'.
Split 'swift::parseDeclName()' et al. into the dedicated files.
When we have both const and non-const version of a function, we import
the non-cont version with the "Mutating" suffix. This logic, however, is
redundant for static member functions as those can never be marked as
"const" since they don't have a "self" or "this" to mutate.
rdar://120858502
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)
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.
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
Swift names provided via C attributes or API notes can be parsed as
special names, such as `init` or `subscript`. However, doing so would
cause the Clang importer to crash, because it assumes that these names
are always identifiers. In these places, we actually want to treat
them as identifiers, where special names are mapped back to their
keywords. Introduce a function to do that, and use it consistently.
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
This makes sure we are printing more than one level of C++ template specializations when emitting a Swift struct name.
For instance, `std::__wrap_iter<char*>` and `std::__wrap_iter<const char*>` are currently imported with the same name in Swift. This means the mangled string will be the same for these specializations, despite them being distinct types. This causes mangling errors.
rdar://117485399
When importing a C++ class template instantiation, Swift translates the template parameter type names from C++ into their Swift equivalent.
For instance, `basic_string<wchar_t, char_traits<wchar_t>, allocator<wchar_t>>` gets imported as `basic_string<Scalar, char_traits<Scalar>, allocator<Scalar>>`: `wchar_t` is imported as `CWideChar`, which is a typealias for `Scalar` on most platforms including Darwin. Notice that Swift goes through the `CWideChar` typealias on the specific platform. Another instantiation `basic_string<uint32_t, char_traits<uint32_t>, allocator<uint32_t>>` also gets imported as `basic_string<Scalar, char_traits<Scalar>, allocator<Scalar>>`: `uint32_t` is also imported as `Scalar`. This is problematic because we have two distinct C++ types that have the same name in Swift.
This change makes sure Swift doesn't go through typealiases when emitting names of template parameters, so `wchar_t` would now get printed as `CWideChar`, `int` would get printed as `CInt`, etc.
This also encourages clients to use the correct type (`CInt`, `CWideChar`, etc) instead of relying on platform-specific typealiases.
rdar://115673622
I discovered this when experimenting with `std::map::iterator`, which has a const overload of `operator*` that returns a non-const reference, and does not have a const overload of `operator*`.
rdar://112471779
C++ `T& operator*()` is mapped to a Swift computed property `var pointee: T`.
Previously `var pointee` only had a getter, after this change it will also have a setter if the C++ type declares an overload of `operator*` that returns a mutable reference.
rdar://112471779
LLVM deprecated, renamed, and removed a bunch of APIs. This patch
contains a lot of the changes needed to deal with that.
The SetVector type changed the template parameters.
APInt updated multiple names, countPopulation became popcount,
getAllOnesValue became getAllOnes, getNullValue became getZero, etc...
Clang type nullability check stopped taking a clang AST context.
The LLVM IRGen Function type stopped exposing basic block list directly,
but gained enough API surface that the translation isn't too bad.
(GenControl.cpp, LLVMMergeFunctions.cpp)
llvm::Optional had a transform function. That was being used in a couple
of places, so I've added a new implementation under STLExtras that
transforms valid optionals, otherwise it returns nullopt.
llvm::Optional had a constructor that took a const l-value
reference, but std::optional does not, resulting in build failures when
returning bit-fields in optionals. Casting the bit-field to the
appropriate type fixes this.
This fixes linker errors when there are multiple instantiations of a templated struct with numeric template parameters.
When mangling the name of a C++ template specialization, we currently ignore non-type templated parameters. This causes two different instantiations of the same templated type to have the same mangled name, triggering linker errors.
rdar://107757051
Reformatting everything now that we have `llvm` namespaces. I've
separated this from the main commit to help manage merge-conflicts and
for making it a bit easier to read the mega-patch.
This is phase-1 of switching from llvm::Optional to std::optional in the
next rebranch. llvm::Optional was removed from upstream LLVM, so we need
to migrate off rather soon. On Darwin, std::optional, and llvm::Optional
have the same layout, so we don't need to be as concerned about ABI
beyond the name mangling. `llvm::Optional` is only returned from one
function in
```
getStandardTypeSubst(StringRef TypeName,
bool allowConcurrencyManglings);
```
It's the return value, so it should not impact the mangling of the
function, and the layout is the same as `std::optional`, so it should be
mostly okay. This function doesn't appear to have users, and the ABI was
already broken 2 years ago for concurrency and no one seemed to notice
so this should be "okay".
I'm doing the migration incrementally so that folks working on main can
cherry-pick back to the release/5.9 branch. Once 5.9 is done and locked
away, then we can go through and finish the replacement. Since `None`
and `Optional` show up in contexts where they are not `llvm::None` and
`llvm::Optional`, I'm preparing the work now by going through and
removing the namespace unwrapping and making the `llvm` namespace
explicit. This should make it fairly mechanical to go through and
replace llvm::Optional with std::optional, and llvm::None with
std::nullopt. It's also a change that can be brought onto the
release/5.9 with minimal impact. This should be an NFC change.
The `isBoolType` operation within the Clang importer has a historical
definition that excludes the C++ `bool` and its use in C as an
extension. Retain that definition, and check for the actual `bool`
when importing C++ conversion functions into Swift.
Fixes two regressions in the Clang importer:
1. We started to import `bool`-typed Objective-C properties with their
getter names.
2. We started importing `bool`-typed Objective-C methods with an
NSError** parameter as `throws`.
Both of these changes could be considered improvements, but they
cannot be made without breaking source compatibility, so roll those
changes back to maintain source compatibility.
We should have a separate discussion about enabling this behavior for
Swift >= 6.
Instead of mangling class template specializations with the prefix "__CxxTemplateInst," simply set the decl name as the class templates plus the types that it is specialized on (so `vector<Int>` rather than `__CxxTemplateInstNSt3__16vectorIi...`).
This is mainly to improve diagnostics. As a side effect of this change, if anyone copies the name of a class template specializaiton from an error/warning and uses it in source code, the compiler will error (that class templates aren't available in swift) rather than silently passing only to cause serailization failures down the road.
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.
Clang recently started wrapping more types in `clang::ElaboratedType` after this change: https://reviews.llvm.org/D112374
This broke some assumptions in ClangImporter, specifically in enum handling logic. This change adjusts those.
Fixes these tests in rebranch:
* `Interop/Cxx/enum/anonymous-with-swift-name-module-interface.swift`
* `Interop/Cxx/enum/anonymous-with-swift-name-objc-module-interface.swift`
* `Interop/Cxx/enum/anonymous-with-swift-name.swift`
* `Interop/Cxx/enum/c-enums-NS_OPTIONS-NS_REFINED_FOR_SWIFT.swift`
* `Interop/Cxx/enum/c-enums-NS_OPTIONS.swift`
* `Interop/Cxx/enum/c-enums-withOptions-omit.swift`
* `Interop/Cxx/class/inheritance/fields-module-interface.swift`
* `Interop/Cxx/class/inheritance/fields.swift`
* `Interop/Cxx/class/inheritance/functions-module-interface.swift`
* `Interop/Cxx/class/inheritance/sub-types-module-interface.swift`
* `Interop/Cxx/class/inheritance/type-aliases-module-interface.swift`
`getValue` -> `value`
`getValueOr` -> `value_or`
`hasValue` -> `has_value`
`map` -> `transform`
The old API will be deprecated in the rebranch.
To avoid merge conflicts, use the new API already in the main branch.
rdar://102362022
When an anonymous enum is imported, its imported name is under some
circumstances derived from the type that it is backed by.
NS_REFINED_FOR_SWIFT is a macro that produces a __attribute__((swift_private))
that when attached to a declaration, the imported name of this
declaration should have two underscores prepended. When the name
anonymous enum is derived from another declaration, and said declaration
does not have the same swift private attribute, the __ is dropped. This
patch fixes this.
This was discovered during interop adoption in SwiftCompilerSources.
```
/Volumes/Projects/swift/swift/include/swift/SIL/SILNode.h:180:5 <Spelling=/Volumes/Projects/swift/swift/include/swift/SIL/SILNode.h:171:3>: while adding SwiftName lookup table entries for clang declaration 'swift::SILNode::SharedUInt8Fields::(anonymous)'
```