From 9fc700e76d74e1bc57e709ca7b096c7dc7025950 Mon Sep 17 00:00:00 2001 From: John McCall Date: Sun, 26 Apr 2015 04:43:26 +0000 Subject: [PATCH] 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 --- clang/lib/CodeGen/CGRecordLayoutBuilder.cpp | 6 +++++- clang/test/CodeGenCXX/empty-classes.cpp | 16 ++++++++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/clang/lib/CodeGen/CGRecordLayoutBuilder.cpp b/clang/lib/CodeGen/CGRecordLayoutBuilder.cpp index 202ea97..c33d2d9 100644 --- a/clang/lib/CodeGen/CGRecordLayoutBuilder.cpp +++ b/clang/lib/CodeGen/CGRecordLayoutBuilder.cpp @@ -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)); } diff --git a/clang/test/CodeGenCXX/empty-classes.cpp b/clang/test/CodeGenCXX/empty-classes.cpp index 8491480..e27a961 100644 --- a/clang/test/CodeGenCXX/empty-classes.cpp +++ b/clang/test/CodeGenCXX/empty-classes.cpp @@ -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; +}; -- 2.7.4