Skip to content

Commit af014c0

Browse files
committed
[cxx-interop] Import iterator types that are not typedef-ed
This prevented `std::vector<std::string>` from being auto-conformed to `CxxRandomAccessCollection`. If an iterator type is templated, and does not have an explicit instantiation via a typedef or a using-decl, its specialization will not have an owning Clang module. Make sure we treat it as a part of the Clang module that owns the template decl. rdar://112762768 / resolves #67410
1 parent f450eb5 commit af014c0

File tree

4 files changed

+42
-5
lines changed

4 files changed

+42
-5
lines changed

lib/ClangImporter/ClangImporter.cpp

+9
Original file line numberDiff line numberDiff line change
@@ -2788,6 +2788,15 @@ getClangOwningModule(ClangNode Node, const clang::ASTContext &ClangCtx) {
27882788
originalDecl = pattern;
27892789
}
27902790
}
2791+
if (!originalDecl->hasOwningModule()) {
2792+
if (auto cxxRecordDecl = dyn_cast<clang::CXXRecordDecl>(D)) {
2793+
if (auto pattern = cxxRecordDecl->getTemplateInstantiationPattern()) {
2794+
// Class template instantiations sometimes don't have an owning Clang
2795+
// module, if the instantiation is not typedef-ed.
2796+
originalDecl = pattern;
2797+
}
2798+
}
2799+
}
27912800

27922801
return ExtSource->getModule(originalDecl->getOwningModuleID());
27932802
}

lib/ClangImporter/ImportDecl.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -2799,7 +2799,7 @@ namespace {
27992799

28002800
// If this module is declared as a C++ module, try to synthesize
28012801
// conformances to Swift protocols from the Cxx module.
2802-
auto clangModule = decl->getOwningModule();
2802+
auto clangModule = Impl.getClangOwningModule(result->getClangNode());
28032803
if (clangModule && requiresCPlusPlus(clangModule)) {
28042804
auto nominalDecl = cast<NominalTypeDecl>(result);
28052805
conformToCxxIteratorIfNeeded(Impl, nominalDecl, decl);

test/Interop/Cxx/stdlib/Inputs/std-vector.h

+2
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,10 @@
22
#define TEST_INTEROP_CXX_STDLIB_INPUTS_STD_VECTOR_H
33

44
#include <vector>
5+
#include <string>
56

67
using Vector = std::vector<int>;
8+
using VectorOfString = std::vector<std::string>;
79

810
inline Vector initVector() { return {}; }
911

test/Interop/Cxx/stdlib/use-std-vector.swift

+30-4
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,13 @@ import CxxStdlib
1313

1414
var StdVectorTestSuite = TestSuite("StdVector")
1515

16-
StdVectorTestSuite.test("init") {
16+
StdVectorTestSuite.test("VectorOfInt.init") {
1717
let v = Vector()
1818
expectEqual(v.size(), 0)
1919
expectTrue(v.empty())
2020
}
2121

22-
StdVectorTestSuite.test("push back") {
22+
StdVectorTestSuite.test("VectorOfInt.push_back") {
2323
var v = Vector()
2424
let _42: CInt = 42
2525
v.push_back(_42)
@@ -34,7 +34,7 @@ func fill(vector v: inout Vector) {
3434
v.push_back(CInt(3))
3535
}
3636

37-
StdVectorTestSuite.test("for loop") {
37+
StdVectorTestSuite.test("VectorOfInt for loop") {
3838
var v = Vector()
3939
fill(vector: &v)
4040

@@ -46,12 +46,38 @@ StdVectorTestSuite.test("for loop") {
4646
expectEqual(count, 4)
4747
}
4848

49-
StdVectorTestSuite.test("map") {
49+
StdVectorTestSuite.test("VectorOfString for loop") {
50+
var v = VectorOfString()
51+
var count = 0
52+
for _ in v {
53+
count += 1
54+
}
55+
expectEqual(count, 0)
56+
57+
v.push_back(std.string("abc"))
58+
v.push_back(std.string("ab"))
59+
for it in v {
60+
count += it.length()
61+
}
62+
expectEqual(count, 5)
63+
}
64+
65+
StdVectorTestSuite.test("VectorOfInt.map") {
5066
var v = Vector()
5167
fill(vector: &v)
5268

5369
let a = v.map { $0 + 5 }
5470
expectEqual(a, [6, 7, 8])
5571
}
5672

73+
StdVectorTestSuite.test("VectorOfString.map") {
74+
var v = VectorOfString()
75+
v.push_back(std.string("abc"))
76+
v.push_back(std.string("a"))
77+
v.push_back(std.string("ab"))
78+
79+
let a = v.map { $0.length() }
80+
expectEqual(a, [3, 1, 2])
81+
}
82+
5783
runAllTests()

0 commit comments

Comments
 (0)