@@ -368,6 +368,7 @@ namespace {
368
368
: public StructTypeInfoBase<LoadableClangRecordTypeInfo, LoadableTypeInfo,
369
369
ClangFieldInfo> {
370
370
const clang::RecordDecl *ClangDecl;
371
+ bool HasReferenceField;
371
372
372
373
public:
373
374
LoadableClangRecordTypeInfo (ArrayRef<ClangFieldInfo> fields,
@@ -376,14 +377,14 @@ namespace {
376
377
Alignment align,
377
378
IsTriviallyDestroyable_t isTriviallyDestroyable,
378
379
IsCopyable_t isCopyable,
379
- const clang::RecordDecl *clangDecl)
380
+ const clang::RecordDecl *clangDecl,
381
+ bool hasReferenceField)
380
382
: StructTypeInfoBase(StructTypeInfoKind::LoadableClangRecordTypeInfo,
381
383
fields, explosionSize, FieldsAreABIAccessible,
382
384
storageType, size, std::move(spareBits), align,
383
- isTriviallyDestroyable,
384
- isCopyable,
385
- IsFixedSize, IsABIAccessible),
386
- ClangDecl (clangDecl) {}
385
+ isTriviallyDestroyable, isCopyable, IsFixedSize,
386
+ IsABIAccessible),
387
+ ClangDecl (clangDecl), HasReferenceField(hasReferenceField) {}
387
388
388
389
TypeLayoutEntry
389
390
*buildTypeLayoutEntry (IRGenModule &IGM,
@@ -447,6 +448,7 @@ namespace {
447
448
const ClangFieldInfo &field) const {
448
449
llvm_unreachable (" non-fixed field in Clang type?" );
449
450
}
451
+ bool hasReferenceField () const { return HasReferenceField; }
450
452
};
451
453
452
454
class AddressOnlyPointerAuthRecordTypeInfo final
@@ -1319,6 +1321,11 @@ class ClangRecordLowering {
1319
1321
Size NextOffset = Size(0 );
1320
1322
Size SubobjectAdjustment = Size(0 );
1321
1323
unsigned NextExplosionIndex = 0 ;
1324
+ // Types that are trivial in C++ but are containing fields to reference types
1325
+ // are not trivial in Swift, they cannot be copied using memcpy as we need to
1326
+ // do the proper retain operations.
1327
+ bool hasReferenceField = false ;
1328
+
1322
1329
public:
1323
1330
ClangRecordLowering (IRGenModule &IGM, StructDecl *swiftDecl,
1324
1331
const clang::RecordDecl *clangDecl,
@@ -1359,11 +1366,12 @@ class ClangRecordLowering {
1359
1366
return LoadableClangRecordTypeInfo::create (
1360
1367
FieldInfos, NextExplosionIndex, llvmType, TotalStride,
1361
1368
std::move (SpareBits), TotalAlignment,
1362
- (SwiftDecl && SwiftDecl->getValueTypeDestructor ())
1363
- ? IsNotTriviallyDestroyable : IsTriviallyDestroyable,
1364
- (SwiftDecl && !SwiftDecl->canBeCopyable ())
1365
- ? IsNotCopyable : IsCopyable,
1366
- ClangDecl);
1369
+ (SwiftDecl &&
1370
+ (SwiftDecl->getValueTypeDestructor () || hasReferenceField))
1371
+ ? IsNotTriviallyDestroyable
1372
+ : IsTriviallyDestroyable,
1373
+ (SwiftDecl && !SwiftDecl->canBeCopyable ()) ? IsNotCopyable : IsCopyable,
1374
+ ClangDecl, hasReferenceField);
1367
1375
}
1368
1376
1369
1377
private:
@@ -1488,6 +1496,14 @@ class ClangRecordLowering {
1488
1496
SwiftType.getFieldType (swiftField, IGM.getSILModule (),
1489
1497
IGM.getMaximalTypeExpansionContext ())));
1490
1498
addField (swiftField, offset, fieldTI, isZeroSized);
1499
+ if (swiftField->getInterfaceType ()
1500
+ ->lookThroughSingleOptionalType ()
1501
+ ->isAnyClassReferenceType ())
1502
+ hasReferenceField = true ;
1503
+ else if (const auto *recordTI =
1504
+ dyn_cast<LoadableClangRecordTypeInfo>(&fieldTI))
1505
+ if (recordTI->hasReferenceField ())
1506
+ hasReferenceField = true ;
1491
1507
return ;
1492
1508
}
1493
1509
0 commit comments