Add Objective-C property setter support.
 - Change Obj-C runtime message API, drop the ObjCMessageExpr arg in
   favor of just result type and selector. Necessary so it can be
   reused in situations where we don't want to cons up an
   ObjCMessageExpr.
 - Update aggregate binary assignment to know about special property
   ref lvalues.
 - Add CodeGenFunction::EmitCallArg overload which takes an already
   emitted rvalue.

Add CodeGenFunction::StoreComplexIntoAddr.

Disabled logic in Sema for parsing Objective-C dot-syntax that
accesses methods. This code does not search in the correct order and
the AST node has no way of properly representing its results.

Updated StmtDumper to print a bit more information about
ObjCPropertyRefExprs.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@55561 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/AST/StmtDumper.cpp b/lib/AST/StmtDumper.cpp
index 0ccf201..af19b61 100644
--- a/lib/AST/StmtDumper.cpp
+++ b/lib/AST/StmtDumper.cpp
@@ -136,6 +136,7 @@
     void VisitObjCMessageExpr(ObjCMessageExpr* Node);
     void VisitObjCSelectorExpr(ObjCSelectorExpr *Node);
     void VisitObjCProtocolExpr(ObjCProtocolExpr *Node);
+    void VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *Node);
     void VisitObjCIvarRefExpr(ObjCIvarRefExpr *Node);
   };
 }
@@ -449,6 +450,18 @@
   fprintf(F, " ");
   fprintf(F, "%s", Node->getProtocol()->getName());
 }
+
+void StmtDumper::VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *Node) {
+  DumpExpr(Node);
+  
+  if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(Node->getDecl())) {
+    fprintf(F, " MethodDecl=\"%s\"", MD->getSelector().getName().c_str());
+  } else {
+    ObjCPropertyDecl *PD = dyn_cast<ObjCPropertyDecl>(Node->getDecl());
+    fprintf(F, " PropertyDecl=\"%s\"", PD->getName());
+  }
+}
+
 //===----------------------------------------------------------------------===//
 // Stmt method implementations
 //===----------------------------------------------------------------------===//
diff --git a/lib/CodeGen/CGExpr.cpp b/lib/CodeGen/CGExpr.cpp
index c8aa261..e189349 100644
--- a/lib/CodeGen/CGExpr.cpp
+++ b/lib/CodeGen/CGExpr.cpp
@@ -830,6 +830,24 @@
   return EmitCall(Callee, ResultType, Args);
 }
 
+// FIXME: Merge the following two functions.
+void CodeGenFunction::EmitCallArg(RValue RV, QualType Ty,
+                                  CallArgList &Args) {
+  llvm::Value *ArgValue;
+
+  if (RV.isScalar()) {
+    ArgValue = RV.getScalarVal();
+  } else if (RV.isComplex()) {
+    // Make a temporary alloca to pass the argument.
+    ArgValue = CreateTempAlloca(ConvertType(Ty));
+    StoreComplexToAddr(RV.getComplexVal(), ArgValue, false); 
+  } else {
+    ArgValue = RV.getAggregateAddr();
+  }
+
+  Args.push_back(std::make_pair(ArgValue, Ty));
+}
+
 void CodeGenFunction::EmitCallArg(const Expr *E, CallArgList &Args) {
   QualType ArgTy = E->getType();
   llvm::Value *ArgValue;
diff --git a/lib/CodeGen/CGExprAgg.cpp b/lib/CodeGen/CGExprAgg.cpp
index d335ea9..11eb9fc 100644
--- a/lib/CodeGen/CGExprAgg.cpp
+++ b/lib/CodeGen/CGExprAgg.cpp
@@ -264,14 +264,26 @@
          && "Invalid assignment");
   LValue LHS = CGF.EmitLValue(E->getLHS());
 
