Handle reference properties correctly in the trivial-getter check.
llvm-svn: 139585
This commit is contained in:
parent
0e5c086de4
commit
bdd8185e22
|
@ -564,13 +564,19 @@ void CodeGenFunction::GenerateObjCGetter(ObjCImplementationDecl *IMP,
|
|||
FinishFunction();
|
||||
}
|
||||
|
||||
static bool hasTrivialGetExpr(const ObjCPropertyImplDecl *PID) {
|
||||
const Expr *getter = PID->getGetterCXXConstructor();
|
||||
static bool hasTrivialGetExpr(const ObjCPropertyImplDecl *propImpl) {
|
||||
const Expr *getter = propImpl->getGetterCXXConstructor();
|
||||
if (!getter) return true;
|
||||
|
||||
// Sema only makes only of these when the ivar has a C++ class type,
|
||||
// so the form is pretty constrained.
|
||||
|
||||
// If the property has a reference type, we might just be binding a
|
||||
// reference, in which case the result will be a gl-value. We should
|
||||
// treat this as a non-trivial operation.
|
||||
if (getter->isGLValue())
|
||||
return false;
|
||||
|
||||
// If we selected a trivial copy-constructor, we're okay.
|
||||
if (const CXXConstructExpr *construct = dyn_cast<CXXConstructExpr>(getter))
|
||||
return (construct->getConstructor()->isTrivial());
|
||||
|
|
|
@ -1,16 +1,14 @@
|
|||
// RUN: %clang_cc1 %s -triple=x86_64-apple-darwin10 -emit-llvm -o - | FileCheck %s
|
||||
// rdar://9208606
|
||||
|
||||
struct MyStruct
|
||||
{
|
||||
int x;
|
||||
int y;
|
||||
int z;
|
||||
struct MyStruct {
|
||||
int x;
|
||||
int y;
|
||||
int z;
|
||||
};
|
||||
|
||||
@interface MyClass
|
||||
{
|
||||
MyStruct _foo;
|
||||
@interface MyClass {
|
||||
MyStruct _foo;
|
||||
}
|
||||
|
||||
@property (assign, readwrite) const MyStruct& foo;
|
||||
|
@ -19,16 +17,38 @@ struct MyStruct
|
|||
- (void) setFoo:(const MyStruct&)inFoo;
|
||||
@end
|
||||
|
||||
int main()
|
||||
{
|
||||
MyClass* myClass;
|
||||
MyStruct myStruct;
|
||||
void test0() {
|
||||
MyClass* myClass;
|
||||
MyStruct myStruct;
|
||||
|
||||
myClass.foo = myStruct;
|
||||
myClass.foo = myStruct;
|
||||
|
||||
const MyStruct& currentMyStruct = myClass.foo;
|
||||
return 0;
|
||||
const MyStruct& currentMyStruct = myClass.foo;
|
||||
}
|
||||
|
||||
// CHECK: [[C:%.*]] = call %struct.MyStruct* bitcast (i8* (i8*, i8*, ...)* @objc_msgSend
|
||||
// CHECK: store %struct.MyStruct* [[C]], %struct.MyStruct** [[D:%.*]]
|
||||
|
||||
namespace test1 {
|
||||
struct A { A(); A(const A&); A&operator=(const A&); ~A(); };
|
||||
}
|
||||
@interface Test1 {
|
||||
test1::A ivar;
|
||||
}
|
||||
@property const test1::A &prop1;
|
||||
@end
|
||||
@implementation Test1
|
||||
@synthesize prop1 = ivar;
|
||||
@end
|
||||
// CHECK: define internal [[A:%.*]]* @"\01-[Test1 prop1]"(
|
||||
// CHECK: [[SELF:%.*]] = alloca [[TEST1:%.*]]*, align 8
|
||||
// CHECK: [[T0:%.*]] = load [[TEST1]]** [[SELF]]
|
||||
// CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST1]]* [[T0]] to i8*
|
||||
// CHECK-NEXT: [[T2:%.*]] = getelementptr inbounds i8* [[T1]], i64 0
|
||||
// CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to [[A]]*
|
||||
// CHECK-NEXT: ret [[A]]* [[T3]]
|
||||
|
||||
// CHECK: define internal void @"\01-[Test1 setProp1:]"(
|
||||
// CHECK: call [[A]]* @_ZN5test11AaSERKS0_(
|
||||
// CHECK-NEXT: ret void
|
||||
|
||||
|
|
Loading…
Reference in New Issue