Skip to content

Commit 20e30f9

Browse files
authored
Merge pull request swiftlang#78420 from swiftlang/egorzhdan/6.1-fq-template-params
🍒[cxx-interop] Use fully-qualified type names of C++ template parameters
2 parents ab9c378 + 2db0b93 commit 20e30f9

15 files changed

+123
-31
lines changed

lib/ClangImporter/ClangClassTemplateNamePrinter.cpp

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -59,9 +59,31 @@ struct TemplateInstantiationNamePrinter
5959
namedArg = typeDefDecl;
6060
llvm::SmallString<128> storage;
6161
llvm::raw_svector_ostream buffer(storage);
62-
nameImporter->importName(namedArg, version, clang::DeclarationName())
63-
.getDeclName()
64-
.print(buffer);
62+
63+
// Print the fully-qualified type name.
64+
std::vector<DeclName> qualifiedNameComponents;
65+
auto unqualifiedName = nameImporter->importName(namedArg, version);
66+
qualifiedNameComponents.push_back(unqualifiedName.getDeclName());
67+
const clang::DeclContext *parentCtx =
68+
unqualifiedName.getEffectiveContext().getAsDeclContext();
69+
while (parentCtx) {
70+
if (auto namedParentDecl = dyn_cast<clang::NamedDecl>(parentCtx)) {
71+
// If this component of the fully-qualified name is a decl that is
72+
// imported into Swift, remember its name.
73+
auto componentName =
74+
nameImporter->importName(namedParentDecl, version);
75+
qualifiedNameComponents.push_back(componentName.getDeclName());
76+
parentCtx = componentName.getEffectiveContext().getAsDeclContext();
77+
} else {
78+
// If this component is not imported into Swift, skip it.
79+
parentCtx = parentCtx->getParent();
80+
}
81+
}
82+
83+
llvm::interleave(
84+
llvm::reverse(qualifiedNameComponents),
85+
[&](const DeclName &each) { each.print(buffer); },
86+
[&]() { buffer << "."; });
6587
return buffer.str().str();
6688
}
6789
return "_";

test/Interop/Cxx/objc-correctness/init-String-with-NSString-utf8String.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import CxxStdlib
77

88
// CHECK: @"\01L_selector(UTF8String)"
99
// CHECK: @objc_msgSend
10-
// CHECK: call swiftcc void @"$sSo3stdO3__1O0071basic_stringCCharchar_traitsCCharallocatorCChar_mHGHsqaGJcraCCfsaqChraaV9CxxStdlibEyAFSPys4Int8VGSgcfC"
10+
// CHECK: call swiftcc void @"$sSo3stdO3__1O0088basic_stringCCharstd__1char_traitsCCharstd__1allocatorCChar_cyHBywaEDexaCidvdFCgAayGjzaaV9CxxStdlibEyAFSPys4Int8VGSgcfC"
1111

1212
let ObjCStr: NSString = "hello"
1313
let CxxStr = std.string(ObjCStr.utf8String) // Should not crash here

test/Interop/Cxx/stdlib/libcxx-module-interface.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,14 +20,14 @@
2020

2121
// CHECK-IOSFWD: enum std {
2222
// CHECK-IOSFWD: enum __1 {
23-
// CHECK-IOSFWD: struct basic_string<CChar, char_traits<CChar>, allocator<CChar>> : CxxMutableRandomAccessCollection {
23+
// CHECK-IOSFWD: struct basic_string<CChar, std.__1.char_traits<CChar>, std.__1.allocator<CChar>> : CxxMutableRandomAccessCollection {
2424
// CHECK-IOSFWD: typealias value_type = CChar
2525
// CHECK-IOSFWD: }
26-
// CHECK-IOSFWD: struct basic_string<CWideChar, char_traits<CWideChar>, allocator<CWideChar>> : CxxMutableRandomAccessCollection {
26+
// CHECK-IOSFWD: struct basic_string<CWideChar, std.__1.char_traits<CWideChar>, std.__1.allocator<CWideChar>> : CxxMutableRandomAccessCollection {
2727
// CHECK-IOSFWD: typealias value_type = CWideChar
2828
// CHECK-IOSFWD: }
29-
// CHECK-IOSFWD: typealias string = std.__1.basic_string<CChar, char_traits<CChar>, allocator<CChar>>
30-
// CHECK-IOSFWD: typealias wstring = std.__1.basic_string<CWideChar, char_traits<CWideChar>, allocator<CWideChar>>
29+
// CHECK-IOSFWD: typealias string = std.__1.basic_string<CChar, std.__1.char_traits<CChar>, std.__1.allocator<CChar>>
30+
// CHECK-IOSFWD: typealias wstring = std.__1.basic_string<CWideChar, std.__1.char_traits<CWideChar>, std.__1.allocator<CWideChar>>
3131
// CHECK-IOSFWD: }
3232
// CHECK-IOSFWD: }
3333
// CHECK-IOSFWD-NOT: enum std

