Commit Graph

19 Commits

Author SHA1 Message Date
Egor Zhdan 5821123a0c [cxx-interop] Disambiguate instantiations with template template parameters
`template<template <typename> typename>` was tripping up the template class name printer – different instantiations of a class template were getting assigned the same name.

rdar://169199221
2026-04-23 12:30:48 +01:00
John Hui 346bfe476b [cxx-interop] [NFCi] Clean up reference type analysis logic
Previously, the getRefParentOrDiag() function was used both to determine
the reference typedness of an imported record, and to diagnose cases
where that determination was invalid (e.g., due to complications that
arise from inheritance). However, it exposed a rather brutish interface
for controlling whether diagnostics are emitted: when it is given
a non-null ClangImporter::Implementation pointer, it emits diagnostics,
and when given a null pointer it doesn't. A lack of consideration for
where we actually needed these diagnostics led to that pointer being
unnecessarily threaded through a couple of requests and a half dozen
call sites, leading to unnecessarily obscure control flow.

This patch gets rid of getRefParentOrDiag() and replaces it with two
well-defined entry points: a request that does not emit diagnostics, and
a function that does. The nullable ClangImporter::Implementation pointer
is hidden from the interface of those entry points, and their side
effects are well-documented.

The code is migrated from ClangImporter.cpp to ClangAnalysis.cpp, which
I've introduced as the new home for various subroutines that analyze and
extract information from clang decls.

The reference type inference logic of getRefParentOrDiag() (and its
associated helpers) is also rewritten to replace the clang-provided
clang::CXXRecordDecl::forAllBases() with an explicit graph traversal
through the class hierarchy that is easier to debug and adjust (with
imminent behavior changes in mind). It also avoids an unnecessary
class hierarchy traversal whose only purpose was to look for reference
types that participates in diamond inheritance.

No behavior change is intended: we (should) still make perform the same
reference typedness analysis, and emit the exact same diagnostics.

rdar://170858418
2026-03-05 14:22:57 -08:00
Gabor Horvath cd4e3ccba3 [cxx-interop] Do not drop CV qualifiers during printing template names
Dropping qualifiers can result in collisions that can trigger compiler
crashes or suprious errors. This PR attempts to make sure we always
handle the qualifiers when a qualified type is present in the Clang API.
The handling of pointers is somewhat special as foreign reference types
has custom printing logic.

rdar://164917816
2025-11-25 16:10:06 +00:00
Gabor Horvath e8c8cded25 [cxx-interop] Fix name mangling for reference types
Fixes #83097

rdar://155973210
2025-07-18 17:57:54 +01:00
Gabor Horvath 11593329ea [cxx-interop] Fix transforming spans that are not behind type aliases
While we expect our users to use type aliases for template
instantiations, there are some contexts when we import instantiations
without aliases. Unfortunately, in case of C++ span we generated a name
for the instantiation that cannot be a syntactically valid Swift type
due to unary negation appearing in the type name. This PR replaces the
unary negation with "Neg" in the type name and also fixed a bug that
ended up printing certain unsigned values as signed. Moreover, this PR
also fixes some other fallouts in the SwiftifyImport macro.

