objective-C: Make order of ivars which are synthesized

in the course of property synthesis deterministic (ordered
by their type size), instead of having hashtable order
(as it is currently). // rdar://13192366

llvm-svn: 175100
This commit is contained in:
Fariborz Jahanian 2013-02-13 22:50:36 +00:00
parent cb06d3030c
commit 3c8220405d
2 changed files with 98 additions and 7 deletions

View File

@ -1074,6 +1074,20 @@ void ObjCInterfaceDecl::setImplementation(ObjCImplementationDecl *ImplD) {
getASTContext().setObjCImplementation(getDefinition(), ImplD);
}
namespace {
struct SynthesizeIvarChunk {
uint64_t Size;
ObjCIvarDecl *Ivar;
SynthesizeIvarChunk(uint64_t size, ObjCIvarDecl *ivar)
: Size(size), Ivar(ivar) {}
};
bool operator<(const SynthesizeIvarChunk & LHS,
const SynthesizeIvarChunk &RHS) {
return LHS.Size < RHS.Size;
}
}
/// all_declared_ivar_begin - return first ivar declared in this class,
/// its extensions and its implementation. Lazily build the list on first
/// access.
@ -1110,14 +1124,33 @@ ObjCIvarDecl *ObjCInterfaceDecl::all_declared_ivar_begin() {
if (ObjCImplementationDecl *ImplDecl = getImplementation()) {
if (!ImplDecl->ivar_empty()) {
ObjCImplementationDecl::ivar_iterator I = ImplDecl->ivar_begin(),
E = ImplDecl->ivar_end();
if (!data().IvarList) {
data().IvarList = *I; ++I;
curIvar = data().IvarList;
SmallVector<SynthesizeIvarChunk, 16> layout;
for (ObjCImplementationDecl::ivar_iterator I = ImplDecl->ivar_begin(),
E = ImplDecl->ivar_end(); I != E; ++I) {
ObjCIvarDecl *IV = *I;
if (IV->getSynthesize() && !IV->isInvalidDecl()) {
layout.push_back(SynthesizeIvarChunk(
IV->getASTContext().getTypeSize(IV->getType()), IV));
continue;
}
if (!data().IvarList)
data().IvarList = *I;
else
curIvar->setNextIvar(*I);
curIvar = *I;
}
if (!layout.empty()) {
// Order synthesized ivars by their size.
std::stable_sort(layout.begin(), layout.end());
unsigned Ix = 0, EIx = layout.size();
if (!data().IvarList) {
data().IvarList = layout[0].Ivar; Ix++;
curIvar = data().IvarList;
}
for ( ; Ix != EIx; curIvar = layout[Ix].Ivar, Ix++)
curIvar->setNextIvar(layout[Ix].Ivar);
}
for ( ;I != E; curIvar = *I, ++I)
curIvar->setNextIvar(*I);
}
}
return data().IvarList;

View File

@ -0,0 +1,58 @@
// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fobjc-default-synthesize-properties -emit-llvm -x objective-c %s -o - | FileCheck %s
// rdar://13192366
typedef signed char BOOL;
@interface NSObject
{
id isa;
}
@end
@interface MyClass : NSObject
@property (readwrite) BOOL boolean1;
@property (readwrite, copy) id object1;
@property (readwrite) BOOL boolean2;
@property (readwrite, copy) id object2;
@property (readwrite) BOOL boolean3;
@property (readwrite, copy) id object3;
@property (readwrite) BOOL boolean4;
@property (readwrite, copy) id object4;
@property (readwrite) BOOL boolean5;
@property (readwrite, copy) id object5;
@property (readwrite) BOOL boolean6;
@property (readwrite, copy) id object6;
@property (readwrite) BOOL boolean7;
@property (readwrite) BOOL MyBool;
@property (readwrite, copy) id object7;
@property (readwrite) BOOL boolean8;
@property (readwrite, copy) id object8;
@property (readwrite) BOOL boolean9;
@property (readwrite, copy) id object9;
@end
@implementation MyClass
{
id MyIvar;
BOOL _MyBool;
char * pc;
}
@end
// CHECK: @"{{.*}}" = internal global [10 x i8] c"_boolean
// CHECK-NEXT: @"{{.*}}" = internal global [10 x i8] c"_boolean
// CHECK-NEXT: @"{{.*}}" = internal global [10 x i8] c"_boolean
// CHECK-NEXT: @"{{.*}}" = internal global [10 x i8] c"_boolean
// CHECK-NEXT: @"{{.*}}" = internal global [10 x i8] c"_boolean
// CHECK-NEXT: @"{{.*}}" = internal global [10 x i8] c"_boolean
// CHECK-NEXT: @"{{.*}}" = internal global [10 x i8] c"_boolean
// CHECK-NEXT: @"{{.*}}" = internal global [10 x i8] c"_boolean
// CHECK-NEXT: @"{{.*}}" = internal global [10 x i8] c"_boolean
// CHECK-NEXT: @"{{.*}}" = internal global [9 x i8] c"_object
// CHECK-NEXT: @"{{.*}}" = internal global [9 x i8] c"_object
// CHECK-NEXT: @"{{.*}}" = internal global [9 x i8] c"_object
// CHECK-NEXT: @"{{.*}}" = internal global [9 x i8] c"_object
// CHECK-NEXT: @"{{.*}}" = internal global [9 x i8] c"_object
// CHECK-NEXT: @"{{.*}}" = internal global [9 x i8] c"_object
// CHECK-NEXT: @"{{.*}}" = internal global [9 x i8] c"_object
// CHECK-NEXT: @"{{.*}}" = internal global [9 x i8] c"_object
// CHECK-NEXT: @"{{.*}}" = internal global [9 x i8] c"_object