When converting a C++ class template instantiation name into Swift, we previously didn't account for possible SIMD types. Those types were printed as `_`. This meant that e.g. `std::vector<simd::float3>` and `std::vector<simd::float4>` would get the same Swift name, causing compiler errors down the road.
rdar://134214091
This is required to make the compiler distinguish between instantiations of `std::function`.
Previously, when generating a Swift type name for a `std::function` instantiation, we would always emit `_` as the template parameter. If someone referenced two different instantiations of `std::function` in a Swift module, they would get mangled with the same name, triggering linker errors later.
rdar://103979602
This code used to crash the compiler:
var s = std.string("hi")
s.append("foo")
`append` in this case resolves to a templated C++ method that accepts `std::string_view`, while we tried passing a Swift String to it as a parameter.
rdar://107018724
Previously we tried to instantiate templates in unevaluated contexts. Some of these templates might not be instantiatable, which caused compile errors, while the equivalent C++ code compiles and runs with no issue.
This was problematic for `std::vector` with libstdc++ on Linux.
Fixes https://github.com/apple/swift/issues/61547.
Dependent types are going to be very hard to support, especially in complex cases. This PR adds a workaround that people can use: `Any`. This requires manual type casting, but it does work.
Adds tests for using std-vector and some other interesting types.
This patch fixes four mis conceptions that the compiler was previously making:
1. Implicit destructors have no side effects. (Yes, this means we were not cleaning up some objects.)
2. Implicit destructors have bodies. (Technically they do, but the body doesn't include CallExprs that they make when lowered to IR.)
3. Functions other than methods can be uninstantiated templates.
4. Uninstantiated templates may have executable code. (I.e., we can never take the fast path.)
And makes sure that we visit the destructor of any VarDecl (including parameters).
If a defaulted template type parameter is not used in the function's
signature, don't create a corresponding generic argument for that
template type. This allows us to call function templates with defaulted
template type parameters. This is very common in the standard library
for things like enable_if which is used to disable various
functions/overloads with SFINAE.
The biggest part of this change is going forward not all function
templates will be imported as generic functions in Swift. This should
work OK but we may discover there was some logic which only looked for
generic function when dealing with function templates.
If a template specialization is more than 8 types deep, bail.
In future we could make this number (much) greater than 8 but first
we'll need to somehow make instantiating these types much fater.
Currently, I think there is some exponential type behavior happening so
this is super slow.
This PR makes it possible to instantiate C++ class templates from Swift. Given a C++ header:
```c++
// C++ module `ClassTemplates`
template<class T>
struct MagicWrapper {
T t;
};
struct MagicNumber {};
```
it is now possible to write in Swift:
```swift
import ClassTemplates
func x() -> MagicWrapper<MagicNumber> {
return MagicWrapper<MagicNumber>()
}
```
This is achieved by importing C++ class templates as generic structs, and then when Swift type checker calls `applyGenericArguments` we detect when the generic struct is backed by the C++ class template and call Clang to instantiate the template. In order to make it possible to put class instantiations such as `MagicWrapper<MagicNumber>` into Swift signatures, we have created a new field in `StructDecl` named `TemplateInstantiationType` where the typechecker stores the `BoundGenericType` which we serialize. Deserializer then notices that the `BoundGenericType` is actually a C++ class template and performs the instantiation logic.
Depends on https://github.com/apple/swift/pull/33420.
Progress towards https://bugs.swift.org/browse/SR-13261.
Fixes https://bugs.swift.org/browse/SR-13775.
Co-authored-by: Dmitri Gribenko <gribozavr@gmail.com>
Co-authored-by: Rosica Dejanovska <rosica@google.com>
The C++ interop modules require C++ support. Explicitly require C++ as
a feature when building these modules. This has no impact on the
changes as all the tests enable C++ already.
This prevents an assertion in "isOverAligned" caused class templates
that contain and use typedefs.
Re-landing 7f2b0aad2b after being reverted
in 5ef0136356.
This is a roll-forward of https://github.com/apple/swift/pull/32950, with explicit c++17 version removed from tests. This is not needed since C++17 is the default anyway.
--
In this PR we teach `ClangImporter` to import typedef statements with template instantiation as its underlying type.
```c++
template<class T>
struct MagicWrapper {
T t;
};
struct MagicNumber {};
typedef MagicWrapper<MagicNumber> WrappedMagicNumber;
```
will be made available in Swift as if `WrappedMagicNumber` is a regular struct.
In C++, multiple distinct typedeffed instantiations resolve to the same canonical type. We implement this by creating a hidden intermediate struct that typedef aliasses.
The struct is named as `__CxxTemplateInst` plus Itanium mangled type of the instantiation. For the example above the name of the hidden struct is `__CxxTemplateInst12MagicWrapperI11MagicNumberE`. Double underscore (denoting a reserved C++ identifier) is used to discourage direct usage. We chose Itanium mangling scheme because it produces valid Swift identifiers and covers all C++ edge cases.
Imported module interface of the example above:
```swift
struct __CxxTemplateInst12MagicWrapperI11MagicNumberE {
var t: MagicNumber
}
struct MagicNumber {}
typealias WrappedMagicNumber = __CxxTemplateInst12MagicWrapperI11MagicNumberE
```
We modified the `SwiftLookupTable` logic to show hidden structs in `swift_ide_test` for convenience.
Co-authored-by: Rosica Dejanovska <rosica@google.com>
Co-authored-by: Dmitri Gribenko <gribozavr@gmail.com>
Co-authored-by: Robert Widmann <devteam.codafi@gmail.com>
In this PR we teach `ClangImporter` to import typedef statements with template instantiation as its underlying type.
```c++
template<class T>
struct MagicWrapper {
T t;
};
struct MagicNumber {};
typedef MagicWrapper<MagicNumber> WrappedMagicNumber;
```
will be made available in Swift as if `WrappedMagicNumber` is a regular struct.
In C++, multiple distinct typedeffed instantiations resolve to the same canonical type. We implement this by creating a hidden intermediate struct that typedef aliasses.
The struct is named as `__CxxTemplateInst` plus Itanium mangled type of the instantiation. For the example above the name of the hidden struct is `__CxxTemplateInst12MagicWrapperI11MagicNumberE`. Double underscore (denoting a reserved C++ identifier) is used to discourage direct usage. We chose Itanium mangling scheme because it produces valid Swift identifiers and covers all C++ edge cases.
Imported module interface of the example above:
```swift
struct __CxxTemplateInst12MagicWrapperI11MagicNumberE {
var t: MagicNumber
}
struct MagicNumber {}
typealias WrappedMagicNumber = __CxxTemplateInst12MagicWrapperI11MagicNumberE
```
We modified the `SwiftLookupTable` logic to show hidden structs in `swift_ide_test` for convenience.
Resolves https://bugs.swift.org/browse/SR-12591.
Co-authored-by: Rosica Dejanovska <rosica@google.com>
Co-authored-by: Dmitri Gribenko <gribozavr@gmail.com>
Co-authored-by: Robert Widmann <devteam.codafi@gmail.com>