Skip to content

Commit

Permalink
Merge pull request swiftlang#78420 from swiftlang/egorzhdan/6.1-fq-te…
Browse files Browse the repository at this point in the history
…mplate-params

🍒[cxx-interop] Use fully-qualified type names of C++ template parameters
  • Loading branch information
egorzhdan authored Jan 9, 2025
2 parents ab9c378 + 2db0b93 commit 20e30f9
Show file tree
Hide file tree
Showing 15 changed files with 123 additions and 31 deletions.
28 changes: 25 additions & 3 deletions lib/ClangImporter/ClangClassTemplateNamePrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -59,9 +59,31 @@ struct TemplateInstantiationNamePrinter
namedArg = typeDefDecl;
llvm::SmallString<128> storage;
llvm::raw_svector_ostream buffer(storage);
nameImporter->importName(namedArg, version, clang::DeclarationName())
.getDeclName()
.print(buffer);

// Print the fully-qualified type name.
std::vector<DeclName> qualifiedNameComponents;
auto unqualifiedName = nameImporter->importName(namedArg, version);
qualifiedNameComponents.push_back(unqualifiedName.getDeclName());
const clang::DeclContext *parentCtx =
unqualifiedName.getEffectiveContext().getAsDeclContext();
while (parentCtx) {
if (auto namedParentDecl = dyn_cast<clang::NamedDecl>(parentCtx)) {
// If this component of the fully-qualified name is a decl that is
// imported into Swift, remember its name.
auto componentName =
nameImporter->importName(namedParentDecl, version);
qualifiedNameComponents.push_back(componentName.getDeclName());
parentCtx = componentName.getEffectiveContext().getAsDeclContext();
} else {
// If this component is not imported into Swift, skip it.
parentCtx = parentCtx->getParent();
}
}

llvm::interleave(
llvm::reverse(qualifiedNameComponents),
[&](const DeclName &each) { each.print(buffer); },
[&]() { buffer << "."; });
return buffer.str().str();
}
return "_";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import CxxStdlib

// CHECK: @"\01L_selector(UTF8String)"
// CHECK: @objc_msgSend
// CHECK: call swiftcc void @"$sSo3stdO3__1O0071basic_stringCCharchar_traitsCCharallocatorCChar_mHGHsqaGJcraCCfsaqChraaV9CxxStdlibEyAFSPys4Int8VGSgcfC"
// CHECK: call swiftcc void @"$sSo3stdO3__1O0088basic_stringCCharstd__1char_traitsCCharstd__1allocatorCChar_cyHBywaEDexaCidvdFCgAayGjzaaV9CxxStdlibEyAFSPys4Int8VGSgcfC"

let ObjCStr: NSString = "hello"
let CxxStr = std.string(ObjCStr.utf8String) // Should not crash here
8 changes: 4 additions & 4 deletions test/Interop/Cxx/stdlib/libcxx-module-interface.swift
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,14 @@

// CHECK-IOSFWD: enum std {
// CHECK-IOSFWD: enum __1 {
// CHECK-IOSFWD: struct basic_string<CChar, char_traits<CChar>, allocator<CChar>> : CxxMutableRandomAccessCollection {
// CHECK-IOSFWD: struct basic_string<CChar, std.__1.char_traits<CChar>, std.__1.allocator<CChar>> : CxxMutableRandomAccessCollection {
// CHECK-IOSFWD: typealias value_type = CChar
// CHECK-IOSFWD: }
// CHECK-IOSFWD: struct basic_string<CWideChar, char_traits<CWideChar>, allocator<CWideChar>> : CxxMutableRandomAccessCollection {
// CHECK-IOSFWD: struct basic_string<CWideChar, std.__1.char_traits<CWideChar>, std.__1.allocator<CWideChar>> : CxxMutableRandomAccessCollection {
// CHECK-IOSFWD: typealias value_type = CWideChar
// CHECK-IOSFWD: }
// CHECK-IOSFWD: typealias string = std.__1.basic_string<CChar, char_traits<CChar>, allocator<CChar>>
// CHECK-IOSFWD: typealias wstring = std.__1.basic_string<CWideChar, char_traits<CWideChar>, allocator<CWideChar>>
// CHECK-IOSFWD: typealias string = std.__1.basic_string<CChar, std.__1.char_traits<CChar>, std.__1.allocator<CChar>>
// CHECK-IOSFWD: typealias wstring = std.__1.basic_string<CWideChar, std.__1.char_traits<CWideChar>, std.__1.allocator<CWideChar>>
// CHECK-IOSFWD: }
// CHECK-IOSFWD: }
// CHECK-IOSFWD-NOT: enum std
Expand Down
8 changes: 4 additions & 4 deletions test/Interop/Cxx/stdlib/libstdcxx-module-interface.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,10 @@
// REQUIRES: OS=linux-gnu

