Handle reference properties correctly in the trivial-getter check.

llvm-svn: 139585
This commit is contained in:
John McCall 2011-09-13 06:00:03 +00:00
parent 0e5c086de4
commit bdd8185e22
2 changed files with 43 additions and 17 deletions

View File

@ -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());

View File

@ -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