diff --git a/lib/ClangImporter/ClangImporter.cpp b/lib/ClangImporter/ClangImporter.cpp index 3d7841a0b7037..c093cd8ffa73b 100644 --- a/lib/ClangImporter/ClangImporter.cpp +++ b/lib/ClangImporter/ClangImporter.cpp @@ -2742,6 +2742,15 @@ getClangOwningModule(ClangNode Node, const clang::ASTContext &ClangCtx) { originalDecl = pattern; } } + if (!originalDecl->hasOwningModule()) { + if (auto cxxRecordDecl = dyn_cast(D)) { + if (auto pattern = cxxRecordDecl->getTemplateInstantiationPattern()) { + // Class template instantiations sometimes don't have an owning Clang + // module, if the instantiation is not typedef-ed. + originalDecl = pattern; + } + } + } return ExtSource->getModule(originalDecl->getOwningModuleID()); } diff --git a/lib/ClangImporter/ImportDecl.cpp b/lib/ClangImporter/ImportDecl.cpp index 25f2fb25f6cfc..d36706bc3b98b 100644 --- a/lib/ClangImporter/ImportDecl.cpp +++ b/lib/ClangImporter/ImportDecl.cpp @@ -2793,7 +2793,7 @@ namespace { // If this module is declared as a C++ module, try to synthesize // conformances to Swift protocols from the Cxx module. - auto clangModule = decl->getOwningModule(); + auto clangModule = Impl.getClangOwningModule(result->getClangNode()); if (clangModule && requiresCPlusPlus(clangModule)) { auto nominalDecl = cast(result); conformToCxxIteratorIfNeeded(Impl, nominalDecl, decl); diff --git a/test/Interop/Cxx/stdlib/Inputs/std-vector.h b/test/Interop/Cxx/stdlib/Inputs/std-vector.h index 319ff52279429..f7c375ad854ff 100644 --- a/test/Interop/Cxx/stdlib/Inputs/std-vector.h +++ b/test/Interop/Cxx/stdlib/Inputs/std-vector.h @@ -2,8 +2,10 @@ #define TEST_INTEROP_CXX_STDLIB_INPUTS_STD_VECTOR_H #include +#include using Vector = std::vector; +using VectorOfString = std::vector; inline Vector initVector() { return {}; } diff --git a/test/Interop/Cxx/stdlib/use-std-vector.swift b/test/Interop/Cxx/stdlib/use-std-vector.swift index 347c6f335feac..80d2ee31bd9cb 100644 --- a/test/Interop/Cxx/stdlib/use-std-vector.swift +++ b/test/Interop/Cxx/stdlib/use-std-vector.swift @@ -12,13 +12,13 @@ import CxxStdlib.vector var StdVectorTestSuite = TestSuite("StdVector") -StdVectorTestSuite.test("init") { +StdVectorTestSuite.test("VectorOfInt.init") { let v = Vector() expectEqual(v.size(), 0) expectTrue(v.empty()) } -StdVectorTestSuite.test("push back") { +StdVectorTestSuite.test("VectorOfInt.push_back") { var v = Vector() let _42: CInt = 42 v.push_back(_42) @@ -33,7 +33,7 @@ func fill(vector v: inout Vector) { v.push_back(CInt(3)) } -StdVectorTestSuite.test("for loop") { +StdVectorTestSuite.test("VectorOfInt for loop") { var v = Vector() fill(vector: &v) @@ -45,7 +45,23 @@ StdVectorTestSuite.test("for loop") { expectEqual(count, 4) } -StdVectorTestSuite.test("map") { +StdVectorTestSuite.test("VectorOfString for loop") { + var v = VectorOfString() + var count = 0 + for _ in v { + count += 1 + } + expectEqual(count, 0) + + v.push_back(std.string("abc")) + v.push_back(std.string("ab")) + for it in v { + count += it.length() + } + expectEqual(count, 5) +} + +StdVectorTestSuite.test("VectorOfInt.map") { var v = Vector() fill(vector: &v) @@ -53,4 +69,14 @@ StdVectorTestSuite.test("map") { expectEqual(a, [6, 7, 8]) } +StdVectorTestSuite.test("VectorOfString.map") { + var v = VectorOfString() + v.push_back(std.string("abc")) + v.push_back(std.string("a")) + v.push_back(std.string("ab")) + + let a = v.map { $0.length() } + expectEqual(a, [3, 1, 2]) +} + runAllTests()