test/Interop/Cxx/stdlib/libstdcxx-module-interface.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,10 @@
1111
// REQUIRES: OS=linux-gnu
1212

1313
// CHECK-STD: enum std {
14-
// CHECK-STRING: struct basic_string<CChar, char_traits<CChar>, allocator<CChar>> : CxxMutableRandomAccessCollection {
14+
// CHECK-STRING: struct basic_string<CChar, std{{(.__cxx11)?}}.char_traits<CChar>, std{{(.__cxx11)?}}.allocator<CChar>> : CxxMutableRandomAccessCollection {
1515
// CHECK-STRING: typealias value_type = std.char_traits<CChar>.char_type
1616
// CHECK-STRING: }
17-
// CHECK-STRING: struct basic_string<CWideChar, char_traits<CWideChar>, allocator<CWideChar>> : CxxMutableRandomAccessCollection {
17+
// CHECK-STRING: struct basic_string<CWideChar, std{{(.__cxx11)?}}.char_traits<CWideChar>, std{{(.__cxx11)?}}.allocator<CWideChar>> : CxxMutableRandomAccessCollection {
1818
// CHECK-STRING: typealias value_type = std.char_traits<CWideChar>.char_type
1919
// CHECK-STRING: }
2020

@@ -23,6 +23,6 @@
2323

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

26-
// CHECK-STRING: typealias string = std{{(.__cxx11)?}}.basic_string<CChar, char_traits<CChar>, allocator<CChar>>
27-
// CHECK-STRING: typealias wstring = std{{(.__cxx11)?}}.basic_string<CWideChar, char_traits<CWideChar>, allocator<CWideChar>>
26+
// CHECK-STRING: typealias string = std{{(.__cxx11)?}}.basic_string<CChar, std{{(.__cxx11)?}}.char_traits<CChar>, std{{(.__cxx11)?}}.allocator<CChar>>
27+
// CHECK-STRING: typealias wstring = std{{(.__cxx11)?}}.basic_string<CWideChar, std{{(.__cxx11)?}}.char_traits<CWideChar>, std{{(.__cxx11)?}}.allocator<CWideChar>>
2828
// CHECK-STD: }

test/Interop/Cxx/stdlib/msvcprt-module-interface.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,13 @@
1212
// CHECK-STRING: typealias size_t = size_t
1313
// CHECK-STRING: static func to_string(_ _Val: Int32) -> std.string
1414
// CHECK-STRING: static func to_wstring(_ _Val: Int32) -> std.wstring
15-
// CHECK-STRING: struct basic_string<CChar, char_traits<CChar>, allocator<CChar>> : CxxRandomAccessCollection {
15+
// CHECK-STRING: struct basic_string<CChar, std.char_traits<CChar>, std.allocator<CChar>> : CxxRandomAccessCollection {
1616
// CHECK-STRING: typealias value_type = CChar
1717
// CHECK-STRING: }
18-
// CHECK-STRING: struct basic_string<CWideChar, char_traits<CWideChar>, allocator<CWideChar>> : CxxRandomAccessCollection {
18+
// CHECK-STRING: struct basic_string<CWideChar, std.char_traits<CWideChar>, std.allocator<CWideChar>> : CxxRandomAccessCollection {
1919
// CHECK-STRING: typealias value_type = CWideChar
2020
// CHECK-STRING: }
21-
// CHECK-STRING: typealias string = std.basic_string<CChar, char_traits<CChar>, allocator<CChar>>
22-
// CHECK-STRING: typealias wstring = std.basic_string<CWideChar, char_traits<CWideChar>, allocator<CWideChar>>
21+
// CHECK-STRING: typealias string = std.basic_string<CChar, std.char_traits<CChar>, std.allocator<CChar>>
22+
// CHECK-STRING: typealias wstring = std.basic_string<CWideChar, std.char_traits<CWideChar>, std.allocator<CWideChar>>
2323
// CHECK-STRING: }
2424

test/Interop/Cxx/stdlib/use-cxxstdlib-types-in-module-interface.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ public:
4040
std::vector<SimplePOD * _Nullable> getMutPODPtrItems() const;
4141
};
4242

