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