]> granicus.if.org Git - clang/commitdiff
Handle reference properties correctly in the trivial-getter check.
authorJohn McCall <rjmccall@apple.com>
Tue, 13 Sep 2011 06:00:03 +0000 (06:00 +0000)
committerJohn McCall <rjmccall@apple.com>
Tue, 13 Sep 2011 06:00:03 +0000 (06:00 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@139585 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/CGObjC.cpp
test/CodeGenObjCXX/property-reference.mm

index f0a47af909e01dfe9ba8e9e1859b333ce7118fbe..ca04a7b17853e2c868d18b05f1eefbfa57557dde 100644 (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());
index 7c235cb9b4ef7cb07f4b2a868922a92abf0d966a..0ba2c430d5d4e8597c5a61b74c4887ef7eb25c8a 100644 (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
+