// CHECK-STD: enum std {
// CHECK-STRING: struct basic_string<CChar, char_traits<CChar>, allocator<CChar>> : CxxMutableRandomAccessCollection {
// CHECK-STRING: struct basic_string<CChar, std{{(.__cxx11)?}}.char_traits<CChar>, std{{(.__cxx11)?}}.allocator<CChar>> : CxxMutableRandomAccessCollection {
// CHECK-STRING: typealias value_type = std.char_traits<CChar>.char_type
// CHECK-STRING: }
// CHECK-STRING: struct basic_string<CWideChar, char_traits<CWideChar>, allocator<CWideChar>> : CxxMutableRandomAccessCollection {
// CHECK-STRING: struct basic_string<CWideChar, std{{(.__cxx11)?}}.char_traits<CWideChar>, std{{(.__cxx11)?}}.allocator<CWideChar>> : CxxMutableRandomAccessCollection {
// CHECK-STRING: typealias value_type = std.char_traits<CWideChar>.char_type
// CHECK-STRING: }

Expand All @@ -23,6 +23,6 @@

// CHECK-SIZE-T: typealias size_t = Int

// CHECK-STRING: typealias string = std{{(.__cxx11)?}}.basic_string<CChar, char_traits<CChar>, allocator<CChar>>
// CHECK-STRING: typealias wstring = std{{(.__cxx11)?}}.basic_string<CWideChar, char_traits<CWideChar>, allocator<CWideChar>>
// CHECK-STRING: typealias string = std{{(.__cxx11)?}}.basic_string<CChar, std{{(.__cxx11)?}}.char_traits<CChar>, std{{(.__cxx11)?}}.allocator<CChar>>
// CHECK-STRING: typealias wstring = std{{(.__cxx11)?}}.basic_string<CWideChar, std{{(.__cxx11)?}}.char_traits<CWideChar>, std{{(.__cxx11)?}}.allocator<CWideChar>>
// CHECK-STD: }
8 changes: 4 additions & 4 deletions test/Interop/Cxx/stdlib/msvcprt-module-interface.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,13 @@
// CHECK-STRING: typealias size_t = size_t
// CHECK-STRING: static func to_string(_ _Val: Int32) -> std.string
// CHECK-STRING: static func to_wstring(_ _Val: Int32) -> std.wstring
// CHECK-STRING: struct basic_string<CChar, char_traits<CChar>, allocator<CChar>> : CxxRandomAccessCollection {
// CHECK-STRING: struct basic_string<CChar, std.char_traits<CChar>, std.allocator<CChar>> : CxxRandomAccessCollection {
// CHECK-STRING: typealias value_type = CChar
// CHECK-STRING: }
// CHECK-STRING: struct basic_string<CWideChar, char_traits<CWideChar>, allocator<CWideChar>> : CxxRandomAccessCollection {
// CHECK-STRING: struct basic_string<CWideChar, std.char_traits<CWideChar>, std.allocator<CWideChar>> : CxxRandomAccessCollection {
// CHECK-STRING: typealias value_type = CWideChar
// CHECK-STRING: }
// CHECK-STRING: typealias string = std.basic_string<CChar, char_traits<CChar>, allocator<CChar>>
// CHECK-STRING: typealias wstring = std.basic_string<CWideChar, char_traits<CWideChar>, allocator<CWideChar>>
// CHECK-STRING: typealias string = std.basic_string<CChar, std.char_traits<CChar>, std.allocator<CChar>>
// CHECK-STRING: typealias wstring = std.basic_string<CWideChar, std.char_traits<CWideChar>, std.allocator<CWideChar>>
// CHECK-STRING: }

Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ public:
std::vector<SimplePOD * _Nullable> getMutPODPtrItems() const;
};