-  // Codegen the RHS so that it stores directly into the LHS.
-  CGF.EmitAggExpr(E->getRHS(), LHS.getAddress(), false /*FIXME: VOLATILE LHS*/);
-
-  if (DestPtr == 0)
-    return;
-
-  // If the result of the assignment is used, copy the RHS there also.
-  EmitAggregateCopy(DestPtr, LHS.getAddress(), E->getType());
+  // We have to special case property setters, otherwise we must have
+  // a simple lvalue (no aggregates inside vectors, bitfields).
+  if (LHS.isPropertyRef()) {
+    // FIXME: Volatility?
+    llvm::Value *AggLoc = DestPtr;
+    if (!AggLoc)
+      AggLoc = CGF.CreateTempAlloca(CGF.ConvertType(E->getRHS()->getType()));
+    CGF.EmitAggExpr(E->getRHS(), AggLoc, false);
+    CGF.EmitObjCPropertySet(LHS.getPropertyRefExpr(), 
+                            RValue::getAggregate(AggLoc));
+  } else {
+    // Codegen the RHS so that it stores directly into the LHS.
+    CGF.EmitAggExpr(E->getRHS(), LHS.getAddress(), false /*FIXME: VOLATILE LHS*/);
+    
+    if (DestPtr == 0)
+      return;
+    
+    // If the result of the assignment is used, copy the RHS there also.
+    EmitAggregateCopy(DestPtr, LHS.getAddress(), E->getType());
+  }
 }
 
 void AggExprEmitter::VisitConditionalOperator(const ConditionalOperator *E) {
diff --git a/lib/CodeGen/CGExprComplex.cpp b/lib/CodeGen/CGExprComplex.cpp
index 3e1f695..abd0ca8 100644
--- a/lib/CodeGen/CGExprComplex.cpp
+++ b/lib/CodeGen/CGExprComplex.cpp
@@ -546,6 +546,13 @@
   Emitter.EmitStoreOfComplex(Val, DestAddr, DestIsVolatile);
 }
 
+/// StoreComplexToAddr - Store a complex number into the specified address.
+void CodeGenFunction::StoreComplexToAddr(ComplexPairTy V,
+                                         llvm::Value *DestAddr,
+                                         bool DestIsVolatile) {
+  ComplexExprEmitter(*this).EmitStoreOfComplex(V, DestAddr, DestIsVolatile);
+}
+
 /// LoadComplexFromAddr - Load a complex number from the specified address.
 ComplexPairTy CodeGenFunction::LoadComplexFromAddr(llvm::Value *SrcAddr, 
                                                    bool SrcIsVolatile) {
diff --git a/lib/CodeGen/CGObjC.cpp b/lib/CodeGen/CGObjC.cpp
index 2a808f8..79b5011 100644
--- a/lib/CodeGen/CGObjC.cpp
+++ b/lib/CodeGen/CGObjC.cpp
@@ -86,13 +86,15 @@
   if (isSuperMessage) {
     // super is only valid in an Objective-C method
     const ObjCMethodDecl *OMD = cast<ObjCMethodDecl>(CurFuncDecl);
-    return Runtime.GenerateMessageSendSuper(*this, E,
+    return Runtime.GenerateMessageSendSuper(*this, E->getType(),
+                                            E->getSelector(),
                                             OMD->getClassInterface(),
                                             Receiver,
                                             isClassMessage,
                                             Args);
   }
-  return Runtime.GenerateMessageSend(*this, E, Receiver, isClassMessage, Args);
+  return Runtime.GenerateMessageSend(*this, E->getType(), E->getSelector(), 
+                                     Receiver, isClassMessage, Args);
 }
 
 /// StartObjCMethod - Begin emission of an ObjCMethod. This generates
@@ -234,20 +236,28 @@
     S = cast<ObjCPropertyDecl>(E->getDecl())->getGetterName();
   }
 