rdar://146833480
2025-03-14 17:59:09 +00:00
John Hui 140552054c [cxx-interop] Fix template parameter printing scheme for const types (#79237)
This patch changes the class template printer to disambiguate const-qualified template arguments by wrapping them with __cxxConst<>, rather than suffixing them with _const.

This is necessary to accommodate template arguments that aren't just identifiers (i.e., Foo<Int_const> is ok, but Foo<Bar<T>_const> and Foo<((Bar) -> Baz)_const> are not syntactically valid). With this patch, we would produce Foo<__cxxConst<Int>>, Foo<__cxxConst<Bar<T>>, and Foo<__cxxConst<((Bar) -> Baz)>> instead.

This patch also disambiguates volatile-qualified template arguments with __cxxVolatile<>, and changes the printing scheme for std::nullptr_t from nil to __cxxNullPtrT (since nil is not a syntactically valid type name).

rdar://143769901
2025-02-28 19:41:55 -08:00
fahadnayyar d8f919778d [cxx-interop] [cxx-interop] Infer SWIFT_SHARED_REFERENCE for types inheriting from a C++ foreign reference type
rdar://97914474
2025-02-20 08:46:57 -08:00
Egor Zhdan e5899ee167 [cxx-interop] Use fully-qualified type names of C++ template parameters
When importing C++ class template instantiations, Swift generates a type name for each instantiation. The generated names must be unique, since they are used for mangling.

If multiple different C++ types declare nested types with the same name, which are then used as template arguments, Swift was generating the same name for those template instantiations (e.g. `shared_ptr<Impl>` for different `Impl` types).

This change makes sure we use fully-qualified type names of template parameters when generating Swift type names for class template instantiations (e.g. `shared_ptr<MyNamespace.MyClass.Impl>`).

This fixes an assertion failure coming out of IRGen:
```
Assertion failed: (Buffer.empty() && "didn't claim all values out of buffer"), function ~ConstantInitBuilderBase, file ConstantInitBuilder.h, line 75.
```

rdar://141962480
2025-01-02 18:03:56 +00:00
Egor Zhdan 3d80ab37b2 [cxx-interop] Disambiguate template instantiations with nullptr parameters
This makes sure that different class template instantiations get distinct generated Swift type names.

Similar to aa6804a3.
2024-11-13 19:18:08 +00:00
Egor Zhdan cbca55af64 [cxx-interop] Simplify name generation for template arguments of builtin types
We were searching for types in the Swift stdlib by name, just to get the names back from the types. Let's just return the type name without performing the search.

No user-facing change intended.
2024-11-12 14:57:18 +00:00
Egor Zhdan e345ebd1a1 [cxx-interop] Disambiguate template instantiations with enum parameters
This makes sure that different class template instantiations with enum arguments get distinct generated Swift type names.

Similar to aa6804a3.

rdar://139437761 / resolves https://github.com/swiftlang/swift/issues/77358
2024-11-11 18:03:09 +00:00
Egor Zhdan d66c8edda2 [cxx-interop] Disambiguate template instantiations with parameter packs
This makes sure that different template instantiations of `std::tuple` get distinct Swift type names.

Similar to aa6804a3.

This also refactors `swift::importer::printClassTemplateSpecializationName` to follow a proper visitor pattern for the C++ template arguments.

rdar://139435937
2024-11-08 16:43:59 +00:00
Egor Zhdan aa6804a30e [cxx-interop] Disambiguate template instantiations with array type parameters
When Swift imports C++ template class instantiations, it generates a human-readable Swift name for each instantiation.

Having name collisions causes multiple Swift type with the same name, which confuses the compiler.

`MyClass<int[]>` and `MyClass<long[]>` were both being imported as `MyClass<_>` into Swift. This patch fixes that:

* `MyClass<int[]>` is now imported as `MyClass<[CInt]>`
* `MyClass<int[123]>` is now imported as `MyClass<Vector<CInt, 123>>`

rdar://138921102
2024-10-30 17:05:14 +00:00
Akira Hatanaka 90e4a98a46 [cxx-interop] Use the name of the typedef when an unnamed class is used as a template argument (#76844)
This fixes a bug where IRGen would try to use the same name for two
different protocol witness methods.

rdar://134149098
2024-10-03 08:58:29 -07:00
Egor Zhdan d19c9eb32b [cxx-interop] Disambiguate template instantiations with SIMD parameters
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
2024-09-04 16:46:23 +01:00
smonteiro2 24fc755024 Add _const to Swift declaration names of const types
This change is necessary to differentiate between C++ const and non-const types in Swift.
For instance, `const int` and `int` would both be printed as `CInt` in Swift.
After this change, `const int` is stored as `CInt_const`
2024-07-18 14:13:57 +01:00
Egor Zhdan 74c444d688 [cxx-interop] Emit function types as Swift closures in templated params
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
2024-01-19 21:02:03 +00:00
Egor Zhdan 7c63cd4ad2 [cxx-interop] Emit _ as a fallback type name in template params
Emit an underscore instead of an empty type name when we weren't able to emit a more meaningful representation of a C++ template parameter in Swift.
2024-01-19 19:31:59 +00:00
Egor Zhdan a45d03a669 [cxx-interop] Use unique mangling for distinct C++ class template specializations
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
2023-10-26 13:29:41 +01:00