Skip to content

Commit 6902041

Browse files
committed
[cxx-interop] Force creating a memberwise init for std::pair
In libc++, `pair()` and `pair(_T1 const& __t1, _T2 const& __t2)` are templated with `enable_if`, so these initializers are not imported into Swift. There should be a way to call `std.pair.init` from Swift, so this change makes sure Swift synthesizes a memberwise initializer for `std.pair`. rdar://113135110
1 parent b92530f commit 6902041

File tree

3 files changed

+28
-1
lines changed

3 files changed

+28
-1
lines changed

lib/ClangImporter/ImportDecl.cpp

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2407,13 +2407,20 @@ namespace {
24072407
}
24082408
}
24092409

2410+
bool forceMemberwiseInitializer = false;
2411+
if (cxxRecordDecl && cxxRecordDecl->isInStdNamespace() &&
2412+
cxxRecordDecl->getIdentifier() &&
2413+
cxxRecordDecl->getName() == "pair") {
2414+
forceMemberwiseInitializer = true;
2415+
}
24102416
// We can assume that it is possible to correctly construct the object by
24112417
// simply initializing its member variables to arbitrary supplied values
24122418
// only when the same is possible in C++. While we could check for that
24132419
// exactly, checking whether the C++ class is an aggregate
24142420
// (C++ [dcl.init.aggr]) has the same effect.
24152421
bool isAggregate = !cxxRecordDecl || cxxRecordDecl->isAggregate();
2416-
if (hasReferenceableFields && hasMemberwiseInitializer && isAggregate) {
2422+
if ((hasReferenceableFields && hasMemberwiseInitializer && isAggregate) ||
2423+
forceMemberwiseInitializer) {
24172424
// The default zero initializer suppresses the implicit value
24182425
// constructor that would normally be formed, so we have to add that
24192426
// explicitly as well.

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
#pragma once
22

33
#include <utility>
4+
#include <string>
45

56
using PairInts = std::pair<int, int>;
7+
using PairStrings = std::pair<std::string, std::string>;
68

79
inline const PairInts &getIntPairPointer() {
810
static PairInts value = { 4, 9 };

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

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,24 @@ import Cxx
99

1010
var StdPairTestSuite = TestSuite("StdPair")
1111

12+
StdPairTestSuite.test("StdPairInts.init") {
13+
let pi = PairInts(first: 1, second: 2)
14+
expectEqual(pi.first, 1)
15+
expectEqual(pi.second, 2)
16+
}
17+
18+
#if !os(Windows) // FIXME: enable once swiftCxxStdlib is built on Windows (https://github.com/apple/swift/issues/67649)
19+
StdPairTestSuite.test("StdPairStrings.init") {
20+
let ps = PairStrings(first: std.string(), second: std.string())
21+
expectEqual(ps.first, std.string())
22+
expectEqual(ps.second, std.string())
23+
24+
let ps2 = PairStrings(first: std.string("abc"), second: std.string("123"))
25+
expectEqual(ps2.first, std.string("abc"))
26+
expectEqual(ps2.second, std.string("123"))
27+
}
28+
#endif
29+
1230
StdPairTestSuite.test("StdPair.elements") {
1331
var pi = getIntPair()
1432
expectEqual(pi.first, -5)

0 commit comments

Comments
 (0)