diff --git a/clang/lib/AST/RecordLayoutBuilder.cpp b/clang/lib/AST/RecordLayoutBuilder.cpp index a51c8b938f411..706991f4fb501 100644 --- a/clang/lib/AST/RecordLayoutBuilder.cpp +++ b/clang/lib/AST/RecordLayoutBuilder.cpp @@ -2942,8 +2942,8 @@ void MicrosoftRecordLayoutBuilder::layoutNonVirtualBase( } if (!FoundBase) { - if (MDCUsesEBO && BaseDecl->isEmpty()) { - assert(BaseLayout.getNonVirtualSize() == CharUnits::Zero()); + if (MDCUsesEBO && BaseDecl->isEmpty() && + (BaseLayout.getNonVirtualSize() == CharUnits::Zero())) { BaseOffset = CharUnits::Zero(); } else { // Otherwise, lay the base out at the end of the MDC. diff --git a/clang/test/Layout/ms-x86-declspec-empty_bases.cpp b/clang/test/Layout/ms-x86-declspec-empty_bases.cpp index cc13a980cb5db..4738ce5720f75 100644 --- a/clang/test/Layout/ms-x86-declspec-empty_bases.cpp +++ b/clang/test/Layout/ms-x86-declspec-empty_bases.cpp @@ -264,3 +264,63 @@ int _ = sizeof(G); // CHECK-NEXT: | [sizeof=12, align=4, // CHECK-NEXT: | nvsize=12, nvalign=4] } + +namespace test5 { + +struct A { + int a; +}; +struct B { + int b; +}; +struct C {}; +struct __declspec(align(16)) D {}; +struct E { + [[msvc::no_unique_address]] C c; +}; +struct __declspec(empty_bases) X : A, D, B, C, E { +}; + +// CHECK: *** Dumping AST Record Layout +// CHECK-NEXT: 0 | struct test5::A +// CHECK-NEXT: 0 | int a +// CHECK-NEXT: | [sizeof=4, align=4, +// CHECK-NEXT: | nvsize=4, nvalign=4] + +// CHECK: *** Dumping AST Record Layout +// CHECK-NEXT: 0 | struct test5::D (empty) +// CHECK-NEXT: | [sizeof=16, align=16, +// CHECK-NEXT: | nvsize=0, nvalign=16] + +// CHECK: *** Dumping AST Record Layout +// CHECK-NEXT: 0 | struct test5::B +// CHECK-NEXT: 0 | int b +// CHECK-NEXT: | [sizeof=4, align=4, +// CHECK-NEXT: | nvsize=4, nvalign=4] + +// CHECK: *** Dumping AST Record Layout +// CHECK-NEXT: 0 | struct test5::C (empty) +// CHECK-NEXT: | [sizeof=1, align=1, +// CHECK-NEXT: | nvsize=0, nvalign=1] + +// CHECK: *** Dumping AST Record Layout +// CHECK-NEXT: 0 | struct test5::E (empty) +// CHECK-NEXT: 0 | struct test5::C c (empty) +// CHECK-NEXT: | [sizeof=1, align=1, +// CHECK-NEXT: | nvsize=1, nvalign=1] + +// CHECK: *** Dumping AST Record Layout +// CHECK-NEXT: 0 | struct test5::X +// CHECK-NEXT: 0 | struct test5::A (base) +// CHECK-NEXT: 0 | int a +// CHECK-NEXT: 0 | struct test5::D (base) (empty) +// CHECK-NEXT: 0 | struct test5::C (base) (empty) +// CHECK-NEXT: 4 | struct test5::B (base) +// CHECK-NEXT: 4 | int b +// CHECK-NEXT: 8 | struct test5::E (base) (empty) +// CHECK-NEXT: 8 | struct test5::C c (empty) +// CHECK-NEXT: | [sizeof=16, align=16, +// CHECK-NEXT: | nvsize=16, nvalign=16] + +int _ = sizeof(X); +}