// CHECK: func getPODItems() -> std{{\.__(ndk)?1\.|\.}}vector<SimplePOD, allocator<SimplePOD>>
// CHECK: func getFRTItems() -> std{{\.__(ndk)?1\.|\.}}vector<FRTType, allocator<FRTType>>
// CHECK: func getPODPtrItems() -> std{{\.__(ndk)?1\.|\.}}vector<UnsafePointer<SimplePOD>, allocator<UnsafePointer<SimplePOD>>>
// CHECK: func getMutPODPtrItems() -> std{{\.__(ndk)?1\.|\.}}vector<UnsafeMutablePointer<SimplePOD>, allocator<UnsafeMutablePointer<SimplePOD>>>
// CHECK: func getPODItems() -> std{{\.__(ndk)?1\.|\.}}vector<SimplePOD, std{{\.__(ndk)?1\.|\.}}allocator<SimplePOD>>
// CHECK: func getFRTItems() -> std{{\.__(ndk)?1\.|\.}}vector<FRTType, std{{\.__(ndk)?1\.|\.}}allocator<FRTType>>
// CHECK: func getPODPtrItems() -> std{{\.__(ndk)?1\.|\.}}vector<UnsafePointer<SimplePOD>, std{{\.__(ndk)?1\.|\.}}allocator<UnsafePointer<SimplePOD>>>
// CHECK: func getMutPODPtrItems() -> std{{\.__(ndk)?1\.|\.}}vector<UnsafeMutablePointer<SimplePOD>, std{{\.__(ndk)?1\.|\.}}allocator<UnsafeMutablePointer<SimplePOD>>>
18 changes: 18 additions & 0 deletions test/Interop/Cxx/templates/Inputs/class-template-in-namespace.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,24 @@ template <class T, class... Args> struct Ship<T(Args...)> {};

using Orbiter = Ship<void(bool)>;

template <class T>
struct Box {
T value;
};

using IntBoxWithinNS = Box<int>;
using BoxOfIntBoxWithinNS = Box<Box<int>>;

namespace NestedNS1 {
struct Impl {};
using ImplBox1 = Box<Impl>;
}

namespace NestedNS2 {
struct Impl {};
using ImplBox2 = Box<Impl>;
}

} // namespace Space

#endif // TEST_INTEROP_CXX_TEMPLATES_INPUTS_CLASS_TEMPLATE_IN_NAMESPACE_H
16 changes: 16 additions & 0 deletions test/Interop/Cxx/templates/Inputs/member-templates.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,22 @@ struct HasTemplatedField {
MyTemplatedStruct<int> x;
};

struct HasNestedInstantiation {
template <typename T>
struct MyNestedTemplatedStruct {};

using NestedInst = MyTemplatedStruct<MyNestedTemplatedStruct<int>>;
};

namespace NS {
struct HasNestedInstantiation {
template <typename T>
struct MyNestedTemplatedStruct {};

using NestedInst = MyTemplatedStruct<MyNestedTemplatedStruct<int>>;
};
}

