2222#include " swift/AST/Decl.h"
2323#include " swift/AST/IRGenOptions.h"
2424#include " swift/AST/Pattern.h"
25+ #include " swift/AST/ReferenceCounting.h"
2526#include " swift/AST/SemanticAttrs.h"
2627#include " swift/AST/SubstitutionMap.h"
2728#include " swift/AST/Types.h"
@@ -369,6 +370,7 @@ namespace {
369370 : public StructTypeInfoBase<LoadableClangRecordTypeInfo, LoadableTypeInfo,
370371 ClangFieldInfo> {
371372 const clang::RecordDecl *ClangDecl;
373+ bool HasReferenceField;
372374
373375 public:
374376 LoadableClangRecordTypeInfo (ArrayRef<ClangFieldInfo> fields,
@@ -377,14 +379,14 @@ namespace {
377379 Alignment align,
378380 IsTriviallyDestroyable_t isTriviallyDestroyable,
379381 IsCopyable_t isCopyable,
380- const clang::RecordDecl *clangDecl)
382+ const clang::RecordDecl *clangDecl,
383+ bool hasReferenceField)
381384 : StructTypeInfoBase(StructTypeInfoKind::LoadableClangRecordTypeInfo,
382385 fields, explosionSize, FieldsAreABIAccessible,
383386 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) {}
388390
389391 TypeLayoutEntry
390392 *buildTypeLayoutEntry (IRGenModule &IGM,
@@ -448,6 +450,7 @@ namespace {
448450 const ClangFieldInfo &field) const {
449451 llvm_unreachable (" non-fixed field in Clang type?" );
450452 }
453+ bool hasReferenceField () const { return HasReferenceField; }
451454 };
452455
453456 class AddressOnlyPointerAuthRecordTypeInfo final
@@ -1320,6 +1323,11 @@ class ClangRecordLowering {
13201323 Size NextOffset = Size(0 );
13211324 Size SubobjectAdjustment = Size(0 );
13221325 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+
13231331public:
13241332 ClangRecordLowering (IRGenModule &IGM, StructDecl *swiftDecl,
13251333 const clang::RecordDecl *clangDecl,
@@ -1360,11 +1368,12 @@ class ClangRecordLowering {
13601368 return LoadableClangRecordTypeInfo::create (
13611369 FieldInfos, NextExplosionIndex, llvmType, TotalStride,
13621370 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);
13681377 }
13691378
13701379private:
@@ -1489,6 +1498,17 @@ class ClangRecordLowering {
14891498 SwiftType.getFieldType (swiftField, IGM.getSILModule (),
14901499 IGM.getMaximalTypeExpansionContext ())));
14911500 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 ;
14921512 return ;
14931513 }
14941514
0 commit comments