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:
parent
cb06d3030c
commit
3c8220405d
|
@ -1074,6 +1074,20 @@ void ObjCInterfaceDecl::setImplementation(ObjCImplementationDecl *ImplD) {
|
||||||
getASTContext().setObjCImplementation(getDefinition(), 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,
|
/// all_declared_ivar_begin - return first ivar declared in this class,
|
||||||
/// its extensions and its implementation. Lazily build the list on first
|
/// its extensions and its implementation. Lazily build the list on first
|
||||||
/// access.
|
/// access.
|
||||||
|
@ -1110,14 +1124,33 @@ ObjCIvarDecl *ObjCInterfaceDecl::all_declared_ivar_begin() {
|
||||||
|
|
||||||
if (ObjCImplementationDecl *ImplDecl = getImplementation()) {
|
if (ObjCImplementationDecl *ImplDecl = getImplementation()) {
|
||||||
if (!ImplDecl->ivar_empty()) {
|
if (!ImplDecl->ivar_empty()) {
|
||||||
ObjCImplementationDecl::ivar_iterator I = ImplDecl->ivar_begin(),
|
SmallVector<SynthesizeIvarChunk, 16> layout;
|
||||||
E = ImplDecl->ivar_end();
|
for (ObjCImplementationDecl::ivar_iterator I = ImplDecl->ivar_begin(),
|
||||||
if (!data().IvarList) {
|
E = ImplDecl->ivar_end(); I != E; ++I) {
|
||||||
data().IvarList = *I; ++I;
|
ObjCIvarDecl *IV = *I;
|
||||||
curIvar = data().IvarList;
|
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;
|
return data().IvarList;
|
||||||
|
|
|
@ -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
|
Loading…
Reference in New Issue