Objective-C @synthesize support.
 - Only supports simple assignment and atomic semantics are ignored.
 - Not quite usable yet because the methods do not actually get added
   to the class metadata.
 - Added ObjCPropertyDecl::getSetterKind (one of Assign, Copy, Retain).
 - Rearrange CodeGenFunction so synthesis can reuse function prolog /
   epilog code.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@55365 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/CodeGen/CGObjC.cpp b/lib/CodeGen/CGObjC.cpp
index ddd7c81..93567a4 100644
--- a/lib/CodeGen/CGObjC.cpp
+++ b/lib/CodeGen/CGObjC.cpp
@@ -88,9 +88,12 @@
   return Runtime.GenerateMessageSend(*this, E, Receiver, isClassMessage);
 }
 
-/// Generate an Objective-C method.  An Objective-C method is a C function with
-/// its pointer, name, and types registered in the class struture.  
-void CodeGenFunction::GenerateObjCMethod(const ObjCMethodDecl *OMD) {
+/// StartObjCMethod - Begin emission of an ObjCMethod. This generates
+/// the LLVM function and sets the other context used by
+/// CodeGenFunction.
+
+// FIXME: This should really be merged with GenerateCode.
+void CodeGenFunction::StartObjCMethod(const ObjCMethodDecl *OMD) {
   CurFn = CGM.getObjCRuntime().GenerateMethod(OMD);
   llvm::BasicBlock *EntryBB = llvm::BasicBlock::Create("entry", CurFn);
   
@@ -127,8 +130,87 @@
     EmitParmDecl(*OMD->getParamDecl(i), AI);
   }
   assert(AI == CurFn->arg_end() && "Argument mismatch");
+}
 
-  GenerateFunction(OMD->getBody());
+/// Generate an Objective-C method.  An Objective-C method is a C function with
+/// its pointer, name, and types registered in the class struture.  
+void CodeGenFunction::GenerateObjCMethod(const ObjCMethodDecl *OMD) {
+  StartObjCMethod(OMD);
+  EmitStmt(OMD->getBody());
+
+  const CompoundStmt *S = dyn_cast<CompoundStmt>(OMD->getBody());
+  if (S) {
+    FinishFunction(S->getRBracLoc());
+  } else {
+    FinishFunction();
+  }
+}
+
+// FIXME: I wasn't sure about the synthesis approach. If we end up
+// generating an AST for the whole body we can just fall back to
+// having a GenerateFunction which takes the body Stmt.
+
+/// GenerateObjCGetter - Generate an Objective-C property getter
+/// function. The given Decl must be either an ObjCCategoryImplDecl
+/// or an ObjCImplementationDecl.
+void CodeGenFunction::GenerateObjCGetter(const ObjCPropertyImplDecl *PID) {
+  const ObjCPropertyDecl *PD = PID->getPropertyDecl();
+  ObjCMethodDecl *OMD = PD->getGetterMethodDecl();
+  assert(OMD && "Invalid call to generate getter (empty method)");
+  // FIXME: This is rather murky, we create this here since they will
+  // not have been created by Sema for us.
+  OMD->createImplicitParams(getContext());
+  StartObjCMethod(OMD);
+
+  // FIXME: What about nonatomic?
+  SourceLocation Loc = PD->getLocation();
+  ValueDecl *Self = OMD->getSelfDecl();
+  ObjCIvarDecl *Ivar = PID->getPropertyIvarDecl();
+  DeclRefExpr Base(Self, Self->getType(), Loc);
+  ObjCIvarRefExpr IvarRef(Ivar, Ivar->getType(), Loc, &Base,
+                          true, true);
+  ReturnStmt Return(Loc, &IvarRef);
+  EmitStmt(&Return);
+
+  FinishFunction();
+}
+
+/// GenerateObjCSetter - Generate an Objective-C property setter
+/// function. The given Decl must be either an ObjCCategoryImplDecl
+/// or an ObjCImplementationDecl.
+void CodeGenFunction::GenerateObjCSetter(const ObjCPropertyImplDecl *PID) {
+  const ObjCPropertyDecl *PD = PID->getPropertyDecl();
+  ObjCMethodDecl *OMD = PD->getSetterMethodDecl();
+  assert(OMD && "Invalid call to generate setter (empty method)");
+  // FIXME: This is rather murky, we create this here since they will
+  // not have been created by Sema for us.  
+  OMD->createImplicitParams(getContext());
+  StartObjCMethod(OMD);
+  
+  switch (PD->getSetterKind()) {
+  case ObjCPropertyDecl::Assign: break;
+  case ObjCPropertyDecl::Copy:
+      CGM.ErrorUnsupported(PID, "Obj-C setter with 'copy'");
+      break;
+  case ObjCPropertyDecl::Retain:
+      CGM.ErrorUnsupported(PID, "Obj-C setter with 'retain'");
+      break;
+  }
+
+  // FIXME: What about nonatomic?
+  SourceLocation Loc = PD->getLocation();
+  ValueDecl *Self = OMD->getSelfDecl();
+  ObjCIvarDecl *Ivar = PID->getPropertyIvarDecl();
+  DeclRefExpr Base(Self, Self->getType(), Loc);
+  ParmVarDecl *ArgDecl = OMD->getParamDecl(0);
+  DeclRefExpr Arg(ArgDecl, ArgDecl->getType(), Loc);
+  ObjCIvarRefExpr IvarRef(Ivar, Ivar->getType(), Loc, &Base,
+                          true, true);
+  BinaryOperator Assign(&IvarRef, &Arg, BinaryOperator::Assign,
+                        Ivar->getType(), Loc);
+  EmitStmt(&Assign);
+
+  FinishFunction();
 }
 
 llvm::Value *CodeGenFunction::LoadObjCSelf(void) {