]> granicus.if.org Git - clang/commitdiff
Fix IRGen issues related to using property-dot syntax
authorFariborz Jahanian <fjahanian@apple.com>
Wed, 30 Mar 2011 16:11:20 +0000 (16:11 +0000)
committerFariborz Jahanian <fjahanian@apple.com>
Wed, 30 Mar 2011 16:11:20 +0000 (16:11 +0000)
for prperty reference types. // rdar://9208606.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@128551 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/AST/ExprObjC.h
lib/CodeGen/CGExpr.cpp
lib/CodeGen/CGExprAgg.cpp
lib/CodeGen/CGObjC.cpp
test/CodeGenObjCXX/property-reference.mm [new file with mode: 0644]

index 0068ee499a8834904a3179494ce157d0b088e2cd..3ee6d1f22940b740739b17cfdf38c4eab10da4e6 100644 (file)
@@ -337,6 +337,39 @@ public:
   QualType getSuperReceiverType() const { 
     return QualType(Receiver.get<const Type*>(), 0); 
   }
+  QualType getGetterResultType() const {
+    QualType ResultType;
+    if (isExplicitProperty()) {
+      const ObjCPropertyDecl *PDecl = getExplicitProperty();
+      if (const ObjCMethodDecl *Getter = PDecl->getGetterMethodDecl())
+        ResultType = Getter->getResultType();
+      else
+        ResultType = getType();
+    } else {
+      const ObjCMethodDecl *Getter = getImplicitPropertyGetter();
+      ResultType = Getter->getResultType(); // with reference!
+    }
+    return ResultType;
+  }
+  
+  QualType getSetterArgType() const {
+    QualType ArgType;
+    if (isImplicitProperty()) {
+      const ObjCMethodDecl *Setter = getImplicitPropertySetter();
+      ObjCMethodDecl::param_iterator P = Setter->param_begin(); 
+      ArgType = (*P)->getType();
+    } else {
+      if (ObjCPropertyDecl *PDecl = getExplicitProperty())
+        if (const ObjCMethodDecl *Setter = PDecl->getSetterMethodDecl()) {
+          ObjCMethodDecl::param_iterator P = Setter->param_begin(); 
+          ArgType = (*P)->getType();
+        }
+      if (ArgType.isNull())
+        ArgType = getType();
+    }
+    return ArgType;
+  }
+  
   ObjCInterfaceDecl *getClassReceiver() const {
     return Receiver.get<ObjCInterfaceDecl*>();
   }
index 6a7be0fe6e8a807b339ef5e2bdf23d33f9f3c10a..ab88a38babf2d6512e0a787d949a00f0ab3d89e9 100644 (file)
@@ -216,10 +216,19 @@ EmitExprForReferenceBinding(CodeGenFunction &CGF, const Expr *E,
                                        InitializedDecl);
   }
 