43-
// CHECK: func getPODItems() -> std{{\.__(ndk)?1\.|\.}}vector<SimplePOD, allocator<SimplePOD>>
44-
// CHECK: func getFRTItems() -> std{{\.__(ndk)?1\.|\.}}vector<FRTType, allocator<FRTType>>
45-
// CHECK: func getPODPtrItems() -> std{{\.__(ndk)?1\.|\.}}vector<UnsafePointer<SimplePOD>, allocator<UnsafePointer<SimplePOD>>>
46-
// CHECK: func getMutPODPtrItems() -> std{{\.__(ndk)?1\.|\.}}vector<UnsafeMutablePointer<SimplePOD>, allocator<UnsafeMutablePointer<SimplePOD>>>
43+
// CHECK: func getPODItems() -> std{{\.__(ndk)?1\.|\.}}vector<SimplePOD, std{{\.__(ndk)?1\.|\.}}allocator<SimplePOD>>
44+
// CHECK: func getFRTItems() -> std{{\.__(ndk)?1\.|\.}}vector<FRTType, std{{\.__(ndk)?1\.|\.}}allocator<FRTType>>
45+
// CHECK: func getPODPtrItems() -> std{{\.__(ndk)?1\.|\.}}vector<UnsafePointer<SimplePOD>, std{{\.__(ndk)?1\.|\.}}allocator<UnsafePointer<SimplePOD>>>
46+
// CHECK: func getMutPODPtrItems() -> std{{\.__(ndk)?1\.|\.}}vector<UnsafeMutablePointer<SimplePOD>, std{{\.__(ndk)?1\.|\.}}allocator<UnsafeMutablePointer<SimplePOD>>>

test/Interop/Cxx/templates/Inputs/class-template-in-namespace.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,24 @@ template <class T, class... Args> struct Ship<T(Args...)> {};
88

99
using Orbiter = Ship<void(bool)>;
1010

11+
template <class T>
12+
struct Box {
13+
T value;
14+
};
15+
16+
using IntBoxWithinNS = Box<int>;
17+
using BoxOfIntBoxWithinNS = Box<Box<int>>;
18+
19+
namespace NestedNS1 {
20+
struct Impl {};
21+
using ImplBox1 = Box<Impl>;
22+
}
23+
24+
namespace NestedNS2 {
25+
struct Impl {};
26+
using ImplBox2 = Box<Impl>;
27+
}
28+
1129
} // namespace Space
1230

1331
#endif // TEST_INTEROP_CXX_TEMPLATES_INPUTS_CLASS_TEMPLATE_IN_NAMESPACE_H

test/Interop/Cxx/templates/Inputs/member-templates.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,22 @@ struct HasTemplatedField {
5050
MyTemplatedStruct<int> x;
5151
};
5252

53+
struct HasNestedInstantiation {
54+
template <typename T>
55+
struct MyNestedTemplatedStruct {};
56+
57+
using NestedInst = MyTemplatedStruct<MyNestedTemplatedStruct<int>>;
58+
};
59+
60+
namespace NS {
61+
struct HasNestedInstantiation {
62+
template <typename T>
63+
struct MyNestedTemplatedStruct {};
64+
65+
using NestedInst = MyTemplatedStruct<MyNestedTemplatedStruct<int>>;
66+
};
67+
}
68+
5369
template <typename A, typename R = TemplateClassWithMemberTemplates<A>>
5470
struct HasUninstantiatableTemplateMember {
5571
R *pointer; // R cannot be instantiated here, because R is an incomplete type,

test/Interop/Cxx/templates/class-template-in-namespace-module-interface.swift

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,16 @@
55
// CHECK: struct Ship<> {
66
// CHECK: }
77
// CHECK: typealias Orbiter = Space.Ship<((CBool) -> Void)>
8+
9+
// CHECK: typealias IntBoxWithinNS = Space.Box<CInt>
10+
// CHECK: typealias BoxOfIntBoxWithinNS = Space.Box<Space.Box<CInt>>
11+
12+
// CHECK: enum NestedNS1 {
13+
// CHECK: typealias ImplBox1 = Space.Box<Space.NestedNS1.Impl>
14+
// CHECK: }
15+
16+
// CHECK: enum NestedNS2 {
17+
// CHECK: typealias ImplBox2 = Space.Box<Space.NestedNS2.Impl>
18+
// CHECK: }
19+
820
// CHECK: }
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// RUN: %target-typecheck-verify-swift -cxx-interoperability-mode=default -I %S/Inputs
2+
3+
import ClassTemplateInNamespace
4+
5+
let _ = Space.NestedNS1.ImplBox1(value: Space.NestedNS1.Impl())
6+
let _ = Space.NestedNS2.ImplBox2(value: Space.NestedNS2.Impl())
7+
8+
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'}}
9+
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'}}

0 commit comments

Comments
 (0)