Skip to content

Commit 0c214fe

Browse files
authored
Merge pull request #64466 from hyp/eng/inontrivvy
[interop] C++ record should use AddressOnly type layout only when it's non-trivial for purpose of calls
2 parents 7e5e720 + 861d99f commit 0c214fe

File tree

5 files changed

+47
-8
lines changed

5 files changed

+47
-8
lines changed

include/swift/AST/Decl.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4297,6 +4297,12 @@ class StructDecl final : public NominalTypeDecl {
42974297
Bits.StructDecl.HasUnreferenceableStorage = v;
42984298
}
42994299

4300+
/// Does this struct represent a non-trivial (for the purpose of calls, as
4301+
/// defined by Itanium ABI) C++ record. A C++ record is considered non-trivial
4302+
/// for the purpose of calls if either its constructor, copy-constructor, or
4303+
/// destructor is non-trivial. As such, a C++ record with a non-trivial
4304+
/// copy-assignment operator but other trivial members is considered to be
4305+
/// trivial.
43004306
bool isCxxNonTrivial() const { return Bits.StructDecl.IsCxxNonTrivial; }
43014307

43024308
void setIsCxxNonTrivial(bool v) { Bits.StructDecl.IsCxxNonTrivial = v; }

lib/ClangImporter/ImportDecl.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2394,9 +2394,15 @@ namespace {
23942394
}
23952395

23962396
if (cxxRecordDecl) {
2397+
auto isNonTrivialForPurposeOfCalls =
2398+
[](const clang::CXXRecordDecl *decl) -> bool {
2399+
return decl->hasNonTrivialCopyConstructor() ||
2400+
decl->hasNonTrivialMoveConstructor() ||
2401+
!decl->hasTrivialDestructor();
2402+
};
23972403
if (auto structResult = dyn_cast<StructDecl>(result))
23982404
structResult->setIsCxxNonTrivial(
2399-
!cxxRecordDecl->isTriviallyCopyable());
2405+
isNonTrivialForPurposeOfCalls(cxxRecordDecl));
24002406

24012407
for (auto &getterAndSetter : Impl.GetterSetterMap) {
24022408
auto getter = getterAndSetter.second.first;

test/Interop/Cxx/class/type-classification-loadable-silgen.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -54,17 +54,17 @@ func pass(s: StructWithSubobjectDefaultedCopyConstructor) {
5454

5555
// CHECK-LABEL: sil hidden [ossa] @$s4main4pass{{.*[ (]}}StructWithCopyAssignment)
5656
func pass(s: StructWithCopyAssignment) {
57-
// CHECK: bb0(%0 : $*StructWithCopyAssignment):
57+
// CHECK: bb0(%0 : $StructWithCopyAssignment):
5858
}
5959

6060
// CHECK-LABEL: sil hidden [ossa] @$s4main4pass{{.*[ (]}}StructWithInheritedCopyAssignment)
6161
func pass(s: StructWithInheritedCopyAssignment) {
62-
// CHECK: bb0(%0 : $*StructWithInheritedCopyAssignment):
62+
// CHECK: bb0(%0 : $StructWithInheritedCopyAssignment):
6363
}
6464

6565
// CHECK-LABEL: sil hidden [ossa] @$s4main4pass{{.*[ (]}}StructWithSubobjectCopyAssignment)
6666
func pass(s: StructWithSubobjectCopyAssignment) {
67-
// CHECK: bb0(%0 : $*StructWithSubobjectCopyAssignment):
67+
// CHECK: bb0(%0 : $StructWithSubobjectCopyAssignment):
6868
}
6969

7070
// CHECK-LABEL: sil hidden [ossa] @$s4main4pass{{.*[ (]}}StructWithDestructor)

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

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,22 @@
44

55
using PairInts = std::pair<int, int>;
66

7-
// FIXME: return pair by value, but it causes IRGen crash atm.
8-
inline const PairInts &getIntPair() {
9-
static PairInts value = { -5, 12 };
7+
inline const PairInts &getIntPairPointer() {
8+
static PairInts value = { 4, 9 };
109
return value;
1110
}
11+
12+
inline PairInts getIntPair() {
13+
return { -5, 12 };
14+
}
15+
16+
struct StructInPair {
17+
int x;
18+
int y;
19+
};
20+
21+
using PairStructInt = std::pair<StructInPair, int>;
22+
23+
inline PairStructInt getPairStructInt(int x) {
24+
return { { x * 2, -x}, x };
25+
}

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

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,25 @@ import Cxx
1212
var StdPairTestSuite = TestSuite("StdPair")
1313

1414
StdPairTestSuite.test("StdPair.elements") {
15-
var pi = getIntPair().pointee
15+
var pi = getIntPair()
1616
expectEqual(pi.first, -5)
1717
expectEqual(pi.second, 12)
1818
pi.first = 11
1919
expectEqual(pi.first, 11)
2020
expectEqual(pi.second, 12)
2121
}
2222

23+
StdPairTestSuite.test("StdPair.ref.elements") {
24+
let pi = getIntPairPointer().pointee
25+
expectEqual(pi.first, 4)
26+
expectEqual(pi.second, 9)
27+
}
28+
29+
StdPairTestSuite.test("PairStructInt.elements") {
30+
let pair = getPairStructInt(11)
31+
expectEqual(pair.first.x, 22)
32+
expectEqual(pair.first.y, -11)
33+
expectEqual(pair.second, 11)
34+
}
35+
2336
runAllTests()

0 commit comments

Comments
 (0)