Skip to content

Commit 4463b53

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 (cherry picked from commit af014c0)
1 parent 7fb670d commit 4463b53

File tree

4 files changed

+42
-5
lines changed

4 files changed

+42
-5
lines changed

lib/ClangImporter/ClangImporter.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2742,6 +2742,15 @@ getClangOwningModule(ClangNode Node, const clang::ASTContext &ClangCtx) {
27422742
originalDecl = pattern;
27432743
}
27442744
}
2745+
if (!originalDecl->hasOwningModule()) {
2746+
if (auto cxxRecordDecl = dyn_cast<clang::CXXRecordDecl>(D)) {
2747+
if (auto pattern = cxxRecordDecl->getTemplateInstantiationPattern()) {
2748+
// Class template instantiations sometimes don't have an owning Clang
2749+
// module, if the instantiation is not typedef-ed.
2750+
originalDecl = pattern;
2751+
}
2752+
}
2753+
}
27452754

27462755
return ExtSource->getModule(originalDecl->getOwningModuleID());
27472756
}

lib/ClangImporter/ImportDecl.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2793,7 +2793,7 @@ namespace {
27932793

27942794
// If this module is declared as a C++ module, try to synthesize
27952795
// conformances to Swift protocols from the Cxx module.
2796-
auto clangModule = decl->getOwningModule();
2796+
auto clangModule = Impl.getClangOwningModule(result->getClangNode());
27972797
if (clangModule && requiresCPlusPlus(clangModule)) {
27982798
auto nominalDecl = cast<NominalTypeDecl>(result);
27992799
conformToCxxIteratorIfNeeded(Impl, nominalDecl, decl);

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

Lines changed: 2 additions & 0 deletions
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

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,13 @@ import CxxStdlib.vector
1212

1313
var StdVectorTestSuite = TestSuite("StdVector")
1414

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

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

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

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

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

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

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

0 commit comments

Comments
 (0)