+  if (const ObjCPropertyRefExpr *PRE = 
+      dyn_cast<ObjCPropertyRefExpr>(E->IgnoreParenImpCasts()))
+    if (PRE->getGetterResultType()->isReferenceType())
+      E = PRE;
+    
   RValue RV;
   if (E->isGLValue()) {
     // Emit the expression as an lvalue.
     LValue LV = CGF.EmitLValue(E);
+    if (LV.isPropertyRef()) {
+      RV = CGF.EmitLoadOfPropertyRefLValue(LV);
+      return RV.getScalarVal();
+    }
     if (LV.isSimple())
       return LV.getAddress();
     
index f992dc7c9cb92c790471660425c3a7f9945bbd35..eb64996bd335693078dbd5cd43acb86fdb8aef3d 100644 (file)
@@ -403,9 +403,17 @@ void AggExprEmitter::VisitBinAssign(const BinaryOperator *E) {
   // We have to special case property setters, otherwise we must have
   // a simple lvalue (no aggregates inside vectors, bitfields).
   if (LHS.isPropertyRef()) {
-    AggValueSlot Slot = EnsureSlot(E->getRHS()->getType());
-    CGF.EmitAggExpr(E->getRHS(), Slot);
-    CGF.EmitStoreThroughPropertyRefLValue(Slot.asRValue(), LHS);
+    const ObjCPropertyRefExpr *RE = LHS.getPropertyRefExpr();
+    QualType ArgType = RE->getSetterArgType();
+    RValue Src;
+    if (ArgType->isReferenceType())
+      Src = CGF.EmitReferenceBindingToExpr(E->getRHS(), 0);
+    else {
+      AggValueSlot Slot = EnsureSlot(E->getRHS()->getType());
+      CGF.EmitAggExpr(E->getRHS(), Slot);
+      Src = Slot.asRValue();
+    }
+    CGF.EmitStoreThroughPropertyRefLValue(Src, LHS);
   } else {
     bool GCollection = false;
     if (CGF.getContext().getLangOptions().getGCMode())
index 99b8b57eb960c243cb69d45c02403963e5cb71b3..ac4e763f89f9f02a1e7bd4c444529625910195d8 100644 (file)
@@ -651,16 +651,14 @@ static RValue GenerateMessageSendSuper(CodeGenFunction &CGF,
 RValue CodeGenFunction::EmitLoadOfPropertyRefLValue(LValue LV,
                                                     ReturnValueSlot Return) {
   const ObjCPropertyRefExpr *E = LV.getPropertyRefExpr();
-  QualType ResultType;
+  QualType ResultType = E->getGetterResultType();
   Selector S;
   if (E->isExplicitProperty()) {
     const ObjCPropertyDecl *Property = E->getExplicitProperty();
     S = Property->getGetterName();
-    ResultType = E->getType();
   } else {
     const ObjCMethodDecl *Getter = E->getImplicitPropertyGetter();
     S = Getter->getSelector();
-    ResultType = Getter->getResultType(); // with reference!
   }
 
   llvm::Value *Receiver = LV.getPropertyRefBaseAddr();
@@ -681,14 +679,8 @@ void CodeGenFunction::EmitStoreThroughPropertyRefLValue(RValue Src,
                                                         LValue Dst) {
   const ObjCPropertyRefExpr *E = Dst.getPropertyRefExpr();
   Selector S = E->getSetterSelector();
-  QualType ArgType;
-  if (E->isImplicitProperty()) {
-    const ObjCMethodDecl *Setter = E->getImplicitPropertySetter();
-    ObjCMethodDecl::param_iterator P = Setter->param_begin(); 
-    ArgType = (*P)->getType();
-  } else {
-    ArgType = E->getType();
-  }
+  QualType ArgType = E->getSetterArgType();
+  
   // FIXME. Other than scalars, AST is not adequate for setter and
   // getter type mismatches which require conversion.
   if (Src.isScalar()) {
diff --git a/test/CodeGenObjCXX/property-reference.mm b/test/CodeGenObjCXX/property-reference.mm
new file mode 100644 (file)
index 0000000..7c235cb
--- /dev/null
@@ -0,0 +1,34 @@
+// RUN: %clang_cc1 %s -triple=x86_64-apple-darwin10 -emit-llvm -o - | FileCheck %s
+// rdar://9208606
+
+struct MyStruct
+{
+       int x;
+       int y;
+       int z;
+};
+
+@interface MyClass
+{
+       MyStruct _foo;
+}
+
+@property (assign, readwrite) const MyStruct& foo;
+
+- (const MyStruct&) foo;
+- (void) setFoo:(const MyStruct&)inFoo;
+@end
+
+int main()
+{
+       MyClass* myClass;
+       MyStruct myStruct;
+
+       myClass.foo = myStruct;
+
+       const MyStruct& currentMyStruct = myClass.foo;   
+       return 0;
+}
+
+// CHECK: [[C:%.*]] = call %struct.MyStruct* bitcast (i8* (i8*, i8*, ...)* @objc_msgSend
+// CHECK:   store %struct.MyStruct* [[C]], %struct.MyStruct** [[D:%.*]]