aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Dunbar <daniel@zuster.org>2009-05-04 23:23:09 +0000
committerDaniel Dunbar <daniel@zuster.org>2009-05-04 23:23:09 +0000
commit6e8575b88bfb2634d7b28c0c4d5ed2a6acc8418a (patch)
tree520161afb1b1586c482f4778beed50730248a4c1
parent31fa7d7022877f24e001c30643de073df427d8dd (diff)
Fix the field count in interface record layout (it was incorrectly
compensating for super classes). This was making the reported class sizes for empty classes very, very wrong. - Also, we now report the size info for an empty class like gcc (as the offset of the start, not as 0, 0). - Add a few more test cases we were mishandling before (padding bit field at end of struct, for example). git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@70938 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/AST/ASTContext.cpp6
-rw-r--r--lib/CodeGen/CGObjCMac.cpp13
-rw-r--r--test/CodeGenObjC/interface-layout-64.m55
3 files changed, 57 insertions, 17 deletions
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index a9f13c9518..a947fea95a 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -713,10 +713,6 @@ ASTContext::getObjCLayout(const ObjCInterfaceDecl *D,
ASTRecordLayout *NewEntry = NULL;
if (ObjCInterfaceDecl *SD = D->getSuperClass()) {
- // FIXME: This increment of FieldCount is wrong, we don't actually
- // count the super class as a member (see the field index passed
- // to LayoutField below).
- FieldCount++;
const ASTRecordLayout &SL = getASTObjCInterfaceLayout(SD);
unsigned Alignment = SL.getAlignment();
uint64_t Size = SL.getSize();
@@ -729,8 +725,6 @@ ASTContext::getObjCLayout(const ObjCInterfaceDecl *D,
ObjCLayouts[Key] = NewEntry = new ASTRecordLayout(Size, Alignment);
NewEntry->InitializeLayout(FieldCount);
- // Super class is at the beginning of the layout.
- NewEntry->SetFieldOffset(0, 0);
} else {
ObjCLayouts[Key] = NewEntry = new ASTRecordLayout();
NewEntry->InitializeLayout(FieldCount);
diff --git a/lib/CodeGen/CGObjCMac.cpp b/lib/CodeGen/CGObjCMac.cpp
index 1a1ef83123..1f58389ab8 100644
--- a/lib/CodeGen/CGObjCMac.cpp
+++ b/lib/CodeGen/CGObjCMac.cpp
@@ -4222,13 +4222,14 @@ void CGObjCNonFragileABIMac::GetClassSizeInfo(const ObjCImplementationDecl *OID,
const ASTRecordLayout &RL =
CGM.getContext().getASTObjCImplementationLayout(OID);
- if (!RL.getFieldCount()) {
- InstanceStart = InstanceSize = 0;
- return;
- }
-
- InstanceStart = RL.getFieldOffset(0) / 8;
+ // InstanceSize is really instance end.
InstanceSize = llvm::RoundUpToAlignment(RL.getNextOffset(), 8) / 8;
+
+ // If there are no fields, the start is the same as the end.
+ if (!RL.getFieldCount())
+ InstanceStart = InstanceSize;
+ else
+ InstanceStart = RL.getFieldOffset(0) / 8;
}
void CGObjCNonFragileABIMac::GenerateClass(const ObjCImplementationDecl *ID) {
diff --git a/test/CodeGenObjC/interface-layout-64.m b/test/CodeGenObjC/interface-layout-64.m
index ee01ac6bb6..db860e8518 100644
--- a/test/CodeGenObjC/interface-layout-64.m
+++ b/test/CodeGenObjC/interface-layout-64.m
@@ -1,17 +1,36 @@
-// RUN: clang-cc -triple x86_64-apple-darwin9 -emit-llvm -o %t %s &&
+// RUN: clang-cc -fobjc-tight-layout -triple x86_64-apple-darwin9 -emit-llvm -o %t %s &&
// RUNX: llvm-gcc -m64 -emit-llvm -S -o %t %s &&
// RUN: grep '@"OBJC_IVAR_$_I3._iv2" = global i64 8, section "__DATA, __objc_const", align 8' %t &&
// RUN: grep '@"OBJC_IVAR_$_I3._iv3" = global i64 12, section "__DATA, __objc_const", align 8' %t &&
-// RUN: grep '@"OBJC_IVAR_$_I4._iv4" = global i64 16, section "__DATA, __objc_const", align 8' %t &&
-// RUN: grep '@"OBJC_IVAR_$_I5._iv5" = global i64 24, section "__DATA, __objc_const", align 8' %t &&
-// RUN: grep '@"OBJC_IVAR_$_I5._iv6_synth" = global i64 28, section "__DATA, __objc_const", align 8' %t &&
-// RUN: grep '@"OBJC_IVAR_$_I5._iv7_synth" = global i64 32, section "__DATA, __objc_const", align 8' %t &&
+// RUN: grep '@"OBJC_IVAR_$_I4._iv4" = global i64 13, section "__DATA, __objc_const", align 8' %t &&
+// RUN: grep '@"OBJC_IVAR_$_I5._iv5" = global i64 14, section "__DATA, __objc_const", align 8' %t &&
+// RUN: grep '@"OBJC_IVAR_$_I5._iv6_synth" = global i64 16, section "__DATA, __objc_const", align 8' %t &&
+// RUN: grep '@"OBJC_IVAR_$_I5._iv7_synth" = global i64 20, section "__DATA, __objc_const", align 8' %t &&
+// RUN: grep '@"OBJC_IVAR_$_I6.iv0" = global i64 0, section "__DATA, __objc_const", align 8' %t &&
+// RUN: grep '@"OBJC_IVAR_$_I8.b" = global i64 8, section "__DATA, __objc_const", align 8' %t &&
+// RUN: grep '@"OBJC_IVAR_$_I9.iv0" = global i64 0, section "__DATA, __objc_const", align 8' %t &&
+// RUN: grep '@"OBJC_IVAR_$_I10.iv1" = global i64 4, section "__DATA, __objc_const", align 8' %t &&
+// RUN: grep '@"OBJC_IVAR_$_I12.iv2" = global i64 8, section "__DATA, __objc_const", align 8' %t &&
+// RUN: grep '_OBJC_CLASS_RO_$_I3" = internal global .* { i32 0, i32 8, i32 13, .*' %t &&
+// RUN: grep '_OBJC_CLASS_RO_$_I4" = internal global .* { i32 0, i32 13, i32 14, .*' %t &&
+// RUN: grep '_OBJC_CLASS_RO_$_I5" = internal global .* { i32 0, i32 14, i32 24, .*' %t &&
// RUN: grep '_OBJC_CLASS_RO_$_I6" = internal global .* { i32 2, i32 0, i32 1, .*' %t &&
// RUN: grep '_OBJC_CLASS_RO_$_I8" = internal global .* { i32 0, i32 8, i32 16, .*' %t &&
+// RUN: grep '_OBJC_CLASS_RO_$_I9" = internal global .* { i32 2, i32 0, i32 4, .*' %t &&
+// RUN: grep '_OBJC_CLASS_RO_$_I10" = internal global .* { i32 0, i32 4, i32 5, .*' %t &&
+// RUN: grep '_OBJC_CLASS_RO_$_I11" = internal global .* { i32 0, i32 5, i32 5, .*' %t &&
+// RUN: grep '_OBJC_CLASS_RO_$_I12" = internal global .* { i32 0, i32 8, i32 12, .*' %t &&
// RUN: true
+/*
+ Compare to:
+ gcc -m64 -S -o - interface-layout-64.m | grep '^_OBJC_IVAR_$_*.*' -A 1
+ and
+ gcc -m64 -S -o - interface-layout-64.m | grep '^l.*_CLASS_RO_$_I[0-9]*' -A 3
+ */
+
struct s0 {
double x;
};
@@ -77,3 +96,29 @@ struct s0 {
@implementation I8
@end
+// Padding bit-fields
+@interface I9 {
+ unsigned iv0 : 2;
+ unsigned : 0;
+}
+@end
+@implementation I9
+@end
+@interface I10 : I9 {
+ unsigned iv1 : 2;
+}
+@end
+@implementation I10
+@end
+
+// Empty structures
+@interface I11 : I10
+@end
+@implementation I11
+@end
+@interface I12 : I11 {
+ unsigned iv2;
+}
+@end
+@implementation I12
+@end