From e87b5c15037d4f9a02290472cb1d70d79edbdb1a Mon Sep 17 00:00:00 2001 From: David Chisnall Date: Mon, 6 Mar 2017 11:38:44 +0000 Subject: [PATCH] Remove an assertion that was useful in debugging, but not actually correct. Instance variables are not normally zero-sized, but some are. Examples include zero-length arrays at the end of a class, and bitfields. Fixes #30 Fixes #31 --- Test/CMakeLists.txt | 1 + Test/zeroSizedIVar.m | 69 ++++++++++++++++++++++++++++++++++++++++++++ ivar.c | 1 - 3 files changed, 70 insertions(+), 1 deletion(-) create mode 100644 Test/zeroSizedIVar.m diff --git a/Test/CMakeLists.txt b/Test/CMakeLists.txt index 77a8fe6..e5304da 100644 --- a/Test/CMakeLists.txt +++ b/Test/CMakeLists.txt @@ -31,6 +31,7 @@ set(TESTS msgInterpose.m NilException.m MethodArguments.m + zeroSizedIVar.m ) # Function for adding a test. This takes the name of the test and the list of diff --git a/Test/zeroSizedIVar.m b/Test/zeroSizedIVar.m new file mode 100644 index 0000000..7b80caa --- /dev/null +++ b/Test/zeroSizedIVar.m @@ -0,0 +1,69 @@ +#include +#include +#include "Test.h" + + +typedef uintptr_t NSUInteger; + +@interface NSArray : Test +{ + NSUInteger count; + id objects[0]; +} +@end + +@implementation NSArray @end + +@interface BitfieldTest : Test +{ + BOOL flag1:1; + BOOL flag2:1; + BOOL flag3:1; +} +@end + +@implementation BitfieldTest @end + +@interface BitfieldTest2 : Test +{ + BOOL flag1:1; + BOOL flag2:1; + BOOL flag3:1; + int x; +} +@end + +@implementation BitfieldTest2 @end + + +int main() +{ + Class nsarray = objc_getClass("NSArray"); + assert(nsarray); + assert(class_getInstanceSize(nsarray) == (sizeof(Class) + sizeof(NSUInteger))); + Ivar count = class_getInstanceVariable(nsarray, "count"); + assert(ivar_getOffset(count) == sizeof(id)); + Ivar objects = class_getInstanceVariable(nsarray, "objects"); + + Class bitfield = objc_getClass("BitfieldTest"); + assert(bitfield); + Ivar flag1 = class_getInstanceVariable(bitfield, "flag1"); + assert(flag1); + assert(ivar_getOffset(flag1) == sizeof(id)); + Ivar flag2 = class_getInstanceVariable(bitfield, "flag2"); + assert(flag2); + assert(ivar_getOffset(flag2) == sizeof(id)); + Ivar flag3 = class_getInstanceVariable(bitfield, "flag3"); + assert(flag3); + assert(ivar_getOffset(flag3) == sizeof(id)); + assert(ivar_getOffset(flag3) + sizeof(int) <= class_getInstanceSize(bitfield)); + + bitfield = objc_getClass("BitfieldTest2"); + flag1 = class_getInstanceVariable(bitfield, "flag1"); + flag3 = class_getInstanceVariable(bitfield, "flag3"); + Ivar x = class_getInstanceVariable(bitfield, "x"); + assert(ivar_getOffset(flag1) == ivar_getOffset(flag3)); + assert(ivar_getOffset(x) > ivar_getOffset(flag3)); + assert(ivar_getOffset(x) + sizeof(int) <= class_getInstanceSize(bitfield)); +} + diff --git a/ivar.c b/ivar.c index d6556f9..2bfdaaf 100644 --- a/ivar.c +++ b/ivar.c @@ -58,7 +58,6 @@ PRIVATE void objc_compute_ivar_offsets(Class class) long ivar_size = (i+1 == class->ivars->count) ? (class_size - ivar->offset) : class->ivars->ivar_list[i+1].offset - ivar->offset ; - assert(ivar_size > 0); ivar->offset += cumulative_fudge; // We only need to do the realignment for things that are // bigger than a pointer, and we don't need to do it in GC mode