-  // FIXME: Improve location information.
-  SourceLocation Loc = E->getLocation();
-  // PropertyRefExprs are always instance messages.
-  // FIXME: Is there any reason to try and pass the method here?
-  ObjCMessageExpr GetExpr(const_cast<Expr*>(E->getBase()), 
-                          S, E->getType(), 0, Loc, Loc,
-                          0, 0);
-
-  return EmitObjCMessageExpr(&GetExpr);
+  return CGM.getObjCRuntime().
+    GenerateMessageSend(*this, E->getType(), S, 
+                        EmitScalarExpr(E->getBase()), 
+                        false, CallArgList());
 }
 
 void CodeGenFunction::EmitObjCPropertySet(const ObjCPropertyRefExpr *E,
                                           RValue Src) {
-  ErrorUnsupported(E, "Objective-C property setter call");
+  Selector S;
+  if (const ObjCPropertyDecl *PD = dyn_cast<ObjCPropertyDecl>(E->getDecl())) {
+    S = PD->getSetterName();
+  } else {
+    // FIXME: How can we have a method decl here?
+    ErrorUnsupported(E, "Objective-C property setter call");
+    return;
+  }
+
+  CallArgList Args;
+  EmitCallArg(Src, E->getType(), Args);
+  CGM.getObjCRuntime().GenerateMessageSend(*this, getContext().VoidTy, S, 
+                                           EmitScalarExpr(E->getBase()), 
+                                           false, Args);
 }
 
 CGObjCRuntime::~CGObjCRuntime() {}
diff --git a/lib/CodeGen/CGObjCGNU.cpp b/lib/CodeGen/CGObjCGNU.cpp
index e5a5d05..4565fbf 100644
--- a/lib/CodeGen/CGObjCGNU.cpp
+++ b/lib/CodeGen/CGObjCGNU.cpp
@@ -96,13 +96,15 @@
   virtual llvm::Constant *GenerateConstantString(const std::string &String);
   virtual CodeGen::RValue 
   GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
-                      const ObjCMessageExpr *E,
+                      QualType ResultType,
+                      Selector Sel,
                       llvm::Value *Receiver,
                       bool IsClassMessage,
                       const CallArgList &CallArgs);
   virtual CodeGen::RValue 
   GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
-                           const ObjCMessageExpr *E,
+                           QualType ResultType,
+                           Selector Sel,
                            const ObjCInterfaceDecl *Class,
                            llvm::Value *Receiver,
                            bool IsClassMessage,
@@ -239,16 +241,17 @@
 ///should be called.
 CodeGen::RValue
 CGObjCGNU::GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
-                                    const ObjCMessageExpr *E,
+                                    QualType ResultType,
+                                    Selector Sel,
                                     const ObjCInterfaceDecl *Class,
                                     llvm::Value *Receiver,
                                     bool IsClassMessage,
                                     const CallArgList &CallArgs) {
   const ObjCInterfaceDecl *SuperClass = Class->getSuperClass();
-  const llvm::Type *ReturnTy = CGM.getTypes().ConvertType(E->getType());
+  const llvm::Type *ReturnTy = CGM.getTypes().ConvertType(ResultType);
   // TODO: This should be cached, not looked up every time.
   llvm::Value *ReceiverClass = GetClass(CGF.Builder, SuperClass);
-  llvm::Value *cmd = GetSelector(CGF.Builder, E->getSelector());
+  llvm::Value *cmd = GetSelector(CGF.Builder, Sel);
   std::vector<const llvm::Type*> impArgTypes;
   impArgTypes.push_back(Receiver->getType());
   impArgTypes.push_back(SelectorTy);
@@ -282,18 +285,19 @@
   ActualArgs.push_back(std::make_pair(cmd,
                                       CGF.getContext().getObjCSelType()));
   ActualArgs.insert(ActualArgs.end(), CallArgs.begin(), CallArgs.end());
-  return CGF.EmitCall(imp, E->getType(), ActualArgs);
+  return CGF.EmitCall(imp, ResultType, ActualArgs);
 }
 
 /// Generate code for a message send expression.  
 CodeGen::RValue
 CGObjCGNU::GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
-                               const ObjCMessageExpr *E,
+                               QualType ResultType,
+                               Selector Sel,
                                llvm::Value *Receiver,
                                bool IsClassMessage,
                                const CallArgList &CallArgs) {
-  const llvm::Type *ReturnTy = CGM.getTypes().ConvertType(E->getType());
-  llvm::Value *cmd = GetSelector(CGF.Builder, E->getSelector());
+  const llvm::Type *ReturnTy = CGM.getTypes().ConvertType(ResultType);
+  llvm::Value *cmd = GetSelector(CGF.Builder, Sel);
 
   // Look up the method implementation.
   std::vector<const llvm::Type*> impArgTypes;
@@ -328,7 +332,7 @@
   ActualArgs.push_back(std::make_pair(cmd,
                                       CGF.getContext().getObjCSelType()));
   ActualArgs.insert(ActualArgs.end(), CallArgs.begin(), CallArgs.end());
-  return CGF.EmitCall(imp, E->getType(), ActualArgs);
+  return CGF.EmitCall(imp, ResultType, ActualArgs);
 }
 
 /// Generates a MethodList.  Used in construction of a objc_class and 
