2929#include " swift/SIL/SILModule.h"
3030#include " clang/AST/ASTContext.h"
3131#include " clang/AST/Attr.h"
32+ #include " clang/AST/CharUnits.h"
3233#include " clang/AST/Decl.h"
34+ #include " clang/AST/DeclCXX.h"
3335#include " clang/AST/GlobalDecl.h"
3436#include " clang/AST/Mangle.h"
3537#include " clang/AST/RecordLayout.h"
3638#include " clang/CodeGen/CodeGenABITypes.h"
3739#include " clang/CodeGen/SwiftCallingConv.h"
3840#include " clang/Sema/Sema.h"
41+ #include " llvm/ADT/STLExtras.h"
3942#include " llvm/IR/DerivedTypes.h"
4043#include " llvm/IR/Function.h"
44+ #include < iterator>
4145
4246#include " GenDecl.h"
4347#include " GenMeta.h"
@@ -1310,6 +1314,7 @@ class ClangRecordLowering {
13101314 SmallVector<llvm::Type *, 8 > LLVMFields;
13111315 SmallVector<ClangFieldInfo, 8 > FieldInfos;
13121316 Size NextOffset = Size(0 );
1317+ Size SubobjectAdjustment = Size(0 );
13131318 unsigned NextExplosionIndex = 0 ;
13141319public:
13151320 ClangRecordLowering (IRGenModule &IGM, StructDecl *swiftDecl,
@@ -1327,8 +1332,8 @@ class ClangRecordLowering {
13271332 if (ClangDecl->isUnion ()) {
13281333 collectUnionFields ();
13291334 } else {
1330- collectBases ();
1331- collectStructFields ();
1335+ collectBases (ClangDecl );
1336+ collectStructFields (ClangDecl );
13321337 }
13331338 }
13341339
@@ -1359,10 +1364,9 @@ class ClangRecordLowering {
13591364 return (swiftField->getClangNode ().castAsDecl () == clangField);
13601365 }
13611366
1362- void collectBases () {
1363- auto &layout = ClangDecl->getASTContext ().getASTRecordLayout (ClangDecl);
1364-
1365- if (auto cxxRecord = dyn_cast<clang::CXXRecordDecl>(ClangDecl)) {
1367+ void collectBases (const clang::RecordDecl *decl) {
1368+ auto &layout = decl->getASTContext ().getASTRecordLayout (decl);
1369+ if (auto cxxRecord = dyn_cast<clang::CXXRecordDecl>(decl)) {
13661370 for (auto base : cxxRecord->bases ()) {
13671371 if (base.isVirtual ())
13681372 continue ;
@@ -1375,17 +1379,24 @@ class ClangRecordLowering {
13751379 if (baseCxxRecord->isEmpty ())
13761380 continue ;
13771381
1378- auto offset = layout.getBaseClassOffset (baseCxxRecord);
1379- auto size = ClangDecl->getASTContext ().getTypeSizeInChars (baseType);
1380- addOpaqueField (Size (offset.getQuantity ()), Size (size.getQuantity ()));
1382+ auto baseOffset = Size (layout.getBaseClassOffset (baseCxxRecord).getQuantity ());
1383+ SubobjectAdjustment += baseOffset;
1384+ collectBases (baseCxxRecord);
1385+ collectStructFields (baseCxxRecord);
1386+ SubobjectAdjustment -= baseOffset;
13811387 }
13821388 }
13831389 }
13841390
1385- void collectStructFields () {
1386- auto cfi = ClangDecl->field_begin (), cfe = ClangDecl->field_end ();
1391+ void collectStructFields (const clang::RecordDecl *decl) {
1392+ auto cfi = decl->field_begin (), cfe = decl->field_end ();
1393+ const auto &layout = ClangContext.getASTRecordLayout (decl);
13871394 auto swiftProperties = SwiftDecl->getStoredProperties ();
13881395 auto sfi = swiftProperties.begin (), sfe = swiftProperties.end ();
1396+ // When collecting fields from the base subobjects, we do not have corresponding swift
1397+ // stored properties.
1398+ if (decl != ClangDecl)
1399+ sfi = swiftProperties.end ();
13891400
13901401 while (cfi != cfe) {
13911402 const clang::FieldDecl *clangField = *cfi++;
@@ -1395,13 +1406,13 @@ class ClangRecordLowering {
13951406 if (clangField->isBitField ()) {
13961407 // Collect all of the following bitfields.
13971408 unsigned bitStart =
1398- ClangLayout .getFieldOffset (clangField->getFieldIndex ());
1409+ layout .getFieldOffset (clangField->getFieldIndex ());
13991410 unsigned bitEnd = bitStart + clangField->getBitWidthValue (ClangContext);
14001411
14011412 while (cfi != cfe && (*cfi)->isBitField ()) {
14021413 clangField = *cfi++;
14031414 unsigned nextStart =
1404- ClangLayout .getFieldOffset (clangField->getFieldIndex ());
1415+ layout .getFieldOffset (clangField->getFieldIndex ());
14051416 assert (nextStart >= bitEnd && " laying out bit-fields out of order?" );
14061417
14071418 // In a heuristic effort to reduce the number of weird-sized
@@ -1419,41 +1430,41 @@ class ClangRecordLowering {
14191430 continue ;
14201431 }
14211432
1422- VarDecl *swiftField;
1433+ VarDecl *swiftField = nullptr ;
14231434 if (sfi != sfe) {
14241435 swiftField = *sfi;
14251436 if (isImportOfClangField (swiftField, clangField)) {
14261437 ++sfi;
14271438 } else {
14281439 swiftField = nullptr ;
14291440 }
1430- } else {
1431- swiftField = nullptr ;
1432- }
1441+ }
14331442
14341443 // Try to position this field. If this fails, it's because we
14351444 // didn't lay out padding correctly.
1436- addStructField (clangField, swiftField);
1445+ addStructField (clangField, swiftField, layout );
14371446 }
14381447
14391448 assert (sfi == sfe && " more Swift fields than there were Clang fields?" );
14401449
1450+ Size objectTotalStride = Size (layout.getSize ().getQuantity ());
14411451 // We never take advantage of tail padding, because that would prevent
14421452 // us from passing the address of the object off to C, which is a pretty
14431453 // likely scenario for imported C types.
1444- assert (NextOffset <= TotalStride);
1445- assert (SpareBits.size () <= TotalStride.getValueInBits ());
1446- if (NextOffset < TotalStride) {
1447- addPaddingField (TotalStride);
1454+ assert (NextOffset <= SubobjectAdjustment + objectTotalStride);
1455+ assert (SpareBits.size () <= SubobjectAdjustment.getValueInBits () +
1456+ objectTotalStride.getValueInBits ());
1457+ if (NextOffset < objectTotalStride) {
1458+ addPaddingField (objectTotalStride);
14481459 }
14491460 }
14501461
14511462 // / Place the next struct field at its appropriate offset.
14521463 void addStructField (const clang::FieldDecl *clangField,
1453- VarDecl *swiftField) {
1454- unsigned fieldOffset = ClangLayout .getFieldOffset (clangField->getFieldIndex ());
1464+ VarDecl *swiftField, const clang::ASTRecordLayout &layout ) {
1465+ unsigned fieldOffset = layout .getFieldOffset (clangField->getFieldIndex ());
14551466 assert (!clangField->isBitField ());
1456- Size offset (fieldOffset / 8 );
1467+ Size offset ( SubobjectAdjustment. getValue () + fieldOffset / 8 );
14571468
14581469 // If we have a Swift import of this type, use our lowered information.
14591470 if (swiftField) {
0 commit comments