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"
@@ -368,6 +369,7 @@ namespace {
368369 : public StructTypeInfoBase<LoadableClangRecordTypeInfo, LoadableTypeInfo,
369370 ClangFieldInfo> {
370371 const clang::RecordDecl *ClangDecl;
372+ bool HasReferenceField;
371373
372374 public:
373375 LoadableClangRecordTypeInfo (ArrayRef<ClangFieldInfo> fields,
@@ -376,14 +378,14 @@ namespace {
376378 Alignment align,
377379 IsTriviallyDestroyable_t isTriviallyDestroyable,
378380 IsCopyable_t isCopyable,
379- const clang::RecordDecl *clangDecl)
381+ const clang::RecordDecl *clangDecl,
382+ bool hasReferenceField)
380383 : StructTypeInfoBase(StructTypeInfoKind::LoadableClangRecordTypeInfo,
381384 fields, explosionSize, FieldsAreABIAccessible,
382385 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) {}
387389
388390 TypeLayoutEntry
389391 *buildTypeLayoutEntry (IRGenModule &IGM,
@@ -447,6 +449,7 @@ namespace {
447449 const ClangFieldInfo &field) const {
448450 llvm_unreachable (" non-fixed field in Clang type?" );
449451 }
452+ bool hasReferenceField () const { return HasReferenceField; }
450453 };
451454
452455 class AddressOnlyPointerAuthRecordTypeInfo final
@@ -1319,6 +1322,11 @@ class ClangRecordLowering {
13191322 Size NextOffset = Size(0 );
13201323 Size SubobjectAdjustment = Size(0 );
13211324 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+
13221330public:
13231331 ClangRecordLowering (IRGenModule &IGM, StructDecl *swiftDecl,
13241332 const clang::RecordDecl *clangDecl,
@@ -1359,11 +1367,12 @@ class ClangRecordLowering {
13591367 return LoadableClangRecordTypeInfo::create (
13601368 FieldInfos, NextExplosionIndex, llvmType, TotalStride,
13611369 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);
13671376 }
13681377
13691378private:
@@ -1488,6 +1497,17 @@ class ClangRecordLowering {
14881497 SwiftType.getFieldType (swiftField, IGM.getSILModule (),
14891498 IGM.getMaximalTypeExpansionContext ())));
14901499 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 ;
14911511 return ;
14921512 }
14931513
0 commit comments