diff --git a/lib/CodeGen/CGObjCMac.cpp b/lib/CodeGen/CGObjCMac.cpp
index 3b4309d..ef4196e 100644
--- a/lib/CodeGen/CGObjCMac.cpp
+++ b/lib/CodeGen/CGObjCMac.cpp
@@ -219,7 +219,8 @@
                             const ObjCInterfaceDecl *ID);
 
   CodeGen::RValue EmitMessageSend(CodeGen::CodeGenFunction &CGF,
-                                  const ObjCMessageExpr *E,
+                                  QualType ResultType,
+                                  Selector Sel,
                                   llvm::Value *Arg0,
                                   QualType Arg0Ty,
                                   bool IsSuper,
@@ -337,14 +338,16 @@
   virtual llvm::Constant *GenerateConstantString(const std::string &String);
 
   virtual CodeGen::RValue GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
-                                              const ObjCMessageExpr *E,
+                                              QualType ResultType,
+                                              Selector Sel,
                                               llvm::Value *Receiver,
                                               bool IsClassMessage,
                                               const CallArgList &CallArgs);
 
   virtual CodeGen::RValue 
   GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
-                           const ObjCMessageExpr *E,
+                           QualType ResultType,
+                           Selector Sel,
                            const ObjCInterfaceDecl *Class,
                            llvm::Value *Receiver,
                            bool IsClassMessage,
@@ -428,7 +431,8 @@
 /// which class's method should be called.
 CodeGen::RValue
 CGObjCMac::GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
-                                    const ObjCMessageExpr *E,
+                                    QualType ResultType,
+                                    Selector Sel,
                                     const ObjCInterfaceDecl *Class,
                                     llvm::Value *Receiver,
                                     bool IsClassMessage,
@@ -460,34 +464,35 @@
   CGF.Builder.CreateStore(Target, 
                           CGF.Builder.CreateStructGEP(ObjCSuper, 1));
     
-  return EmitMessageSend(CGF, E, 
+  return EmitMessageSend(CGF, ResultType, Sel, 
                          ObjCSuper, ObjCTypes.SuperPtrCTy,
                          true, CallArgs);
 }
                                            
 /// Generate code for a message send expression.  
 CodeGen::RValue CGObjCMac::GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
