Correctly handle zero-sized but non-empty base classes in IRGen.
authorJohn McCall <rjmccall@apple.com>
Sun, 26 Apr 2015 04:43:26 +0000 (04:43 +0000)
committerJohn McCall <rjmccall@apple.com>
Sun, 26 Apr 2015 04:43:26 +0000 (04:43 +0000)
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
clang/test/CodeGenCXX/empty-classes.cpp

index 202ea97..c33d2d9 100644 (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));
   }
index 8491480..e27a961 100644 (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;
+};