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