Correctly handle zero-sized but non-empty base classes in IRGen.

Fixes rdar://20621065.

A more elegant fix would preclude this case by defining the
rules such that zero-size classes are always formally empty.
I believe the only extensions which create zero-size classes
right now are flexible arrays and zero-length arrays; it's
not abstractly unreasonable to say that those don't count
as members for the purposes of emptiness, just as zero-width
bitfields don't count.  But that's an ABI-affecting change
and requires further discussion; in the meantime, let's not
assert / miscompile.

llvm-svn: 235815
This commit is contained in:
John McCall 2015-04-26 04:43:26 +00:00
parent f26c748b1b
commit 9fc700e76d
2 changed files with 21 additions and 1 deletions

View File

@ -438,8 +438,12 @@ void CGRecordLowering::accumulateBases() {
for (const auto &Base : RD->bases()) {
if (Base.isVirtual())
continue;
// Bases can be zero-sized even if not technically empty if they
// contain only a trailing array member.
const CXXRecordDecl *BaseDecl = Base.getType()->getAsCXXRecordDecl();
if (!BaseDecl->isEmpty())
if (!BaseDecl->isEmpty() &&
!Context.getASTRecordLayout(BaseDecl).getSize().isZero())
Members.push_back(MemberInfo(Layout.getBaseClassOffset(BaseDecl),
MemberInfo::Base, getStorageType(BaseDecl), BaseDecl));
}

View File

@ -1,5 +1,7 @@
// RUN: %clang_cc1 %s -I%S -triple=x86_64-apple-darwin10 -emit-llvm -O3 -o - | FileCheck %s
// CHECK: %"struct.rdar20621065::B" = type { float, float }
struct Empty { };
struct A {
@ -80,3 +82,17 @@ int main() {
return result;
}
#endif
namespace rdar20621065 {
struct A {
float array[0];
};
struct B : A {
float left;
float right;
};
// Type checked at the top of the file.
B b;
};