-                                               const ObjCMessageExpr *E,
+                                               QualType ResultType,
+                                               Selector Sel,
                                                llvm::Value *Receiver,
                                                bool IsClassMessage,
                                                const CallArgList &CallArgs) {
   llvm::Value *Arg0 = 
     CGF.Builder.CreateBitCast(Receiver, ObjCTypes.ObjectPtrTy, "tmp");
-  return EmitMessageSend(CGF, E, 
+  return EmitMessageSend(CGF, ResultType, Sel,
                          Arg0, CGF.getContext().getObjCIdType(),
                          false, CallArgs);
 }
 
 CodeGen::RValue CGObjCMac::EmitMessageSend(CodeGen::CodeGenFunction &CGF,
-                                           const ObjCMessageExpr *E,
+                                           QualType ResultType,
+                                           Selector Sel,
                                            llvm::Value *Arg0,
                                            QualType Arg0Ty,
                                            bool IsSuper,
                                            const CallArgList &CallArgs) {
   CallArgList ActualArgs;
   ActualArgs.push_back(std::make_pair(Arg0, Arg0Ty));
-  ActualArgs.push_back(std::make_pair(EmitSelector(CGF.Builder, 
-                                                   E->getSelector()),
+  ActualArgs.push_back(std::make_pair(EmitSelector(CGF.Builder, Sel),
                                       CGF.getContext().getObjCSelType()));
   ActualArgs.insert(ActualArgs.end(), CallArgs.begin(), CallArgs.end());
 
@@ -496,10 +501,9 @@
   // parameter and set the structure return flag. See
   // getMessageSendFn().
                                                    
-  const llvm::Type *ReturnTy = CGM.getTypes().ConvertType(E->getType());
+  const llvm::Type *ReturnTy = CGM.getTypes().ConvertType(ResultType);
   return CGF.EmitCall(ObjCTypes.getMessageSendFn(IsSuper, ReturnTy),
-                      E->getType(),
-                      ActualArgs);
+                      ResultType, ActualArgs);
 }
 
 llvm::Value *CGObjCMac::GenerateProtocolRef(llvm::IRBuilder<> &Builder, 
diff --git a/lib/CodeGen/CGObjCRuntime.h b/lib/CodeGen/CGObjCRuntime.h
index 54591a3..c0044e9 100644
--- a/lib/CodeGen/CGObjCRuntime.h
+++ b/lib/CodeGen/CGObjCRuntime.h
@@ -81,7 +81,8 @@
   /// Generate an Objective-C message send operation.
   virtual CodeGen::RValue 
   GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
-                      const ObjCMessageExpr *E,
+                      QualType ResultType,
+                      Selector Sel,
                       llvm::Value *Receiver,
                       bool IsClassMessage,
                       const CallArgList &CallArgs) = 0;
@@ -91,7 +92,8 @@
   /// object.
   virtual CodeGen::RValue
   GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
-                           const ObjCMessageExpr *E,
+                           QualType ResultType,
+                           Selector Sel,
                            const ObjCInterfaceDecl *Class,
                            llvm::Value *Self,
                            bool IsClassMessage,
diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h
index e00c665..c8421e6 100644
--- a/lib/CodeGen/CodeGenFunction.h
+++ b/lib/CodeGen/CodeGenFunction.h
@@ -299,8 +299,22 @@
   //                         Scalar Expression Emission
   //===--------------------------------------------------------------------===//
 
+  /// CallArgList - Type for representing both the value and type of
+  /// arguments in a call.
   typedef llvm::SmallVector<std::pair<llvm::Value*, QualType>, 16> CallArgList;
+
+  /// EmitCallArg - Emit the given expression and append the result
+  /// onto the given Args list.
   void EmitCallArg(const Expr *E, CallArgList &Args);
+
+  /// EmitCallArg - Append the appropriate call argument for the given
+  /// rvalue and type onto the Args list.
+  void EmitCallArg(RValue RV, QualType Ty, CallArgList &Args);
+
+  /// EmitCall - Generate a call of the given function, expecting the
+  /// given result type, and using the given argument list which
+  /// specifies both the LLVM arguments and the types they were
+  /// derived from.
   RValue EmitCall(llvm::Value *Callee,
                   QualType ResultType,
                   const CallArgList &Args);
@@ -366,6 +380,10 @@
   /// of complex type, storing into the specified Value*.
   void EmitComplexExprIntoAddr(const Expr *E, llvm::Value *DestAddr,
                                bool DestIsVolatile);
+
+  /// StoreComplexToAddr - Store a complex number into the specified address.
+  void StoreComplexToAddr(ComplexPairTy V, llvm::Value *DestAddr,
+                          bool DestIsVolatile);
   /// LoadComplexFromAddr - Load a complex number from the specified address.
   ComplexPairTy LoadComplexFromAddr(llvm::Value *SrcAddr, bool SrcIsVolatile);
 
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index 5169ce1..ba13e7f 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -869,7 +869,11 @@
     
     // FIXME: The logic for looking up nullary and unary selectors should be
     // shared with the code in ActOnInstanceMessage.
-    
+
+    // FIXME: This logic is not correct, we should search for
+    // properties first. Additionally, the AST node doesn't currently
+    // have enough information to store the setter argument.
+#if 0
     // Before we look for explicit property declarations, we check for
     // nullary methods (which allow '.' notation).
     Selector Sel = PP.getSelectorTable().getNullarySelector(&Member);
@@ -886,6 +890,7 @@
             return new ObjCPropertyRefExpr(MD, MD->getResultType(), 
                                            MemberLoc, BaseExpr);
     }      
+#endif
     
     // FIXME: Need to deal with setter methods that take 1 argument. E.g.:
     // @interface NSBundle : NSObject {}