template <typename A, typename R = TemplateClassWithMemberTemplates<A>>
struct HasUninstantiatableTemplateMember {
R *pointer; // R cannot be instantiated here, because R is an incomplete type,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,16 @@
// CHECK: struct Ship<> {
// CHECK: }
// CHECK: typealias Orbiter = Space.Ship<((CBool) -> Void)>

// CHECK: typealias IntBoxWithinNS = Space.Box<CInt>
// CHECK: typealias BoxOfIntBoxWithinNS = Space.Box<Space.Box<CInt>>

// CHECK: enum NestedNS1 {
// CHECK: typealias ImplBox1 = Space.Box<Space.NestedNS1.Impl>
// CHECK: }

// CHECK: enum NestedNS2 {
// CHECK: typealias ImplBox2 = Space.Box<Space.NestedNS2.Impl>
// CHECK: }

// CHECK: }
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// RUN: %target-typecheck-verify-swift -cxx-interoperability-mode=default -I %S/Inputs

import ClassTemplateInNamespace

let _ = Space.NestedNS1.ImplBox1(value: Space.NestedNS1.Impl())
let _ = Space.NestedNS2.ImplBox2(value: Space.NestedNS2.Impl())

let _ = Space.NestedNS1.ImplBox1(value: Space.NestedNS2.Impl()) // expected-error {{cannot convert value of type 'Space.NestedNS2.Impl' to expected argument type 'Space.NestedNS1.Impl'}}
let _ = Space.NestedNS2.ImplBox2(value: Space.NestedNS1.Impl()) // expected-error {{cannot convert value of type 'Space.NestedNS1.Impl' to expected argument type 'Space.NestedNS2.Impl'}}
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,4 @@

// TODO: we should not be importing functions that use this type in their
// signature (such as the function below).
// CHECK: mutating func test1() -> RegressionTest.ValExpr<SliceExpr<SliceExpr<Array<CInt>, _CInt_1>, _CInt_1>>
// CHECK: mutating func test1() -> RegressionTest.ValExpr<RegressionTest.SliceExpr<RegressionTest.SliceExpr<RegressionTest.Array<CInt>, _CInt_1>, _CInt_1>>
21 changes: 18 additions & 3 deletions test/Interop/Cxx/templates/member-templates-module-interface.swift
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,27 @@
// CHECK: var x: MyTemplatedStruct<CInt>
// CHECK: }

// CHECK: struct HasUninstantiatableTemplateMember<NoDefinition, TemplateClassWithMemberTemplates<NoDefinition>> {
// CHECK: struct HasNestedInstantiation {
// CHECK: struct MyNestedTemplatedStruct<T> {
// CHECK: }
// CHECK: typealias NestedInst = MyTemplatedStruct<HasNestedInstantiation.MyNestedTemplatedStruct<CInt>>
// CHECK: }

// CHECK: enum NS {
// CHECK: struct HasNestedInstantiation {
// CHECK: struct MyNestedTemplatedStruct<T> {
// CHECK: }
// CHECK: typealias NestedInst = MyTemplatedStruct<NS.HasNestedInstantiation.MyNestedTemplatedStruct<CInt>>
// CHECK: }
// CHECK: }


// CHECK: struct HasUninstantiatableTemplateMember<HasTemplateInstantiationWithForwardDecl.NoDefinition, TemplateClassWithMemberTemplates<HasTemplateInstantiationWithForwardDecl.NoDefinition>> {
// CHECK: init(pointer: OpaquePointer!)
// CHECK: var pointer: OpaquePointer!
// CHECK: }

// CHECK: struct HasTemplateInstantiationWithForwardDecl {
// CHECK: init(noDefMember: HasUninstantiatableTemplateMember<NoDefinition, TemplateClassWithMemberTemplates<NoDefinition>>)
// CHECK: var noDefMember: HasUninstantiatableTemplateMember<NoDefinition, TemplateClassWithMemberTemplates<NoDefinition>>
// CHECK: init(noDefMember: HasUninstantiatableTemplateMember<HasTemplateInstantiationWithForwardDecl.NoDefinition, TemplateClassWithMemberTemplates<HasTemplateInstantiationWithForwardDecl.NoDefinition>>)
// CHECK: var noDefMember: HasUninstantiatableTemplateMember<HasTemplateInstantiationWithForwardDecl.NoDefinition, TemplateClassWithMemberTemplates<HasTemplateInstantiationWithForwardDecl.NoDefinition>>
// CHECK: }
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,7 @@ public struct Strct {
// CHECK-NEXT: namespace _impl {
// CHECK-EMPTY:
// CHECK-NEXT: // Type metadata accessor for NonTrivialTemplateTrivial
// CHECK-NEXT: SWIFT_EXTERN swift::_impl::MetadataResponseTy $sSo2nsO0037NonTrivialTemplateTrivialinNS_CsGGkdcVMa(swift::_impl::MetadataRequestTy) SWIFT_NOEXCEPT SWIFT_CALL;
// CHECK-NEXT: SWIFT_EXTERN swift::_impl::MetadataResponseTy $sSo2nsO0042NonTrivialTemplatensTrivialinNS_HlGFlenawcVMa(swift::_impl::MetadataRequestTy) SWIFT_NOEXCEPT SWIFT_CALL;
// CHECK-EMPTY:
// CHECK-EMPTY:
// CHECK-NEXT: } // namespace _impl
Expand All @@ -258,7 +258,7 @@ public struct Strct {
// CHECK-NEXT: template<>
// CHECK-NEXT: struct TypeMetadataTrait<ns::NonTrivialTemplateTrivial> {
// CHECK-NEXT: static SWIFT_INLINE_PRIVATE_HELPER void * _Nonnull getTypeMetadata() {
// CHECK-NEXT: return _impl::$sSo2nsO0037NonTrivialTemplateTrivialinNS_CsGGkdcVMa(0)._0;
// CHECK-NEXT: return _impl::$sSo2nsO0042NonTrivialTemplatensTrivialinNS_HlGFlenawcVMa(0)._0;
// CHECK-NEXT: }
// CHECK-NEXT: };
// CHECK-NEXT: namespace _impl{
Expand All @@ -273,7 +273,7 @@ public struct Strct {
// CHECK-NEXT: SWIFT_INLINE_THUNK ns::NonTrivialTemplate<ns::TrivialinNS> retNonTrivial2() noexcept SWIFT_SYMBOL({{.*}}) SWIFT_WARN_UNUSED_RESULT {
// CHECK-NEXT: alignas(alignof(ns::NonTrivialTemplate<ns::TrivialinNS>)) char storage[sizeof(ns::NonTrivialTemplate<ns::TrivialinNS>)];
// CHECK-NEXT: auto * _Nonnull storageObjectPtr = reinterpret_cast<ns::NonTrivialTemplate<ns::TrivialinNS> *>(storage);
// CHECK-NEXT: _impl::$s8UseCxxTy14retNonTrivial2So2nsO0037NonTrivialTemplateTrivialinNS_CsGGkdcVyF(storage);
// CHECK-NEXT: _impl::$s8UseCxxTy14retNonTrivial2So2nsO0042NonTrivialTemplatensTrivialinNS_HlGFlenawcVyF(storage);
// CHECK-NEXT: ns::NonTrivialTemplate<ns::TrivialinNS> result(static_cast<ns::NonTrivialTemplate<ns::TrivialinNS> &&>(*storageObjectPtr));
// CHECK-NEXT: storageObjectPtr->~NonTrivialTemplate();
// CHECK-NEXT: return result;
Expand Down Expand Up @@ -312,7 +312,7 @@ public struct Strct {
// CHECK-NEXT: }

// CHECK: SWIFT_INLINE_THUNK void takeNonTrivial2(const ns::NonTrivialTemplate<ns::TrivialinNS>& x) noexcept SWIFT_SYMBOL({{.*}}) {
// CHECK-NEXT: _impl::$s8UseCxxTy15takeNonTrivial2yySo2nsO0037NonTrivialTemplateTrivialinNS_CsGGkdcVF(swift::_impl::getOpaquePointer(x));
// CHECK-NEXT: _impl::$s8UseCxxTy15takeNonTrivial2yySo2nsO0042NonTrivialTemplatensTrivialinNS_HlGFlenawcVF(swift::_impl::getOpaquePointer(x));
// CHECK-NEXT: }

// CHECK: SWIFT_INLINE_THUNK void takeSimpleScopedEnum(const SimpleScopedEnum& x) noexcept SWIFT_SYMBOL({{.*}}) {
Expand Down
4 changes: 2 additions & 2 deletions test/SILGen/opaque_values_cxx.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,14 @@

import Cxx

// CHECK-LABEL: sil {{.*}}[ossa] @$sSo3stdO3__1O0055vectorCUnsignedIntallocatorCUnsignedInt_iqGBpboaivxaEhaV3Cxx0B8SequenceSCAgHP13__beginUnsafe11RawIteratorQzyFTW : {{.*}} {
// CHECK-LABEL: sil {{.*}}[ossa] @$sSo3stdO3__1O0065vectorCUnsignedIntstd__1allocatorCUnsignedInt_dDGIrdqahddCJdFaAjaV3Cxx0B8SequenceSCAgHP13__beginUnsafe11RawIteratorQzyFTW : {{.*}} {
// CHECK: bb0([[VECTOR_ADDR:%[^,]+]] :
// CHECK: [[VECTOR:%[^,]+]] = load_borrow [[VECTOR_ADDR]]
// CHECK: [[BEGIN_FN:%[^,]+]] = function_ref
// CHECK: [[BEGIN:%[^,]+]] = apply [[BEGIN_FN]]([[VECTOR]])
// CHECK: end_borrow [[VECTOR]]
// CHECK: return [[BEGIN]]
// CHECK-LABEL: } // end sil function '$sSo3stdO3__1O0055vectorCUnsignedIntallocatorCUnsignedInt_iqGBpboaivxaEhaV3Cxx0B8SequenceSCAgHP13__beginUnsafe11RawIteratorQzyFTW'
// CHECK-LABEL: } // end sil function '$sSo3stdO3__1O0065vectorCUnsignedIntstd__1allocatorCUnsignedInt_dDGIrdqahddCJdFaAjaV3Cxx0B8SequenceSCAgHP13__beginUnsafe11RawIteratorQzyFTW'
// CHECK-LABEL: sil {{.*}}[ossa] @$sSo3stdO{{(3__1O)?}}0047___wrap_iterUnsafePointerCUnsignedInt_heCInnaEgaVSQSCSQ2eeoiySbx_xtFZTW : {{.*}} {
// CHECK: bb0([[LHS:%[^,]+]] : $std.__1.__wrap_iter<UnsafePointer<CUnsignedInt>>, [[RHS:%[^,]+]] :
// CHECK: [[CALLEE:%[^,]+]] = function_ref @$sSo2eeoiySbSo3stdO{{(3__1O)?}}0047___wrap_iterUnsafePointerCUnsignedInt_heCInnaEgaV_AGtFTO
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@
// REQUIRES: OS=macosx

// CHECK: import {{CxxStdlib.vector|std_vector}}
// CHECK: extension std.basic_string<CChar, char_traits<CChar>, allocator<CChar>> {
// CHECK: extension std.basic_string<CChar, std.__1.char_traits<CChar>, std.__1.allocator<CChar>> {

0 comments on commit 20e30f9

Please sign in to comment.