[cfe-commits] r146160 - /cfe/trunk/lib/Rewrite/RewriteObjC.cpp

Fariborz Jahanian fjahanian at apple.com
Thu Dec 8 12:25:15 CST 2011


Author: fjahanian
Date: Thu Dec  8 12:25:15 2011
New Revision: 146160

URL: http://llvm.org/viewvc/llvm-project?rev=146160&view=rev
Log:
More refactoring of objective-C rewriter.


Modified:
    cfe/trunk/lib/Rewrite/RewriteObjC.cpp

Modified: cfe/trunk/lib/Rewrite/RewriteObjC.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Rewrite/RewriteObjC.cpp?rev=146160&r1=146159&r2=146160&view=diff
==============================================================================
--- cfe/trunk/lib/Rewrite/RewriteObjC.cpp (original)
+++ cfe/trunk/lib/Rewrite/RewriteObjC.cpp Thu Dec  8 12:25:15 2011
@@ -32,6 +32,8 @@
 
 namespace {
   class RewriteObjC : public ASTConsumer {
+  protected:
+    
     enum {
       BLOCK_FIELD_IS_OBJECT   =  3,  /* id, NSObject, __attribute__((NSObject)),
                                         block, ... */
@@ -54,7 +56,7 @@
       BLOCK_HAS_DESCRIPTOR =    (1 << 29)
     };
     static const int OBJC_ABI_VERSION = 7;
-
+    
     Rewriter Rewrite;
     DiagnosticsEngine &Diags;
     const LangOptions &LangOpts;
@@ -72,7 +74,6 @@
     TypeDecl *ProtocolTypeDecl;
     VarDecl *GlobalVarDecl;
     unsigned RewriteFailedDiag;
-    unsigned TryFinallyContainsReturnDiag;
     // ObjC string constant support.
     unsigned NumObjCStringLiterals;
     VarDecl *ConstantStringClassReference;
@@ -81,6 +82,7 @@
     // ObjC foreach break/continue generation support.
     int BcLabelCount;
     
+    unsigned TryFinallyContainsReturnDiag;
     // Needed for super.
     ObjCMethodDecl *CurMethodDef;
     RecordDecl *SuperStructDecl;
@@ -156,9 +158,9 @@
         R.DisableReplaceStmt = SavedValue;
       }
     };
+    void InitializeCommon(ASTContext &context);
 
   public:
-    virtual void Initialize(ASTContext &context);
 
     // Top Level Driver code.
     virtual bool HandleTopLevelDecl(DeclGroupRef D) {
@@ -284,7 +286,6 @@
     // Expression Rewriting.
     Stmt *RewriteFunctionBodyOrGlobalInitializer(Stmt *S);
     Stmt *RewriteAtEncode(ObjCEncodeExpr *Exp);
-    Stmt *RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV);
     Stmt *RewritePropertyOrImplicitGetter(PseudoObjectExpr *Pseudo);
     Stmt *RewritePropertyOrImplicitSetter(PseudoObjectExpr *Pseudo);
     Stmt *RewriteAtSelector(ObjCSelectorExpr *Exp);
@@ -301,31 +302,7 @@
     Stmt *RewriteBreakStmt(BreakStmt *S);
     Stmt *RewriteContinueStmt(ContinueStmt *S);
     void RewriteCastExpr(CStyleCastExpr *CE);
-
-    // Metadata Rewriting.
-    void RewriteMetaDataIntoBuffer(std::string &Result);
-    void RewriteObjCClassMetaData(ObjCImplementationDecl *IDecl,
-                                  std::string &Result);
-
-    void RewriteObjCCategoryImplDecl(ObjCCategoryImplDecl *CDecl,
-                                     std::string &Result);
-
-    template<typename MethodIterator>
-    void RewriteObjCMethodsMetaData(MethodIterator MethodBegin,
-                                    MethodIterator MethodEnd,
-                                    bool IsInstanceMethod,
-                                    StringRef prefix,
-                                    StringRef ClassName,
-                                    std::string &Result);
-
-    void RewriteObjCProtocolMetaData(ObjCProtocolDecl *Protocol,
-                                     StringRef prefix,
-                                     StringRef ClassName,
-                                     std::string &Result);
-    void RewriteObjCProtocolListMetaData(const ObjCList<ObjCProtocolDecl> &Prots,
-                                         StringRef prefix,
-                                         StringRef ClassName,
-                                         std::string &Result);
+    
     // Block rewriting.
     void RewriteBlocksInFunctionProtoType(QualType funcType, NamedDecl *D);
     
@@ -338,8 +315,28 @@
     
     void RewriteObjCInternalStruct(ObjCInterfaceDecl *CDecl,
                                       std::string &Result);
-    void RewriteIvarOffsetComputation(ObjCIvarDecl *ivar,
-                                         std::string &Result);
+    
+    virtual void Initialize(ASTContext &context) = 0;
+    
+    // Metadata Rewriting.
+    virtual void RewriteMetaDataIntoBuffer(std::string &Result) = 0;
+    virtual void RewriteObjCProtocolListMetaData(const ObjCList<ObjCProtocolDecl> &Prots,
+                                                 StringRef prefix,
+                                                 StringRef ClassName,
+                                                 std::string &Result) = 0;
+    virtual void RewriteObjCCategoryImplDecl(ObjCCategoryImplDecl *CDecl,
+                                             std::string &Result) = 0;
+    virtual void RewriteObjCProtocolMetaData(ObjCProtocolDecl *Protocol,
+                                     StringRef prefix,
+                                     StringRef ClassName,
+                                     std::string &Result) = 0;
+    virtual void RewriteObjCClassMetaData(ObjCImplementationDecl *IDecl,
+                                          std::string &Result) = 0;
+    
+    // Rewriting ivar access
+    virtual Stmt *RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV) = 0;
+    virtual void RewriteIvarOffsetComputation(ObjCIvarDecl *ivar,
+                                         std::string &Result) = 0;
     
     // Misc. AST transformation routines. Somtimes they end up calling
     // rewriting routines on the new ASTs.
@@ -488,6 +485,45 @@
                                     SourceLocation(), SourceLocation());
     }
   };
+  
+  class RewriteObjCFragileABI : public RewriteObjC {
+  public:
+    
+    RewriteObjCFragileABI(std::string inFile, raw_ostream *OS,
+                DiagnosticsEngine &D, const LangOptions &LOpts,
+                bool silenceMacroWarn) : RewriteObjC(inFile, OS,
+                                                     D, LOpts,
+                                                     silenceMacroWarn) {}
+    
+    ~RewriteObjCFragileABI() {}
+    virtual void Initialize(ASTContext &context);
+    
+    // Rewriting metadata
+    template<typename MethodIterator>
+    void RewriteObjCMethodsMetaData(MethodIterator MethodBegin,
+                                    MethodIterator MethodEnd,
+                                    bool IsInstanceMethod,
+                                    StringRef prefix,
+                                    StringRef ClassName,
+                                    std::string &Result);
+    virtual void RewriteObjCProtocolMetaData(ObjCProtocolDecl *Protocol,
+                                             StringRef prefix,
+                                             StringRef ClassName,
+                                             std::string &Result);
+    virtual void RewriteObjCProtocolListMetaData(
+                  const ObjCList<ObjCProtocolDecl> &Prots,
+                  StringRef prefix, StringRef ClassName, std::string &Result);
+    virtual void RewriteObjCClassMetaData(ObjCImplementationDecl *IDecl,
+                                          std::string &Result);
+    virtual void RewriteMetaDataIntoBuffer(std::string &Result);
+    virtual void RewriteObjCCategoryImplDecl(ObjCCategoryImplDecl *CDecl,
+                                             std::string &Result);
+    
+    // Rewriting ivar
+    virtual void RewriteIvarOffsetComputation(ObjCIvarDecl *ivar,
+                                              std::string &Result);
+    virtual Stmt *RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV);
+  };
 }
 
 void RewriteObjC::RewriteBlocksInFunctionProtoType(QualType funcType,
@@ -543,10 +579,15 @@
                                        DiagnosticsEngine &Diags,
                                        const LangOptions &LOpts,
                                        bool SilenceRewriteMacroWarning) {
-  return new RewriteObjC(InFile, OS, Diags, LOpts, SilenceRewriteMacroWarning);
+  if (true /*!LOpts.ObjCNonFragileABI*/)
+    return new RewriteObjCFragileABI(InFile, OS, Diags, LOpts, SilenceRewriteMacroWarning);
+  else {
+    assert(false && "objective-C rewriter for nonfragile ABI = NYI");
+    return 0;
+  }
 }
 
-void RewriteObjC::Initialize(ASTContext &context) {
+void RewriteObjC::InitializeCommon(ASTContext &context) {
   Context = &context;
   SM = &Context->getSourceManager();
   TUDecl = Context->getTranslationUnitDecl();
@@ -584,120 +625,8 @@
   MainFileEnd = MainBuf->getBufferEnd();
 
   Rewrite.setSourceMgr(Context->getSourceManager(), Context->getLangOptions());
-
-  // declaring objc_selector outside the parameter list removes a silly
-  // scope related warning...
-  if (IsHeader)
-    Preamble = "#pragma once\n";
-  Preamble += "struct objc_selector; struct objc_class;\n";
-  Preamble += "struct __rw_objc_super { struct objc_object *object; ";
-  Preamble += "struct objc_object *superClass; ";
-  if (LangOpts.MicrosoftExt) {
-    // Add a constructor for creating temporary objects.
-    Preamble += "__rw_objc_super(struct objc_object *o, struct objc_object *s) "
-                ": ";
-    Preamble += "object(o), superClass(s) {} ";
-  }
-  Preamble += "};\n";
-  Preamble += "#ifndef _REWRITER_typedef_Protocol\n";
-  Preamble += "typedef struct objc_object Protocol;\n";
-  Preamble += "#define _REWRITER_typedef_Protocol\n";
-  Preamble += "#endif\n";
-  if (LangOpts.MicrosoftExt) {
-    Preamble += "#define __OBJC_RW_DLLIMPORT extern \"C\" __declspec(dllimport)\n";
-    Preamble += "#define __OBJC_RW_STATICIMPORT extern \"C\"\n";
-  } else
-  Preamble += "#define __OBJC_RW_DLLIMPORT extern\n";
-  Preamble += "__OBJC_RW_DLLIMPORT struct objc_object *objc_msgSend";
-  Preamble += "(struct objc_object *, struct objc_selector *, ...);\n";
-  Preamble += "__OBJC_RW_DLLIMPORT struct objc_object *objc_msgSendSuper";
-  Preamble += "(struct objc_super *, struct objc_selector *, ...);\n";
-  Preamble += "__OBJC_RW_DLLIMPORT struct objc_object* objc_msgSend_stret";
-  Preamble += "(struct objc_object *, struct objc_selector *, ...);\n";
-  Preamble += "__OBJC_RW_DLLIMPORT struct objc_object* objc_msgSendSuper_stret";
-  Preamble += "(struct objc_super *, struct objc_selector *, ...);\n";
-  Preamble += "__OBJC_RW_DLLIMPORT double objc_msgSend_fpret";
-  Preamble += "(struct objc_object *, struct objc_selector *, ...);\n";
-  Preamble += "__OBJC_RW_DLLIMPORT struct objc_object *objc_getClass";
-  Preamble += "(const char *);\n";
-  Preamble += "__OBJC_RW_DLLIMPORT struct objc_class *class_getSuperclass";
-  Preamble += "(struct objc_class *);\n";
-  Preamble += "__OBJC_RW_DLLIMPORT struct objc_object *objc_getMetaClass";
-  Preamble += "(const char *);\n";
-  Preamble += "__OBJC_RW_DLLIMPORT void objc_exception_throw(struct objc_object *);\n";
-  Preamble += "__OBJC_RW_DLLIMPORT void objc_exception_try_enter(void *);\n";
-  Preamble += "__OBJC_RW_DLLIMPORT void objc_exception_try_exit(void *);\n";
-  Preamble += "__OBJC_RW_DLLIMPORT struct objc_object *objc_exception_extract(void *);\n";
-  Preamble += "__OBJC_RW_DLLIMPORT int objc_exception_match";
-  Preamble += "(struct objc_class *, struct objc_object *);\n";
-  // @synchronized hooks.
-  Preamble += "__OBJC_RW_DLLIMPORT void objc_sync_enter(struct objc_object *);\n";
-  Preamble += "__OBJC_RW_DLLIMPORT void objc_sync_exit(struct objc_object *);\n";
-  Preamble += "__OBJC_RW_DLLIMPORT Protocol *objc_getProtocol(const char *);\n";
-  Preamble += "#ifndef __FASTENUMERATIONSTATE\n";
-  Preamble += "struct __objcFastEnumerationState {\n\t";
-  Preamble += "unsigned long state;\n\t";
-  Preamble += "void **itemsPtr;\n\t";
-  Preamble += "unsigned long *mutationsPtr;\n\t";
-  Preamble += "unsigned long extra[5];\n};\n";
-  Preamble += "__OBJC_RW_DLLIMPORT void objc_enumerationMutation(struct objc_object *);\n";
-  Preamble += "#define __FASTENUMERATIONSTATE\n";
-  Preamble += "#endif\n";
-  Preamble += "#ifndef __NSCONSTANTSTRINGIMPL\n";
-  Preamble += "struct __NSConstantStringImpl {\n";
-  Preamble += "  int *isa;\n";
-  Preamble += "  int flags;\n";
-  Preamble += "  char *str;\n";
-  Preamble += "  long length;\n";
-  Preamble += "};\n";
-  Preamble += "#ifdef CF_EXPORT_CONSTANT_STRING\n";
-  Preamble += "extern \"C\" __declspec(dllexport) int __CFConstantStringClassReference[];\n";
-  Preamble += "#else\n";
-  Preamble += "__OBJC_RW_DLLIMPORT int __CFConstantStringClassReference[];\n";
-  Preamble += "#endif\n";
-  Preamble += "#define __NSCONSTANTSTRINGIMPL\n";
-  Preamble += "#endif\n";
-  // Blocks preamble.
-  Preamble += "#ifndef BLOCK_IMPL\n";
-  Preamble += "#define BLOCK_IMPL\n";
-  Preamble += "struct __block_impl {\n";
-  Preamble += "  void *isa;\n";
-  Preamble += "  int Flags;\n";
-  Preamble += "  int Reserved;\n";
-  Preamble += "  void *FuncPtr;\n";
-  Preamble += "};\n";
-  Preamble += "// Runtime copy/destroy helper functions (from Block_private.h)\n";
-  Preamble += "#ifdef __OBJC_EXPORT_BLOCKS\n";
-  Preamble += "extern \"C\" __declspec(dllexport) "
-              "void _Block_object_assign(void *, const void *, const int);\n";
-  Preamble += "extern \"C\" __declspec(dllexport) void _Block_object_dispose(const void *, const int);\n";
-  Preamble += "extern \"C\" __declspec(dllexport) void *_NSConcreteGlobalBlock[32];\n";
-  Preamble += "extern \"C\" __declspec(dllexport) void *_NSConcreteStackBlock[32];\n";
-  Preamble += "#else\n";
-  Preamble += "__OBJC_RW_DLLIMPORT void _Block_object_assign(void *, const void *, const int);\n";
-  Preamble += "__OBJC_RW_DLLIMPORT void _Block_object_dispose(const void *, const int);\n";
-  Preamble += "__OBJC_RW_DLLIMPORT void *_NSConcreteGlobalBlock[32];\n";
-  Preamble += "__OBJC_RW_DLLIMPORT void *_NSConcreteStackBlock[32];\n";
-  Preamble += "#endif\n";
-  Preamble += "#endif\n";
-  if (LangOpts.MicrosoftExt) {
-    Preamble += "#undef __OBJC_RW_DLLIMPORT\n";
-    Preamble += "#undef __OBJC_RW_STATICIMPORT\n";
-    Preamble += "#ifndef KEEP_ATTRIBUTES\n";  // We use this for clang tests.
-    Preamble += "#define __attribute__(X)\n";
-    Preamble += "#endif\n";
-    Preamble += "#define __weak\n";
-  }
-  else {
-    Preamble += "#define __block\n";
-    Preamble += "#define __weak\n";
-  }
-  // NOTE! Windows uses LLP64 for 64bit mode. So, cast pointer to long long
-  // as this avoids warning in any 64bit/32bit compilation model.
-  Preamble += "\n#define __OFFSETOFIVAR__(TYPE, MEMBER) ((long long) &((TYPE *)0)->MEMBER)\n";
 }
 
-
 //===----------------------------------------------------------------------===//
 // Top Level Driver Code
 //===----------------------------------------------------------------------===//
@@ -1436,98 +1365,6 @@
   return Replacement;
 }
 
-Stmt *RewriteObjC::RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV) {
-  SourceRange OldRange = IV->getSourceRange();
-  Expr *BaseExpr = IV->getBase();
-
-  // Rewrite the base, but without actually doing replaces.
-  {
-    DisableReplaceStmtScope S(*this);
-    BaseExpr = cast<Expr>(RewriteFunctionBodyOrGlobalInitializer(BaseExpr));
-    IV->setBase(BaseExpr);
-  }
-
-  ObjCIvarDecl *D = IV->getDecl();
-
-  Expr *Replacement = IV;
-  if (CurMethodDef) {
-    if (BaseExpr->getType()->isObjCObjectPointerType()) {
-      const ObjCInterfaceType *iFaceDecl =
-        dyn_cast<ObjCInterfaceType>(BaseExpr->getType()->getPointeeType());
-      assert(iFaceDecl && "RewriteObjCIvarRefExpr - iFaceDecl is null");
-      // lookup which class implements the instance variable.
-      ObjCInterfaceDecl *clsDeclared = 0;
-      iFaceDecl->getDecl()->lookupInstanceVariable(D->getIdentifier(),
-                                                   clsDeclared);
-      assert(clsDeclared && "RewriteObjCIvarRefExpr(): Can't find class");
-
-      // Synthesize an explicit cast to gain access to the ivar.
-      std::string RecName = clsDeclared->getIdentifier()->getName();
-      RecName += "_IMPL";
-      IdentifierInfo *II = &Context->Idents.get(RecName);
-      RecordDecl *RD = RecordDecl::Create(*Context, TTK_Struct, TUDecl,
-                                          SourceLocation(), SourceLocation(),
-                                          II);
-      assert(RD && "RewriteObjCIvarRefExpr(): Can't find RecordDecl");
-      QualType castT = Context->getPointerType(Context->getTagDeclType(RD));
-      CastExpr *castExpr = NoTypeInfoCStyleCastExpr(Context, castT,
-                                                    CK_BitCast,
-                                                    IV->getBase());
-      // Don't forget the parens to enforce the proper binding.
-      ParenExpr *PE = new (Context) ParenExpr(OldRange.getBegin(),
-                                              OldRange.getEnd(),
-                                              castExpr);
-      if (IV->isFreeIvar() &&
-          CurMethodDef->getClassInterface() == iFaceDecl->getDecl()) {
-        MemberExpr *ME = new (Context) MemberExpr(PE, true, D,
-                                                  IV->getLocation(),
-                                                  D->getType(),
-                                                  VK_LValue, OK_Ordinary);
-        Replacement = ME;
-      } else {
-        IV->setBase(PE);
-      }
-    }
-  } else { // we are outside a method.
-    assert(!IV->isFreeIvar() && "Cannot have a free standing ivar outside a method");
-
-    // Explicit ivar refs need to have a cast inserted.
-    // FIXME: consider sharing some of this code with the code above.
-    if (BaseExpr->getType()->isObjCObjectPointerType()) {
-      const ObjCInterfaceType *iFaceDecl =
-        dyn_cast<ObjCInterfaceType>(BaseExpr->getType()->getPointeeType());
-      // lookup which class implements the instance variable.
-      ObjCInterfaceDecl *clsDeclared = 0;
-      iFaceDecl->getDecl()->lookupInstanceVariable(D->getIdentifier(),
-                                                   clsDeclared);
-      assert(clsDeclared && "RewriteObjCIvarRefExpr(): Can't find class");
-
-      // Synthesize an explicit cast to gain access to the ivar.
-      std::string RecName = clsDeclared->getIdentifier()->getName();
-      RecName += "_IMPL";
-      IdentifierInfo *II = &Context->Idents.get(RecName);
-      RecordDecl *RD = RecordDecl::Create(*Context, TTK_Struct, TUDecl,
-                                          SourceLocation(), SourceLocation(),
-                                          II);
-      assert(RD && "RewriteObjCIvarRefExpr(): Can't find RecordDecl");
-      QualType castT = Context->getPointerType(Context->getTagDeclType(RD));
-      CastExpr *castExpr = NoTypeInfoCStyleCastExpr(Context, castT,
-                                                    CK_BitCast,
-                                                    IV->getBase());
-      // Don't forget the parens to enforce the proper binding.
-      ParenExpr *PE = new (Context) ParenExpr(IV->getBase()->getLocStart(),
-                                    IV->getBase()->getLocEnd(), castExpr);
-      // Cannot delete IV->getBase(), since PE points to it.
-      // Replace the old base with the cast. This is important when doing
-      // embedded rewrites. For example, [newInv->_container addObject:0].
-      IV->setBase(PE);
-    }
-  }
-
-  ReplaceStmtWithRange(IV, Replacement, OldRange);
-  return Replacement;  
-}
-
 /// SynthCountByEnumWithState - To print:
 /// ((unsigned int (*)
 ///  (id, SEL, struct __objcFastEnumerationState *, id *, unsigned int))
@@ -3405,2541 +3242,2749 @@
     llvm_unreachable("struct already synthesize- SynthesizeObjCInternalStruct");
 }
 
-// RewriteObjCMethodsMetaData - Rewrite methods metadata for instance or
-/// class methods.
-template<typename MethodIterator>
-void RewriteObjC::RewriteObjCMethodsMetaData(MethodIterator MethodBegin,
-                                             MethodIterator MethodEnd,
-                                             bool IsInstanceMethod,
-                                             StringRef prefix,
-                                             StringRef ClassName,
-                                             std::string &Result) {
-  if (MethodBegin == MethodEnd) return;
+//===----------------------------------------------------------------------===//
+// Meta Data Emission
+//===----------------------------------------------------------------------===//
 
-  if (!objc_impl_method) {
-    /* struct _objc_method {
-       SEL _cmd;
-       char *method_types;
-       void *_imp;
-       }
-     */
-    Result += "\nstruct _objc_method {\n";
-    Result += "\tSEL _cmd;\n";
-    Result += "\tchar *method_types;\n";
-    Result += "\tvoid *_imp;\n";
-    Result += "};\n";
 
-    objc_impl_method = true;
-  }
+/// RewriteImplementations - This routine rewrites all method implementations
+/// and emits meta-data.
 
-  // Build _objc_method_list for class's methods if needed
+void RewriteObjC::RewriteImplementations() {
+  int ClsDefCount = ClassImplementation.size();
+  int CatDefCount = CategoryImplementation.size();
 
-  /* struct  {
-   struct _objc_method_list *next_method;
-   int method_count;
-   struct _objc_method method_list[];
-   }
-   */
-  unsigned NumMethods = std::distance(MethodBegin, MethodEnd);
-  Result += "\nstatic struct {\n";
-  Result += "\tstruct _objc_method_list *next_method;\n";
-  Result += "\tint method_count;\n";
-  Result += "\tstruct _objc_method method_list[";
-  Result += utostr(NumMethods);
-  Result += "];\n} _OBJC_";
-  Result += prefix;
-  Result += IsInstanceMethod ? "INSTANCE" : "CLASS";
-  Result += "_METHODS_";
-  Result += ClassName;
-  Result += " __attribute__ ((used, section (\"__OBJC, __";
-  Result += IsInstanceMethod ? "inst" : "cls";
-  Result += "_meth\")))= ";
-  Result += "{\n\t0, " + utostr(NumMethods) + "\n";
+  // Rewrite implemented methods
+  for (int i = 0; i < ClsDefCount; i++)
+    RewriteImplementationDecl(ClassImplementation[i]);
 
-  Result += "\t,{{(SEL)\"";
-  Result += (*MethodBegin)->getSelector().getAsString().c_str();
-  std::string MethodTypeString;
-  Context->getObjCEncodingForMethodDecl(*MethodBegin, MethodTypeString);
-  Result += "\", \"";
-  Result += MethodTypeString;
-  Result += "\", (void *)";
-  Result += MethodInternalNames[*MethodBegin];
-  Result += "}\n";
-  for (++MethodBegin; MethodBegin != MethodEnd; ++MethodBegin) {
-    Result += "\t  ,{(SEL)\"";
-    Result += (*MethodBegin)->getSelector().getAsString().c_str();
-    std::string MethodTypeString;
-    Context->getObjCEncodingForMethodDecl(*MethodBegin, MethodTypeString);
-    Result += "\", \"";
-    Result += MethodTypeString;
-    Result += "\", (void *)";
-    Result += MethodInternalNames[*MethodBegin];
-    Result += "}\n";
-  }
-  Result += "\t }\n};\n";
+  for (int i = 0; i < CatDefCount; i++)
+    RewriteImplementationDecl(CategoryImplementation[i]);
 }
 
-/// RewriteObjCProtocolMetaData - Rewrite protocols meta-data.
-void RewriteObjC::
-RewriteObjCProtocolMetaData(ObjCProtocolDecl *PDecl, StringRef prefix,
-                            StringRef ClassName, std::string &Result) {
-  static bool objc_protocol_methods = false;
+void RewriteObjC::RewriteByRefString(std::string &ResultStr, 
+                                     const std::string &Name,
+                                     ValueDecl *VD, bool def) {
+  assert(BlockByRefDeclNo.count(VD) && 
+         "RewriteByRefString: ByRef decl missing");
+  if (def)
+    ResultStr += "struct ";
+  ResultStr += "__Block_byref_" + Name + 
+    "_" + utostr(BlockByRefDeclNo[VD]) ;
+}
 
-  // Output struct protocol_methods holder of method selector and type.
-  if (!objc_protocol_methods && !PDecl->isForwardDecl()) {
-    /* struct protocol_methods {
-     SEL _cmd;
-     char *method_types;
-     }
-     */
-    Result += "\nstruct _protocol_methods {\n";
-    Result += "\tstruct objc_selector *_cmd;\n";
-    Result += "\tchar *method_types;\n";
-    Result += "};\n";
+static bool HasLocalVariableExternalStorage(ValueDecl *VD) {
+  if (VarDecl *Var = dyn_cast<VarDecl>(VD))
+    return (Var->isFunctionOrMethodVarDecl() && !Var->hasLocalStorage());
+  return false;
+}
 
-    objc_protocol_methods = true;
-  }
-  // Do not synthesize the protocol more than once.
-  if (ObjCSynthesizedProtocols.count(PDecl))
-    return;
+std::string RewriteObjC::SynthesizeBlockFunc(BlockExpr *CE, int i,
+                                                   StringRef funcName,
+                                                   std::string Tag) {
+  const FunctionType *AFT = CE->getFunctionType();
+  QualType RT = AFT->getResultType();
+  std::string StructRef = "struct " + Tag;
+  std::string S = "static " + RT.getAsString(Context->getPrintingPolicy()) + " __" +
+                  funcName.str() + "_" + "block_func_" + utostr(i);
 
-    if (PDecl->instmeth_begin() != PDecl->instmeth_end()) {
-      unsigned NumMethods = std::distance(PDecl->instmeth_begin(),
-                                          PDecl->instmeth_end());
-    /* struct _objc_protocol_method_list {
-     int protocol_method_count;
-     struct protocol_methods protocols[];
-     }
-     */
-    Result += "\nstatic struct {\n";
-    Result += "\tint protocol_method_count;\n";
-    Result += "\tstruct _protocol_methods protocol_methods[";
-    Result += utostr(NumMethods);
-    Result += "];\n} _OBJC_PROTOCOL_INSTANCE_METHODS_";
-    Result += PDecl->getNameAsString();
-    Result += " __attribute__ ((used, section (\"__OBJC, __cat_inst_meth\")))= "
-      "{\n\t" + utostr(NumMethods) + "\n";
+  BlockDecl *BD = CE->getBlockDecl();
 
-    // Output instance methods declared in this protocol.
-    for (ObjCProtocolDecl::instmeth_iterator
-           I = PDecl->instmeth_begin(), E = PDecl->instmeth_end();
-         I != E; ++I) {
-      if (I == PDecl->instmeth_begin())
-        Result += "\t  ,{{(struct objc_selector *)\"";
+  if (isa<FunctionNoProtoType>(AFT)) {
+    // No user-supplied arguments. Still need to pass in a pointer to the
+    // block (to reference imported block decl refs).
+    S += "(" + StructRef + " *__cself)";
+  } else if (BD->param_empty()) {
+    S += "(" + StructRef + " *__cself)";
+  } else {
+    const FunctionProtoType *FT = cast<FunctionProtoType>(AFT);
+    assert(FT && "SynthesizeBlockFunc: No function proto");
+    S += '(';
+    // first add the implicit argument.
+    S += StructRef + " *__cself, ";
+    std::string ParamStr;
+    for (BlockDecl::param_iterator AI = BD->param_begin(),
+         E = BD->param_end(); AI != E; ++AI) {
+      if (AI != BD->param_begin()) S += ", ";
+      ParamStr = (*AI)->getNameAsString();
+      QualType QT = (*AI)->getType();
+      if (convertBlockPointerToFunctionPointer(QT))
+        QT.getAsStringInternal(ParamStr, Context->getPrintingPolicy());
       else
-        Result += "\t  ,{(struct objc_selector *)\"";
-      Result += (*I)->getSelector().getAsString();
-      std::string MethodTypeString;
-      Context->getObjCEncodingForMethodDecl((*I), MethodTypeString);
-      Result += "\", \"";
-      Result += MethodTypeString;
-      Result += "\"}\n";
+        QT.getAsStringInternal(ParamStr, Context->getPrintingPolicy());      
+      S += ParamStr;
     }
-    Result += "\t }\n};\n";
+    if (FT->isVariadic()) {
+      if (!BD->param_empty()) S += ", ";
+      S += "...";
+    }
+    S += ')';
   }
+  S += " {\n";
 
-  // Output class methods declared in this protocol.
-  unsigned NumMethods = std::distance(PDecl->classmeth_begin(),
-                                      PDecl->classmeth_end());
-  if (NumMethods > 0) {
-    /* struct _objc_protocol_method_list {
-     int protocol_method_count;
-     struct protocol_methods protocols[];
-     }
-     */
-    Result += "\nstatic struct {\n";
-    Result += "\tint protocol_method_count;\n";
-    Result += "\tstruct _protocol_methods protocol_methods[";
-    Result += utostr(NumMethods);
-    Result += "];\n} _OBJC_PROTOCOL_CLASS_METHODS_";
-    Result += PDecl->getNameAsString();
-    Result += " __attribute__ ((used, section (\"__OBJC, __cat_cls_meth\")))= "
-           "{\n\t";
-    Result += utostr(NumMethods);
-    Result += "\n";
-
-    // Output instance methods declared in this protocol.
-    for (ObjCProtocolDecl::classmeth_iterator
-           I = PDecl->classmeth_begin(), E = PDecl->classmeth_end();
-         I != E; ++I) {
-      if (I == PDecl->classmeth_begin())
-        Result += "\t  ,{{(struct objc_selector *)\"";
-      else
-        Result += "\t  ,{(struct objc_selector *)\"";
-      Result += (*I)->getSelector().getAsString();
-      std::string MethodTypeString;
-      Context->getObjCEncodingForMethodDecl((*I), MethodTypeString);
-      Result += "\", \"";
-      Result += MethodTypeString;
-      Result += "\"}\n";
+  // Create local declarations to avoid rewriting all closure decl ref exprs.
+  // First, emit a declaration for all "by ref" decls.
+  for (SmallVector<ValueDecl*,8>::iterator I = BlockByRefDecls.begin(),
+       E = BlockByRefDecls.end(); I != E; ++I) {
+    S += "  ";
+    std::string Name = (*I)->getNameAsString();
+    std::string TypeString;
+    RewriteByRefString(TypeString, Name, (*I));
+    TypeString += " *";
+    Name = TypeString + Name;
+    S += Name + " = __cself->" + (*I)->getNameAsString() + "; // bound by ref\n";
+  }
+  // Next, emit a declaration for all "by copy" declarations.
+  for (SmallVector<ValueDecl*,8>::iterator I = BlockByCopyDecls.begin(),
+       E = BlockByCopyDecls.end(); I != E; ++I) {
+    S += "  ";
+    // Handle nested closure invocation. For example:
+    //
+    //   void (^myImportedClosure)(void);
+    //   myImportedClosure  = ^(void) { setGlobalInt(x + y); };
+    //
+    //   void (^anotherClosure)(void);
+    //   anotherClosure = ^(void) {
+    //     myImportedClosure(); // import and invoke the closure
+    //   };
+    //
+    if (isTopLevelBlockPointerType((*I)->getType())) {
+      RewriteBlockPointerTypeVariable(S, (*I));
+      S += " = (";
+      RewriteBlockPointerType(S, (*I)->getType());
+      S += ")";
+      S += "__cself->" + (*I)->getNameAsString() + "; // bound by copy\n";
+    }
+    else {
+      std::string Name = (*I)->getNameAsString();
+      QualType QT = (*I)->getType();
+      if (HasLocalVariableExternalStorage(*I))
+        QT = Context->getPointerType(QT);
+      QT.getAsStringInternal(Name, Context->getPrintingPolicy());
+      S += Name + " = __cself->" + 
+                              (*I)->getNameAsString() + "; // bound by copy\n";
     }
-    Result += "\t }\n};\n";
   }
+  std::string RewrittenStr = RewrittenBlockExprs[CE];
+  const char *cstr = RewrittenStr.c_str();
+  while (*cstr++ != '{') ;
+  S += cstr;
+  S += "\n";
+  return S;
+}
 
-  // Output:
-  /* struct _objc_protocol {
-   // Objective-C 1.0 extensions
-   struct _objc_protocol_extension *isa;
-   char *protocol_name;
-   struct _objc_protocol **protocol_list;
-   struct _objc_protocol_method_list *instance_methods;
-   struct _objc_protocol_method_list *class_methods;
-   };
-   */
-  static bool objc_protocol = false;
-  if (!objc_protocol) {
-    Result += "\nstruct _objc_protocol {\n";
-    Result += "\tstruct _objc_protocol_extension *isa;\n";
-    Result += "\tchar *protocol_name;\n";
-    Result += "\tstruct _objc_protocol **protocol_list;\n";
-    Result += "\tstruct _objc_protocol_method_list *instance_methods;\n";
-    Result += "\tstruct _objc_protocol_method_list *class_methods;\n";
-    Result += "};\n";
-
-    objc_protocol = true;
-  }
+std::string RewriteObjC::SynthesizeBlockHelperFuncs(BlockExpr *CE, int i,
+                                                   StringRef funcName,
+                                                   std::string Tag) {
+  std::string StructRef = "struct " + Tag;
+  std::string S = "static void __";
 
-  Result += "\nstatic struct _objc_protocol _OBJC_PROTOCOL_";
-  Result += PDecl->getNameAsString();
-  Result += " __attribute__ ((used, section (\"__OBJC, __protocol\")))= "
-    "{\n\t0, \"";
-  Result += PDecl->getNameAsString();
-  Result += "\", 0, ";
-  if (PDecl->instmeth_begin() != PDecl->instmeth_end()) {
-    Result += "(struct _objc_protocol_method_list *)&_OBJC_PROTOCOL_INSTANCE_METHODS_";
-    Result += PDecl->getNameAsString();
-    Result += ", ";
+  S += funcName;
+  S += "_block_copy_" + utostr(i);
+  S += "(" + StructRef;
+  S += "*dst, " + StructRef;
+  S += "*src) {";
+  for (llvm::SmallPtrSet<ValueDecl*,8>::iterator I = ImportedBlockDecls.begin(),
+      E = ImportedBlockDecls.end(); I != E; ++I) {
+    ValueDecl *VD = (*I);
+    S += "_Block_object_assign((void*)&dst->";
+    S += (*I)->getNameAsString();
+    S += ", (void*)src->";
+    S += (*I)->getNameAsString();
+    if (BlockByRefDeclsPtrSet.count((*I)))
+      S += ", " + utostr(BLOCK_FIELD_IS_BYREF) + "/*BLOCK_FIELD_IS_BYREF*/);";
+    else if (VD->getType()->isBlockPointerType())
+      S += ", " + utostr(BLOCK_FIELD_IS_BLOCK) + "/*BLOCK_FIELD_IS_BLOCK*/);";
+    else
+      S += ", " + utostr(BLOCK_FIELD_IS_OBJECT) + "/*BLOCK_FIELD_IS_OBJECT*/);";
   }
-  else
-    Result += "0, ";
-  if (PDecl->classmeth_begin() != PDecl->classmeth_end()) {
-    Result += "(struct _objc_protocol_method_list *)&_OBJC_PROTOCOL_CLASS_METHODS_";
-    Result += PDecl->getNameAsString();
-    Result += "\n";
+  S += "}\n";
+  
+  S += "\nstatic void __";
+  S += funcName;
+  S += "_block_dispose_" + utostr(i);
+  S += "(" + StructRef;
+  S += "*src) {";
+  for (llvm::SmallPtrSet<ValueDecl*,8>::iterator I = ImportedBlockDecls.begin(),
+      E = ImportedBlockDecls.end(); I != E; ++I) {
+    ValueDecl *VD = (*I);
+    S += "_Block_object_dispose((void*)src->";
+    S += (*I)->getNameAsString();
+    if (BlockByRefDeclsPtrSet.count((*I)))
+      S += ", " + utostr(BLOCK_FIELD_IS_BYREF) + "/*BLOCK_FIELD_IS_BYREF*/);";
+    else if (VD->getType()->isBlockPointerType())
+      S += ", " + utostr(BLOCK_FIELD_IS_BLOCK) + "/*BLOCK_FIELD_IS_BLOCK*/);";
+    else
+      S += ", " + utostr(BLOCK_FIELD_IS_OBJECT) + "/*BLOCK_FIELD_IS_OBJECT*/);";
   }
-  else
-    Result += "0\n";
-  Result += "};\n";
-
-  // Mark this protocol as having been generated.
-  if (!ObjCSynthesizedProtocols.insert(PDecl))
-    llvm_unreachable("protocol already synthesized");
-
+  S += "}\n";
+  return S;
 }
 
-void RewriteObjC::
-RewriteObjCProtocolListMetaData(const ObjCList<ObjCProtocolDecl> &Protocols,
-                                StringRef prefix, StringRef ClassName,
-                                std::string &Result) {
-  if (Protocols.empty()) return;
+std::string RewriteObjC::SynthesizeBlockImpl(BlockExpr *CE, std::string Tag, 
+                                             std::string Desc) {
+  std::string S = "\nstruct " + Tag;
+  std::string Constructor = "  " + Tag;
 
-  for (unsigned i = 0; i != Protocols.size(); i++)
-    RewriteObjCProtocolMetaData(Protocols[i], prefix, ClassName, Result);
+  S += " {\n  struct __block_impl impl;\n";
+  S += "  struct " + Desc;
+  S += "* Desc;\n";
 
-  // Output the top lovel protocol meta-data for the class.
-  /* struct _objc_protocol_list {
-   struct _objc_protocol_list *next;
-   int    protocol_count;
-   struct _objc_protocol *class_protocols[];
-   }
-   */
-  Result += "\nstatic struct {\n";
-  Result += "\tstruct _objc_protocol_list *next;\n";
-  Result += "\tint    protocol_count;\n";
-  Result += "\tstruct _objc_protocol *class_protocols[";
-  Result += utostr(Protocols.size());
-  Result += "];\n} _OBJC_";
-  Result += prefix;
-  Result += "_PROTOCOLS_";
-  Result += ClassName;
-  Result += " __attribute__ ((used, section (\"__OBJC, __cat_cls_meth\")))= "
-    "{\n\t0, ";
-  Result += utostr(Protocols.size());
-  Result += "\n";
+  Constructor += "(void *fp, "; // Invoke function pointer.
+  Constructor += "struct " + Desc; // Descriptor pointer.
+  Constructor += " *desc";
 
-  Result += "\t,{&_OBJC_PROTOCOL_";
-  Result += Protocols[0]->getNameAsString();
-  Result += " \n";
+  if (BlockDeclRefs.size()) {
+    // Output all "by copy" declarations.
+    for (SmallVector<ValueDecl*,8>::iterator I = BlockByCopyDecls.begin(),
+         E = BlockByCopyDecls.end(); I != E; ++I) {
+      S += "  ";
+      std::string FieldName = (*I)->getNameAsString();
+      std::string ArgName = "_" + FieldName;
+      // Handle nested closure invocation. For example:
+      //
+      //   void (^myImportedBlock)(void);
+      //   myImportedBlock  = ^(void) { setGlobalInt(x + y); };
+      //
+      //   void (^anotherBlock)(void);
+      //   anotherBlock = ^(void) {
+      //     myImportedBlock(); // import and invoke the closure
+      //   };
+      //
+      if (isTopLevelBlockPointerType((*I)->getType())) {
+        S += "struct __block_impl *";
+        Constructor += ", void *" + ArgName;
+      } else {
+        QualType QT = (*I)->getType();
+        if (HasLocalVariableExternalStorage(*I))
+          QT = Context->getPointerType(QT);
+        QT.getAsStringInternal(FieldName, Context->getPrintingPolicy());
+        QT.getAsStringInternal(ArgName, Context->getPrintingPolicy());
+        Constructor += ", " + ArgName;
+      }
+      S += FieldName + ";\n";
+    }
+    // Output all "by ref" declarations.
+    for (SmallVector<ValueDecl*,8>::iterator I = BlockByRefDecls.begin(),
+         E = BlockByRefDecls.end(); I != E; ++I) {
+      S += "  ";
+      std::string FieldName = (*I)->getNameAsString();
+      std::string ArgName = "_" + FieldName;
+      {
+        std::string TypeString;
+        RewriteByRefString(TypeString, FieldName, (*I));
+        TypeString += " *";
+        FieldName = TypeString + FieldName;
+        ArgName = TypeString + ArgName;
+        Constructor += ", " + ArgName;
+      }
+      S += FieldName + "; // by ref\n";
+    }
+    // Finish writing the constructor.
+    Constructor += ", int flags=0)";
+    // Initialize all "by copy" arguments.
+    bool firsTime = true;
+    for (SmallVector<ValueDecl*,8>::iterator I = BlockByCopyDecls.begin(),
+         E = BlockByCopyDecls.end(); I != E; ++I) {
+      std::string Name = (*I)->getNameAsString();
+        if (firsTime) {
+          Constructor += " : ";
+          firsTime = false;
+        }
+        else
+          Constructor += ", ";
+        if (isTopLevelBlockPointerType((*I)->getType()))
+          Constructor += Name + "((struct __block_impl *)_" + Name + ")";
+        else
+          Constructor += Name + "(_" + Name + ")";
+    }
+    // Initialize all "by ref" arguments.
+    for (SmallVector<ValueDecl*,8>::iterator I = BlockByRefDecls.begin(),
+         E = BlockByRefDecls.end(); I != E; ++I) {
+      std::string Name = (*I)->getNameAsString();
+      if (firsTime) {
+        Constructor += " : ";
+        firsTime = false;
+      }
+      else
+        Constructor += ", ";
+      Constructor += Name + "(_" + Name + "->__forwarding)";
+    }
+    
+    Constructor += " {\n";
+    if (GlobalVarDecl)
+      Constructor += "    impl.isa = &_NSConcreteGlobalBlock;\n";
+    else
+      Constructor += "    impl.isa = &_NSConcreteStackBlock;\n";
+    Constructor += "    impl.Flags = flags;\n    impl.FuncPtr = fp;\n";
 
-  for (unsigned i = 1; i != Protocols.size(); i++) {
-    Result += "\t ,&_OBJC_PROTOCOL_";
-    Result += Protocols[i]->getNameAsString();
-    Result += "\n";
+    Constructor += "    Desc = desc;\n";
+  } else {
+    // Finish writing the constructor.
+    Constructor += ", int flags=0) {\n";
+    if (GlobalVarDecl)
+      Constructor += "    impl.isa = &_NSConcreteGlobalBlock;\n";
+    else
+      Constructor += "    impl.isa = &_NSConcreteStackBlock;\n";
+    Constructor += "    impl.Flags = flags;\n    impl.FuncPtr = fp;\n";
+    Constructor += "    Desc = desc;\n";
   }
-  Result += "\t }\n};\n";
+  Constructor += "  ";
+  Constructor += "}\n";
+  S += Constructor;
+  S += "};\n";
+  return S;
 }
 
+std::string RewriteObjC::SynthesizeBlockDescriptor(std::string DescTag, 
+                                                   std::string ImplTag, int i,
+                                                   StringRef FunName,
+                                                   unsigned hasCopy) {
+  std::string S = "\nstatic struct " + DescTag;
+  
+  S += " {\n  unsigned long reserved;\n";
+  S += "  unsigned long Block_size;\n";
+  if (hasCopy) {
+    S += "  void (*copy)(struct ";
+    S += ImplTag; S += "*, struct ";
+    S += ImplTag; S += "*);\n";
+    
+    S += "  void (*dispose)(struct ";
+    S += ImplTag; S += "*);\n";
+  }
+  S += "} ";
 
-/// RewriteObjCCategoryImplDecl - Rewrite metadata for each category
-/// implementation.
-void RewriteObjC::RewriteObjCCategoryImplDecl(ObjCCategoryImplDecl *IDecl,
-                                              std::string &Result) {
-  ObjCInterfaceDecl *ClassDecl = IDecl->getClassInterface();
-  // Find category declaration for this implementation.
-  ObjCCategoryDecl *CDecl;
-  for (CDecl = ClassDecl->getCategoryList(); CDecl;
-       CDecl = CDecl->getNextClassCategory())
-    if (CDecl->getIdentifier() == IDecl->getIdentifier())
-      break;
-
-  std::string FullCategoryName = ClassDecl->getNameAsString();
-  FullCategoryName += '_';
-  FullCategoryName += IDecl->getNameAsString();
-
-  // Build _objc_method_list for class's instance methods if needed
-  SmallVector<ObjCMethodDecl *, 32>
-    InstanceMethods(IDecl->instmeth_begin(), IDecl->instmeth_end());
+  S += DescTag + "_DATA = { 0, sizeof(struct ";
+  S += ImplTag + ")";
+  if (hasCopy) {
+    S += ", __" + FunName.str() + "_block_copy_" + utostr(i);
+    S += ", __" + FunName.str() + "_block_dispose_" + utostr(i);
+  }
+  S += "};\n";
+  return S;
+}
 
-  // If any of our property implementations have associated getters or
-  // setters, produce metadata for them as well.
-  for (ObjCImplDecl::propimpl_iterator Prop = IDecl->propimpl_begin(),
-         PropEnd = IDecl->propimpl_end();
-       Prop != PropEnd; ++Prop) {
-    if ((*Prop)->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic)
-      continue;
-    if (!(*Prop)->getPropertyIvarDecl())
-      continue;
-    ObjCPropertyDecl *PD = (*Prop)->getPropertyDecl();
-    if (!PD)
-      continue;
-    if (ObjCMethodDecl *Getter = PD->getGetterMethodDecl())
-      InstanceMethods.push_back(Getter);
-    if (PD->isReadOnly())
-      continue;
-    if (ObjCMethodDecl *Setter = PD->getSetterMethodDecl())
-      InstanceMethods.push_back(Setter);
+void RewriteObjC::SynthesizeBlockLiterals(SourceLocation FunLocStart,
+                                          StringRef FunName) {
+  // Insert declaration for the function in which block literal is used.
+  if (CurFunctionDeclToDeclareForBlock && !Blocks.empty())
+    RewriteBlockLiteralFunctionDecl(CurFunctionDeclToDeclareForBlock);
+  bool RewriteSC = (GlobalVarDecl &&
+                    !Blocks.empty() &&
+                    GlobalVarDecl->getStorageClass() == SC_Static &&
+                    GlobalVarDecl->getType().getCVRQualifiers());
+  if (RewriteSC) {
+    std::string SC(" void __");
+    SC += GlobalVarDecl->getNameAsString();
+    SC += "() {}";
+    InsertText(FunLocStart, SC);
   }
-  RewriteObjCMethodsMetaData(InstanceMethods.begin(), InstanceMethods.end(),
-                             true, "CATEGORY_", FullCategoryName.c_str(),
-                             Result);
+  
+  // Insert closures that were part of the function.
+  for (unsigned i = 0, count=0; i < Blocks.size(); i++) {
+    CollectBlockDeclRefInfo(Blocks[i]);
+    // Need to copy-in the inner copied-in variables not actually used in this
+    // block.
+    for (int j = 0; j < InnerDeclRefsCount[i]; j++) {
+      BlockDeclRefExpr *Exp = InnerDeclRefs[count++];
+      ValueDecl *VD = Exp->getDecl();
+      BlockDeclRefs.push_back(Exp);
+      if (!Exp->isByRef() && !BlockByCopyDeclsPtrSet.count(VD)) {
+        BlockByCopyDeclsPtrSet.insert(VD);
+        BlockByCopyDecls.push_back(VD);
+      }
+      if (Exp->isByRef() && !BlockByRefDeclsPtrSet.count(VD)) {
+        BlockByRefDeclsPtrSet.insert(VD);
+        BlockByRefDecls.push_back(VD);
+      }
+      // imported objects in the inner blocks not used in the outer
+      // blocks must be copied/disposed in the outer block as well.
+      if (Exp->isByRef() ||
+          VD->getType()->isObjCObjectPointerType() || 
+          VD->getType()->isBlockPointerType())
+        ImportedBlockDecls.insert(VD);
+    }
 
-  // Build _objc_method_list for class's class methods if needed
-  RewriteObjCMethodsMetaData(IDecl->classmeth_begin(), IDecl->classmeth_end(),
-                             false, "CATEGORY_", FullCategoryName.c_str(),
-                             Result);
+    std::string ImplTag = "__" + FunName.str() + "_block_impl_" + utostr(i);
+    std::string DescTag = "__" + FunName.str() + "_block_desc_" + utostr(i);
 
-  // Protocols referenced in class declaration?
-  // Null CDecl is case of a category implementation with no category interface
-  if (CDecl)
-    RewriteObjCProtocolListMetaData(CDecl->getReferencedProtocols(), "CATEGORY",
-                                    FullCategoryName, Result);
-  /* struct _objc_category {
-   char *category_name;
-   char *class_name;
-   struct _objc_method_list *instance_methods;
-   struct _objc_method_list *class_methods;
-   struct _objc_protocol_list *protocols;
-   // Objective-C 1.0 extensions
-   uint32_t size;     // sizeof (struct _objc_category)
-   struct _objc_property_list *instance_properties;  // category's own
-                                                     // @property decl.
-   };
-   */
+    std::string CI = SynthesizeBlockImpl(Blocks[i], ImplTag, DescTag);
 
-  static bool objc_category = false;
-  if (!objc_category) {
-    Result += "\nstruct _objc_category {\n";
-    Result += "\tchar *category_name;\n";
-    Result += "\tchar *class_name;\n";
-    Result += "\tstruct _objc_method_list *instance_methods;\n";
-    Result += "\tstruct _objc_method_list *class_methods;\n";
-    Result += "\tstruct _objc_protocol_list *protocols;\n";
-    Result += "\tunsigned int size;\n";
-    Result += "\tstruct _objc_property_list *instance_properties;\n";
-    Result += "};\n";
-    objc_category = true;
-  }
-  Result += "\nstatic struct _objc_category _OBJC_CATEGORY_";
-  Result += FullCategoryName;
-  Result += " __attribute__ ((used, section (\"__OBJC, __category\")))= {\n\t\"";
-  Result += IDecl->getNameAsString();
-  Result += "\"\n\t, \"";
-  Result += ClassDecl->getNameAsString();
-  Result += "\"\n";
+    InsertText(FunLocStart, CI);
 
-  if (IDecl->instmeth_begin() != IDecl->instmeth_end()) {
-    Result += "\t, (struct _objc_method_list *)"
-           "&_OBJC_CATEGORY_INSTANCE_METHODS_";
-    Result += FullCategoryName;
-    Result += "\n";
-  }
-  else
-    Result += "\t, 0\n";
-  if (IDecl->classmeth_begin() != IDecl->classmeth_end()) {
-    Result += "\t, (struct _objc_method_list *)"
-           "&_OBJC_CATEGORY_CLASS_METHODS_";
-    Result += FullCategoryName;
-    Result += "\n";
-  }
-  else
-    Result += "\t, 0\n";
+    std::string CF = SynthesizeBlockFunc(Blocks[i], i, FunName, ImplTag);
 
-  if (CDecl && CDecl->protocol_begin() != CDecl->protocol_end()) {
-    Result += "\t, (struct _objc_protocol_list *)&_OBJC_CATEGORY_PROTOCOLS_";
-    Result += FullCategoryName;
-    Result += "\n";
-  }
-  else
-    Result += "\t, 0\n";
-  Result += "\t, sizeof(struct _objc_category), 0\n};\n";
-}
+    InsertText(FunLocStart, CF);
 
-/// RewriteIvarOffsetComputation - This rutine synthesizes computation of
-/// ivar offset.
-void RewriteObjC::RewriteIvarOffsetComputation(ObjCIvarDecl *ivar,
-                                                  std::string &Result) {
-  if (ivar->isBitField()) {
-    // FIXME: The hack below doesn't work for bitfields. For now, we simply
-    // place all bitfields at offset 0.
-    Result += "0";
-  } else {
-    Result += "__OFFSETOFIVAR__(struct ";
-    Result += ivar->getContainingInterface()->getNameAsString();
-    if (LangOpts.MicrosoftExt)
-      Result += "_IMPL";
-    Result += ", ";
-    Result += ivar->getNameAsString();
-    Result += ")";
+    if (ImportedBlockDecls.size()) {
+      std::string HF = SynthesizeBlockHelperFuncs(Blocks[i], i, FunName, ImplTag);
+      InsertText(FunLocStart, HF);
+    }
+    std::string BD = SynthesizeBlockDescriptor(DescTag, ImplTag, i, FunName,
+                                               ImportedBlockDecls.size() > 0);
+    InsertText(FunLocStart, BD);
+
+    BlockDeclRefs.clear();
+    BlockByRefDecls.clear();
+    BlockByRefDeclsPtrSet.clear();
+    BlockByCopyDecls.clear();
+    BlockByCopyDeclsPtrSet.clear();
+    ImportedBlockDecls.clear();
+  }
+  if (RewriteSC) {
+    // Must insert any 'const/volatile/static here. Since it has been
+    // removed as result of rewriting of block literals.
+    std::string SC;
+    if (GlobalVarDecl->getStorageClass() == SC_Static)
+      SC = "static ";
+    if (GlobalVarDecl->getType().isConstQualified())
+      SC += "const ";
+    if (GlobalVarDecl->getType().isVolatileQualified())
+      SC += "volatile ";
+    if (GlobalVarDecl->getType().isRestrictQualified())
+      SC += "restrict ";
+    InsertText(FunLocStart, SC);
   }
+  
+  Blocks.clear();
+  InnerDeclRefsCount.clear();
+  InnerDeclRefs.clear();
+  RewrittenBlockExprs.clear();
 }
 
-//===----------------------------------------------------------------------===//
-// Meta Data Emission
-//===----------------------------------------------------------------------===//
+void RewriteObjC::InsertBlockLiteralsWithinFunction(FunctionDecl *FD) {
+  SourceLocation FunLocStart = FD->getTypeSpecStartLoc();
+  StringRef FuncName = FD->getName();
 
-void RewriteObjC::RewriteObjCClassMetaData(ObjCImplementationDecl *IDecl,
-                                           std::string &Result) {
-  ObjCInterfaceDecl *CDecl = IDecl->getClassInterface();
+  SynthesizeBlockLiterals(FunLocStart, FuncName);
+}
 
-  // Explicitly declared @interface's are already synthesized.
-  if (CDecl->isImplicitInterfaceDecl()) {
-    // FIXME: Implementation of a class with no @interface (legacy) doese not
-    // produce correct synthesis as yet.
-    RewriteObjCInternalStruct(CDecl, Result);
-  }
+static void BuildUniqueMethodName(std::string &Name,
+                                  ObjCMethodDecl *MD) {
+  ObjCInterfaceDecl *IFace = MD->getClassInterface();
+  Name = IFace->getName();
+  Name += "__" + MD->getSelector().getAsString();
+  // Convert colons to underscores.
+  std::string::size_type loc = 0;
+  while ((loc = Name.find(":", loc)) != std::string::npos)
+    Name.replace(loc, 1, "_");
+}
 
-  // Build _objc_ivar_list metadata for classes ivars if needed
-  unsigned NumIvars = !IDecl->ivar_empty()
-                      ? IDecl->ivar_size()
-                      : (CDecl ? CDecl->ivar_size() : 0);
-  if (NumIvars > 0) {
-    static bool objc_ivar = false;
-    if (!objc_ivar) {
-      /* struct _objc_ivar {
-          char *ivar_name;
-          char *ivar_type;
-          int ivar_offset;
-        };
-       */
-      Result += "\nstruct _objc_ivar {\n";
-      Result += "\tchar *ivar_name;\n";
-      Result += "\tchar *ivar_type;\n";
-      Result += "\tint ivar_offset;\n";
-      Result += "};\n";
+void RewriteObjC::InsertBlockLiteralsWithinMethod(ObjCMethodDecl *MD) {
+  //fprintf(stderr,"In InsertBlockLiteralsWitinMethod\n");
+  //SourceLocation FunLocStart = MD->getLocStart();
+  SourceLocation FunLocStart = MD->getLocStart();
+  std::string FuncName;
+  BuildUniqueMethodName(FuncName, MD);
+  SynthesizeBlockLiterals(FunLocStart, FuncName);
+}
 
-      objc_ivar = true;
+void RewriteObjC::GetBlockDeclRefExprs(Stmt *S) {
+  for (Stmt::child_range CI = S->children(); CI; ++CI)
+    if (*CI) {
+      if (BlockExpr *CBE = dyn_cast<BlockExpr>(*CI))
+        GetBlockDeclRefExprs(CBE->getBody());
+      else
+        GetBlockDeclRefExprs(*CI);
+    }
+  // Handle specific things.
+  if (BlockDeclRefExpr *CDRE = dyn_cast<BlockDeclRefExpr>(S)) {
+    // FIXME: Handle enums.
+    if (!isa<FunctionDecl>(CDRE->getDecl()))
+      BlockDeclRefs.push_back(CDRE);
+  }
+  else if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(S))
+    if (HasLocalVariableExternalStorage(DRE->getDecl())) {
+        BlockDeclRefExpr *BDRE = 
+          new (Context)BlockDeclRefExpr(cast<VarDecl>(DRE->getDecl()),
+                                        DRE->getType(), 
+                                        VK_LValue, DRE->getLocation(), false);
+        BlockDeclRefs.push_back(BDRE);
     }
+  
+  return;
+}
 
-    /* struct {
-       int ivar_count;
-       struct _objc_ivar ivar_list[nIvars];
-       };
-     */
-    Result += "\nstatic struct {\n";
-    Result += "\tint ivar_count;\n";
-    Result += "\tstruct _objc_ivar ivar_list[";
-    Result += utostr(NumIvars);
-    Result += "];\n} _OBJC_INSTANCE_VARIABLES_";
-    Result += IDecl->getNameAsString();
-    Result += " __attribute__ ((used, section (\"__OBJC, __instance_vars\")))= "
-      "{\n\t";
-    Result += utostr(NumIvars);
-    Result += "\n";
+void RewriteObjC::GetInnerBlockDeclRefExprs(Stmt *S, 
+                SmallVector<BlockDeclRefExpr *, 8> &InnerBlockDeclRefs,
+                llvm::SmallPtrSet<const DeclContext *, 8> &InnerContexts) {
+  for (Stmt::child_range CI = S->children(); CI; ++CI)
+    if (*CI) {
+      if (BlockExpr *CBE = dyn_cast<BlockExpr>(*CI)) {
+        InnerContexts.insert(cast<DeclContext>(CBE->getBlockDecl()));
+        GetInnerBlockDeclRefExprs(CBE->getBody(),
+                                  InnerBlockDeclRefs,
+                                  InnerContexts);
+      }
+      else
+        GetInnerBlockDeclRefExprs(*CI,
+                                  InnerBlockDeclRefs,
+                                  InnerContexts);
 
-    ObjCInterfaceDecl::ivar_iterator IVI, IVE;
-    SmallVector<ObjCIvarDecl *, 8> IVars;
-    if (!IDecl->ivar_empty()) {
-      for (ObjCInterfaceDecl::ivar_iterator
-             IV = IDecl->ivar_begin(), IVEnd = IDecl->ivar_end();
-           IV != IVEnd; ++IV)
-        IVars.push_back(*IV);
-      IVI = IDecl->ivar_begin();
-      IVE = IDecl->ivar_end();
-    } else {
-      IVI = CDecl->ivar_begin();
-      IVE = CDecl->ivar_end();
-    }
-    Result += "\t,{{\"";
-    Result += (*IVI)->getNameAsString();
-    Result += "\", \"";
-    std::string TmpString, StrEncoding;
-    Context->getObjCEncodingForType((*IVI)->getType(), TmpString, *IVI);
-    QuoteDoublequotes(TmpString, StrEncoding);
-    Result += StrEncoding;
-    Result += "\", ";
-    RewriteIvarOffsetComputation(*IVI, Result);
-    Result += "}\n";
-    for (++IVI; IVI != IVE; ++IVI) {
-      Result += "\t  ,{\"";
-      Result += (*IVI)->getNameAsString();
-      Result += "\", \"";
-      std::string TmpString, StrEncoding;
-      Context->getObjCEncodingForType((*IVI)->getType(), TmpString, *IVI);
-      QuoteDoublequotes(TmpString, StrEncoding);
-      Result += StrEncoding;
-      Result += "\", ";
-      RewriteIvarOffsetComputation((*IVI), Result);
-      Result += "}\n";
     }
+  // Handle specific things.
+  if (BlockDeclRefExpr *CDRE = dyn_cast<BlockDeclRefExpr>(S)) {
+    if (!isa<FunctionDecl>(CDRE->getDecl()) &&
+        !InnerContexts.count(CDRE->getDecl()->getDeclContext()))
+      InnerBlockDeclRefs.push_back(CDRE);
+  }
+  else if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(S)) {
+    if (VarDecl *Var = dyn_cast<VarDecl>(DRE->getDecl()))
+      if (Var->isFunctionOrMethodVarDecl())
+        ImportedLocalExternalDecls.insert(Var);
+  }
+  
+  return;
+}
 
-    Result += "\t }\n};\n";
+/// convertFunctionTypeOfBlocks - This routine converts a function type
+/// whose result type may be a block pointer or whose argument type(s)
+/// might be block pointers to an equivalent function type replacing
+/// all block pointers to function pointers.
+QualType RewriteObjC::convertFunctionTypeOfBlocks(const FunctionType *FT) {
+  const FunctionProtoType *FTP = dyn_cast<FunctionProtoType>(FT);
+  // FTP will be null for closures that don't take arguments.
+  // Generate a funky cast.
+  SmallVector<QualType, 8> ArgTypes;
+  QualType Res = FT->getResultType();
+  bool HasBlockType = convertBlockPointerToFunctionPointer(Res);
+  
+  if (FTP) {
+    for (FunctionProtoType::arg_type_iterator I = FTP->arg_type_begin(),
+         E = FTP->arg_type_end(); I && (I != E); ++I) {
+      QualType t = *I;
+      // Make sure we convert "t (^)(...)" to "t (*)(...)".
+      if (convertBlockPointerToFunctionPointer(t))
+        HasBlockType = true;
+      ArgTypes.push_back(t);
+    }
   }
+  QualType FuncType;
+  // FIXME. Does this work if block takes no argument but has a return type
+  // which is of block type?
+  if (HasBlockType)
+    FuncType = getSimpleFunctionType(Res, &ArgTypes[0], ArgTypes.size());
+  else FuncType = QualType(FT, 0);
+  return FuncType;
+}
 
-  // Build _objc_method_list for class's instance methods if needed
-  SmallVector<ObjCMethodDecl *, 32>
-    InstanceMethods(IDecl->instmeth_begin(), IDecl->instmeth_end());
+Stmt *RewriteObjC::SynthesizeBlockCall(CallExpr *Exp, const Expr *BlockExp) {
+  // Navigate to relevant type information.
+  const BlockPointerType *CPT = 0;
 
-  // If any of our property implementations have associated getters or
-  // setters, produce metadata for them as well.
-  for (ObjCImplDecl::propimpl_iterator Prop = IDecl->propimpl_begin(),
-         PropEnd = IDecl->propimpl_end();
-       Prop != PropEnd; ++Prop) {
-    if ((*Prop)->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic)
-      continue;
-    if (!(*Prop)->getPropertyIvarDecl())
-      continue;
-    ObjCPropertyDecl *PD = (*Prop)->getPropertyDecl();
-    if (!PD)
-      continue;
-    if (ObjCMethodDecl *Getter = PD->getGetterMethodDecl())
-      if (!Getter->isDefined())
-        InstanceMethods.push_back(Getter);
-    if (PD->isReadOnly())
-      continue;
-    if (ObjCMethodDecl *Setter = PD->getSetterMethodDecl())
-      if (!Setter->isDefined())
-        InstanceMethods.push_back(Setter);
+  if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(BlockExp)) {
+    CPT = DRE->getType()->getAs<BlockPointerType>();
+  } else if (const BlockDeclRefExpr *CDRE = 
+              dyn_cast<BlockDeclRefExpr>(BlockExp)) {
+    CPT = CDRE->getType()->getAs<BlockPointerType>();
+  } else if (const MemberExpr *MExpr = dyn_cast<MemberExpr>(BlockExp)) {
+    CPT = MExpr->getType()->getAs<BlockPointerType>();
+  } 
+  else if (const ParenExpr *PRE = dyn_cast<ParenExpr>(BlockExp)) {
+    return SynthesizeBlockCall(Exp, PRE->getSubExpr());
   }
-  RewriteObjCMethodsMetaData(InstanceMethods.begin(), InstanceMethods.end(),
-                             true, "", IDecl->getName(), Result);
+  else if (const ImplicitCastExpr *IEXPR = dyn_cast<ImplicitCastExpr>(BlockExp)) 
+    CPT = IEXPR->getType()->getAs<BlockPointerType>();
+  else if (const ConditionalOperator *CEXPR = 
+            dyn_cast<ConditionalOperator>(BlockExp)) {
+    Expr *LHSExp = CEXPR->getLHS();
+    Stmt *LHSStmt = SynthesizeBlockCall(Exp, LHSExp);
+    Expr *RHSExp = CEXPR->getRHS();
+    Stmt *RHSStmt = SynthesizeBlockCall(Exp, RHSExp);
+    Expr *CONDExp = CEXPR->getCond();
+    ConditionalOperator *CondExpr =
+      new (Context) ConditionalOperator(CONDExp,
+                                      SourceLocation(), cast<Expr>(LHSStmt),
+                                      SourceLocation(), cast<Expr>(RHSStmt),
+                                      Exp->getType(), VK_RValue, OK_Ordinary);
+    return CondExpr;
+  } else if (const ObjCIvarRefExpr *IRE = dyn_cast<ObjCIvarRefExpr>(BlockExp)) {
+    CPT = IRE->getType()->getAs<BlockPointerType>();
+  } else if (const PseudoObjectExpr *POE
+               = dyn_cast<PseudoObjectExpr>(BlockExp)) {
+    CPT = POE->getType()->castAs<BlockPointerType>();
+  } else {
+    assert(1 && "RewriteBlockClass: Bad type");
+  }
+  assert(CPT && "RewriteBlockClass: Bad type");
+  const FunctionType *FT = CPT->getPointeeType()->getAs<FunctionType>();
+  assert(FT && "RewriteBlockClass: Bad type");
+  const FunctionProtoType *FTP = dyn_cast<FunctionProtoType>(FT);
+  // FTP will be null for closures that don't take arguments.
 
-  // Build _objc_method_list for class's class methods if needed
-  RewriteObjCMethodsMetaData(IDecl->classmeth_begin(), IDecl->classmeth_end(),
-                             false, "", IDecl->getName(), Result);
+  RecordDecl *RD = RecordDecl::Create(*Context, TTK_Struct, TUDecl,
+                                      SourceLocation(), SourceLocation(),
+                                      &Context->Idents.get("__block_impl"));
+  QualType PtrBlock = Context->getPointerType(Context->getTagDeclType(RD));
 
-  // Protocols referenced in class declaration?
-  RewriteObjCProtocolListMetaData(CDecl->getReferencedProtocols(),
-                                  "CLASS", CDecl->getName(), Result);
+  // Generate a funky cast.
+  SmallVector<QualType, 8> ArgTypes;
 
-  // Declaration of class/meta-class metadata
-  /* struct _objc_class {
-   struct _objc_class *isa; // or const char *root_class_name when metadata
-   const char *super_class_name;
-   char *name;
-   long version;
-   long info;
-   long instance_size;
-   struct _objc_ivar_list *ivars;
-   struct _objc_method_list *methods;
-   struct objc_cache *cache;
-   struct objc_protocol_list *protocols;
-   const char *ivar_layout;
-   struct _objc_class_ext  *ext;
-   };
-  */
-  static bool objc_class = false;
-  if (!objc_class) {
-    Result += "\nstruct _objc_class {\n";
-    Result += "\tstruct _objc_class *isa;\n";
-    Result += "\tconst char *super_class_name;\n";
-    Result += "\tchar *name;\n";
-    Result += "\tlong version;\n";
-    Result += "\tlong info;\n";
-    Result += "\tlong instance_size;\n";
-    Result += "\tstruct _objc_ivar_list *ivars;\n";
-    Result += "\tstruct _objc_method_list *methods;\n";
-    Result += "\tstruct objc_cache *cache;\n";
-    Result += "\tstruct _objc_protocol_list *protocols;\n";
-    Result += "\tconst char *ivar_layout;\n";
-    Result += "\tstruct _objc_class_ext  *ext;\n";
-    Result += "};\n";
-    objc_class = true;
+  // Push the block argument type.
+  ArgTypes.push_back(PtrBlock);
+  if (FTP) {
+    for (FunctionProtoType::arg_type_iterator I = FTP->arg_type_begin(),
+         E = FTP->arg_type_end(); I && (I != E); ++I) {
+      QualType t = *I;
+      // Make sure we convert "t (^)(...)" to "t (*)(...)".
+      if (!convertBlockPointerToFunctionPointer(t))
+        convertToUnqualifiedObjCType(t);
+      ArgTypes.push_back(t);
+    }
   }
+  // Now do the pointer to function cast.
+  QualType PtrToFuncCastType
+    = getSimpleFunctionType(Exp->getType(), &ArgTypes[0], ArgTypes.size());
 
-  // Meta-class metadata generation.
-  ObjCInterfaceDecl *RootClass = 0;
-  ObjCInterfaceDecl *SuperClass = CDecl->getSuperClass();
-  while (SuperClass) {
-    RootClass = SuperClass;
-    SuperClass = SuperClass->getSuperClass();
-  }
-  SuperClass = CDecl->getSuperClass();
+  PtrToFuncCastType = Context->getPointerType(PtrToFuncCastType);
 
-  Result += "\nstatic struct _objc_class _OBJC_METACLASS_";
-  Result += CDecl->getNameAsString();
-  Result += " __attribute__ ((used, section (\"__OBJC, __meta_class\")))= "
-  "{\n\t(struct _objc_class *)\"";
-  Result += (RootClass ? RootClass->getNameAsString() : CDecl->getNameAsString());
-  Result += "\"";
+  CastExpr *BlkCast = NoTypeInfoCStyleCastExpr(Context, PtrBlock,
+                                               CK_BitCast,
+                                               const_cast<Expr*>(BlockExp));
+  // Don't forget the parens to enforce the proper binding.
+  ParenExpr *PE = new (Context) ParenExpr(SourceLocation(), SourceLocation(),
+                                          BlkCast);
+  //PE->dump();
 
-  if (SuperClass) {
-    Result += ", \"";
-    Result += SuperClass->getNameAsString();
-    Result += "\", \"";
-    Result += CDecl->getNameAsString();
-    Result += "\"";
-  }
-  else {
-    Result += ", 0, \"";
-    Result += CDecl->getNameAsString();
-    Result += "\"";
-  }
-  // Set 'ivars' field for root class to 0. ObjC1 runtime does not use it.
-  // 'info' field is initialized to CLS_META(2) for metaclass
-  Result += ", 0,2, sizeof(struct _objc_class), 0";
-  if (IDecl->classmeth_begin() != IDecl->classmeth_end()) {
-    Result += "\n\t, (struct _objc_method_list *)&_OBJC_CLASS_METHODS_";
-    Result += IDecl->getNameAsString();
-    Result += "\n";
-  }
-  else
-    Result += ", 0\n";
-  if (CDecl->protocol_begin() != CDecl->protocol_end()) {
-    Result += "\t,0, (struct _objc_protocol_list *)&_OBJC_CLASS_PROTOCOLS_";
-    Result += CDecl->getNameAsString();
-    Result += ",0,0\n";
-  }
-  else
-    Result += "\t,0,0,0,0\n";
-  Result += "};\n";
+  FieldDecl *FD = FieldDecl::Create(*Context, 0, SourceLocation(),
+                                    SourceLocation(),
+                                    &Context->Idents.get("FuncPtr"),
+                                    Context->VoidPtrTy, 0,
+                                    /*BitWidth=*/0, /*Mutable=*/true,
+                                    /*HasInit=*/false);
+  MemberExpr *ME = new (Context) MemberExpr(PE, true, FD, SourceLocation(),
+                                            FD->getType(), VK_LValue,
+                                            OK_Ordinary);
 
-  // class metadata generation.
-  Result += "\nstatic struct _objc_class _OBJC_CLASS_";
-  Result += CDecl->getNameAsString();
-  Result += " __attribute__ ((used, section (\"__OBJC, __class\")))= "
-            "{\n\t&_OBJC_METACLASS_";
-  Result += CDecl->getNameAsString();
-  if (SuperClass) {
-    Result += ", \"";
-    Result += SuperClass->getNameAsString();
-    Result += "\", \"";
-    Result += CDecl->getNameAsString();
-    Result += "\"";
-  }
-  else {
-    Result += ", 0, \"";
-    Result += CDecl->getNameAsString();
-    Result += "\"";
-  }
-  // 'info' field is initialized to CLS_CLASS(1) for class
-  Result += ", 0,1";
-  if (!ObjCSynthesizedStructs.count(CDecl))
-    Result += ",0";
-  else {
-    // class has size. Must synthesize its size.
-    Result += ",sizeof(struct ";
-    Result += CDecl->getNameAsString();
-    if (LangOpts.MicrosoftExt)
-      Result += "_IMPL";
-    Result += ")";
-  }
-  if (NumIvars > 0) {
-    Result += ", (struct _objc_ivar_list *)&_OBJC_INSTANCE_VARIABLES_";
-    Result += CDecl->getNameAsString();
-    Result += "\n\t";
-  }
-  else
-    Result += ",0";
-  if (IDecl->instmeth_begin() != IDecl->instmeth_end()) {
-    Result += ", (struct _objc_method_list *)&_OBJC_INSTANCE_METHODS_";
-    Result += CDecl->getNameAsString();
-    Result += ", 0\n\t";
-  }
-  else
-    Result += ",0,0";
-  if (CDecl->protocol_begin() != CDecl->protocol_end()) {
-    Result += ", (struct _objc_protocol_list*)&_OBJC_CLASS_PROTOCOLS_";
-    Result += CDecl->getNameAsString();
-    Result += ", 0,0\n";
+  
+  CastExpr *FunkCast = NoTypeInfoCStyleCastExpr(Context, PtrToFuncCastType,
+                                                CK_BitCast, ME);
+  PE = new (Context) ParenExpr(SourceLocation(), SourceLocation(), FunkCast);
+
+  SmallVector<Expr*, 8> BlkExprs;
+  // Add the implicit argument.
+  BlkExprs.push_back(BlkCast);
+  // Add the user arguments.
+  for (CallExpr::arg_iterator I = Exp->arg_begin(),
+       E = Exp->arg_end(); I != E; ++I) {
+    BlkExprs.push_back(*I);
   }
-  else
-    Result += ",0,0,0\n";
-  Result += "};\n";
+  CallExpr *CE = new (Context) CallExpr(*Context, PE, &BlkExprs[0],
+                                        BlkExprs.size(),
+                                        Exp->getType(), VK_RValue,
+                                        SourceLocation());
+  return CE;
 }
 
-/// RewriteImplementations - This routine rewrites all method implementations
-/// and emits meta-data.
-
-void RewriteObjC::RewriteImplementations() {
-  int ClsDefCount = ClassImplementation.size();
-  int CatDefCount = CategoryImplementation.size();
-
-  // Rewrite implemented methods
-  for (int i = 0; i < ClsDefCount; i++)
-    RewriteImplementationDecl(ClassImplementation[i]);
-
-  for (int i = 0; i < CatDefCount; i++)
-    RewriteImplementationDecl(CategoryImplementation[i]);
-}
+// We need to return the rewritten expression to handle cases where the
+// BlockDeclRefExpr is embedded in another expression being rewritten.
+// For example:
+//
+// int main() {
+//    __block Foo *f;
+//    __block int i;
+//
+//    void (^myblock)() = ^() {
+//        [f test]; // f is a BlockDeclRefExpr embedded in a message (which is being rewritten).
+//        i = 77;
+//    };
+//}
+Stmt *RewriteObjC::RewriteBlockDeclRefExpr(Expr *DeclRefExp) {
+  // Rewrite the byref variable into BYREFVAR->__forwarding->BYREFVAR 
+  // for each DeclRefExp where BYREFVAR is name of the variable.
+  ValueDecl *VD;
+  bool isArrow = true;
+  if (BlockDeclRefExpr *BDRE = dyn_cast<BlockDeclRefExpr>(DeclRefExp))
+    VD = BDRE->getDecl();
+  else {
+    VD = cast<DeclRefExpr>(DeclRefExp)->getDecl();
+    isArrow = false;
+  }
+  
+  FieldDecl *FD = FieldDecl::Create(*Context, 0, SourceLocation(),
+                                    SourceLocation(),
+                                    &Context->Idents.get("__forwarding"), 
+                                    Context->VoidPtrTy, 0,
+                                    /*BitWidth=*/0, /*Mutable=*/true,
+                                    /*HasInit=*/false);
+  MemberExpr *ME = new (Context) MemberExpr(DeclRefExp, isArrow,
+                                            FD, SourceLocation(),
+                                            FD->getType(), VK_LValue,
+                                            OK_Ordinary);
 
-void RewriteObjC::RewriteMetaDataIntoBuffer(std::string &Result) {
-  int ClsDefCount = ClassImplementation.size();
-  int CatDefCount = CategoryImplementation.size();
+  StringRef Name = VD->getName();
+  FD = FieldDecl::Create(*Context, 0, SourceLocation(), SourceLocation(),
+                         &Context->Idents.get(Name), 
+                         Context->VoidPtrTy, 0,
+                         /*BitWidth=*/0, /*Mutable=*/true,
+                         /*HasInit=*/false);
+  ME = new (Context) MemberExpr(ME, true, FD, SourceLocation(),
+                                DeclRefExp->getType(), VK_LValue, OK_Ordinary);
   
-  // For each implemented class, write out all its meta data.
-  for (int i = 0; i < ClsDefCount; i++)
-    RewriteObjCClassMetaData(ClassImplementation[i], Result);
+  
+  
+  // Need parens to enforce precedence.
+  ParenExpr *PE = new (Context) ParenExpr(DeclRefExp->getExprLoc(), 
+                                          DeclRefExp->getExprLoc(), 
+                                          ME);
+  ReplaceStmt(DeclRefExp, PE);
+  return PE;
+}
 
-  // For each implemented category, write out all its meta data.
-  for (int i = 0; i < CatDefCount; i++)
-    RewriteObjCCategoryImplDecl(CategoryImplementation[i], Result);
+// Rewrites the imported local variable V with external storage 
+// (static, extern, etc.) as *V
+//
+Stmt *RewriteObjC::RewriteLocalVariableExternalStorage(DeclRefExpr *DRE) {
+  ValueDecl *VD = DRE->getDecl();
+  if (VarDecl *Var = dyn_cast<VarDecl>(VD))
+    if (!ImportedLocalExternalDecls.count(Var))
+      return DRE;
+  Expr *Exp = new (Context) UnaryOperator(DRE, UO_Deref, DRE->getType(),
+                                          VK_LValue, OK_Ordinary,
+                                          DRE->getLocation());
+  // Need parens to enforce precedence.
+  ParenExpr *PE = new (Context) ParenExpr(SourceLocation(), SourceLocation(), 
+                                          Exp);
+  ReplaceStmt(DRE, PE);
+  return PE;
+}
 
-  // Write objc_symtab metadata
-  /*
-   struct _objc_symtab
-   {
-   long sel_ref_cnt;
-   SEL *refs;
-   short cls_def_cnt;
-   short cat_def_cnt;
-   void *defs[cls_def_cnt + cat_def_cnt];
-   };
-   */
+void RewriteObjC::RewriteCastExpr(CStyleCastExpr *CE) {
+  SourceLocation LocStart = CE->getLParenLoc();
+  SourceLocation LocEnd = CE->getRParenLoc();
 
-  Result += "\nstruct _objc_symtab {\n";
-  Result += "\tlong sel_ref_cnt;\n";
-  Result += "\tSEL *refs;\n";
-  Result += "\tshort cls_def_cnt;\n";
-  Result += "\tshort cat_def_cnt;\n";
-  Result += "\tvoid *defs[" + utostr(ClsDefCount + CatDefCount)+ "];\n";
-  Result += "};\n\n";
+  // Need to avoid trying to rewrite synthesized casts.
+  if (LocStart.isInvalid())
+    return;
+  // Need to avoid trying to rewrite casts contained in macros.
+  if (!Rewriter::isRewritable(LocStart) || !Rewriter::isRewritable(LocEnd))
+    return;
 
-  Result += "static struct _objc_symtab "
-         "_OBJC_SYMBOLS __attribute__((used, section (\"__OBJC, __symbols\")))= {\n";
-  Result += "\t0, 0, " + utostr(ClsDefCount)
-            + ", " + utostr(CatDefCount) + "\n";
-  for (int i = 0; i < ClsDefCount; i++) {
-    Result += "\t,&_OBJC_CLASS_";
-    Result += ClassImplementation[i]->getNameAsString();
-    Result += "\n";
+  const char *startBuf = SM->getCharacterData(LocStart);
+  const char *endBuf = SM->getCharacterData(LocEnd);
+  QualType QT = CE->getType();
+  const Type* TypePtr = QT->getAs<Type>();
+  if (isa<TypeOfExprType>(TypePtr)) {
+    const TypeOfExprType *TypeOfExprTypePtr = cast<TypeOfExprType>(TypePtr);
+    QT = TypeOfExprTypePtr->getUnderlyingExpr()->getType();
+    std::string TypeAsString = "(";
+    RewriteBlockPointerType(TypeAsString, QT);
+    TypeAsString += ")";
+    ReplaceText(LocStart, endBuf-startBuf+1, TypeAsString);
+    return;
   }
+  // advance the location to startArgList.
+  const char *argPtr = startBuf;
 
-  for (int i = 0; i < CatDefCount; i++) {
-    Result += "\t,&_OBJC_CATEGORY_";
-    Result += CategoryImplementation[i]->getClassInterface()->getNameAsString();
-    Result += "_";
-    Result += CategoryImplementation[i]->getNameAsString();
-    Result += "\n";
+  while (*argPtr++ && (argPtr < endBuf)) {
+    switch (*argPtr) {
+    case '^':
+      // Replace the '^' with '*'.
+      LocStart = LocStart.getLocWithOffset(argPtr-startBuf);
+      ReplaceText(LocStart, 1, "*");
+      break;
+    }
   }
+  return;
+}
 
-  Result += "};\n\n";
+void RewriteObjC::RewriteBlockPointerFunctionArgs(FunctionDecl *FD) {
+  SourceLocation DeclLoc = FD->getLocation();
+  unsigned parenCount = 0;
 
-  // Write objc_module metadata
+  // We have 1 or more arguments that have closure pointers.
+  const char *startBuf = SM->getCharacterData(DeclLoc);
+  const char *startArgList = strchr(startBuf, '(');
 
-  /*
-   struct _objc_module {
-    long version;
-    long size;
-    const char *name;
-    struct _objc_symtab *symtab;
-   }
-  */
+  assert((*startArgList == '(') && "Rewriter fuzzy parser confused");
 
-  Result += "\nstruct _objc_module {\n";
-  Result += "\tlong version;\n";
-  Result += "\tlong size;\n";
-  Result += "\tconst char *name;\n";
-  Result += "\tstruct _objc_symtab *symtab;\n";
-  Result += "};\n\n";
-  Result += "static struct _objc_module "
-    "_OBJC_MODULES __attribute__ ((used, section (\"__OBJC, __module_info\")))= {\n";
-  Result += "\t" + utostr(OBJC_ABI_VERSION) +
-  ", sizeof(struct _objc_module), \"\", &_OBJC_SYMBOLS\n";
-  Result += "};\n\n";
+  parenCount++;
+  // advance the location to startArgList.
+  DeclLoc = DeclLoc.getLocWithOffset(startArgList-startBuf);
+  assert((DeclLoc.isValid()) && "Invalid DeclLoc");
 
-  if (LangOpts.MicrosoftExt) {
-    if (ProtocolExprDecls.size()) {
-      Result += "#pragma section(\".objc_protocol$B\",long,read,write)\n";
-      Result += "#pragma data_seg(push, \".objc_protocol$B\")\n";
-      for (llvm::SmallPtrSet<ObjCProtocolDecl *,8>::iterator I = ProtocolExprDecls.begin(),
-           E = ProtocolExprDecls.end(); I != E; ++I) {
-        Result += "static struct _objc_protocol *_POINTER_OBJC_PROTOCOL_";
-        Result += (*I)->getNameAsString();
-        Result += " = &_OBJC_PROTOCOL_";
-        Result += (*I)->getNameAsString();
-        Result += ";\n";
-      }
-      Result += "#pragma data_seg(pop)\n\n";
+  const char *argPtr = startArgList;
+
+  while (*argPtr++ && parenCount) {
+    switch (*argPtr) {
+    case '^':
+      // Replace the '^' with '*'.
+      DeclLoc = DeclLoc.getLocWithOffset(argPtr-startArgList);
+      ReplaceText(DeclLoc, 1, "*");
+      break;
+    case '(':
+      parenCount++;
+      break;
+    case ')':
+      parenCount--;
+      break;
     }
-    Result += "#pragma section(\".objc_module_info$B\",long,read,write)\n";
-    Result += "#pragma data_seg(push, \".objc_module_info$B\")\n";
-    Result += "static struct _objc_module *_POINTER_OBJC_MODULES = ";
-    Result += "&_OBJC_MODULES;\n";
-    Result += "#pragma data_seg(pop)\n\n";
   }
+  return;
 }
 
-void RewriteObjC::RewriteByRefString(std::string &ResultStr, 
-                                     const std::string &Name,
-                                     ValueDecl *VD, bool def) {
-  assert(BlockByRefDeclNo.count(VD) && 
-         "RewriteByRefString: ByRef decl missing");
-  if (def)
-    ResultStr += "struct ";
-  ResultStr += "__Block_byref_" + Name + 
-    "_" + utostr(BlockByRefDeclNo[VD]) ;
-}
-
-static bool HasLocalVariableExternalStorage(ValueDecl *VD) {
-  if (VarDecl *Var = dyn_cast<VarDecl>(VD))
-    return (Var->isFunctionOrMethodVarDecl() && !Var->hasLocalStorage());
+bool RewriteObjC::PointerTypeTakesAnyBlockArguments(QualType QT) {
+  const FunctionProtoType *FTP;
+  const PointerType *PT = QT->getAs<PointerType>();
+  if (PT) {
+    FTP = PT->getPointeeType()->getAs<FunctionProtoType>();
+  } else {
+    const BlockPointerType *BPT = QT->getAs<BlockPointerType>();
+    assert(BPT && "BlockPointerTypeTakeAnyBlockArguments(): not a block pointer type");
+    FTP = BPT->getPointeeType()->getAs<FunctionProtoType>();
+  }
+  if (FTP) {
+    for (FunctionProtoType::arg_type_iterator I = FTP->arg_type_begin(),
+         E = FTP->arg_type_end(); I != E; ++I)
+      if (isTopLevelBlockPointerType(*I))
+        return true;
+  }
   return false;
 }
 
-std::string RewriteObjC::SynthesizeBlockFunc(BlockExpr *CE, int i,
-                                                   StringRef funcName,
-                                                   std::string Tag) {
-  const FunctionType *AFT = CE->getFunctionType();
-  QualType RT = AFT->getResultType();
-  std::string StructRef = "struct " + Tag;
-  std::string S = "static " + RT.getAsString(Context->getPrintingPolicy()) + " __" +
-                  funcName.str() + "_" + "block_func_" + utostr(i);
-
-  BlockDecl *BD = CE->getBlockDecl();
-
-  if (isa<FunctionNoProtoType>(AFT)) {
-    // No user-supplied arguments. Still need to pass in a pointer to the
-    // block (to reference imported block decl refs).
-    S += "(" + StructRef + " *__cself)";
-  } else if (BD->param_empty()) {
-    S += "(" + StructRef + " *__cself)";
+bool RewriteObjC::PointerTypeTakesAnyObjCQualifiedType(QualType QT) {
+  const FunctionProtoType *FTP;
+  const PointerType *PT = QT->getAs<PointerType>();
+  if (PT) {
+    FTP = PT->getPointeeType()->getAs<FunctionProtoType>();
   } else {
-    const FunctionProtoType *FT = cast<FunctionProtoType>(AFT);
-    assert(FT && "SynthesizeBlockFunc: No function proto");
-    S += '(';
-    // first add the implicit argument.
-    S += StructRef + " *__cself, ";
-    std::string ParamStr;
-    for (BlockDecl::param_iterator AI = BD->param_begin(),
-         E = BD->param_end(); AI != E; ++AI) {
-      if (AI != BD->param_begin()) S += ", ";
-      ParamStr = (*AI)->getNameAsString();
-      QualType QT = (*AI)->getType();
-      if (convertBlockPointerToFunctionPointer(QT))
-        QT.getAsStringInternal(ParamStr, Context->getPrintingPolicy());
-      else
-        QT.getAsStringInternal(ParamStr, Context->getPrintingPolicy());      
-      S += ParamStr;
-    }
-    if (FT->isVariadic()) {
-      if (!BD->param_empty()) S += ", ";
-      S += "...";
-    }
-    S += ')';
-  }
-  S += " {\n";
-
-  // Create local declarations to avoid rewriting all closure decl ref exprs.
-  // First, emit a declaration for all "by ref" decls.
-  for (SmallVector<ValueDecl*,8>::iterator I = BlockByRefDecls.begin(),
-       E = BlockByRefDecls.end(); I != E; ++I) {
-    S += "  ";
-    std::string Name = (*I)->getNameAsString();
-    std::string TypeString;
-    RewriteByRefString(TypeString, Name, (*I));
-    TypeString += " *";
-    Name = TypeString + Name;
-    S += Name + " = __cself->" + (*I)->getNameAsString() + "; // bound by ref\n";
+    const BlockPointerType *BPT = QT->getAs<BlockPointerType>();
+    assert(BPT && "BlockPointerTypeTakeAnyBlockArguments(): not a block pointer type");
+    FTP = BPT->getPointeeType()->getAs<FunctionProtoType>();
   }
-  // Next, emit a declaration for all "by copy" declarations.
-  for (SmallVector<ValueDecl*,8>::iterator I = BlockByCopyDecls.begin(),
-       E = BlockByCopyDecls.end(); I != E; ++I) {
-    S += "  ";
-    // Handle nested closure invocation. For example:
-    //
-    //   void (^myImportedClosure)(void);
-    //   myImportedClosure  = ^(void) { setGlobalInt(x + y); };
-    //
-    //   void (^anotherClosure)(void);
-    //   anotherClosure = ^(void) {
-    //     myImportedClosure(); // import and invoke the closure
-    //   };
-    //
-    if (isTopLevelBlockPointerType((*I)->getType())) {
-      RewriteBlockPointerTypeVariable(S, (*I));
-      S += " = (";
-      RewriteBlockPointerType(S, (*I)->getType());
-      S += ")";
-      S += "__cself->" + (*I)->getNameAsString() + "; // bound by copy\n";
-    }
-    else {
-      std::string Name = (*I)->getNameAsString();
-      QualType QT = (*I)->getType();
-      if (HasLocalVariableExternalStorage(*I))
-        QT = Context->getPointerType(QT);
-      QT.getAsStringInternal(Name, Context->getPrintingPolicy());
-      S += Name + " = __cself->" + 
-                              (*I)->getNameAsString() + "; // bound by copy\n";
+  if (FTP) {
+    for (FunctionProtoType::arg_type_iterator I = FTP->arg_type_begin(),
+         E = FTP->arg_type_end(); I != E; ++I) {
+      if ((*I)->isObjCQualifiedIdType())
+        return true;
+      if ((*I)->isObjCObjectPointerType() &&
+          (*I)->getPointeeType()->isObjCQualifiedInterfaceType())
+        return true;
     }
+        
   }
-  std::string RewrittenStr = RewrittenBlockExprs[CE];
-  const char *cstr = RewrittenStr.c_str();
-  while (*cstr++ != '{') ;
-  S += cstr;
-  S += "\n";
-  return S;
+  return false;
 }
 
-std::string RewriteObjC::SynthesizeBlockHelperFuncs(BlockExpr *CE, int i,
-                                                   StringRef funcName,
-                                                   std::string Tag) {
-  std::string StructRef = "struct " + Tag;
-  std::string S = "static void __";
+void RewriteObjC::GetExtentOfArgList(const char *Name, const char *&LParen,
+                                     const char *&RParen) {
+  const char *argPtr = strchr(Name, '(');
+  assert((*argPtr == '(') && "Rewriter fuzzy parser confused");
 
-  S += funcName;
-  S += "_block_copy_" + utostr(i);
-  S += "(" + StructRef;
-  S += "*dst, " + StructRef;
-  S += "*src) {";
-  for (llvm::SmallPtrSet<ValueDecl*,8>::iterator I = ImportedBlockDecls.begin(),
-      E = ImportedBlockDecls.end(); I != E; ++I) {
-    ValueDecl *VD = (*I);
-    S += "_Block_object_assign((void*)&dst->";
-    S += (*I)->getNameAsString();
-    S += ", (void*)src->";
-    S += (*I)->getNameAsString();
-    if (BlockByRefDeclsPtrSet.count((*I)))
-      S += ", " + utostr(BLOCK_FIELD_IS_BYREF) + "/*BLOCK_FIELD_IS_BYREF*/);";
-    else if (VD->getType()->isBlockPointerType())
-      S += ", " + utostr(BLOCK_FIELD_IS_BLOCK) + "/*BLOCK_FIELD_IS_BLOCK*/);";
-    else
-      S += ", " + utostr(BLOCK_FIELD_IS_OBJECT) + "/*BLOCK_FIELD_IS_OBJECT*/);";
-  }
-  S += "}\n";
-  
-  S += "\nstatic void __";
-  S += funcName;
-  S += "_block_dispose_" + utostr(i);
-  S += "(" + StructRef;
-  S += "*src) {";
-  for (llvm::SmallPtrSet<ValueDecl*,8>::iterator I = ImportedBlockDecls.begin(),
-      E = ImportedBlockDecls.end(); I != E; ++I) {
-    ValueDecl *VD = (*I);
-    S += "_Block_object_dispose((void*)src->";
-    S += (*I)->getNameAsString();
-    if (BlockByRefDeclsPtrSet.count((*I)))
-      S += ", " + utostr(BLOCK_FIELD_IS_BYREF) + "/*BLOCK_FIELD_IS_BYREF*/);";
-    else if (VD->getType()->isBlockPointerType())
-      S += ", " + utostr(BLOCK_FIELD_IS_BLOCK) + "/*BLOCK_FIELD_IS_BLOCK*/);";
-    else
-      S += ", " + utostr(BLOCK_FIELD_IS_OBJECT) + "/*BLOCK_FIELD_IS_OBJECT*/);";
+  LParen = argPtr; // output the start.
+  argPtr++; // skip past the left paren.
+  unsigned parenCount = 1;
+
+  while (*argPtr && parenCount) {
+    switch (*argPtr) {
+    case '(': parenCount++; break;
+    case ')': parenCount--; break;
+    default: break;
+    }
+    if (parenCount) argPtr++;
   }
-  S += "}\n";
-  return S;
+  assert((*argPtr == ')') && "Rewriter fuzzy parser confused");
+  RParen = argPtr; // output the end
 }
 
-std::string RewriteObjC::SynthesizeBlockImpl(BlockExpr *CE, std::string Tag, 
-                                             std::string Desc) {
-  std::string S = "\nstruct " + Tag;
-  std::string Constructor = "  " + Tag;
-
-  S += " {\n  struct __block_impl impl;\n";
-  S += "  struct " + Desc;
-  S += "* Desc;\n";
-
-  Constructor += "(void *fp, "; // Invoke function pointer.
-  Constructor += "struct " + Desc; // Descriptor pointer.
-  Constructor += " *desc";
-
-  if (BlockDeclRefs.size()) {
-    // Output all "by copy" declarations.
-    for (SmallVector<ValueDecl*,8>::iterator I = BlockByCopyDecls.begin(),
-         E = BlockByCopyDecls.end(); I != E; ++I) {
-      S += "  ";
-      std::string FieldName = (*I)->getNameAsString();
-      std::string ArgName = "_" + FieldName;
-      // Handle nested closure invocation. For example:
-      //
-      //   void (^myImportedBlock)(void);
-      //   myImportedBlock  = ^(void) { setGlobalInt(x + y); };
-      //
-      //   void (^anotherBlock)(void);
-      //   anotherBlock = ^(void) {
-      //     myImportedBlock(); // import and invoke the closure
-      //   };
-      //
-      if (isTopLevelBlockPointerType((*I)->getType())) {
-        S += "struct __block_impl *";
-        Constructor += ", void *" + ArgName;
-      } else {
-        QualType QT = (*I)->getType();
-        if (HasLocalVariableExternalStorage(*I))
-          QT = Context->getPointerType(QT);
-        QT.getAsStringInternal(FieldName, Context->getPrintingPolicy());
-        QT.getAsStringInternal(ArgName, Context->getPrintingPolicy());
-        Constructor += ", " + ArgName;
-      }
-      S += FieldName + ";\n";
-    }
-    // Output all "by ref" declarations.
-    for (SmallVector<ValueDecl*,8>::iterator I = BlockByRefDecls.begin(),
-         E = BlockByRefDecls.end(); I != E; ++I) {
-      S += "  ";
-      std::string FieldName = (*I)->getNameAsString();
-      std::string ArgName = "_" + FieldName;
-      {
-        std::string TypeString;
-        RewriteByRefString(TypeString, FieldName, (*I));
-        TypeString += " *";
-        FieldName = TypeString + FieldName;
-        ArgName = TypeString + ArgName;
-        Constructor += ", " + ArgName;
-      }
-      S += FieldName + "; // by ref\n";
-    }
-    // Finish writing the constructor.
-    Constructor += ", int flags=0)";
-    // Initialize all "by copy" arguments.
-    bool firsTime = true;
-    for (SmallVector<ValueDecl*,8>::iterator I = BlockByCopyDecls.begin(),
-         E = BlockByCopyDecls.end(); I != E; ++I) {
-      std::string Name = (*I)->getNameAsString();
-        if (firsTime) {
-          Constructor += " : ";
-          firsTime = false;
+void RewriteObjC::RewriteBlockPointerDecl(NamedDecl *ND) {
+  if (FunctionDecl *FD = dyn_cast<FunctionDecl>(ND)) {
+    RewriteBlockPointerFunctionArgs(FD);
+    return;
+  }
+  // Handle Variables and Typedefs.
+  SourceLocation DeclLoc = ND->getLocation();
+  QualType DeclT;
+  if (VarDecl *VD = dyn_cast<VarDecl>(ND))
+    DeclT = VD->getType();
+  else if (TypedefNameDecl *TDD = dyn_cast<TypedefNameDecl>(ND))
+    DeclT = TDD->getUnderlyingType();
+  else if (FieldDecl *FD = dyn_cast<FieldDecl>(ND))
+    DeclT = FD->getType();
+  else
+    llvm_unreachable("RewriteBlockPointerDecl(): Decl type not yet handled");
+
+  const char *startBuf = SM->getCharacterData(DeclLoc);
+  const char *endBuf = startBuf;
+  // scan backward (from the decl location) for the end of the previous decl.
+  while (*startBuf != '^' && *startBuf != ';' && startBuf != MainFileStart)
+    startBuf--;
+  SourceLocation Start = DeclLoc.getLocWithOffset(startBuf-endBuf);
+  std::string buf;
+  unsigned OrigLength=0;
+  // *startBuf != '^' if we are dealing with a pointer to function that
+  // may take block argument types (which will be handled below).
+  if (*startBuf == '^') {
+    // Replace the '^' with '*', computing a negative offset.
+    buf = '*';
+    startBuf++;
+    OrigLength++;
+  }
+  while (*startBuf != ')') {
+    buf += *startBuf;
+    startBuf++;
+    OrigLength++;
+  }
+  buf += ')';
+  OrigLength++;
+  
+  if (PointerTypeTakesAnyBlockArguments(DeclT) ||
+      PointerTypeTakesAnyObjCQualifiedType(DeclT)) {
+    // Replace the '^' with '*' for arguments.
+    // Replace id<P> with id/*<>*/
+    DeclLoc = ND->getLocation();
+    startBuf = SM->getCharacterData(DeclLoc);
+    const char *argListBegin, *argListEnd;
+    GetExtentOfArgList(startBuf, argListBegin, argListEnd);
+    while (argListBegin < argListEnd) {
+      if (*argListBegin == '^')
+        buf += '*';
+      else if (*argListBegin ==  '<') {
+        buf += "/*"; 
+        buf += *argListBegin++;
+        OrigLength++;;
+        while (*argListBegin != '>') {
+          buf += *argListBegin++;
+          OrigLength++;
         }
-        else
-          Constructor += ", ";
-        if (isTopLevelBlockPointerType((*I)->getType()))
-          Constructor += Name + "((struct __block_impl *)_" + Name + ")";
-        else
-          Constructor += Name + "(_" + Name + ")";
-    }
-    // Initialize all "by ref" arguments.
-    for (SmallVector<ValueDecl*,8>::iterator I = BlockByRefDecls.begin(),
-         E = BlockByRefDecls.end(); I != E; ++I) {
-      std::string Name = (*I)->getNameAsString();
-      if (firsTime) {
-        Constructor += " : ";
-        firsTime = false;
+        buf += *argListBegin;
+        buf += "*/";
       }
       else
-        Constructor += ", ";
-      Constructor += Name + "(_" + Name + "->__forwarding)";
+        buf += *argListBegin;
+      argListBegin++;
+      OrigLength++;
     }
-    
-    Constructor += " {\n";
-    if (GlobalVarDecl)
-      Constructor += "    impl.isa = &_NSConcreteGlobalBlock;\n";
-    else
-      Constructor += "    impl.isa = &_NSConcreteStackBlock;\n";
-    Constructor += "    impl.Flags = flags;\n    impl.FuncPtr = fp;\n";
-
-    Constructor += "    Desc = desc;\n";
-  } else {
-    // Finish writing the constructor.
-    Constructor += ", int flags=0) {\n";
-    if (GlobalVarDecl)
-      Constructor += "    impl.isa = &_NSConcreteGlobalBlock;\n";
-    else
-      Constructor += "    impl.isa = &_NSConcreteStackBlock;\n";
-    Constructor += "    impl.Flags = flags;\n    impl.FuncPtr = fp;\n";
-    Constructor += "    Desc = desc;\n";
+    buf += ')';
+    OrigLength++;
   }
-  Constructor += "  ";
-  Constructor += "}\n";
-  S += Constructor;
-  S += "};\n";
-  return S;
+  ReplaceText(Start, OrigLength, buf);
+  
+  return;
 }
 
-std::string RewriteObjC::SynthesizeBlockDescriptor(std::string DescTag, 
-                                                   std::string ImplTag, int i,
-                                                   StringRef FunName,
-                                                   unsigned hasCopy) {
-  std::string S = "\nstatic struct " + DescTag;
-  
-  S += " {\n  unsigned long reserved;\n";
-  S += "  unsigned long Block_size;\n";
-  if (hasCopy) {
-    S += "  void (*copy)(struct ";
-    S += ImplTag; S += "*, struct ";
-    S += ImplTag; S += "*);\n";
-    
-    S += "  void (*dispose)(struct ";
-    S += ImplTag; S += "*);\n";
-  }
-  S += "} ";
 
-  S += DescTag + "_DATA = { 0, sizeof(struct ";
-  S += ImplTag + ")";
-  if (hasCopy) {
-    S += ", __" + FunName.str() + "_block_copy_" + utostr(i);
-    S += ", __" + FunName.str() + "_block_dispose_" + utostr(i);
-  }
-  S += "};\n";
+/// SynthesizeByrefCopyDestroyHelper - This routine synthesizes:
+/// void __Block_byref_id_object_copy(struct Block_byref_id_object *dst,
+///                    struct Block_byref_id_object *src) {
+///  _Block_object_assign (&_dest->object, _src->object, 
+///                        BLOCK_BYREF_CALLER | BLOCK_FIELD_IS_OBJECT
+///                        [|BLOCK_FIELD_IS_WEAK]) // object
+///  _Block_object_assign(&_dest->object, _src->object, 
+///                       BLOCK_BYREF_CALLER | BLOCK_FIELD_IS_BLOCK
+///                       [|BLOCK_FIELD_IS_WEAK]) // block
+/// }
+/// And:
+/// void __Block_byref_id_object_dispose(struct Block_byref_id_object *_src) {
+///  _Block_object_dispose(_src->object, 
+///                        BLOCK_BYREF_CALLER | BLOCK_FIELD_IS_OBJECT
+///                        [|BLOCK_FIELD_IS_WEAK]) // object
+///  _Block_object_dispose(_src->object, 
+///                         BLOCK_BYREF_CALLER | BLOCK_FIELD_IS_BLOCK
+///                         [|BLOCK_FIELD_IS_WEAK]) // block
+/// }
+
+std::string RewriteObjC::SynthesizeByrefCopyDestroyHelper(VarDecl *VD,
+                                                          int flag) {
+  std::string S;
+  if (CopyDestroyCache.count(flag))
+    return S;
+  CopyDestroyCache.insert(flag);
+  S = "static void __Block_byref_id_object_copy_";
+  S += utostr(flag);
+  S += "(void *dst, void *src) {\n";
+  
+  // offset into the object pointer is computed as:
+  // void * + void* + int + int + void* + void *
+  unsigned IntSize = 
+  static_cast<unsigned>(Context->getTypeSize(Context->IntTy));
+  unsigned VoidPtrSize = 
+  static_cast<unsigned>(Context->getTypeSize(Context->VoidPtrTy));
+  
+  unsigned offset = (VoidPtrSize*4 + IntSize + IntSize)/Context->getCharWidth();
+  S += " _Block_object_assign((char*)dst + ";
+  S += utostr(offset);
+  S += ", *(void * *) ((char*)src + ";
+  S += utostr(offset);
+  S += "), ";
+  S += utostr(flag);
+  S += ");\n}\n";
+  
+  S += "static void __Block_byref_id_object_dispose_";
+  S += utostr(flag);
+  S += "(void *src) {\n";
+  S += " _Block_object_dispose(*(void * *) ((char*)src + ";
+  S += utostr(offset);
+  S += "), ";
+  S += utostr(flag);
+  S += ");\n}\n";
   return S;
 }
 
-void RewriteObjC::SynthesizeBlockLiterals(SourceLocation FunLocStart,
-                                          StringRef FunName) {
-  // Insert declaration for the function in which block literal is used.
-  if (CurFunctionDeclToDeclareForBlock && !Blocks.empty())
-    RewriteBlockLiteralFunctionDecl(CurFunctionDeclToDeclareForBlock);
-  bool RewriteSC = (GlobalVarDecl &&
-                    !Blocks.empty() &&
-                    GlobalVarDecl->getStorageClass() == SC_Static &&
-                    GlobalVarDecl->getType().getCVRQualifiers());
-  if (RewriteSC) {
-    std::string SC(" void __");
-    SC += GlobalVarDecl->getNameAsString();
-    SC += "() {}";
-    InsertText(FunLocStart, SC);
-  }
+/// RewriteByRefVar - For each __block typex ND variable this routine transforms
+/// the declaration into:
+/// struct __Block_byref_ND {
+/// void *__isa;                  // NULL for everything except __weak pointers
+/// struct __Block_byref_ND *__forwarding;
+/// int32_t __flags;
+/// int32_t __size;
+/// void *__Block_byref_id_object_copy; // If variable is __block ObjC object
+/// void *__Block_byref_id_object_dispose; // If variable is __block ObjC object
+/// typex ND;
+/// };
+///
+/// It then replaces declaration of ND variable with:
+/// struct __Block_byref_ND ND = {__isa=0B, __forwarding=&ND, __flags=some_flag, 
+///                               __size=sizeof(struct __Block_byref_ND), 
+///                               ND=initializer-if-any};
+///
+///
+void RewriteObjC::RewriteByRefVar(VarDecl *ND) {
+  // Insert declaration for the function in which block literal is
+  // used.
+  if (CurFunctionDeclToDeclareForBlock)
+    RewriteBlockLiteralFunctionDecl(CurFunctionDeclToDeclareForBlock);
+  int flag = 0;
+  int isa = 0;
+  SourceLocation DeclLoc = ND->getTypeSpecStartLoc();
+  if (DeclLoc.isInvalid())
+    // If type location is missing, it is because of missing type (a warning).
+    // Use variable's location which is good for this case.
+    DeclLoc = ND->getLocation();
+  const char *startBuf = SM->getCharacterData(DeclLoc);
+  SourceLocation X = ND->getLocEnd();
+  X = SM->getExpansionLoc(X);
+  const char *endBuf = SM->getCharacterData(X);
+  std::string Name(ND->getNameAsString());
+  std::string ByrefType;
+  RewriteByRefString(ByrefType, Name, ND, true);
+  ByrefType += " {\n";
+  ByrefType += "  void *__isa;\n";
+  RewriteByRefString(ByrefType, Name, ND);
+  ByrefType += " *__forwarding;\n";
+  ByrefType += " int __flags;\n";
+  ByrefType += " int __size;\n";
+  // Add void *__Block_byref_id_object_copy; 
+  // void *__Block_byref_id_object_dispose; if needed.
+  QualType Ty = ND->getType();
+  bool HasCopyAndDispose = Context->BlockRequiresCopying(Ty);
+  if (HasCopyAndDispose) {
+    ByrefType += " void (*__Block_byref_id_object_copy)(void*, void*);\n";
+    ByrefType += " void (*__Block_byref_id_object_dispose)(void*);\n";
+  }
+
+  QualType T = Ty;
+  (void)convertBlockPointerToFunctionPointer(T);
+  T.getAsStringInternal(Name, Context->getPrintingPolicy());
+    
+  ByrefType += " " + Name + ";\n";
+  ByrefType += "};\n";
+  // Insert this type in global scope. It is needed by helper function.
+  SourceLocation FunLocStart;
+  if (CurFunctionDef)
+     FunLocStart = CurFunctionDef->getTypeSpecStartLoc();
+  else {
+    assert(CurMethodDef && "RewriteByRefVar - CurMethodDef is null");
+    FunLocStart = CurMethodDef->getLocStart();
+  }
+  InsertText(FunLocStart, ByrefType);
+  if (Ty.isObjCGCWeak()) {
+    flag |= BLOCK_FIELD_IS_WEAK;
+    isa = 1;
+  }
   
-  // Insert closures that were part of the function.
-  for (unsigned i = 0, count=0; i < Blocks.size(); i++) {
-    CollectBlockDeclRefInfo(Blocks[i]);
-    // Need to copy-in the inner copied-in variables not actually used in this
-    // block.
-    for (int j = 0; j < InnerDeclRefsCount[i]; j++) {
-      BlockDeclRefExpr *Exp = InnerDeclRefs[count++];
+  if (HasCopyAndDispose) {
+    flag = BLOCK_BYREF_CALLER;
+    QualType Ty = ND->getType();
+    // FIXME. Handle __weak variable (BLOCK_FIELD_IS_WEAK) as well.
+    if (Ty->isBlockPointerType())
+      flag |= BLOCK_FIELD_IS_BLOCK;
+    else
+      flag |= BLOCK_FIELD_IS_OBJECT;
+    std::string HF = SynthesizeByrefCopyDestroyHelper(ND, flag);
+    if (!HF.empty())
+      InsertText(FunLocStart, HF);
+  }
+  
+  // struct __Block_byref_ND ND = 
+  // {0, &ND, some_flag, __size=sizeof(struct __Block_byref_ND), 
+  //  initializer-if-any};
+  bool hasInit = (ND->getInit() != 0);
+  unsigned flags = 0;
+  if (HasCopyAndDispose)
+    flags |= BLOCK_HAS_COPY_DISPOSE;
+  Name = ND->getNameAsString();
+  ByrefType.clear();
+  RewriteByRefString(ByrefType, Name, ND);
+  std::string ForwardingCastType("(");
+  ForwardingCastType += ByrefType + " *)";
+  if (!hasInit) {
+    ByrefType += " " + Name + " = {(void*)";
+    ByrefType += utostr(isa);
+    ByrefType += "," +  ForwardingCastType + "&" + Name + ", ";
+    ByrefType += utostr(flags);
+    ByrefType += ", ";
+    ByrefType += "sizeof(";
+    RewriteByRefString(ByrefType, Name, ND);
+    ByrefType += ")";
+    if (HasCopyAndDispose) {
+      ByrefType += ", __Block_byref_id_object_copy_";
+      ByrefType += utostr(flag);
+      ByrefType += ", __Block_byref_id_object_dispose_";
+      ByrefType += utostr(flag);
+    }
+    ByrefType += "};\n";
+    unsigned nameSize = Name.size();
+    // for block or function pointer declaration. Name is aleady
+    // part of the declaration.
+    if (Ty->isBlockPointerType() || Ty->isFunctionPointerType())
+      nameSize = 1;
+    ReplaceText(DeclLoc, endBuf-startBuf+nameSize, ByrefType);
+  }
+  else {
+    SourceLocation startLoc;
+    Expr *E = ND->getInit();
+    if (const CStyleCastExpr *ECE = dyn_cast<CStyleCastExpr>(E))
+      startLoc = ECE->getLParenLoc();
+    else
+      startLoc = E->getLocStart();
+    startLoc = SM->getExpansionLoc(startLoc);
+    endBuf = SM->getCharacterData(startLoc);
+    ByrefType += " " + Name;
+    ByrefType += " = {(void*)";
+    ByrefType += utostr(isa);
+    ByrefType += "," +  ForwardingCastType + "&" + Name + ", ";
+    ByrefType += utostr(flags);
+    ByrefType += ", ";
+    ByrefType += "sizeof(";
+    RewriteByRefString(ByrefType, Name, ND);
+    ByrefType += "), ";
+    if (HasCopyAndDispose) {
+      ByrefType += "__Block_byref_id_object_copy_";
+      ByrefType += utostr(flag);
+      ByrefType += ", __Block_byref_id_object_dispose_";
+      ByrefType += utostr(flag);
+      ByrefType += ", ";
+    }
+    ReplaceText(DeclLoc, endBuf-startBuf, ByrefType);
+    
+    // Complete the newly synthesized compound expression by inserting a right
+    // curly brace before the end of the declaration.
+    // FIXME: This approach avoids rewriting the initializer expression. It
+    // also assumes there is only one declarator. For example, the following
+    // isn't currently supported by this routine (in general):
+    // 
+    // double __block BYREFVAR = 1.34, BYREFVAR2 = 1.37;
+    //
+    const char *startInitializerBuf = SM->getCharacterData(startLoc);
+    const char *semiBuf = strchr(startInitializerBuf, ';');
+    assert((*semiBuf == ';') && "RewriteByRefVar: can't find ';'");
+    SourceLocation semiLoc =
+      startLoc.getLocWithOffset(semiBuf-startInitializerBuf);
+
+    InsertText(semiLoc, "}");
+  }
+  return;
+}
+
+void RewriteObjC::CollectBlockDeclRefInfo(BlockExpr *Exp) {
+  // Add initializers for any closure decl refs.
+  GetBlockDeclRefExprs(Exp->getBody());
+  if (BlockDeclRefs.size()) {
+    // Unique all "by copy" declarations.
+    for (unsigned i = 0; i < BlockDeclRefs.size(); i++)
+      if (!BlockDeclRefs[i]->isByRef()) {
+        if (!BlockByCopyDeclsPtrSet.count(BlockDeclRefs[i]->getDecl())) {
+          BlockByCopyDeclsPtrSet.insert(BlockDeclRefs[i]->getDecl());
+          BlockByCopyDecls.push_back(BlockDeclRefs[i]->getDecl());
+        }
+      }
+    // Unique all "by ref" declarations.
+    for (unsigned i = 0; i < BlockDeclRefs.size(); i++)
+      if (BlockDeclRefs[i]->isByRef()) {
+        if (!BlockByRefDeclsPtrSet.count(BlockDeclRefs[i]->getDecl())) {
+          BlockByRefDeclsPtrSet.insert(BlockDeclRefs[i]->getDecl());
+          BlockByRefDecls.push_back(BlockDeclRefs[i]->getDecl());
+        }
+      }
+    // Find any imported blocks...they will need special attention.
+    for (unsigned i = 0; i < BlockDeclRefs.size(); i++)
+      if (BlockDeclRefs[i]->isByRef() ||
+          BlockDeclRefs[i]->getType()->isObjCObjectPointerType() || 
+          BlockDeclRefs[i]->getType()->isBlockPointerType())
+        ImportedBlockDecls.insert(BlockDeclRefs[i]->getDecl());
+  }
+}
+
+FunctionDecl *RewriteObjC::SynthBlockInitFunctionDecl(StringRef name) {
+  IdentifierInfo *ID = &Context->Idents.get(name);
+  QualType FType = Context->getFunctionNoProtoType(Context->VoidPtrTy);
+  return FunctionDecl::Create(*Context, TUDecl, SourceLocation(),
+                              SourceLocation(), ID, FType, 0, SC_Extern,
+                              SC_None, false, false);
+}
+
+Stmt *RewriteObjC::SynthBlockInitExpr(BlockExpr *Exp,
+          const SmallVector<BlockDeclRefExpr *, 8> &InnerBlockDeclRefs) {
+  const BlockDecl *block = Exp->getBlockDecl();
+  Blocks.push_back(Exp);
+
+  CollectBlockDeclRefInfo(Exp);
+  
+  // Add inner imported variables now used in current block.
+ int countOfInnerDecls = 0;
+  if (!InnerBlockDeclRefs.empty()) {
+    for (unsigned i = 0; i < InnerBlockDeclRefs.size(); i++) {
+      BlockDeclRefExpr *Exp = InnerBlockDeclRefs[i];
       ValueDecl *VD = Exp->getDecl();
-      BlockDeclRefs.push_back(Exp);
       if (!Exp->isByRef() && !BlockByCopyDeclsPtrSet.count(VD)) {
+      // We need to save the copied-in variables in nested
+      // blocks because it is needed at the end for some of the API generations.
+      // See SynthesizeBlockLiterals routine.
+        InnerDeclRefs.push_back(Exp); countOfInnerDecls++;
+        BlockDeclRefs.push_back(Exp);
         BlockByCopyDeclsPtrSet.insert(VD);
         BlockByCopyDecls.push_back(VD);
       }
       if (Exp->isByRef() && !BlockByRefDeclsPtrSet.count(VD)) {
+        InnerDeclRefs.push_back(Exp); countOfInnerDecls++;
+        BlockDeclRefs.push_back(Exp);
         BlockByRefDeclsPtrSet.insert(VD);
         BlockByRefDecls.push_back(VD);
       }
-      // imported objects in the inner blocks not used in the outer
-      // blocks must be copied/disposed in the outer block as well.
-      if (Exp->isByRef() ||
-          VD->getType()->isObjCObjectPointerType() || 
-          VD->getType()->isBlockPointerType())
-        ImportedBlockDecls.insert(VD);
     }
+    // Find any imported blocks...they will need special attention.
+    for (unsigned i = 0; i < InnerBlockDeclRefs.size(); i++)
+      if (InnerBlockDeclRefs[i]->isByRef() ||
+          InnerBlockDeclRefs[i]->getType()->isObjCObjectPointerType() || 
+          InnerBlockDeclRefs[i]->getType()->isBlockPointerType())
+        ImportedBlockDecls.insert(InnerBlockDeclRefs[i]->getDecl());
+  }
+  InnerDeclRefsCount.push_back(countOfInnerDecls);
+  
+  std::string FuncName;
 
-    std::string ImplTag = "__" + FunName.str() + "_block_impl_" + utostr(i);
-    std::string DescTag = "__" + FunName.str() + "_block_desc_" + utostr(i);
+  if (CurFunctionDef)
+    FuncName = CurFunctionDef->getNameAsString();
+  else if (CurMethodDef)
+    BuildUniqueMethodName(FuncName, CurMethodDef);
+  else if (GlobalVarDecl)
+    FuncName = std::string(GlobalVarDecl->getNameAsString());
 
-    std::string CI = SynthesizeBlockImpl(Blocks[i], ImplTag, DescTag);
+  std::string BlockNumber = utostr(Blocks.size()-1);
 
-    InsertText(FunLocStart, CI);
+  std::string Tag = "__" + FuncName + "_block_impl_" + BlockNumber;
+  std::string Func = "__" + FuncName + "_block_func_" + BlockNumber;
 
-    std::string CF = SynthesizeBlockFunc(Blocks[i], i, FunName, ImplTag);
+  // Get a pointer to the function type so we can cast appropriately.
+  QualType BFT = convertFunctionTypeOfBlocks(Exp->getFunctionType());
+  QualType FType = Context->getPointerType(BFT);
 
-    InsertText(FunLocStart, CF);
+  FunctionDecl *FD;
+  Expr *NewRep;
 
-    if (ImportedBlockDecls.size()) {
-      std::string HF = SynthesizeBlockHelperFuncs(Blocks[i], i, FunName, ImplTag);
-      InsertText(FunLocStart, HF);
-    }
-    std::string BD = SynthesizeBlockDescriptor(DescTag, ImplTag, i, FunName,
-                                               ImportedBlockDecls.size() > 0);
-    InsertText(FunLocStart, BD);
+  // Simulate a contructor call...
+  FD = SynthBlockInitFunctionDecl(Tag);
+  DeclRefExpr *DRE = new (Context) DeclRefExpr(FD, FType, VK_RValue,
+                                               SourceLocation());
 
-    BlockDeclRefs.clear();
-    BlockByRefDecls.clear();
-    BlockByRefDeclsPtrSet.clear();
-    BlockByCopyDecls.clear();
-    BlockByCopyDeclsPtrSet.clear();
-    ImportedBlockDecls.clear();
+  SmallVector<Expr*, 4> InitExprs;
+
+  // Initialize the block function.
+  FD = SynthBlockInitFunctionDecl(Func);
+  DeclRefExpr *Arg = new (Context) DeclRefExpr(FD, FD->getType(), VK_LValue,
+                                               SourceLocation());
+  CastExpr *castExpr = NoTypeInfoCStyleCastExpr(Context, Context->VoidPtrTy,
+                                                CK_BitCast, Arg);
+  InitExprs.push_back(castExpr);
+
+  // Initialize the block descriptor.
+  std::string DescData = "__" + FuncName + "_block_desc_" + BlockNumber + "_DATA";
+
+  VarDecl *NewVD = VarDecl::Create(*Context, TUDecl,
+                                   SourceLocation(), SourceLocation(),
+                                   &Context->Idents.get(DescData.c_str()),
+                                   Context->VoidPtrTy, 0,
+                                   SC_Static, SC_None);
+  UnaryOperator *DescRefExpr =
+    new (Context) UnaryOperator(new (Context) DeclRefExpr(NewVD,
+                                                          Context->VoidPtrTy,
+                                                          VK_LValue,
+                                                          SourceLocation()), 
+                                UO_AddrOf,
+                                Context->getPointerType(Context->VoidPtrTy), 
+                                VK_RValue, OK_Ordinary,
+                                SourceLocation());
+  InitExprs.push_back(DescRefExpr); 
+  
+  // Add initializers for any closure decl refs.
+  if (BlockDeclRefs.size()) {
+    Expr *Exp;
+    // Output all "by copy" declarations.
+    for (SmallVector<ValueDecl*,8>::iterator I = BlockByCopyDecls.begin(),
+         E = BlockByCopyDecls.end(); I != E; ++I) {
+      if (isObjCType((*I)->getType())) {
+        // FIXME: Conform to ABI ([[obj retain] autorelease]).
+        FD = SynthBlockInitFunctionDecl((*I)->getName());
+        Exp = new (Context) DeclRefExpr(FD, FD->getType(), VK_LValue,
+                                        SourceLocation());
+        if (HasLocalVariableExternalStorage(*I)) {
+          QualType QT = (*I)->getType();
+          QT = Context->getPointerType(QT);
+          Exp = new (Context) UnaryOperator(Exp, UO_AddrOf, QT, VK_RValue,
+                                            OK_Ordinary, SourceLocation());
+        }
+      } else if (isTopLevelBlockPointerType((*I)->getType())) {
+        FD = SynthBlockInitFunctionDecl((*I)->getName());
+        Arg = new (Context) DeclRefExpr(FD, FD->getType(), VK_LValue,
+                                        SourceLocation());
+        Exp = NoTypeInfoCStyleCastExpr(Context, Context->VoidPtrTy,
+                                       CK_BitCast, Arg);
+      } else {
+        FD = SynthBlockInitFunctionDecl((*I)->getName());
+        Exp = new (Context) DeclRefExpr(FD, FD->getType(), VK_LValue,
+                                        SourceLocation());
+        if (HasLocalVariableExternalStorage(*I)) {
+          QualType QT = (*I)->getType();
+          QT = Context->getPointerType(QT);
+          Exp = new (Context) UnaryOperator(Exp, UO_AddrOf, QT, VK_RValue,
+                                            OK_Ordinary, SourceLocation());
+        }
+        
+      }
+      InitExprs.push_back(Exp);
+    }
+    // Output all "by ref" declarations.
+    for (SmallVector<ValueDecl*,8>::iterator I = BlockByRefDecls.begin(),
+         E = BlockByRefDecls.end(); I != E; ++I) {
+      ValueDecl *ND = (*I);
+      std::string Name(ND->getNameAsString());
+      std::string RecName;
+      RewriteByRefString(RecName, Name, ND, true);
+      IdentifierInfo *II = &Context->Idents.get(RecName.c_str() 
+                                                + sizeof("struct"));
+      RecordDecl *RD = RecordDecl::Create(*Context, TTK_Struct, TUDecl,
+                                          SourceLocation(), SourceLocation(),
+                                          II);
+      assert(RD && "SynthBlockInitExpr(): Can't find RecordDecl");
+      QualType castT = Context->getPointerType(Context->getTagDeclType(RD));
+      
+      FD = SynthBlockInitFunctionDecl((*I)->getName());
+      Exp = new (Context) DeclRefExpr(FD, FD->getType(), VK_LValue,
+                                      SourceLocation());
+      bool isNestedCapturedVar = false;
+      if (block)
+        for (BlockDecl::capture_const_iterator ci = block->capture_begin(),
+             ce = block->capture_end(); ci != ce; ++ci) {
+          const VarDecl *variable = ci->getVariable();
+          if (variable == ND && ci->isNested()) {
+            assert (ci->isByRef() && 
+                    "SynthBlockInitExpr - captured block variable is not byref");
+            isNestedCapturedVar = true;
+            break;
+          }
+        }
+      // captured nested byref variable has its address passed. Do not take
+      // its address again.
+      if (!isNestedCapturedVar)
+          Exp = new (Context) UnaryOperator(Exp, UO_AddrOf,
+                                     Context->getPointerType(Exp->getType()),
+                                     VK_RValue, OK_Ordinary, SourceLocation());
+      Exp = NoTypeInfoCStyleCastExpr(Context, castT, CK_BitCast, Exp);
+      InitExprs.push_back(Exp);
+    }
   }
-  if (RewriteSC) {
-    // Must insert any 'const/volatile/static here. Since it has been
-    // removed as result of rewriting of block literals.
-    std::string SC;
-    if (GlobalVarDecl->getStorageClass() == SC_Static)
-      SC = "static ";
-    if (GlobalVarDecl->getType().isConstQualified())
-      SC += "const ";
-    if (GlobalVarDecl->getType().isVolatileQualified())
-      SC += "volatile ";
-    if (GlobalVarDecl->getType().isRestrictQualified())
-      SC += "restrict ";
-    InsertText(FunLocStart, SC);
+  if (ImportedBlockDecls.size()) {
+    // generate BLOCK_HAS_COPY_DISPOSE(have helper funcs) | BLOCK_HAS_DESCRIPTOR
+    int flag = (BLOCK_HAS_COPY_DISPOSE | BLOCK_HAS_DESCRIPTOR);
+    unsigned IntSize = 
+      static_cast<unsigned>(Context->getTypeSize(Context->IntTy));
+    Expr *FlagExp = IntegerLiteral::Create(*Context, llvm::APInt(IntSize, flag), 
+                                           Context->IntTy, SourceLocation());
+    InitExprs.push_back(FlagExp);
   }
-  
-  Blocks.clear();
-  InnerDeclRefsCount.clear();
-  InnerDeclRefs.clear();
-  RewrittenBlockExprs.clear();
+  NewRep = new (Context) CallExpr(*Context, DRE, &InitExprs[0], InitExprs.size(),
+                                  FType, VK_LValue, SourceLocation());
+  NewRep = new (Context) UnaryOperator(NewRep, UO_AddrOf,
+                             Context->getPointerType(NewRep->getType()),
+                             VK_RValue, OK_Ordinary, SourceLocation());
+  NewRep = NoTypeInfoCStyleCastExpr(Context, FType, CK_BitCast,
+                                    NewRep);
+  BlockDeclRefs.clear();
+  BlockByRefDecls.clear();
+  BlockByRefDeclsPtrSet.clear();
+  BlockByCopyDecls.clear();
+  BlockByCopyDeclsPtrSet.clear();
+  ImportedBlockDecls.clear();
+  return NewRep;
 }
 
-void RewriteObjC::InsertBlockLiteralsWithinFunction(FunctionDecl *FD) {
-  SourceLocation FunLocStart = FD->getTypeSpecStartLoc();
-  StringRef FuncName = FD->getName();
-
-  SynthesizeBlockLiterals(FunLocStart, FuncName);
+bool RewriteObjC::IsDeclStmtInForeachHeader(DeclStmt *DS) {
+  if (const ObjCForCollectionStmt * CS = 
+      dyn_cast<ObjCForCollectionStmt>(Stmts.back()))
+        return CS->getElement() == DS;
+  return false;
 }
 
-static void BuildUniqueMethodName(std::string &Name,
-                                  ObjCMethodDecl *MD) {
-  ObjCInterfaceDecl *IFace = MD->getClassInterface();
-  Name = IFace->getName();
-  Name += "__" + MD->getSelector().getAsString();
-  // Convert colons to underscores.
-  std::string::size_type loc = 0;
-  while ((loc = Name.find(":", loc)) != std::string::npos)
-    Name.replace(loc, 1, "_");
-}
+//===----------------------------------------------------------------------===//
+// Function Body / Expression rewriting
+//===----------------------------------------------------------------------===//
 
-void RewriteObjC::InsertBlockLiteralsWithinMethod(ObjCMethodDecl *MD) {
-  //fprintf(stderr,"In InsertBlockLiteralsWitinMethod\n");
-  //SourceLocation FunLocStart = MD->getLocStart();
-  SourceLocation FunLocStart = MD->getLocStart();
-  std::string FuncName;
-  BuildUniqueMethodName(FuncName, MD);
-  SynthesizeBlockLiterals(FunLocStart, FuncName);
-}
+Stmt *RewriteObjC::RewriteFunctionBodyOrGlobalInitializer(Stmt *S) {
+  if (isa<SwitchStmt>(S) || isa<WhileStmt>(S) ||
+      isa<DoStmt>(S) || isa<ForStmt>(S))
+    Stmts.push_back(S);
+  else if (isa<ObjCForCollectionStmt>(S)) {
+    Stmts.push_back(S);
+    ObjCBcLabelNo.push_back(++BcLabelCount);
+  }
 
-void RewriteObjC::GetBlockDeclRefExprs(Stmt *S) {
-  for (Stmt::child_range CI = S->children(); CI; ++CI)
-    if (*CI) {
-      if (BlockExpr *CBE = dyn_cast<BlockExpr>(*CI))
-        GetBlockDeclRefExprs(CBE->getBody());
-      else
-        GetBlockDeclRefExprs(*CI);
+  // Pseudo-object operations and ivar references need special
+  // treatment because we're going to recursively rewrite them.
+  if (PseudoObjectExpr *PseudoOp = dyn_cast<PseudoObjectExpr>(S)) {
+    if (isa<BinaryOperator>(PseudoOp->getSyntacticForm())) {
+      return RewritePropertyOrImplicitSetter(PseudoOp);
+    } else {
+      return RewritePropertyOrImplicitGetter(PseudoOp);
     }
-  // Handle specific things.
-  if (BlockDeclRefExpr *CDRE = dyn_cast<BlockDeclRefExpr>(S)) {
-    // FIXME: Handle enums.
-    if (!isa<FunctionDecl>(CDRE->getDecl()))
-      BlockDeclRefs.push_back(CDRE);
+  } else if (ObjCIvarRefExpr *IvarRefExpr = dyn_cast<ObjCIvarRefExpr>(S)) {
+    return RewriteObjCIvarRefExpr(IvarRefExpr);
   }
-  else if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(S))
-    if (HasLocalVariableExternalStorage(DRE->getDecl())) {
-        BlockDeclRefExpr *BDRE = 
-          new (Context)BlockDeclRefExpr(cast<VarDecl>(DRE->getDecl()),
-                                        DRE->getType(), 
-                                        VK_LValue, DRE->getLocation(), false);
-        BlockDeclRefs.push_back(BDRE);
-    }
-  
-  return;
-}
 
-void RewriteObjC::GetInnerBlockDeclRefExprs(Stmt *S, 
-                SmallVector<BlockDeclRefExpr *, 8> &InnerBlockDeclRefs,
-                llvm::SmallPtrSet<const DeclContext *, 8> &InnerContexts) {
+  SourceRange OrigStmtRange = S->getSourceRange();
+
+  // Perform a bottom up rewrite of all children.
   for (Stmt::child_range CI = S->children(); CI; ++CI)
     if (*CI) {
-      if (BlockExpr *CBE = dyn_cast<BlockExpr>(*CI)) {
-        InnerContexts.insert(cast<DeclContext>(CBE->getBlockDecl()));
-        GetInnerBlockDeclRefExprs(CBE->getBody(),
-                                  InnerBlockDeclRefs,
-                                  InnerContexts);
-      }
-      else
-        GetInnerBlockDeclRefExprs(*CI,
-                                  InnerBlockDeclRefs,
-                                  InnerContexts);
-
+      Stmt *childStmt = (*CI);
+      Stmt *newStmt = RewriteFunctionBodyOrGlobalInitializer(childStmt);
+      if (newStmt) {
+        *CI = newStmt;
+      }
     }
-  // Handle specific things.
-  if (BlockDeclRefExpr *CDRE = dyn_cast<BlockDeclRefExpr>(S)) {
-    if (!isa<FunctionDecl>(CDRE->getDecl()) &&
-        !InnerContexts.count(CDRE->getDecl()->getDeclContext()))
-      InnerBlockDeclRefs.push_back(CDRE);
-  }
-  else if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(S)) {
-    if (VarDecl *Var = dyn_cast<VarDecl>(DRE->getDecl()))
-      if (Var->isFunctionOrMethodVarDecl())
-        ImportedLocalExternalDecls.insert(Var);
-  }
-  
-  return;
-}
 
-/// convertFunctionTypeOfBlocks - This routine converts a function type
-/// whose result type may be a block pointer or whose argument type(s)
-/// might be block pointers to an equivalent function type replacing
-/// all block pointers to function pointers.
-QualType RewriteObjC::convertFunctionTypeOfBlocks(const FunctionType *FT) {
-  const FunctionProtoType *FTP = dyn_cast<FunctionProtoType>(FT);
-  // FTP will be null for closures that don't take arguments.
-  // Generate a funky cast.
-  SmallVector<QualType, 8> ArgTypes;
-  QualType Res = FT->getResultType();
-  bool HasBlockType = convertBlockPointerToFunctionPointer(Res);
-  
-  if (FTP) {
-    for (FunctionProtoType::arg_type_iterator I = FTP->arg_type_begin(),
-         E = FTP->arg_type_end(); I && (I != E); ++I) {
-      QualType t = *I;
-      // Make sure we convert "t (^)(...)" to "t (*)(...)".
-      if (convertBlockPointerToFunctionPointer(t))
-        HasBlockType = true;
-      ArgTypes.push_back(t);
-    }
+  if (BlockExpr *BE = dyn_cast<BlockExpr>(S)) {
+    SmallVector<BlockDeclRefExpr *, 8> InnerBlockDeclRefs;
+    llvm::SmallPtrSet<const DeclContext *, 8> InnerContexts;
+    InnerContexts.insert(BE->getBlockDecl());
+    ImportedLocalExternalDecls.clear();
+    GetInnerBlockDeclRefExprs(BE->getBody(),
+                              InnerBlockDeclRefs, InnerContexts);
+    // Rewrite the block body in place.
+    Stmt *SaveCurrentBody = CurrentBody;
+    CurrentBody = BE->getBody();
+    PropParentMap = 0;
+    // block literal on rhs of a property-dot-sytax assignment
+    // must be replaced by its synthesize ast so getRewrittenText
+    // works as expected. In this case, what actually ends up on RHS
+    // is the blockTranscribed which is the helper function for the
+    // block literal; as in: self.c = ^() {[ace ARR];};
+    bool saveDisableReplaceStmt = DisableReplaceStmt;
+    DisableReplaceStmt = false;
+    RewriteFunctionBodyOrGlobalInitializer(BE->getBody());
+    DisableReplaceStmt = saveDisableReplaceStmt;
+    CurrentBody = SaveCurrentBody;
+    PropParentMap = 0;
+    ImportedLocalExternalDecls.clear();
+    // Now we snarf the rewritten text and stash it away for later use.
+    std::string Str = Rewrite.getRewrittenText(BE->getSourceRange());
+    RewrittenBlockExprs[BE] = Str;
+
+    Stmt *blockTranscribed = SynthBlockInitExpr(BE, InnerBlockDeclRefs);
+                            
+    //blockTranscribed->dump();
+    ReplaceStmt(S, blockTranscribed);
+    return blockTranscribed;
   }
-  QualType FuncType;
-  // FIXME. Does this work if block takes no argument but has a return type
-  // which is of block type?
-  if (HasBlockType)
-    FuncType = getSimpleFunctionType(Res, &ArgTypes[0], ArgTypes.size());
-  else FuncType = QualType(FT, 0);
-  return FuncType;
-}
+  // Handle specific things.
+  if (ObjCEncodeExpr *AtEncode = dyn_cast<ObjCEncodeExpr>(S))
+    return RewriteAtEncode(AtEncode);
 
-Stmt *RewriteObjC::SynthesizeBlockCall(CallExpr *Exp, const Expr *BlockExp) {
-  // Navigate to relevant type information.
-  const BlockPointerType *CPT = 0;
+  if (ObjCSelectorExpr *AtSelector = dyn_cast<ObjCSelectorExpr>(S))
+    return RewriteAtSelector(AtSelector);
 
-  if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(BlockExp)) {
-    CPT = DRE->getType()->getAs<BlockPointerType>();
-  } else if (const BlockDeclRefExpr *CDRE = 
-              dyn_cast<BlockDeclRefExpr>(BlockExp)) {
-    CPT = CDRE->getType()->getAs<BlockPointerType>();
-  } else if (const MemberExpr *MExpr = dyn_cast<MemberExpr>(BlockExp)) {
-    CPT = MExpr->getType()->getAs<BlockPointerType>();
-  } 
-  else if (const ParenExpr *PRE = dyn_cast<ParenExpr>(BlockExp)) {
-    return SynthesizeBlockCall(Exp, PRE->getSubExpr());
-  }
-  else if (const ImplicitCastExpr *IEXPR = dyn_cast<ImplicitCastExpr>(BlockExp)) 
-    CPT = IEXPR->getType()->getAs<BlockPointerType>();
-  else if (const ConditionalOperator *CEXPR = 
-            dyn_cast<ConditionalOperator>(BlockExp)) {
-    Expr *LHSExp = CEXPR->getLHS();
-    Stmt *LHSStmt = SynthesizeBlockCall(Exp, LHSExp);
-    Expr *RHSExp = CEXPR->getRHS();
-    Stmt *RHSStmt = SynthesizeBlockCall(Exp, RHSExp);
-    Expr *CONDExp = CEXPR->getCond();
-    ConditionalOperator *CondExpr =
-      new (Context) ConditionalOperator(CONDExp,
-                                      SourceLocation(), cast<Expr>(LHSStmt),
-                                      SourceLocation(), cast<Expr>(RHSStmt),
-                                      Exp->getType(), VK_RValue, OK_Ordinary);
-    return CondExpr;
-  } else if (const ObjCIvarRefExpr *IRE = dyn_cast<ObjCIvarRefExpr>(BlockExp)) {
-    CPT = IRE->getType()->getAs<BlockPointerType>();
-  } else if (const PseudoObjectExpr *POE
-               = dyn_cast<PseudoObjectExpr>(BlockExp)) {
-    CPT = POE->getType()->castAs<BlockPointerType>();
-  } else {
-    assert(1 && "RewriteBlockClass: Bad type");
-  }
-  assert(CPT && "RewriteBlockClass: Bad type");
-  const FunctionType *FT = CPT->getPointeeType()->getAs<FunctionType>();
-  assert(FT && "RewriteBlockClass: Bad type");
-  const FunctionProtoType *FTP = dyn_cast<FunctionProtoType>(FT);
-  // FTP will be null for closures that don't take arguments.
+  if (ObjCStringLiteral *AtString = dyn_cast<ObjCStringLiteral>(S))
+    return RewriteObjCStringLiteral(AtString);
 
-  RecordDecl *RD = RecordDecl::Create(*Context, TTK_Struct, TUDecl,
-                                      SourceLocation(), SourceLocation(),
-                                      &Context->Idents.get("__block_impl"));
-  QualType PtrBlock = Context->getPointerType(Context->getTagDeclType(RD));
+  if (ObjCMessageExpr *MessExpr = dyn_cast<ObjCMessageExpr>(S)) {
+#if 0
+    // Before we rewrite it, put the original message expression in a comment.
+    SourceLocation startLoc = MessExpr->getLocStart();
+    SourceLocation endLoc = MessExpr->getLocEnd();
 
-  // Generate a funky cast.
-  SmallVector<QualType, 8> ArgTypes;
+    const char *startBuf = SM->getCharacterData(startLoc);
+    const char *endBuf = SM->getCharacterData(endLoc);
 
-  // Push the block argument type.
-  ArgTypes.push_back(PtrBlock);
-  if (FTP) {
-    for (FunctionProtoType::arg_type_iterator I = FTP->arg_type_begin(),
-         E = FTP->arg_type_end(); I && (I != E); ++I) {
-      QualType t = *I;
-      // Make sure we convert "t (^)(...)" to "t (*)(...)".
-      if (!convertBlockPointerToFunctionPointer(t))
-        convertToUnqualifiedObjCType(t);
-      ArgTypes.push_back(t);
-    }
+    std::string messString;
+    messString += "// ";
+    messString.append(startBuf, endBuf-startBuf+1);
+    messString += "\n";
+
+    // FIXME: Missing definition of
+    // InsertText(clang::SourceLocation, char const*, unsigned int).
+    // InsertText(startLoc, messString.c_str(), messString.size());
+    // Tried this, but it didn't work either...
+    // ReplaceText(startLoc, 0, messString.c_str(), messString.size());
+#endif
+    return RewriteMessageExpr(MessExpr);
   }
-  // Now do the pointer to function cast.
-  QualType PtrToFuncCastType
-    = getSimpleFunctionType(Exp->getType(), &ArgTypes[0], ArgTypes.size());
 
-  PtrToFuncCastType = Context->getPointerType(PtrToFuncCastType);
+  if (ObjCAtTryStmt *StmtTry = dyn_cast<ObjCAtTryStmt>(S))
+    return RewriteObjCTryStmt(StmtTry);
 
-  CastExpr *BlkCast = NoTypeInfoCStyleCastExpr(Context, PtrBlock,
-                                               CK_BitCast,
-                                               const_cast<Expr*>(BlockExp));
-  // Don't forget the parens to enforce the proper binding.
-  ParenExpr *PE = new (Context) ParenExpr(SourceLocation(), SourceLocation(),
-                                          BlkCast);
-  //PE->dump();
+  if (ObjCAtSynchronizedStmt *StmtTry = dyn_cast<ObjCAtSynchronizedStmt>(S))
+    return RewriteObjCSynchronizedStmt(StmtTry);
 
-  FieldDecl *FD = FieldDecl::Create(*Context, 0, SourceLocation(),
-                                    SourceLocation(),
-                                    &Context->Idents.get("FuncPtr"),
-                                    Context->VoidPtrTy, 0,
-                                    /*BitWidth=*/0, /*Mutable=*/true,
-                                    /*HasInit=*/false);
-  MemberExpr *ME = new (Context) MemberExpr(PE, true, FD, SourceLocation(),
-                                            FD->getType(), VK_LValue,
-                                            OK_Ordinary);
+  if (ObjCAtThrowStmt *StmtThrow = dyn_cast<ObjCAtThrowStmt>(S))
+    return RewriteObjCThrowStmt(StmtThrow);
 
-  
-  CastExpr *FunkCast = NoTypeInfoCStyleCastExpr(Context, PtrToFuncCastType,
-                                                CK_BitCast, ME);
-  PE = new (Context) ParenExpr(SourceLocation(), SourceLocation(), FunkCast);
+  if (ObjCProtocolExpr *ProtocolExp = dyn_cast<ObjCProtocolExpr>(S))
+    return RewriteObjCProtocolExpr(ProtocolExp);
 
-  SmallVector<Expr*, 8> BlkExprs;
-  // Add the implicit argument.
-  BlkExprs.push_back(BlkCast);
-  // Add the user arguments.
-  for (CallExpr::arg_iterator I = Exp->arg_begin(),
-       E = Exp->arg_end(); I != E; ++I) {
-    BlkExprs.push_back(*I);
-  }
-  CallExpr *CE = new (Context) CallExpr(*Context, PE, &BlkExprs[0],
-                                        BlkExprs.size(),
-                                        Exp->getType(), VK_RValue,
-                                        SourceLocation());
-  return CE;
-}
+  if (ObjCForCollectionStmt *StmtForCollection =
+        dyn_cast<ObjCForCollectionStmt>(S))
+    return RewriteObjCForCollectionStmt(StmtForCollection,
+                                        OrigStmtRange.getEnd());
+  if (BreakStmt *StmtBreakStmt =
+      dyn_cast<BreakStmt>(S))
+    return RewriteBreakStmt(StmtBreakStmt);
+  if (ContinueStmt *StmtContinueStmt =
+      dyn_cast<ContinueStmt>(S))
+    return RewriteContinueStmt(StmtContinueStmt);
 
-// We need to return the rewritten expression to handle cases where the
-// BlockDeclRefExpr is embedded in another expression being rewritten.
-// For example:
-//
-// int main() {
-//    __block Foo *f;
-//    __block int i;
-//
-//    void (^myblock)() = ^() {
-//        [f test]; // f is a BlockDeclRefExpr embedded in a message (which is being rewritten).
-//        i = 77;
-//    };
-//}
-Stmt *RewriteObjC::RewriteBlockDeclRefExpr(Expr *DeclRefExp) {
-  // Rewrite the byref variable into BYREFVAR->__forwarding->BYREFVAR 
-  // for each DeclRefExp where BYREFVAR is name of the variable.
-  ValueDecl *VD;
-  bool isArrow = true;
-  if (BlockDeclRefExpr *BDRE = dyn_cast<BlockDeclRefExpr>(DeclRefExp))
-    VD = BDRE->getDecl();
-  else {
-    VD = cast<DeclRefExpr>(DeclRefExp)->getDecl();
-    isArrow = false;
-  }
-  
-  FieldDecl *FD = FieldDecl::Create(*Context, 0, SourceLocation(),
-                                    SourceLocation(),
-                                    &Context->Idents.get("__forwarding"), 
-                                    Context->VoidPtrTy, 0,
-                                    /*BitWidth=*/0, /*Mutable=*/true,
-                                    /*HasInit=*/false);
-  MemberExpr *ME = new (Context) MemberExpr(DeclRefExp, isArrow,
-                                            FD, SourceLocation(),
-                                            FD->getType(), VK_LValue,
-                                            OK_Ordinary);
-
-  StringRef Name = VD->getName();
-  FD = FieldDecl::Create(*Context, 0, SourceLocation(), SourceLocation(),
-                         &Context->Idents.get(Name), 
-                         Context->VoidPtrTy, 0,
-                         /*BitWidth=*/0, /*Mutable=*/true,
-                         /*HasInit=*/false);
-  ME = new (Context) MemberExpr(ME, true, FD, SourceLocation(),
-                                DeclRefExp->getType(), VK_LValue, OK_Ordinary);
-  
-  
-  
-  // Need parens to enforce precedence.
-  ParenExpr *PE = new (Context) ParenExpr(DeclRefExp->getExprLoc(), 
-                                          DeclRefExp->getExprLoc(), 
-                                          ME);
-  ReplaceStmt(DeclRefExp, PE);
-  return PE;
-}
-
-// Rewrites the imported local variable V with external storage 
-// (static, extern, etc.) as *V
-//
-Stmt *RewriteObjC::RewriteLocalVariableExternalStorage(DeclRefExpr *DRE) {
-  ValueDecl *VD = DRE->getDecl();
-  if (VarDecl *Var = dyn_cast<VarDecl>(VD))
-    if (!ImportedLocalExternalDecls.count(Var))
-      return DRE;
-  Expr *Exp = new (Context) UnaryOperator(DRE, UO_Deref, DRE->getType(),
-                                          VK_LValue, OK_Ordinary,
-                                          DRE->getLocation());
-  // Need parens to enforce precedence.
-  ParenExpr *PE = new (Context) ParenExpr(SourceLocation(), SourceLocation(), 
-                                          Exp);
-  ReplaceStmt(DRE, PE);
-  return PE;
-}
-
-void RewriteObjC::RewriteCastExpr(CStyleCastExpr *CE) {
-  SourceLocation LocStart = CE->getLParenLoc();
-  SourceLocation LocEnd = CE->getRParenLoc();
-
-  // Need to avoid trying to rewrite synthesized casts.
-  if (LocStart.isInvalid())
-    return;
-  // Need to avoid trying to rewrite casts contained in macros.
-  if (!Rewriter::isRewritable(LocStart) || !Rewriter::isRewritable(LocEnd))
-    return;
-
-  const char *startBuf = SM->getCharacterData(LocStart);
-  const char *endBuf = SM->getCharacterData(LocEnd);
-  QualType QT = CE->getType();
-  const Type* TypePtr = QT->getAs<Type>();
-  if (isa<TypeOfExprType>(TypePtr)) {
-    const TypeOfExprType *TypeOfExprTypePtr = cast<TypeOfExprType>(TypePtr);
-    QT = TypeOfExprTypePtr->getUnderlyingExpr()->getType();
-    std::string TypeAsString = "(";
-    RewriteBlockPointerType(TypeAsString, QT);
-    TypeAsString += ")";
-    ReplaceText(LocStart, endBuf-startBuf+1, TypeAsString);
-    return;
-  }
-  // advance the location to startArgList.
-  const char *argPtr = startBuf;
+  // Need to check for protocol refs (id <P>, Foo <P> *) in variable decls
+  // and cast exprs.
+  if (DeclStmt *DS = dyn_cast<DeclStmt>(S)) {
+    // FIXME: What we're doing here is modifying the type-specifier that
+    // precedes the first Decl.  In the future the DeclGroup should have
+    // a separate type-specifier that we can rewrite.
+    // NOTE: We need to avoid rewriting the DeclStmt if it is within
+    // the context of an ObjCForCollectionStmt. For example:
+    //   NSArray *someArray;
+    //   for (id <FooProtocol> index in someArray) ;
+    // This is because RewriteObjCForCollectionStmt() does textual rewriting 
+    // and it depends on the original text locations/positions.
+    if (Stmts.empty() || !IsDeclStmtInForeachHeader(DS))
+      RewriteObjCQualifiedInterfaceTypes(*DS->decl_begin());
 
-  while (*argPtr++ && (argPtr < endBuf)) {
-    switch (*argPtr) {
-    case '^':
-      // Replace the '^' with '*'.
-      LocStart = LocStart.getLocWithOffset(argPtr-startBuf);
-      ReplaceText(LocStart, 1, "*");
-      break;
+    // Blocks rewrite rules.
+    for (DeclStmt::decl_iterator DI = DS->decl_begin(), DE = DS->decl_end();
+         DI != DE; ++DI) {
+      Decl *SD = *DI;
+      if (ValueDecl *ND = dyn_cast<ValueDecl>(SD)) {
+        if (isTopLevelBlockPointerType(ND->getType()))
+          RewriteBlockPointerDecl(ND);
+        else if (ND->getType()->isFunctionPointerType())
+          CheckFunctionPointerDecl(ND->getType(), ND);
+        if (VarDecl *VD = dyn_cast<VarDecl>(SD)) {
+          if (VD->hasAttr<BlocksAttr>()) {
+            static unsigned uniqueByrefDeclCount = 0;
+            assert(!BlockByRefDeclNo.count(ND) &&
+              "RewriteFunctionBodyOrGlobalInitializer: Duplicate byref decl");
+            BlockByRefDeclNo[ND] = uniqueByrefDeclCount++;
+            RewriteByRefVar(VD);
+          }
+          else           
+            RewriteTypeOfDecl(VD);
+        }
+      }
+      if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(SD)) {
+        if (isTopLevelBlockPointerType(TD->getUnderlyingType()))
+          RewriteBlockPointerDecl(TD);
+        else if (TD->getUnderlyingType()->isFunctionPointerType())
+          CheckFunctionPointerDecl(TD->getUnderlyingType(), TD);
+      }
     }
   }
-  return;
-}
-
-void RewriteObjC::RewriteBlockPointerFunctionArgs(FunctionDecl *FD) {
-  SourceLocation DeclLoc = FD->getLocation();
-  unsigned parenCount = 0;
-
-  // We have 1 or more arguments that have closure pointers.
-  const char *startBuf = SM->getCharacterData(DeclLoc);
-  const char *startArgList = strchr(startBuf, '(');
-
-  assert((*startArgList == '(') && "Rewriter fuzzy parser confused");
-
-  parenCount++;
-  // advance the location to startArgList.
-  DeclLoc = DeclLoc.getLocWithOffset(startArgList-startBuf);
-  assert((DeclLoc.isValid()) && "Invalid DeclLoc");
 
-  const char *argPtr = startArgList;
+  if (CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(S))
+    RewriteObjCQualifiedInterfaceTypes(CE);
 
-  while (*argPtr++ && parenCount) {
-    switch (*argPtr) {
-    case '^':
-      // Replace the '^' with '*'.
-      DeclLoc = DeclLoc.getLocWithOffset(argPtr-startArgList);
-      ReplaceText(DeclLoc, 1, "*");
-      break;
-    case '(':
-      parenCount++;
-      break;
-    case ')':
-      parenCount--;
-      break;
+  if (isa<SwitchStmt>(S) || isa<WhileStmt>(S) ||
+      isa<DoStmt>(S) || isa<ForStmt>(S)) {
+    assert(!Stmts.empty() && "Statement stack is empty");
+    assert ((isa<SwitchStmt>(Stmts.back()) || isa<WhileStmt>(Stmts.back()) ||
+             isa<DoStmt>(Stmts.back()) || isa<ForStmt>(Stmts.back()))
+            && "Statement stack mismatch");
+    Stmts.pop_back();
+  }
+  // Handle blocks rewriting.
+  if (BlockDeclRefExpr *BDRE = dyn_cast<BlockDeclRefExpr>(S)) {
+    if (BDRE->isByRef())
+      return RewriteBlockDeclRefExpr(BDRE);
+  }
+  if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(S)) {
+    ValueDecl *VD = DRE->getDecl(); 
+    if (VD->hasAttr<BlocksAttr>())
+      return RewriteBlockDeclRefExpr(DRE);
+    if (HasLocalVariableExternalStorage(VD))
+      return RewriteLocalVariableExternalStorage(DRE);
+  }
+  
+  if (CallExpr *CE = dyn_cast<CallExpr>(S)) {
+    if (CE->getCallee()->getType()->isBlockPointerType()) {
+      Stmt *BlockCall = SynthesizeBlockCall(CE, CE->getCallee());
+      ReplaceStmt(S, BlockCall);
+      return BlockCall;
     }
   }
-  return;
-}
-
-bool RewriteObjC::PointerTypeTakesAnyBlockArguments(QualType QT) {
-  const FunctionProtoType *FTP;
-  const PointerType *PT = QT->getAs<PointerType>();
-  if (PT) {
-    FTP = PT->getPointeeType()->getAs<FunctionProtoType>();
-  } else {
-    const BlockPointerType *BPT = QT->getAs<BlockPointerType>();
-    assert(BPT && "BlockPointerTypeTakeAnyBlockArguments(): not a block pointer type");
-    FTP = BPT->getPointeeType()->getAs<FunctionProtoType>();
+  if (CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(S)) {
+    RewriteCastExpr(CE);
   }
-  if (FTP) {
-    for (FunctionProtoType::arg_type_iterator I = FTP->arg_type_begin(),
-         E = FTP->arg_type_end(); I != E; ++I)
-      if (isTopLevelBlockPointerType(*I))
-        return true;
+#if 0
+  if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(S)) {
+    CastExpr *Replacement = new (Context) CastExpr(ICE->getType(),
+                                                   ICE->getSubExpr(),
+                                                   SourceLocation());
+    // Get the new text.
+    std::string SStr;
+    llvm::raw_string_ostream Buf(SStr);
+    Replacement->printPretty(Buf, *Context);
+    const std::string &Str = Buf.str();
+
+    printf("CAST = %s\n", &Str[0]);
+    InsertText(ICE->getSubExpr()->getLocStart(), &Str[0], Str.size());
+    delete S;
+    return Replacement;
   }
-  return false;
+#endif
+  // Return this stmt unmodified.
+  return S;
 }
 
-bool RewriteObjC::PointerTypeTakesAnyObjCQualifiedType(QualType QT) {
-  const FunctionProtoType *FTP;
-  const PointerType *PT = QT->getAs<PointerType>();
-  if (PT) {
-    FTP = PT->getPointeeType()->getAs<FunctionProtoType>();
-  } else {
-    const BlockPointerType *BPT = QT->getAs<BlockPointerType>();
-    assert(BPT && "BlockPointerTypeTakeAnyBlockArguments(): not a block pointer type");
-    FTP = BPT->getPointeeType()->getAs<FunctionProtoType>();
-  }
-  if (FTP) {
-    for (FunctionProtoType::arg_type_iterator I = FTP->arg_type_begin(),
-         E = FTP->arg_type_end(); I != E; ++I) {
-      if ((*I)->isObjCQualifiedIdType())
-        return true;
-      if ((*I)->isObjCObjectPointerType() &&
-          (*I)->getPointeeType()->isObjCQualifiedInterfaceType())
-        return true;
-    }
-        
+void RewriteObjC::RewriteRecordBody(RecordDecl *RD) {
+  for (RecordDecl::field_iterator i = RD->field_begin(), 
+                                  e = RD->field_end(); i != e; ++i) {
+    FieldDecl *FD = *i;
+    if (isTopLevelBlockPointerType(FD->getType()))
+      RewriteBlockPointerDecl(FD);
+    if (FD->getType()->isObjCQualifiedIdType() ||
+        FD->getType()->isObjCQualifiedInterfaceType())
+      RewriteObjCQualifiedInterfaceTypes(FD);
   }
-  return false;
 }
 
-void RewriteObjC::GetExtentOfArgList(const char *Name, const char *&LParen,
-                                     const char *&RParen) {
-  const char *argPtr = strchr(Name, '(');
-  assert((*argPtr == '(') && "Rewriter fuzzy parser confused");
+/// HandleDeclInMainFile - This is called for each top-level decl defined in the
+/// main file of the input.
+void RewriteObjC::HandleDeclInMainFile(Decl *D) {
+  switch (D->getKind()) {
+    case Decl::Function: {
+      FunctionDecl *FD = cast<FunctionDecl>(D);
+      if (FD->isOverloadedOperator())
+        return;
 
-  LParen = argPtr; // output the start.
-  argPtr++; // skip past the left paren.
-  unsigned parenCount = 1;
+      // Since function prototypes don't have ParmDecl's, we check the function
+      // prototype. This enables us to rewrite function declarations and
+      // definitions using the same code.
+      RewriteBlocksInFunctionProtoType(FD->getType(), FD);
 
-  while (*argPtr && parenCount) {
-    switch (*argPtr) {
-    case '(': parenCount++; break;
-    case ')': parenCount--; break;
-    default: break;
+      // FIXME: If this should support Obj-C++, support CXXTryStmt
+      if (CompoundStmt *Body = dyn_cast_or_null<CompoundStmt>(FD->getBody())) {
+        CurFunctionDef = FD;
+        CurFunctionDeclToDeclareForBlock = FD;
+        CurrentBody = Body;
+        Body =
+        cast_or_null<CompoundStmt>(RewriteFunctionBodyOrGlobalInitializer(Body));
+        FD->setBody(Body);
+        CurrentBody = 0;
+        if (PropParentMap) {
+          delete PropParentMap;
+          PropParentMap = 0;
+        }
+        // This synthesizes and inserts the block "impl" struct, invoke function,
+        // and any copy/dispose helper functions.
+        InsertBlockLiteralsWithinFunction(FD);
+        CurFunctionDef = 0;
+        CurFunctionDeclToDeclareForBlock = 0;
+      }
+      break;
     }
-    if (parenCount) argPtr++;
+    case Decl::ObjCMethod: {
+      ObjCMethodDecl *MD = cast<ObjCMethodDecl>(D);
+      if (CompoundStmt *Body = MD->getCompoundBody()) {
+        CurMethodDef = MD;
+        CurrentBody = Body;
+        Body =
+          cast_or_null<CompoundStmt>(RewriteFunctionBodyOrGlobalInitializer(Body));
+        MD->setBody(Body);
+        CurrentBody = 0;
+        if (PropParentMap) {
+          delete PropParentMap;
+          PropParentMap = 0;
+        }
+        InsertBlockLiteralsWithinMethod(MD);
+        CurMethodDef = 0;
+      }
+      break;
+    }
+    case Decl::ObjCImplementation: {
+      ObjCImplementationDecl *CI = cast<ObjCImplementationDecl>(D);
+      ClassImplementation.push_back(CI);
+      break;
+    }
+    case Decl::ObjCCategoryImpl: {
+      ObjCCategoryImplDecl *CI = cast<ObjCCategoryImplDecl>(D);
+      CategoryImplementation.push_back(CI);
+      break;
+    }
+    case Decl::Var: {
+      VarDecl *VD = cast<VarDecl>(D);
+      RewriteObjCQualifiedInterfaceTypes(VD);
+      if (isTopLevelBlockPointerType(VD->getType()))
+        RewriteBlockPointerDecl(VD);
+      else if (VD->getType()->isFunctionPointerType()) {
+        CheckFunctionPointerDecl(VD->getType(), VD);
+        if (VD->getInit()) {
+          if (CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(VD->getInit())) {
+            RewriteCastExpr(CE);
+          }
+        }
+      } else if (VD->getType()->isRecordType()) {
+        RecordDecl *RD = VD->getType()->getAs<RecordType>()->getDecl();
+        if (RD->isCompleteDefinition())
+          RewriteRecordBody(RD);
+      }
+      if (VD->getInit()) {
+        GlobalVarDecl = VD;
+        CurrentBody = VD->getInit();
+        RewriteFunctionBodyOrGlobalInitializer(VD->getInit());
+        CurrentBody = 0;
+        if (PropParentMap) {
+          delete PropParentMap;
+          PropParentMap = 0;
+        }
+        SynthesizeBlockLiterals(VD->getTypeSpecStartLoc(), VD->getName());
+        GlobalVarDecl = 0;
+          
+        // This is needed for blocks.
+        if (CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(VD->getInit())) {
+            RewriteCastExpr(CE);
+        }
+      }
+      break;
+    }
+    case Decl::TypeAlias:
+    case Decl::Typedef: {
+      if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(D)) {
+        if (isTopLevelBlockPointerType(TD->getUnderlyingType()))
+          RewriteBlockPointerDecl(TD);
+        else if (TD->getUnderlyingType()->isFunctionPointerType())
+          CheckFunctionPointerDecl(TD->getUnderlyingType(), TD);
+      }
+      break;
+    }
+    case Decl::CXXRecord:
+    case Decl::Record: {
+      RecordDecl *RD = cast<RecordDecl>(D);
+      if (RD->isCompleteDefinition()) 
+        RewriteRecordBody(RD);
+      break;
+    }
+    case Decl::ObjCClass: {
+      llvm_unreachable("RewriteObjC::HandleDeclInMainFile - ObjCClassDecl");
+      break;
+    }
+    default:
+      break;
   }
-  assert((*argPtr == ')') && "Rewriter fuzzy parser confused");
-  RParen = argPtr; // output the end
+  // Nothing yet.
 }
 
-void RewriteObjC::RewriteBlockPointerDecl(NamedDecl *ND) {
-  if (FunctionDecl *FD = dyn_cast<FunctionDecl>(ND)) {
-    RewriteBlockPointerFunctionArgs(FD);
+void RewriteObjC::HandleTranslationUnit(ASTContext &C) {
+  if (Diags.hasErrorOccurred())
     return;
-  }
-  // Handle Variables and Typedefs.
-  SourceLocation DeclLoc = ND->getLocation();
-  QualType DeclT;
-  if (VarDecl *VD = dyn_cast<VarDecl>(ND))
-    DeclT = VD->getType();
-  else if (TypedefNameDecl *TDD = dyn_cast<TypedefNameDecl>(ND))
-    DeclT = TDD->getUnderlyingType();
-  else if (FieldDecl *FD = dyn_cast<FieldDecl>(ND))
-    DeclT = FD->getType();
-  else
-    llvm_unreachable("RewriteBlockPointerDecl(): Decl type not yet handled");
 
-  const char *startBuf = SM->getCharacterData(DeclLoc);
-  const char *endBuf = startBuf;
-  // scan backward (from the decl location) for the end of the previous decl.
-  while (*startBuf != '^' && *startBuf != ';' && startBuf != MainFileStart)
-    startBuf--;
-  SourceLocation Start = DeclLoc.getLocWithOffset(startBuf-endBuf);
-  std::string buf;
-  unsigned OrigLength=0;
-  // *startBuf != '^' if we are dealing with a pointer to function that
-  // may take block argument types (which will be handled below).
-  if (*startBuf == '^') {
-    // Replace the '^' with '*', computing a negative offset.
-    buf = '*';
-    startBuf++;
-    OrigLength++;
-  }
-  while (*startBuf != ')') {
-    buf += *startBuf;
-    startBuf++;
-    OrigLength++;
+  RewriteInclude();
+
+  // Here's a great place to add any extra declarations that may be needed.
+  // Write out meta data for each @protocol(<expr>).
+  for (llvm::SmallPtrSet<ObjCProtocolDecl *,8>::iterator I = ProtocolExprDecls.begin(),
+       E = ProtocolExprDecls.end(); I != E; ++I)
+    RewriteObjCProtocolMetaData(*I, "", "", Preamble);
+
+  InsertText(SM->getLocForStartOfFile(MainFileID), Preamble, false);
+  if (ClassImplementation.size() || CategoryImplementation.size())
+    RewriteImplementations();
+
+  // Get the buffer corresponding to MainFileID.  If we haven't changed it, then
+  // we are done.
+  if (const RewriteBuffer *RewriteBuf =
+      Rewrite.getRewriteBufferFor(MainFileID)) {
+    //printf("Changed:\n");
+    *OutFile << std::string(RewriteBuf->begin(), RewriteBuf->end());
+  } else {
+    llvm::errs() << "No changes\n";
   }
-  buf += ')';
-  OrigLength++;
-  
-  if (PointerTypeTakesAnyBlockArguments(DeclT) ||
-      PointerTypeTakesAnyObjCQualifiedType(DeclT)) {
-    // Replace the '^' with '*' for arguments.
-    // Replace id<P> with id/*<>*/
-    DeclLoc = ND->getLocation();
-    startBuf = SM->getCharacterData(DeclLoc);
-    const char *argListBegin, *argListEnd;
-    GetExtentOfArgList(startBuf, argListBegin, argListEnd);
-    while (argListBegin < argListEnd) {
-      if (*argListBegin == '^')
-        buf += '*';
-      else if (*argListBegin ==  '<') {
-        buf += "/*"; 
-        buf += *argListBegin++;
-        OrigLength++;;
-        while (*argListBegin != '>') {
-          buf += *argListBegin++;
-          OrigLength++;
-        }
-        buf += *argListBegin;
-        buf += "*/";
-      }
-      else
-        buf += *argListBegin;
-      argListBegin++;
-      OrigLength++;
-    }
-    buf += ')';
-    OrigLength++;
+
+  if (ClassImplementation.size() || CategoryImplementation.size() ||
+      ProtocolExprDecls.size()) {
+    // Rewrite Objective-c meta data*
+    std::string ResultStr;
+    RewriteMetaDataIntoBuffer(ResultStr);
+    // Emit metadata.
+    *OutFile << ResultStr;
   }
-  ReplaceText(Start, OrigLength, buf);
-  
-  return;
+  OutFile->flush();
 }
 
-
-/// SynthesizeByrefCopyDestroyHelper - This routine synthesizes:
-/// void __Block_byref_id_object_copy(struct Block_byref_id_object *dst,
-///                    struct Block_byref_id_object *src) {
-///  _Block_object_assign (&_dest->object, _src->object, 
-///                        BLOCK_BYREF_CALLER | BLOCK_FIELD_IS_OBJECT
-///                        [|BLOCK_FIELD_IS_WEAK]) // object
-///  _Block_object_assign(&_dest->object, _src->object, 
-///                       BLOCK_BYREF_CALLER | BLOCK_FIELD_IS_BLOCK
-///                       [|BLOCK_FIELD_IS_WEAK]) // block
-/// }
-/// And:
-/// void __Block_byref_id_object_dispose(struct Block_byref_id_object *_src) {
-///  _Block_object_dispose(_src->object, 
-///                        BLOCK_BYREF_CALLER | BLOCK_FIELD_IS_OBJECT
-///                        [|BLOCK_FIELD_IS_WEAK]) // object
-///  _Block_object_dispose(_src->object, 
-///                         BLOCK_BYREF_CALLER | BLOCK_FIELD_IS_BLOCK
-///                         [|BLOCK_FIELD_IS_WEAK]) // block
-/// }
-
-std::string RewriteObjC::SynthesizeByrefCopyDestroyHelper(VarDecl *VD,
-                                                          int flag) {
-  std::string S;
-  if (CopyDestroyCache.count(flag))
-    return S;
-  CopyDestroyCache.insert(flag);
-  S = "static void __Block_byref_id_object_copy_";
-  S += utostr(flag);
-  S += "(void *dst, void *src) {\n";
+void RewriteObjCFragileABI::Initialize(ASTContext &context) {
+  InitializeCommon(context);
   
-  // offset into the object pointer is computed as:
-  // void * + void* + int + int + void* + void *
-  unsigned IntSize = 
-  static_cast<unsigned>(Context->getTypeSize(Context->IntTy));
-  unsigned VoidPtrSize = 
-  static_cast<unsigned>(Context->getTypeSize(Context->VoidPtrTy));
-  
-  unsigned offset = (VoidPtrSize*4 + IntSize + IntSize)/Context->getCharWidth();
-  S += " _Block_object_assign((char*)dst + ";
-  S += utostr(offset);
-  S += ", *(void * *) ((char*)src + ";
-  S += utostr(offset);
-  S += "), ";
-  S += utostr(flag);
-  S += ");\n}\n";
-  
-  S += "static void __Block_byref_id_object_dispose_";
-  S += utostr(flag);
-  S += "(void *src) {\n";
-  S += " _Block_object_dispose(*(void * *) ((char*)src + ";
-  S += utostr(offset);
-  S += "), ";
-  S += utostr(flag);
-  S += ");\n}\n";
-  return S;
-}
-
-/// RewriteByRefVar - For each __block typex ND variable this routine transforms
-/// the declaration into:
-/// struct __Block_byref_ND {
-/// void *__isa;                  // NULL for everything except __weak pointers
-/// struct __Block_byref_ND *__forwarding;
-/// int32_t __flags;
-/// int32_t __size;
-/// void *__Block_byref_id_object_copy; // If variable is __block ObjC object
-/// void *__Block_byref_id_object_dispose; // If variable is __block ObjC object
-/// typex ND;
-/// };
-///
-/// It then replaces declaration of ND variable with:
-/// struct __Block_byref_ND ND = {__isa=0B, __forwarding=&ND, __flags=some_flag, 
-///                               __size=sizeof(struct __Block_byref_ND), 
-///                               ND=initializer-if-any};
-///
-///
-void RewriteObjC::RewriteByRefVar(VarDecl *ND) {
-  // Insert declaration for the function in which block literal is
-  // used.
-  if (CurFunctionDeclToDeclareForBlock)
-    RewriteBlockLiteralFunctionDecl(CurFunctionDeclToDeclareForBlock);
-  int flag = 0;
-  int isa = 0;
-  SourceLocation DeclLoc = ND->getTypeSpecStartLoc();
-  if (DeclLoc.isInvalid())
-    // If type location is missing, it is because of missing type (a warning).
-    // Use variable's location which is good for this case.
-    DeclLoc = ND->getLocation();
-  const char *startBuf = SM->getCharacterData(DeclLoc);
-  SourceLocation X = ND->getLocEnd();
-  X = SM->getExpansionLoc(X);
-  const char *endBuf = SM->getCharacterData(X);
-  std::string Name(ND->getNameAsString());
-  std::string ByrefType;
-  RewriteByRefString(ByrefType, Name, ND, true);
-  ByrefType += " {\n";
-  ByrefType += "  void *__isa;\n";
-  RewriteByRefString(ByrefType, Name, ND);
-  ByrefType += " *__forwarding;\n";
-  ByrefType += " int __flags;\n";
-  ByrefType += " int __size;\n";
-  // Add void *__Block_byref_id_object_copy; 
-  // void *__Block_byref_id_object_dispose; if needed.
-  QualType Ty = ND->getType();
-  bool HasCopyAndDispose = Context->BlockRequiresCopying(Ty);
-  if (HasCopyAndDispose) {
-    ByrefType += " void (*__Block_byref_id_object_copy)(void*, void*);\n";
-    ByrefType += " void (*__Block_byref_id_object_dispose)(void*);\n";
+  // declaring objc_selector outside the parameter list removes a silly
+  // scope related warning...
+  if (IsHeader)
+    Preamble = "#pragma once\n";
+  Preamble += "struct objc_selector; struct objc_class;\n";
+  Preamble += "struct __rw_objc_super { struct objc_object *object; ";
+  Preamble += "struct objc_object *superClass; ";
+  if (LangOpts.MicrosoftExt) {
+    // Add a constructor for creating temporary objects.
+    Preamble += "__rw_objc_super(struct objc_object *o, struct objc_object *s) "
+    ": ";
+    Preamble += "object(o), superClass(s) {} ";
+  }
+  Preamble += "};\n";
+  Preamble += "#ifndef _REWRITER_typedef_Protocol\n";
+  Preamble += "typedef struct objc_object Protocol;\n";
+  Preamble += "#define _REWRITER_typedef_Protocol\n";
+  Preamble += "#endif\n";
+  if (LangOpts.MicrosoftExt) {
+    Preamble += "#define __OBJC_RW_DLLIMPORT extern \"C\" __declspec(dllimport)\n";
+    Preamble += "#define __OBJC_RW_STATICIMPORT extern \"C\"\n";
+  } else
+    Preamble += "#define __OBJC_RW_DLLIMPORT extern\n";
+  Preamble += "__OBJC_RW_DLLIMPORT struct objc_object *objc_msgSend";
+  Preamble += "(struct objc_object *, struct objc_selector *, ...);\n";
+  Preamble += "__OBJC_RW_DLLIMPORT struct objc_object *objc_msgSendSuper";
+  Preamble += "(struct objc_super *, struct objc_selector *, ...);\n";
+  Preamble += "__OBJC_RW_DLLIMPORT struct objc_object* objc_msgSend_stret";
+  Preamble += "(struct objc_object *, struct objc_selector *, ...);\n";
+  Preamble += "__OBJC_RW_DLLIMPORT struct objc_object* objc_msgSendSuper_stret";
+  Preamble += "(struct objc_super *, struct objc_selector *, ...);\n";
+  Preamble += "__OBJC_RW_DLLIMPORT double objc_msgSend_fpret";
+  Preamble += "(struct objc_object *, struct objc_selector *, ...);\n";
+  Preamble += "__OBJC_RW_DLLIMPORT struct objc_object *objc_getClass";
+  Preamble += "(const char *);\n";
+  Preamble += "__OBJC_RW_DLLIMPORT struct objc_class *class_getSuperclass";
+  Preamble += "(struct objc_class *);\n";
+  Preamble += "__OBJC_RW_DLLIMPORT struct objc_object *objc_getMetaClass";
+  Preamble += "(const char *);\n";
+  Preamble += "__OBJC_RW_DLLIMPORT void objc_exception_throw(struct objc_object *);\n";
+  Preamble += "__OBJC_RW_DLLIMPORT void objc_exception_try_enter(void *);\n";
+  Preamble += "__OBJC_RW_DLLIMPORT void objc_exception_try_exit(void *);\n";
+  Preamble += "__OBJC_RW_DLLIMPORT struct objc_object *objc_exception_extract(void *);\n";
+  Preamble += "__OBJC_RW_DLLIMPORT int objc_exception_match";
+  Preamble += "(struct objc_class *, struct objc_object *);\n";
+  // @synchronized hooks.
+  Preamble += "__OBJC_RW_DLLIMPORT void objc_sync_enter(struct objc_object *);\n";
+  Preamble += "__OBJC_RW_DLLIMPORT void objc_sync_exit(struct objc_object *);\n";
+  Preamble += "__OBJC_RW_DLLIMPORT Protocol *objc_getProtocol(const char *);\n";
+  Preamble += "#ifndef __FASTENUMERATIONSTATE\n";
+  Preamble += "struct __objcFastEnumerationState {\n\t";
+  Preamble += "unsigned long state;\n\t";
+  Preamble += "void **itemsPtr;\n\t";
+  Preamble += "unsigned long *mutationsPtr;\n\t";
+  Preamble += "unsigned long extra[5];\n};\n";
+  Preamble += "__OBJC_RW_DLLIMPORT void objc_enumerationMutation(struct objc_object *);\n";
+  Preamble += "#define __FASTENUMERATIONSTATE\n";
+  Preamble += "#endif\n";
+  Preamble += "#ifndef __NSCONSTANTSTRINGIMPL\n";
+  Preamble += "struct __NSConstantStringImpl {\n";
+  Preamble += "  int *isa;\n";
+  Preamble += "  int flags;\n";
+  Preamble += "  char *str;\n";
+  Preamble += "  long length;\n";
+  Preamble += "};\n";
+  Preamble += "#ifdef CF_EXPORT_CONSTANT_STRING\n";
+  Preamble += "extern \"C\" __declspec(dllexport) int __CFConstantStringClassReference[];\n";
+  Preamble += "#else\n";
+  Preamble += "__OBJC_RW_DLLIMPORT int __CFConstantStringClassReference[];\n";
+  Preamble += "#endif\n";
+  Preamble += "#define __NSCONSTANTSTRINGIMPL\n";
+  Preamble += "#endif\n";
+  // Blocks preamble.
+  Preamble += "#ifndef BLOCK_IMPL\n";
+  Preamble += "#define BLOCK_IMPL\n";
+  Preamble += "struct __block_impl {\n";
+  Preamble += "  void *isa;\n";
+  Preamble += "  int Flags;\n";
+  Preamble += "  int Reserved;\n";
+  Preamble += "  void *FuncPtr;\n";
+  Preamble += "};\n";
+  Preamble += "// Runtime copy/destroy helper functions (from Block_private.h)\n";
+  Preamble += "#ifdef __OBJC_EXPORT_BLOCKS\n";
+  Preamble += "extern \"C\" __declspec(dllexport) "
+  "void _Block_object_assign(void *, const void *, const int);\n";
+  Preamble += "extern \"C\" __declspec(dllexport) void _Block_object_dispose(const void *, const int);\n";
+  Preamble += "extern \"C\" __declspec(dllexport) void *_NSConcreteGlobalBlock[32];\n";
+  Preamble += "extern \"C\" __declspec(dllexport) void *_NSConcreteStackBlock[32];\n";
+  Preamble += "#else\n";
+  Preamble += "__OBJC_RW_DLLIMPORT void _Block_object_assign(void *, const void *, const int);\n";
+  Preamble += "__OBJC_RW_DLLIMPORT void _Block_object_dispose(const void *, const int);\n";
+  Preamble += "__OBJC_RW_DLLIMPORT void *_NSConcreteGlobalBlock[32];\n";
+  Preamble += "__OBJC_RW_DLLIMPORT void *_NSConcreteStackBlock[32];\n";
+  Preamble += "#endif\n";
+  Preamble += "#endif\n";
+  if (LangOpts.MicrosoftExt) {
+    Preamble += "#undef __OBJC_RW_DLLIMPORT\n";
+    Preamble += "#undef __OBJC_RW_STATICIMPORT\n";
+    Preamble += "#ifndef KEEP_ATTRIBUTES\n";  // We use this for clang tests.
+    Preamble += "#define __attribute__(X)\n";
+    Preamble += "#endif\n";
+    Preamble += "#define __weak\n";
   }
-
-  QualType T = Ty;
-  (void)convertBlockPointerToFunctionPointer(T);
-  T.getAsStringInternal(Name, Context->getPrintingPolicy());
-    
-  ByrefType += " " + Name + ";\n";
-  ByrefType += "};\n";
-  // Insert this type in global scope. It is needed by helper function.
-  SourceLocation FunLocStart;
-  if (CurFunctionDef)
-     FunLocStart = CurFunctionDef->getTypeSpecStartLoc();
   else {
-    assert(CurMethodDef && "RewriteByRefVar - CurMethodDef is null");
-    FunLocStart = CurMethodDef->getLocStart();
+    Preamble += "#define __block\n";
+    Preamble += "#define __weak\n";
   }
-  InsertText(FunLocStart, ByrefType);
-  if (Ty.isObjCGCWeak()) {
-    flag |= BLOCK_FIELD_IS_WEAK;
-    isa = 1;
+  // NOTE! Windows uses LLP64 for 64bit mode. So, cast pointer to long long
+  // as this avoids warning in any 64bit/32bit compilation model.
+  Preamble += "\n#define __OFFSETOFIVAR__(TYPE, MEMBER) ((long long) &((TYPE *)0)->MEMBER)\n";
+}
+
+/// RewriteIvarOffsetComputation - This rutine synthesizes computation of
+/// ivar offset.
+void RewriteObjCFragileABI::RewriteIvarOffsetComputation(ObjCIvarDecl *ivar,
+                                                         std::string &Result) {
+  if (ivar->isBitField()) {
+    // FIXME: The hack below doesn't work for bitfields. For now, we simply
+    // place all bitfields at offset 0.
+    Result += "0";
+  } else {
+    Result += "__OFFSETOFIVAR__(struct ";
+    Result += ivar->getContainingInterface()->getNameAsString();
+    if (LangOpts.MicrosoftExt)
+      Result += "_IMPL";
+    Result += ", ";
+    Result += ivar->getNameAsString();
+    Result += ")";
   }
+}
+
+/// RewriteObjCProtocolMetaData - Rewrite protocols meta-data.
+void RewriteObjCFragileABI::RewriteObjCProtocolMetaData(
+                            ObjCProtocolDecl *PDecl, StringRef prefix,
+                            StringRef ClassName, std::string &Result) {
+  static bool objc_protocol_methods = false;
   
-  if (HasCopyAndDispose) {
-    flag = BLOCK_BYREF_CALLER;
-    QualType Ty = ND->getType();
-    // FIXME. Handle __weak variable (BLOCK_FIELD_IS_WEAK) as well.
-    if (Ty->isBlockPointerType())
-      flag |= BLOCK_FIELD_IS_BLOCK;
-    else
-      flag |= BLOCK_FIELD_IS_OBJECT;
-    std::string HF = SynthesizeByrefCopyDestroyHelper(ND, flag);
-    if (!HF.empty())
-      InsertText(FunLocStart, HF);
+  // Output struct protocol_methods holder of method selector and type.
+  if (!objc_protocol_methods && !PDecl->isForwardDecl()) {
+    /* struct protocol_methods {
+     SEL _cmd;
+     char *method_types;
+     }
+     */
+    Result += "\nstruct _protocol_methods {\n";
+    Result += "\tstruct objc_selector *_cmd;\n";
+    Result += "\tchar *method_types;\n";
+    Result += "};\n";
+    
+    objc_protocol_methods = true;
   }
+  // Do not synthesize the protocol more than once.
+  if (ObjCSynthesizedProtocols.count(PDecl))
+    return;
   
-  // struct __Block_byref_ND ND = 
-  // {0, &ND, some_flag, __size=sizeof(struct __Block_byref_ND), 
-  //  initializer-if-any};
-  bool hasInit = (ND->getInit() != 0);
-  unsigned flags = 0;
-  if (HasCopyAndDispose)
-    flags |= BLOCK_HAS_COPY_DISPOSE;
-  Name = ND->getNameAsString();
-  ByrefType.clear();
-  RewriteByRefString(ByrefType, Name, ND);
-  std::string ForwardingCastType("(");
-  ForwardingCastType += ByrefType + " *)";
-  if (!hasInit) {
-    ByrefType += " " + Name + " = {(void*)";
-    ByrefType += utostr(isa);
-    ByrefType += "," +  ForwardingCastType + "&" + Name + ", ";
-    ByrefType += utostr(flags);
-    ByrefType += ", ";
-    ByrefType += "sizeof(";
-    RewriteByRefString(ByrefType, Name, ND);
-    ByrefType += ")";
-    if (HasCopyAndDispose) {
-      ByrefType += ", __Block_byref_id_object_copy_";
-      ByrefType += utostr(flag);
-      ByrefType += ", __Block_byref_id_object_dispose_";
-      ByrefType += utostr(flag);
+  if (PDecl->instmeth_begin() != PDecl->instmeth_end()) {
+    unsigned NumMethods = std::distance(PDecl->instmeth_begin(),
+                                        PDecl->instmeth_end());
+    /* struct _objc_protocol_method_list {
+     int protocol_method_count;
+     struct protocol_methods protocols[];
+     }
+     */
+    Result += "\nstatic struct {\n";
+    Result += "\tint protocol_method_count;\n";
+    Result += "\tstruct _protocol_methods protocol_methods[";
+    Result += utostr(NumMethods);
+    Result += "];\n} _OBJC_PROTOCOL_INSTANCE_METHODS_";
+    Result += PDecl->getNameAsString();
+    Result += " __attribute__ ((used, section (\"__OBJC, __cat_inst_meth\")))= "
+    "{\n\t" + utostr(NumMethods) + "\n";
+    
+    // Output instance methods declared in this protocol.
+    for (ObjCProtocolDecl::instmeth_iterator
+         I = PDecl->instmeth_begin(), E = PDecl->instmeth_end();
+         I != E; ++I) {
+      if (I == PDecl->instmeth_begin())
+        Result += "\t  ,{{(struct objc_selector *)\"";
+      else
+        Result += "\t  ,{(struct objc_selector *)\"";
+      Result += (*I)->getSelector().getAsString();
+      std::string MethodTypeString;
+      Context->getObjCEncodingForMethodDecl((*I), MethodTypeString);
+      Result += "\", \"";
+      Result += MethodTypeString;
+      Result += "\"}\n";
     }
-    ByrefType += "};\n";
-    unsigned nameSize = Name.size();
-    // for block or function pointer declaration. Name is aleady
-    // part of the declaration.
-    if (Ty->isBlockPointerType() || Ty->isFunctionPointerType())
-      nameSize = 1;
-    ReplaceText(DeclLoc, endBuf-startBuf+nameSize, ByrefType);
+    Result += "\t }\n};\n";
   }
-  else {
-    SourceLocation startLoc;
-    Expr *E = ND->getInit();
-    if (const CStyleCastExpr *ECE = dyn_cast<CStyleCastExpr>(E))
-      startLoc = ECE->getLParenLoc();
-    else
-      startLoc = E->getLocStart();
-    startLoc = SM->getExpansionLoc(startLoc);
-    endBuf = SM->getCharacterData(startLoc);
-    ByrefType += " " + Name;
-    ByrefType += " = {(void*)";
-    ByrefType += utostr(isa);
-    ByrefType += "," +  ForwardingCastType + "&" + Name + ", ";
-    ByrefType += utostr(flags);
-    ByrefType += ", ";
-    ByrefType += "sizeof(";
-    RewriteByRefString(ByrefType, Name, ND);
-    ByrefType += "), ";
-    if (HasCopyAndDispose) {
-      ByrefType += "__Block_byref_id_object_copy_";
-      ByrefType += utostr(flag);
-      ByrefType += ", __Block_byref_id_object_dispose_";
-      ByrefType += utostr(flag);
-      ByrefType += ", ";
+  
+  // Output class methods declared in this protocol.
+  unsigned NumMethods = std::distance(PDecl->classmeth_begin(),
+                                      PDecl->classmeth_end());
+  if (NumMethods > 0) {
+    /* struct _objc_protocol_method_list {
+     int protocol_method_count;
+     struct protocol_methods protocols[];
+     }
+     */
+    Result += "\nstatic struct {\n";
+    Result += "\tint protocol_method_count;\n";
+    Result += "\tstruct _protocol_methods protocol_methods[";
+    Result += utostr(NumMethods);
+    Result += "];\n} _OBJC_PROTOCOL_CLASS_METHODS_";
+    Result += PDecl->getNameAsString();
+    Result += " __attribute__ ((used, section (\"__OBJC, __cat_cls_meth\")))= "
+    "{\n\t";
+    Result += utostr(NumMethods);
+    Result += "\n";
+    
+    // Output instance methods declared in this protocol.
+    for (ObjCProtocolDecl::classmeth_iterator
+         I = PDecl->classmeth_begin(), E = PDecl->classmeth_end();
+         I != E; ++I) {
+      if (I == PDecl->classmeth_begin())
+        Result += "\t  ,{{(struct objc_selector *)\"";
+      else
+        Result += "\t  ,{(struct objc_selector *)\"";
+      Result += (*I)->getSelector().getAsString();
+      std::string MethodTypeString;
+      Context->getObjCEncodingForMethodDecl((*I), MethodTypeString);
+      Result += "\", \"";
+      Result += MethodTypeString;
+      Result += "\"}\n";
     }
-    ReplaceText(DeclLoc, endBuf-startBuf, ByrefType);
+    Result += "\t }\n};\n";
+  }
+  
+  // Output:
+  /* struct _objc_protocol {
+   // Objective-C 1.0 extensions
+   struct _objc_protocol_extension *isa;
+   char *protocol_name;
+   struct _objc_protocol **protocol_list;
+   struct _objc_protocol_method_list *instance_methods;
+   struct _objc_protocol_method_list *class_methods;
+   };
+   */
+  static bool objc_protocol = false;
+  if (!objc_protocol) {
+    Result += "\nstruct _objc_protocol {\n";
+    Result += "\tstruct _objc_protocol_extension *isa;\n";
+    Result += "\tchar *protocol_name;\n";
+    Result += "\tstruct _objc_protocol **protocol_list;\n";
+    Result += "\tstruct _objc_protocol_method_list *instance_methods;\n";
+    Result += "\tstruct _objc_protocol_method_list *class_methods;\n";
+    Result += "};\n";
     
-    // Complete the newly synthesized compound expression by inserting a right
-    // curly brace before the end of the declaration.
-    // FIXME: This approach avoids rewriting the initializer expression. It
-    // also assumes there is only one declarator. For example, the following
-    // isn't currently supported by this routine (in general):
-    // 
-    // double __block BYREFVAR = 1.34, BYREFVAR2 = 1.37;
-    //
-    const char *startInitializerBuf = SM->getCharacterData(startLoc);
-    const char *semiBuf = strchr(startInitializerBuf, ';');
-    assert((*semiBuf == ';') && "RewriteByRefVar: can't find ';'");
-    SourceLocation semiLoc =
-      startLoc.getLocWithOffset(semiBuf-startInitializerBuf);
-
-    InsertText(semiLoc, "}");
+    objc_protocol = true;
   }
-  return;
-}
-
-void RewriteObjC::CollectBlockDeclRefInfo(BlockExpr *Exp) {
-  // Add initializers for any closure decl refs.
-  GetBlockDeclRefExprs(Exp->getBody());
-  if (BlockDeclRefs.size()) {
-    // Unique all "by copy" declarations.
-    for (unsigned i = 0; i < BlockDeclRefs.size(); i++)
-      if (!BlockDeclRefs[i]->isByRef()) {
-        if (!BlockByCopyDeclsPtrSet.count(BlockDeclRefs[i]->getDecl())) {
-          BlockByCopyDeclsPtrSet.insert(BlockDeclRefs[i]->getDecl());
-          BlockByCopyDecls.push_back(BlockDeclRefs[i]->getDecl());
-        }
-      }
-    // Unique all "by ref" declarations.
-    for (unsigned i = 0; i < BlockDeclRefs.size(); i++)
-      if (BlockDeclRefs[i]->isByRef()) {
-        if (!BlockByRefDeclsPtrSet.count(BlockDeclRefs[i]->getDecl())) {
-          BlockByRefDeclsPtrSet.insert(BlockDeclRefs[i]->getDecl());
-          BlockByRefDecls.push_back(BlockDeclRefs[i]->getDecl());
-        }
-      }
-    // Find any imported blocks...they will need special attention.
-    for (unsigned i = 0; i < BlockDeclRefs.size(); i++)
-      if (BlockDeclRefs[i]->isByRef() ||
-          BlockDeclRefs[i]->getType()->isObjCObjectPointerType() || 
-          BlockDeclRefs[i]->getType()->isBlockPointerType())
-        ImportedBlockDecls.insert(BlockDeclRefs[i]->getDecl());
+  
+  Result += "\nstatic struct _objc_protocol _OBJC_PROTOCOL_";
+  Result += PDecl->getNameAsString();
+  Result += " __attribute__ ((used, section (\"__OBJC, __protocol\")))= "
+  "{\n\t0, \"";
+  Result += PDecl->getNameAsString();
+  Result += "\", 0, ";
+  if (PDecl->instmeth_begin() != PDecl->instmeth_end()) {
+    Result += "(struct _objc_protocol_method_list *)&_OBJC_PROTOCOL_INSTANCE_METHODS_";
+    Result += PDecl->getNameAsString();
+    Result += ", ";
   }
+  else
+    Result += "0, ";
+  if (PDecl->classmeth_begin() != PDecl->classmeth_end()) {
+    Result += "(struct _objc_protocol_method_list *)&_OBJC_PROTOCOL_CLASS_METHODS_";
+    Result += PDecl->getNameAsString();
+    Result += "\n";
+  }
+  else
+    Result += "0\n";
+  Result += "};\n";
+  
+  // Mark this protocol as having been generated.
+  if (!ObjCSynthesizedProtocols.insert(PDecl))
+    llvm_unreachable("protocol already synthesized");
+  
 }
 
-FunctionDecl *RewriteObjC::SynthBlockInitFunctionDecl(StringRef name) {
-  IdentifierInfo *ID = &Context->Idents.get(name);
-  QualType FType = Context->getFunctionNoProtoType(Context->VoidPtrTy);
-  return FunctionDecl::Create(*Context, TUDecl, SourceLocation(),
-                              SourceLocation(), ID, FType, 0, SC_Extern,
-                              SC_None, false, false);
+void RewriteObjCFragileABI::RewriteObjCProtocolListMetaData(
+                                const ObjCList<ObjCProtocolDecl> &Protocols,
+                                StringRef prefix, StringRef ClassName,
+                                std::string &Result) {
+  if (Protocols.empty()) return;
+  
+  for (unsigned i = 0; i != Protocols.size(); i++)
+    RewriteObjCProtocolMetaData(Protocols[i], prefix, ClassName, Result);
+  
+  // Output the top lovel protocol meta-data for the class.
+  /* struct _objc_protocol_list {
+   struct _objc_protocol_list *next;
+   int    protocol_count;
+   struct _objc_protocol *class_protocols[];
+   }
+   */
+  Result += "\nstatic struct {\n";
+  Result += "\tstruct _objc_protocol_list *next;\n";
+  Result += "\tint    protocol_count;\n";
+  Result += "\tstruct _objc_protocol *class_protocols[";
+  Result += utostr(Protocols.size());
+  Result += "];\n} _OBJC_";
+  Result += prefix;
+  Result += "_PROTOCOLS_";
+  Result += ClassName;
+  Result += " __attribute__ ((used, section (\"__OBJC, __cat_cls_meth\")))= "
+  "{\n\t0, ";
+  Result += utostr(Protocols.size());
+  Result += "\n";
+  
+  Result += "\t,{&_OBJC_PROTOCOL_";
+  Result += Protocols[0]->getNameAsString();
+  Result += " \n";
+  
+  for (unsigned i = 1; i != Protocols.size(); i++) {
+    Result += "\t ,&_OBJC_PROTOCOL_";
+    Result += Protocols[i]->getNameAsString();
+    Result += "\n";
+  }
+  Result += "\t }\n};\n";
 }
 
-Stmt *RewriteObjC::SynthBlockInitExpr(BlockExpr *Exp,
-          const SmallVector<BlockDeclRefExpr *, 8> &InnerBlockDeclRefs) {
-  const BlockDecl *block = Exp->getBlockDecl();
-  Blocks.push_back(Exp);
-
-  CollectBlockDeclRefInfo(Exp);
+void RewriteObjCFragileABI::RewriteObjCClassMetaData(ObjCImplementationDecl *IDecl,
+                                           std::string &Result) {
+  ObjCInterfaceDecl *CDecl = IDecl->getClassInterface();
   
-  // Add inner imported variables now used in current block.
- int countOfInnerDecls = 0;
-  if (!InnerBlockDeclRefs.empty()) {
-    for (unsigned i = 0; i < InnerBlockDeclRefs.size(); i++) {
-      BlockDeclRefExpr *Exp = InnerBlockDeclRefs[i];
-      ValueDecl *VD = Exp->getDecl();
-      if (!Exp->isByRef() && !BlockByCopyDeclsPtrSet.count(VD)) {
-      // We need to save the copied-in variables in nested
-      // blocks because it is needed at the end for some of the API generations.
-      // See SynthesizeBlockLiterals routine.
-        InnerDeclRefs.push_back(Exp); countOfInnerDecls++;
-        BlockDeclRefs.push_back(Exp);
-        BlockByCopyDeclsPtrSet.insert(VD);
-        BlockByCopyDecls.push_back(VD);
-      }
-      if (Exp->isByRef() && !BlockByRefDeclsPtrSet.count(VD)) {
-        InnerDeclRefs.push_back(Exp); countOfInnerDecls++;
-        BlockDeclRefs.push_back(Exp);
-        BlockByRefDeclsPtrSet.insert(VD);
-        BlockByRefDecls.push_back(VD);
-      }
-    }
-    // Find any imported blocks...they will need special attention.
-    for (unsigned i = 0; i < InnerBlockDeclRefs.size(); i++)
-      if (InnerBlockDeclRefs[i]->isByRef() ||
-          InnerBlockDeclRefs[i]->getType()->isObjCObjectPointerType() || 
-          InnerBlockDeclRefs[i]->getType()->isBlockPointerType())
-        ImportedBlockDecls.insert(InnerBlockDeclRefs[i]->getDecl());
+  // Explicitly declared @interface's are already synthesized.
+  if (CDecl->isImplicitInterfaceDecl()) {
+    // FIXME: Implementation of a class with no @interface (legacy) doese not
+    // produce correct synthesis as yet.
+    RewriteObjCInternalStruct(CDecl, Result);
   }
-  InnerDeclRefsCount.push_back(countOfInnerDecls);
-  
-  std::string FuncName;
-
-  if (CurFunctionDef)
-    FuncName = CurFunctionDef->getNameAsString();
-  else if (CurMethodDef)
-    BuildUniqueMethodName(FuncName, CurMethodDef);
-  else if (GlobalVarDecl)
-    FuncName = std::string(GlobalVarDecl->getNameAsString());
-
-  std::string BlockNumber = utostr(Blocks.size()-1);
-
-  std::string Tag = "__" + FuncName + "_block_impl_" + BlockNumber;
-  std::string Func = "__" + FuncName + "_block_func_" + BlockNumber;
-
-  // Get a pointer to the function type so we can cast appropriately.
-  QualType BFT = convertFunctionTypeOfBlocks(Exp->getFunctionType());
-  QualType FType = Context->getPointerType(BFT);
-
-  FunctionDecl *FD;
-  Expr *NewRep;
-
-  // Simulate a contructor call...
-  FD = SynthBlockInitFunctionDecl(Tag);
-  DeclRefExpr *DRE = new (Context) DeclRefExpr(FD, FType, VK_RValue,
-                                               SourceLocation());
-
-  SmallVector<Expr*, 4> InitExprs;
-
-  // Initialize the block function.
-  FD = SynthBlockInitFunctionDecl(Func);
-  DeclRefExpr *Arg = new (Context) DeclRefExpr(FD, FD->getType(), VK_LValue,
-                                               SourceLocation());
-  CastExpr *castExpr = NoTypeInfoCStyleCastExpr(Context, Context->VoidPtrTy,
-                                                CK_BitCast, Arg);
-  InitExprs.push_back(castExpr);
-
-  // Initialize the block descriptor.
-  std::string DescData = "__" + FuncName + "_block_desc_" + BlockNumber + "_DATA";
-
-  VarDecl *NewVD = VarDecl::Create(*Context, TUDecl,
-                                   SourceLocation(), SourceLocation(),
-                                   &Context->Idents.get(DescData.c_str()),
-                                   Context->VoidPtrTy, 0,
-                                   SC_Static, SC_None);
-  UnaryOperator *DescRefExpr =
-    new (Context) UnaryOperator(new (Context) DeclRefExpr(NewVD,
-                                                          Context->VoidPtrTy,
-                                                          VK_LValue,
-                                                          SourceLocation()), 
-                                UO_AddrOf,
-                                Context->getPointerType(Context->VoidPtrTy), 
-                                VK_RValue, OK_Ordinary,
-                                SourceLocation());
-  InitExprs.push_back(DescRefExpr); 
   
-  // Add initializers for any closure decl refs.
-  if (BlockDeclRefs.size()) {
-    Expr *Exp;
-    // Output all "by copy" declarations.
-    for (SmallVector<ValueDecl*,8>::iterator I = BlockByCopyDecls.begin(),
-         E = BlockByCopyDecls.end(); I != E; ++I) {
-      if (isObjCType((*I)->getType())) {
-        // FIXME: Conform to ABI ([[obj retain] autorelease]).
-        FD = SynthBlockInitFunctionDecl((*I)->getName());
-        Exp = new (Context) DeclRefExpr(FD, FD->getType(), VK_LValue,
-                                        SourceLocation());
-        if (HasLocalVariableExternalStorage(*I)) {
-          QualType QT = (*I)->getType();
-          QT = Context->getPointerType(QT);
-          Exp = new (Context) UnaryOperator(Exp, UO_AddrOf, QT, VK_RValue,
-                                            OK_Ordinary, SourceLocation());
-        }
-      } else if (isTopLevelBlockPointerType((*I)->getType())) {
-        FD = SynthBlockInitFunctionDecl((*I)->getName());
-        Arg = new (Context) DeclRefExpr(FD, FD->getType(), VK_LValue,
-                                        SourceLocation());
-        Exp = NoTypeInfoCStyleCastExpr(Context, Context->VoidPtrTy,
-                                       CK_BitCast, Arg);
-      } else {
-        FD = SynthBlockInitFunctionDecl((*I)->getName());
-        Exp = new (Context) DeclRefExpr(FD, FD->getType(), VK_LValue,
-                                        SourceLocation());
-        if (HasLocalVariableExternalStorage(*I)) {
-          QualType QT = (*I)->getType();
-          QT = Context->getPointerType(QT);
-          Exp = new (Context) UnaryOperator(Exp, UO_AddrOf, QT, VK_RValue,
-                                            OK_Ordinary, SourceLocation());
-        }
-        
-      }
-      InitExprs.push_back(Exp);
-    }
-    // Output all "by ref" declarations.
-    for (SmallVector<ValueDecl*,8>::iterator I = BlockByRefDecls.begin(),
-         E = BlockByRefDecls.end(); I != E; ++I) {
-      ValueDecl *ND = (*I);
-      std::string Name(ND->getNameAsString());
-      std::string RecName;
-      RewriteByRefString(RecName, Name, ND, true);
-      IdentifierInfo *II = &Context->Idents.get(RecName.c_str() 
-                                                + sizeof("struct"));
-      RecordDecl *RD = RecordDecl::Create(*Context, TTK_Struct, TUDecl,
-                                          SourceLocation(), SourceLocation(),
-                                          II);
-      assert(RD && "SynthBlockInitExpr(): Can't find RecordDecl");
-      QualType castT = Context->getPointerType(Context->getTagDeclType(RD));
+  // Build _objc_ivar_list metadata for classes ivars if needed
+  unsigned NumIvars = !IDecl->ivar_empty()
+  ? IDecl->ivar_size()
+  : (CDecl ? CDecl->ivar_size() : 0);
+  if (NumIvars > 0) {
+    static bool objc_ivar = false;
+    if (!objc_ivar) {
+      /* struct _objc_ivar {
+       char *ivar_name;
+       char *ivar_type;
+       int ivar_offset;
+       };
+       */
+      Result += "\nstruct _objc_ivar {\n";
+      Result += "\tchar *ivar_name;\n";
+      Result += "\tchar *ivar_type;\n";
+      Result += "\tint ivar_offset;\n";
+      Result += "};\n";
       
-      FD = SynthBlockInitFunctionDecl((*I)->getName());
-      Exp = new (Context) DeclRefExpr(FD, FD->getType(), VK_LValue,
-                                      SourceLocation());
-      bool isNestedCapturedVar = false;
-      if (block)
-        for (BlockDecl::capture_const_iterator ci = block->capture_begin(),
-             ce = block->capture_end(); ci != ce; ++ci) {
-          const VarDecl *variable = ci->getVariable();
-          if (variable == ND && ci->isNested()) {
-            assert (ci->isByRef() && 
-                    "SynthBlockInitExpr - captured block variable is not byref");
-            isNestedCapturedVar = true;
-            break;
-          }
-        }
-      // captured nested byref variable has its address passed. Do not take
-      // its address again.
-      if (!isNestedCapturedVar)
-          Exp = new (Context) UnaryOperator(Exp, UO_AddrOf,
-                                     Context->getPointerType(Exp->getType()),
-                                     VK_RValue, OK_Ordinary, SourceLocation());
-      Exp = NoTypeInfoCStyleCastExpr(Context, castT, CK_BitCast, Exp);
-      InitExprs.push_back(Exp);
+      objc_ivar = true;
+    }
+    
+    /* struct {
+     int ivar_count;
+     struct _objc_ivar ivar_list[nIvars];
+     };
+     */
+    Result += "\nstatic struct {\n";
+    Result += "\tint ivar_count;\n";
+    Result += "\tstruct _objc_ivar ivar_list[";
+    Result += utostr(NumIvars);
+    Result += "];\n} _OBJC_INSTANCE_VARIABLES_";
+    Result += IDecl->getNameAsString();
+    Result += " __attribute__ ((used, section (\"__OBJC, __instance_vars\")))= "
+    "{\n\t";
+    Result += utostr(NumIvars);
+    Result += "\n";
+    
+    ObjCInterfaceDecl::ivar_iterator IVI, IVE;
+    SmallVector<ObjCIvarDecl *, 8> IVars;
+    if (!IDecl->ivar_empty()) {
+      for (ObjCInterfaceDecl::ivar_iterator
+           IV = IDecl->ivar_begin(), IVEnd = IDecl->ivar_end();
+           IV != IVEnd; ++IV)
+        IVars.push_back(*IV);
+      IVI = IDecl->ivar_begin();
+      IVE = IDecl->ivar_end();
+    } else {
+      IVI = CDecl->ivar_begin();
+      IVE = CDecl->ivar_end();
     }
+    Result += "\t,{{\"";
+    Result += (*IVI)->getNameAsString();
+    Result += "\", \"";
+    std::string TmpString, StrEncoding;
+    Context->getObjCEncodingForType((*IVI)->getType(), TmpString, *IVI);
+    QuoteDoublequotes(TmpString, StrEncoding);
+    Result += StrEncoding;
+    Result += "\", ";
+    RewriteIvarOffsetComputation(*IVI, Result);
+    Result += "}\n";
+    for (++IVI; IVI != IVE; ++IVI) {
+      Result += "\t  ,{\"";
+      Result += (*IVI)->getNameAsString();
+      Result += "\", \"";
+      std::string TmpString, StrEncoding;
+      Context->getObjCEncodingForType((*IVI)->getType(), TmpString, *IVI);
+      QuoteDoublequotes(TmpString, StrEncoding);
+      Result += StrEncoding;
+      Result += "\", ";
+      RewriteIvarOffsetComputation((*IVI), Result);
+      Result += "}\n";
+    }
+    
+    Result += "\t }\n};\n";
   }
-  if (ImportedBlockDecls.size()) {
-    // generate BLOCK_HAS_COPY_DISPOSE(have helper funcs) | BLOCK_HAS_DESCRIPTOR
-    int flag = (BLOCK_HAS_COPY_DISPOSE | BLOCK_HAS_DESCRIPTOR);
-    unsigned IntSize = 
-      static_cast<unsigned>(Context->getTypeSize(Context->IntTy));
-    Expr *FlagExp = IntegerLiteral::Create(*Context, llvm::APInt(IntSize, flag), 
-                                           Context->IntTy, SourceLocation());
-    InitExprs.push_back(FlagExp);
+  
+  // Build _objc_method_list for class's instance methods if needed
+  SmallVector<ObjCMethodDecl *, 32>
+  InstanceMethods(IDecl->instmeth_begin(), IDecl->instmeth_end());
+  
+  // If any of our property implementations have associated getters or
+  // setters, produce metadata for them as well.
+  for (ObjCImplDecl::propimpl_iterator Prop = IDecl->propimpl_begin(),
+       PropEnd = IDecl->propimpl_end();
+       Prop != PropEnd; ++Prop) {
+    if ((*Prop)->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic)
+      continue;
+    if (!(*Prop)->getPropertyIvarDecl())
+      continue;
+    ObjCPropertyDecl *PD = (*Prop)->getPropertyDecl();
+    if (!PD)
+      continue;
+    if (ObjCMethodDecl *Getter = PD->getGetterMethodDecl())
+      if (!Getter->isDefined())
+        InstanceMethods.push_back(Getter);
+    if (PD->isReadOnly())
+      continue;
+    if (ObjCMethodDecl *Setter = PD->getSetterMethodDecl())
+      if (!Setter->isDefined())
+        InstanceMethods.push_back(Setter);
+  }
+  RewriteObjCMethodsMetaData(InstanceMethods.begin(), InstanceMethods.end(),
+                             true, "", IDecl->getName(), Result);
+  
+  // Build _objc_method_list for class's class methods if needed
+  RewriteObjCMethodsMetaData(IDecl->classmeth_begin(), IDecl->classmeth_end(),
+                             false, "", IDecl->getName(), Result);
+  
+  // Protocols referenced in class declaration?
+  RewriteObjCProtocolListMetaData(CDecl->getReferencedProtocols(),
+                                  "CLASS", CDecl->getName(), Result);
+  
+  // Declaration of class/meta-class metadata
+  /* struct _objc_class {
+   struct _objc_class *isa; // or const char *root_class_name when metadata
+   const char *super_class_name;
+   char *name;
+   long version;
+   long info;
+   long instance_size;
+   struct _objc_ivar_list *ivars;
+   struct _objc_method_list *methods;
+   struct objc_cache *cache;
+   struct objc_protocol_list *protocols;
+   const char *ivar_layout;
+   struct _objc_class_ext  *ext;
+   };
+   */
+  static bool objc_class = false;
+  if (!objc_class) {
+    Result += "\nstruct _objc_class {\n";
+    Result += "\tstruct _objc_class *isa;\n";
+    Result += "\tconst char *super_class_name;\n";
+    Result += "\tchar *name;\n";
+    Result += "\tlong version;\n";
+    Result += "\tlong info;\n";
+    Result += "\tlong instance_size;\n";
+    Result += "\tstruct _objc_ivar_list *ivars;\n";
+    Result += "\tstruct _objc_method_list *methods;\n";
+    Result += "\tstruct objc_cache *cache;\n";
+    Result += "\tstruct _objc_protocol_list *protocols;\n";
+    Result += "\tconst char *ivar_layout;\n";
+    Result += "\tstruct _objc_class_ext  *ext;\n";
+    Result += "};\n";
+    objc_class = true;
+  }
+  
+  // Meta-class metadata generation.
+  ObjCInterfaceDecl *RootClass = 0;
+  ObjCInterfaceDecl *SuperClass = CDecl->getSuperClass();
+  while (SuperClass) {
+    RootClass = SuperClass;
+    SuperClass = SuperClass->getSuperClass();
+  }
+  SuperClass = CDecl->getSuperClass();
+  
+  Result += "\nstatic struct _objc_class _OBJC_METACLASS_";
+  Result += CDecl->getNameAsString();
+  Result += " __attribute__ ((used, section (\"__OBJC, __meta_class\")))= "
+  "{\n\t(struct _objc_class *)\"";
+  Result += (RootClass ? RootClass->getNameAsString() : CDecl->getNameAsString());
+  Result += "\"";
+  
+  if (SuperClass) {
+    Result += ", \"";
+    Result += SuperClass->getNameAsString();
+    Result += "\", \"";
+    Result += CDecl->getNameAsString();
+    Result += "\"";
+  }
+  else {
+    Result += ", 0, \"";
+    Result += CDecl->getNameAsString();
+    Result += "\"";
+  }
+  // Set 'ivars' field for root class to 0. ObjC1 runtime does not use it.
+  // 'info' field is initialized to CLS_META(2) for metaclass
+  Result += ", 0,2, sizeof(struct _objc_class), 0";
+  if (IDecl->classmeth_begin() != IDecl->classmeth_end()) {
+    Result += "\n\t, (struct _objc_method_list *)&_OBJC_CLASS_METHODS_";
+    Result += IDecl->getNameAsString();
+    Result += "\n";
+  }
+  else
+    Result += ", 0\n";
+  if (CDecl->protocol_begin() != CDecl->protocol_end()) {
+    Result += "\t,0, (struct _objc_protocol_list *)&_OBJC_CLASS_PROTOCOLS_";
+    Result += CDecl->getNameAsString();
+    Result += ",0,0\n";
+  }
+  else
+    Result += "\t,0,0,0,0\n";
+  Result += "};\n";
+  
+  // class metadata generation.
+  Result += "\nstatic struct _objc_class _OBJC_CLASS_";
+  Result += CDecl->getNameAsString();
+  Result += " __attribute__ ((used, section (\"__OBJC, __class\")))= "
+  "{\n\t&_OBJC_METACLASS_";
+  Result += CDecl->getNameAsString();
+  if (SuperClass) {
+    Result += ", \"";
+    Result += SuperClass->getNameAsString();
+    Result += "\", \"";
+    Result += CDecl->getNameAsString();
+    Result += "\"";
+  }
+  else {
+    Result += ", 0, \"";
+    Result += CDecl->getNameAsString();
+    Result += "\"";
   }
-  NewRep = new (Context) CallExpr(*Context, DRE, &InitExprs[0], InitExprs.size(),
-                                  FType, VK_LValue, SourceLocation());
-  NewRep = new (Context) UnaryOperator(NewRep, UO_AddrOf,
-                             Context->getPointerType(NewRep->getType()),
-                             VK_RValue, OK_Ordinary, SourceLocation());
-  NewRep = NoTypeInfoCStyleCastExpr(Context, FType, CK_BitCast,
-                                    NewRep);
-  BlockDeclRefs.clear();
-  BlockByRefDecls.clear();
-  BlockByRefDeclsPtrSet.clear();
-  BlockByCopyDecls.clear();
-  BlockByCopyDeclsPtrSet.clear();
-  ImportedBlockDecls.clear();
-  return NewRep;
-}
-
-bool RewriteObjC::IsDeclStmtInForeachHeader(DeclStmt *DS) {
-  if (const ObjCForCollectionStmt * CS = 
-      dyn_cast<ObjCForCollectionStmt>(Stmts.back()))
-        return CS->getElement() == DS;
-  return false;
-}
-
-//===----------------------------------------------------------------------===//
-// Function Body / Expression rewriting
-//===----------------------------------------------------------------------===//
-
-Stmt *RewriteObjC::RewriteFunctionBodyOrGlobalInitializer(Stmt *S) {
-  if (isa<SwitchStmt>(S) || isa<WhileStmt>(S) ||
-      isa<DoStmt>(S) || isa<ForStmt>(S))
-    Stmts.push_back(S);
-  else if (isa<ObjCForCollectionStmt>(S)) {
-    Stmts.push_back(S);
-    ObjCBcLabelNo.push_back(++BcLabelCount);
+  // 'info' field is initialized to CLS_CLASS(1) for class
+  Result += ", 0,1";
+  if (!ObjCSynthesizedStructs.count(CDecl))
+    Result += ",0";
+  else {
+    // class has size. Must synthesize its size.
+    Result += ",sizeof(struct ";
+    Result += CDecl->getNameAsString();
+    if (LangOpts.MicrosoftExt)
+      Result += "_IMPL";
+    Result += ")";
   }
-
-  // Pseudo-object operations and ivar references need special
-  // treatment because we're going to recursively rewrite them.
-  if (PseudoObjectExpr *PseudoOp = dyn_cast<PseudoObjectExpr>(S)) {
-    if (isa<BinaryOperator>(PseudoOp->getSyntacticForm())) {
-      return RewritePropertyOrImplicitSetter(PseudoOp);
-    } else {
-      return RewritePropertyOrImplicitGetter(PseudoOp);
-    }
-  } else if (ObjCIvarRefExpr *IvarRefExpr = dyn_cast<ObjCIvarRefExpr>(S)) {
-    return RewriteObjCIvarRefExpr(IvarRefExpr);
+  if (NumIvars > 0) {
+    Result += ", (struct _objc_ivar_list *)&_OBJC_INSTANCE_VARIABLES_";
+    Result += CDecl->getNameAsString();
+    Result += "\n\t";
   }
-
-  SourceRange OrigStmtRange = S->getSourceRange();
-
-  // Perform a bottom up rewrite of all children.
-  for (Stmt::child_range CI = S->children(); CI; ++CI)
-    if (*CI) {
-      Stmt *childStmt = (*CI);
-      Stmt *newStmt = RewriteFunctionBodyOrGlobalInitializer(childStmt);
-      if (newStmt) {
-        *CI = newStmt;
-      }
-    }
-
-  if (BlockExpr *BE = dyn_cast<BlockExpr>(S)) {
-    SmallVector<BlockDeclRefExpr *, 8> InnerBlockDeclRefs;
-    llvm::SmallPtrSet<const DeclContext *, 8> InnerContexts;
-    InnerContexts.insert(BE->getBlockDecl());
-    ImportedLocalExternalDecls.clear();
-    GetInnerBlockDeclRefExprs(BE->getBody(),
-                              InnerBlockDeclRefs, InnerContexts);
-    // Rewrite the block body in place.
-    Stmt *SaveCurrentBody = CurrentBody;
-    CurrentBody = BE->getBody();
-    PropParentMap = 0;
-    // block literal on rhs of a property-dot-sytax assignment
-    // must be replaced by its synthesize ast so getRewrittenText
-    // works as expected. In this case, what actually ends up on RHS
-    // is the blockTranscribed which is the helper function for the
-    // block literal; as in: self.c = ^() {[ace ARR];};
-    bool saveDisableReplaceStmt = DisableReplaceStmt;
-    DisableReplaceStmt = false;
-    RewriteFunctionBodyOrGlobalInitializer(BE->getBody());
-    DisableReplaceStmt = saveDisableReplaceStmt;
-    CurrentBody = SaveCurrentBody;
-    PropParentMap = 0;
-    ImportedLocalExternalDecls.clear();
-    // Now we snarf the rewritten text and stash it away for later use.
-    std::string Str = Rewrite.getRewrittenText(BE->getSourceRange());
-    RewrittenBlockExprs[BE] = Str;
-
-    Stmt *blockTranscribed = SynthBlockInitExpr(BE, InnerBlockDeclRefs);
-                            
-    //blockTranscribed->dump();
-    ReplaceStmt(S, blockTranscribed);
-    return blockTranscribed;
+  else
+    Result += ",0";
+  if (IDecl->instmeth_begin() != IDecl->instmeth_end()) {
+    Result += ", (struct _objc_method_list *)&_OBJC_INSTANCE_METHODS_";
+    Result += CDecl->getNameAsString();
+    Result += ", 0\n\t";
   }
-  // Handle specific things.
-  if (ObjCEncodeExpr *AtEncode = dyn_cast<ObjCEncodeExpr>(S))
-    return RewriteAtEncode(AtEncode);
-
-  if (ObjCSelectorExpr *AtSelector = dyn_cast<ObjCSelectorExpr>(S))
-    return RewriteAtSelector(AtSelector);
-
-  if (ObjCStringLiteral *AtString = dyn_cast<ObjCStringLiteral>(S))
-    return RewriteObjCStringLiteral(AtString);
-
-  if (ObjCMessageExpr *MessExpr = dyn_cast<ObjCMessageExpr>(S)) {
-#if 0
-    // Before we rewrite it, put the original message expression in a comment.
-    SourceLocation startLoc = MessExpr->getLocStart();
-    SourceLocation endLoc = MessExpr->getLocEnd();
-
-    const char *startBuf = SM->getCharacterData(startLoc);
-    const char *endBuf = SM->getCharacterData(endLoc);
-
-    std::string messString;
-    messString += "// ";
-    messString.append(startBuf, endBuf-startBuf+1);
-    messString += "\n";
-
-    // FIXME: Missing definition of
-    // InsertText(clang::SourceLocation, char const*, unsigned int).
-    // InsertText(startLoc, messString.c_str(), messString.size());
-    // Tried this, but it didn't work either...
-    // ReplaceText(startLoc, 0, messString.c_str(), messString.size());
-#endif
-    return RewriteMessageExpr(MessExpr);
+  else
+    Result += ",0,0";
+  if (CDecl->protocol_begin() != CDecl->protocol_end()) {
+    Result += ", (struct _objc_protocol_list*)&_OBJC_CLASS_PROTOCOLS_";
+    Result += CDecl->getNameAsString();
+    Result += ", 0,0\n";
   }
+  else
+    Result += ",0,0,0\n";
+  Result += "};\n";
+}
 
-  if (ObjCAtTryStmt *StmtTry = dyn_cast<ObjCAtTryStmt>(S))
-    return RewriteObjCTryStmt(StmtTry);
-
-  if (ObjCAtSynchronizedStmt *StmtTry = dyn_cast<ObjCAtSynchronizedStmt>(S))
-    return RewriteObjCSynchronizedStmt(StmtTry);
-
-  if (ObjCAtThrowStmt *StmtThrow = dyn_cast<ObjCAtThrowStmt>(S))
-    return RewriteObjCThrowStmt(StmtThrow);
-
-  if (ObjCProtocolExpr *ProtocolExp = dyn_cast<ObjCProtocolExpr>(S))
-    return RewriteObjCProtocolExpr(ProtocolExp);
-
-  if (ObjCForCollectionStmt *StmtForCollection =
-        dyn_cast<ObjCForCollectionStmt>(S))
-    return RewriteObjCForCollectionStmt(StmtForCollection,
-                                        OrigStmtRange.getEnd());
-  if (BreakStmt *StmtBreakStmt =
-      dyn_cast<BreakStmt>(S))
-    return RewriteBreakStmt(StmtBreakStmt);
-  if (ContinueStmt *StmtContinueStmt =
-      dyn_cast<ContinueStmt>(S))
-    return RewriteContinueStmt(StmtContinueStmt);
-
-  // Need to check for protocol refs (id <P>, Foo <P> *) in variable decls
-  // and cast exprs.
-  if (DeclStmt *DS = dyn_cast<DeclStmt>(S)) {
-    // FIXME: What we're doing here is modifying the type-specifier that
-    // precedes the first Decl.  In the future the DeclGroup should have
-    // a separate type-specifier that we can rewrite.
-    // NOTE: We need to avoid rewriting the DeclStmt if it is within
-    // the context of an ObjCForCollectionStmt. For example:
-    //   NSArray *someArray;
-    //   for (id <FooProtocol> index in someArray) ;
-    // This is because RewriteObjCForCollectionStmt() does textual rewriting 
-    // and it depends on the original text locations/positions.
-    if (Stmts.empty() || !IsDeclStmtInForeachHeader(DS))
-      RewriteObjCQualifiedInterfaceTypes(*DS->decl_begin());
-
-    // Blocks rewrite rules.
-    for (DeclStmt::decl_iterator DI = DS->decl_begin(), DE = DS->decl_end();
-         DI != DE; ++DI) {
-      Decl *SD = *DI;
-      if (ValueDecl *ND = dyn_cast<ValueDecl>(SD)) {
-        if (isTopLevelBlockPointerType(ND->getType()))
-          RewriteBlockPointerDecl(ND);
-        else if (ND->getType()->isFunctionPointerType())
-          CheckFunctionPointerDecl(ND->getType(), ND);
-        if (VarDecl *VD = dyn_cast<VarDecl>(SD)) {
-          if (VD->hasAttr<BlocksAttr>()) {
-            static unsigned uniqueByrefDeclCount = 0;
-            assert(!BlockByRefDeclNo.count(ND) &&
-              "RewriteFunctionBodyOrGlobalInitializer: Duplicate byref decl");
-            BlockByRefDeclNo[ND] = uniqueByrefDeclCount++;
-            RewriteByRefVar(VD);
-          }
-          else           
-            RewriteTypeOfDecl(VD);
-        }
-      }
-      if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(SD)) {
-        if (isTopLevelBlockPointerType(TD->getUnderlyingType()))
-          RewriteBlockPointerDecl(TD);
-        else if (TD->getUnderlyingType()->isFunctionPointerType())
-          CheckFunctionPointerDecl(TD->getUnderlyingType(), TD);
+void RewriteObjCFragileABI::RewriteMetaDataIntoBuffer(std::string &Result) {
+  int ClsDefCount = ClassImplementation.size();
+  int CatDefCount = CategoryImplementation.size();
+  
+  // For each implemented class, write out all its meta data.
+  for (int i = 0; i < ClsDefCount; i++)
+    RewriteObjCClassMetaData(ClassImplementation[i], Result);
+  
+  // For each implemented category, write out all its meta data.
+  for (int i = 0; i < CatDefCount; i++)
+    RewriteObjCCategoryImplDecl(CategoryImplementation[i], Result);
+  
+  // Write objc_symtab metadata
+  /*
+   struct _objc_symtab
+   {
+   long sel_ref_cnt;
+   SEL *refs;
+   short cls_def_cnt;
+   short cat_def_cnt;
+   void *defs[cls_def_cnt + cat_def_cnt];
+   };
+   */
+  
+  Result += "\nstruct _objc_symtab {\n";
+  Result += "\tlong sel_ref_cnt;\n";
+  Result += "\tSEL *refs;\n";
+  Result += "\tshort cls_def_cnt;\n";
+  Result += "\tshort cat_def_cnt;\n";
+  Result += "\tvoid *defs[" + utostr(ClsDefCount + CatDefCount)+ "];\n";
+  Result += "};\n\n";
+  
+  Result += "static struct _objc_symtab "
+  "_OBJC_SYMBOLS __attribute__((used, section (\"__OBJC, __symbols\")))= {\n";
+  Result += "\t0, 0, " + utostr(ClsDefCount)
+  + ", " + utostr(CatDefCount) + "\n";
+  for (int i = 0; i < ClsDefCount; i++) {
+    Result += "\t,&_OBJC_CLASS_";
+    Result += ClassImplementation[i]->getNameAsString();
+    Result += "\n";
+  }
+  
+  for (int i = 0; i < CatDefCount; i++) {
+    Result += "\t,&_OBJC_CATEGORY_";
+    Result += CategoryImplementation[i]->getClassInterface()->getNameAsString();
+    Result += "_";
+    Result += CategoryImplementation[i]->getNameAsString();
+    Result += "\n";
+  }
+  
+  Result += "};\n\n";
+  
+  // Write objc_module metadata
+  
+  /*
+   struct _objc_module {
+   long version;
+   long size;
+   const char *name;
+   struct _objc_symtab *symtab;
+   }
+   */
+  
+  Result += "\nstruct _objc_module {\n";
+  Result += "\tlong version;\n";
+  Result += "\tlong size;\n";
+  Result += "\tconst char *name;\n";
+  Result += "\tstruct _objc_symtab *symtab;\n";
+  Result += "};\n\n";
+  Result += "static struct _objc_module "
+  "_OBJC_MODULES __attribute__ ((used, section (\"__OBJC, __module_info\")))= {\n";
+  Result += "\t" + utostr(OBJC_ABI_VERSION) +
+  ", sizeof(struct _objc_module), \"\", &_OBJC_SYMBOLS\n";
+  Result += "};\n\n";
+  
+  if (LangOpts.MicrosoftExt) {
+    if (ProtocolExprDecls.size()) {
+      Result += "#pragma section(\".objc_protocol$B\",long,read,write)\n";
+      Result += "#pragma data_seg(push, \".objc_protocol$B\")\n";
+      for (llvm::SmallPtrSet<ObjCProtocolDecl *,8>::iterator I = ProtocolExprDecls.begin(),
+           E = ProtocolExprDecls.end(); I != E; ++I) {
+        Result += "static struct _objc_protocol *_POINTER_OBJC_PROTOCOL_";
+        Result += (*I)->getNameAsString();
+        Result += " = &_OBJC_PROTOCOL_";
+        Result += (*I)->getNameAsString();
+        Result += ";\n";
       }
+      Result += "#pragma data_seg(pop)\n\n";
     }
+    Result += "#pragma section(\".objc_module_info$B\",long,read,write)\n";
+    Result += "#pragma data_seg(push, \".objc_module_info$B\")\n";
+    Result += "static struct _objc_module *_POINTER_OBJC_MODULES = ";
+    Result += "&_OBJC_MODULES;\n";
+    Result += "#pragma data_seg(pop)\n\n";
   }
+}
 
-  if (CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(S))
-    RewriteObjCQualifiedInterfaceTypes(CE);
-
-  if (isa<SwitchStmt>(S) || isa<WhileStmt>(S) ||
-      isa<DoStmt>(S) || isa<ForStmt>(S)) {
-    assert(!Stmts.empty() && "Statement stack is empty");
-    assert ((isa<SwitchStmt>(Stmts.back()) || isa<WhileStmt>(Stmts.back()) ||
-             isa<DoStmt>(Stmts.back()) || isa<ForStmt>(Stmts.back()))
-            && "Statement stack mismatch");
-    Stmts.pop_back();
-  }
-  // Handle blocks rewriting.
-  if (BlockDeclRefExpr *BDRE = dyn_cast<BlockDeclRefExpr>(S)) {
-    if (BDRE->isByRef())
-      return RewriteBlockDeclRefExpr(BDRE);
+/// RewriteObjCCategoryImplDecl - Rewrite metadata for each category
+/// implementation.
+void RewriteObjCFragileABI::RewriteObjCCategoryImplDecl(ObjCCategoryImplDecl *IDecl,
+                                              std::string &Result) {
+  ObjCInterfaceDecl *ClassDecl = IDecl->getClassInterface();
+  // Find category declaration for this implementation.
+  ObjCCategoryDecl *CDecl;
+  for (CDecl = ClassDecl->getCategoryList(); CDecl;
+       CDecl = CDecl->getNextClassCategory())
+    if (CDecl->getIdentifier() == IDecl->getIdentifier())
+      break;
+  
+  std::string FullCategoryName = ClassDecl->getNameAsString();
+  FullCategoryName += '_';
+  FullCategoryName += IDecl->getNameAsString();
+  
+  // Build _objc_method_list for class's instance methods if needed
+  SmallVector<ObjCMethodDecl *, 32>
+  InstanceMethods(IDecl->instmeth_begin(), IDecl->instmeth_end());
+  
+  // If any of our property implementations have associated getters or
+  // setters, produce metadata for them as well.
+  for (ObjCImplDecl::propimpl_iterator Prop = IDecl->propimpl_begin(),
+       PropEnd = IDecl->propimpl_end();
+       Prop != PropEnd; ++Prop) {
+    if ((*Prop)->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic)
+      continue;
+    if (!(*Prop)->getPropertyIvarDecl())
+      continue;
+    ObjCPropertyDecl *PD = (*Prop)->getPropertyDecl();
+    if (!PD)
+      continue;
+    if (ObjCMethodDecl *Getter = PD->getGetterMethodDecl())
+      InstanceMethods.push_back(Getter);
+    if (PD->isReadOnly())
+      continue;
+    if (ObjCMethodDecl *Setter = PD->getSetterMethodDecl())
+      InstanceMethods.push_back(Setter);
   }
-  if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(S)) {
-    ValueDecl *VD = DRE->getDecl(); 
-    if (VD->hasAttr<BlocksAttr>())
-      return RewriteBlockDeclRefExpr(DRE);
-    if (HasLocalVariableExternalStorage(VD))
-      return RewriteLocalVariableExternalStorage(DRE);
+  RewriteObjCMethodsMetaData(InstanceMethods.begin(), InstanceMethods.end(),
+                             true, "CATEGORY_", FullCategoryName.c_str(),
+                             Result);
+  
+  // Build _objc_method_list for class's class methods if needed
+  RewriteObjCMethodsMetaData(IDecl->classmeth_begin(), IDecl->classmeth_end(),
+                             false, "CATEGORY_", FullCategoryName.c_str(),
+                             Result);
+  
+  // Protocols referenced in class declaration?
+  // Null CDecl is case of a category implementation with no category interface
+  if (CDecl)
+    RewriteObjCProtocolListMetaData(CDecl->getReferencedProtocols(), "CATEGORY",
+                                    FullCategoryName, Result);
+  /* struct _objc_category {
+   char *category_name;
+   char *class_name;
+   struct _objc_method_list *instance_methods;
+   struct _objc_method_list *class_methods;
+   struct _objc_protocol_list *protocols;
+   // Objective-C 1.0 extensions
+   uint32_t size;     // sizeof (struct _objc_category)
+   struct _objc_property_list *instance_properties;  // category's own
+   // @property decl.
+   };
+   */
+  
+  static bool objc_category = false;
+  if (!objc_category) {
+    Result += "\nstruct _objc_category {\n";
+    Result += "\tchar *category_name;\n";
+    Result += "\tchar *class_name;\n";
+    Result += "\tstruct _objc_method_list *instance_methods;\n";
+    Result += "\tstruct _objc_method_list *class_methods;\n";
+    Result += "\tstruct _objc_protocol_list *protocols;\n";
+    Result += "\tunsigned int size;\n";
+    Result += "\tstruct _objc_property_list *instance_properties;\n";
+    Result += "};\n";
+    objc_category = true;
   }
+  Result += "\nstatic struct _objc_category _OBJC_CATEGORY_";
+  Result += FullCategoryName;
+  Result += " __attribute__ ((used, section (\"__OBJC, __category\")))= {\n\t\"";
+  Result += IDecl->getNameAsString();
+  Result += "\"\n\t, \"";
+  Result += ClassDecl->getNameAsString();
+  Result += "\"\n";
   
-  if (CallExpr *CE = dyn_cast<CallExpr>(S)) {
-    if (CE->getCallee()->getType()->isBlockPointerType()) {
-      Stmt *BlockCall = SynthesizeBlockCall(CE, CE->getCallee());
-      ReplaceStmt(S, BlockCall);
-      return BlockCall;
-    }
+  if (IDecl->instmeth_begin() != IDecl->instmeth_end()) {
+    Result += "\t, (struct _objc_method_list *)"
+    "&_OBJC_CATEGORY_INSTANCE_METHODS_";
+    Result += FullCategoryName;
+    Result += "\n";
   }
-  if (CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(S)) {
-    RewriteCastExpr(CE);
+  else
+    Result += "\t, 0\n";
+  if (IDecl->classmeth_begin() != IDecl->classmeth_end()) {
+    Result += "\t, (struct _objc_method_list *)"
+    "&_OBJC_CATEGORY_CLASS_METHODS_";
+    Result += FullCategoryName;
+    Result += "\n";
   }
-#if 0
-  if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(S)) {
-    CastExpr *Replacement = new (Context) CastExpr(ICE->getType(),
-                                                   ICE->getSubExpr(),
-                                                   SourceLocation());
-    // Get the new text.
-    std::string SStr;
-    llvm::raw_string_ostream Buf(SStr);
-    Replacement->printPretty(Buf, *Context);
-    const std::string &Str = Buf.str();
+  else
+    Result += "\t, 0\n";
+  
+  if (CDecl && CDecl->protocol_begin() != CDecl->protocol_end()) {
+    Result += "\t, (struct _objc_protocol_list *)&_OBJC_CATEGORY_PROTOCOLS_";
+    Result += FullCategoryName;
+    Result += "\n";
+  }
+  else
+    Result += "\t, 0\n";
+  Result += "\t, sizeof(struct _objc_category), 0\n};\n";
+}
 
-    printf("CAST = %s\n", &Str[0]);
-    InsertText(ICE->getSubExpr()->getLocStart(), &Str[0], Str.size());
-    delete S;
-    return Replacement;
+// RewriteObjCMethodsMetaData - Rewrite methods metadata for instance or
+/// class methods.
+template<typename MethodIterator>
+void RewriteObjCFragileABI::RewriteObjCMethodsMetaData(MethodIterator MethodBegin,
+                                             MethodIterator MethodEnd,
+                                             bool IsInstanceMethod,
+                                             StringRef prefix,
+                                             StringRef ClassName,
+                                             std::string &Result) {
+  if (MethodBegin == MethodEnd) return;
+  
+  if (!objc_impl_method) {
+    /* struct _objc_method {
+     SEL _cmd;
+     char *method_types;
+     void *_imp;
+     }
+     */
+    Result += "\nstruct _objc_method {\n";
+    Result += "\tSEL _cmd;\n";
+    Result += "\tchar *method_types;\n";
+    Result += "\tvoid *_imp;\n";
+    Result += "};\n";
+    
+    objc_impl_method = true;
+  }
+  
+  // Build _objc_method_list for class's methods if needed
+  
+  /* struct  {
+   struct _objc_method_list *next_method;
+   int method_count;
+   struct _objc_method method_list[];
+   }
+   */
+  unsigned NumMethods = std::distance(MethodBegin, MethodEnd);
+  Result += "\nstatic struct {\n";
+  Result += "\tstruct _objc_method_list *next_method;\n";
+  Result += "\tint method_count;\n";
+  Result += "\tstruct _objc_method method_list[";
+  Result += utostr(NumMethods);
+  Result += "];\n} _OBJC_";
+  Result += prefix;
+  Result += IsInstanceMethod ? "INSTANCE" : "CLASS";
+  Result += "_METHODS_";
+  Result += ClassName;
+  Result += " __attribute__ ((used, section (\"__OBJC, __";
+  Result += IsInstanceMethod ? "inst" : "cls";
+  Result += "_meth\")))= ";
+  Result += "{\n\t0, " + utostr(NumMethods) + "\n";
+  
+  Result += "\t,{{(SEL)\"";
+  Result += (*MethodBegin)->getSelector().getAsString().c_str();
+  std::string MethodTypeString;
+  Context->getObjCEncodingForMethodDecl(*MethodBegin, MethodTypeString);
+  Result += "\", \"";
+  Result += MethodTypeString;
+  Result += "\", (void *)";
+  Result += MethodInternalNames[*MethodBegin];
+  Result += "}\n";
+  for (++MethodBegin; MethodBegin != MethodEnd; ++MethodBegin) {
+    Result += "\t  ,{(SEL)\"";
+    Result += (*MethodBegin)->getSelector().getAsString().c_str();
+    std::string MethodTypeString;
+    Context->getObjCEncodingForMethodDecl(*MethodBegin, MethodTypeString);
+    Result += "\", \"";
+    Result += MethodTypeString;
+    Result += "\", (void *)";
+    Result += MethodInternalNames[*MethodBegin];
+    Result += "}\n";
   }
-#endif
-  // Return this stmt unmodified.
-  return S;
+  Result += "\t }\n};\n";
 }
 
-void RewriteObjC::RewriteRecordBody(RecordDecl *RD) {
-  for (RecordDecl::field_iterator i = RD->field_begin(), 
-                                  e = RD->field_end(); i != e; ++i) {
-    FieldDecl *FD = *i;
-    if (isTopLevelBlockPointerType(FD->getType()))
-      RewriteBlockPointerDecl(FD);
-    if (FD->getType()->isObjCQualifiedIdType() ||
-        FD->getType()->isObjCQualifiedInterfaceType())
-      RewriteObjCQualifiedInterfaceTypes(FD);
+Stmt *RewriteObjCFragileABI::RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV) {
+  SourceRange OldRange = IV->getSourceRange();
+  Expr *BaseExpr = IV->getBase();
+  
+  // Rewrite the base, but without actually doing replaces.
+  {
+    DisableReplaceStmtScope S(*this);
+    BaseExpr = cast<Expr>(RewriteFunctionBodyOrGlobalInitializer(BaseExpr));
+    IV->setBase(BaseExpr);
   }
-}
-
-/// HandleDeclInMainFile - This is called for each top-level decl defined in the
-/// main file of the input.
-void RewriteObjC::HandleDeclInMainFile(Decl *D) {
-  switch (D->getKind()) {
-    case Decl::Function: {
-      FunctionDecl *FD = cast<FunctionDecl>(D);
-      if (FD->isOverloadedOperator())
-        return;
-
-      // Since function prototypes don't have ParmDecl's, we check the function
-      // prototype. This enables us to rewrite function declarations and
-      // definitions using the same code.
-      RewriteBlocksInFunctionProtoType(FD->getType(), FD);
-
-      // FIXME: If this should support Obj-C++, support CXXTryStmt
-      if (CompoundStmt *Body = dyn_cast_or_null<CompoundStmt>(FD->getBody())) {
-        CurFunctionDef = FD;
-        CurFunctionDeclToDeclareForBlock = FD;
-        CurrentBody = Body;
-        Body =
-        cast_or_null<CompoundStmt>(RewriteFunctionBodyOrGlobalInitializer(Body));
-        FD->setBody(Body);
-        CurrentBody = 0;
-        if (PropParentMap) {
-          delete PropParentMap;
-          PropParentMap = 0;
-        }
-        // This synthesizes and inserts the block "impl" struct, invoke function,
-        // and any copy/dispose helper functions.
-        InsertBlockLiteralsWithinFunction(FD);
-        CurFunctionDef = 0;
-        CurFunctionDeclToDeclareForBlock = 0;
-      }
-      break;
-    }
-    case Decl::ObjCMethod: {
-      ObjCMethodDecl *MD = cast<ObjCMethodDecl>(D);
-      if (CompoundStmt *Body = MD->getCompoundBody()) {
-        CurMethodDef = MD;
-        CurrentBody = Body;
-        Body =
-          cast_or_null<CompoundStmt>(RewriteFunctionBodyOrGlobalInitializer(Body));
-        MD->setBody(Body);
-        CurrentBody = 0;
-        if (PropParentMap) {
-          delete PropParentMap;
-          PropParentMap = 0;
-        }
-        InsertBlockLiteralsWithinMethod(MD);
-        CurMethodDef = 0;
-      }
-      break;
-    }
-    case Decl::ObjCImplementation: {
-      ObjCImplementationDecl *CI = cast<ObjCImplementationDecl>(D);
-      ClassImplementation.push_back(CI);
-      break;
-    }
-    case Decl::ObjCCategoryImpl: {
-      ObjCCategoryImplDecl *CI = cast<ObjCCategoryImplDecl>(D);
-      CategoryImplementation.push_back(CI);
-      break;
-    }
-    case Decl::Var: {
-      VarDecl *VD = cast<VarDecl>(D);
-      RewriteObjCQualifiedInterfaceTypes(VD);
-      if (isTopLevelBlockPointerType(VD->getType()))
-        RewriteBlockPointerDecl(VD);
-      else if (VD->getType()->isFunctionPointerType()) {
-        CheckFunctionPointerDecl(VD->getType(), VD);
-        if (VD->getInit()) {
-          if (CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(VD->getInit())) {
-            RewriteCastExpr(CE);
-          }
-        }
-      } else if (VD->getType()->isRecordType()) {
-        RecordDecl *RD = VD->getType()->getAs<RecordType>()->getDecl();
-        if (RD->isCompleteDefinition())
-          RewriteRecordBody(RD);
-      }
-      if (VD->getInit()) {
-        GlobalVarDecl = VD;
-        CurrentBody = VD->getInit();
-        RewriteFunctionBodyOrGlobalInitializer(VD->getInit());
-        CurrentBody = 0;
-        if (PropParentMap) {
-          delete PropParentMap;
-          PropParentMap = 0;
-        }
-        SynthesizeBlockLiterals(VD->getTypeSpecStartLoc(), VD->getName());
-        GlobalVarDecl = 0;
-          
-        // This is needed for blocks.
-        if (CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(VD->getInit())) {
-            RewriteCastExpr(CE);
-        }
-      }
-      break;
-    }
-    case Decl::TypeAlias:
-    case Decl::Typedef: {
-      if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(D)) {
-        if (isTopLevelBlockPointerType(TD->getUnderlyingType()))
-          RewriteBlockPointerDecl(TD);
-        else if (TD->getUnderlyingType()->isFunctionPointerType())
-          CheckFunctionPointerDecl(TD->getUnderlyingType(), TD);
+  
+  ObjCIvarDecl *D = IV->getDecl();
+  
+  Expr *Replacement = IV;
+  if (CurMethodDef) {
+    if (BaseExpr->getType()->isObjCObjectPointerType()) {
+      const ObjCInterfaceType *iFaceDecl =
+      dyn_cast<ObjCInterfaceType>(BaseExpr->getType()->getPointeeType());
+      assert(iFaceDecl && "RewriteObjCIvarRefExpr - iFaceDecl is null");
+      // lookup which class implements the instance variable.
+      ObjCInterfaceDecl *clsDeclared = 0;
+      iFaceDecl->getDecl()->lookupInstanceVariable(D->getIdentifier(),
+                                                   clsDeclared);
+      assert(clsDeclared && "RewriteObjCIvarRefExpr(): Can't find class");
+      
+      // Synthesize an explicit cast to gain access to the ivar.
+      std::string RecName = clsDeclared->getIdentifier()->getName();
+      RecName += "_IMPL";
+      IdentifierInfo *II = &Context->Idents.get(RecName);
+      RecordDecl *RD = RecordDecl::Create(*Context, TTK_Struct, TUDecl,
+                                          SourceLocation(), SourceLocation(),
+                                          II);
+      assert(RD && "RewriteObjCIvarRefExpr(): Can't find RecordDecl");
+      QualType castT = Context->getPointerType(Context->getTagDeclType(RD));
+      CastExpr *castExpr = NoTypeInfoCStyleCastExpr(Context, castT,
+                                                    CK_BitCast,
+                                                    IV->getBase());
+      // Don't forget the parens to enforce the proper binding.
+      ParenExpr *PE = new (Context) ParenExpr(OldRange.getBegin(),
+                                              OldRange.getEnd(),
+                                              castExpr);
+      if (IV->isFreeIvar() &&
+          CurMethodDef->getClassInterface() == iFaceDecl->getDecl()) {
+        MemberExpr *ME = new (Context) MemberExpr(PE, true, D,
+                                                  IV->getLocation(),
+                                                  D->getType(),
+                                                  VK_LValue, OK_Ordinary);
+        Replacement = ME;
+      } else {
+        IV->setBase(PE);
       }
-      break;
-    }
-    case Decl::CXXRecord:
-    case Decl::Record: {
-      RecordDecl *RD = cast<RecordDecl>(D);
-      if (RD->isCompleteDefinition()) 
-        RewriteRecordBody(RD);
-      break;
     }
-    case Decl::ObjCClass: {
-      llvm_unreachable("RewriteObjC::HandleDeclInMainFile - ObjCClassDecl");
-      break;
+  } else { // we are outside a method.
+    assert(!IV->isFreeIvar() && "Cannot have a free standing ivar outside a method");
+    
+    // Explicit ivar refs need to have a cast inserted.
+    // FIXME: consider sharing some of this code with the code above.
+    if (BaseExpr->getType()->isObjCObjectPointerType()) {
+      const ObjCInterfaceType *iFaceDecl =
+      dyn_cast<ObjCInterfaceType>(BaseExpr->getType()->getPointeeType());
+      // lookup which class implements the instance variable.
+      ObjCInterfaceDecl *clsDeclared = 0;
+      iFaceDecl->getDecl()->lookupInstanceVariable(D->getIdentifier(),
+                                                   clsDeclared);
+      assert(clsDeclared && "RewriteObjCIvarRefExpr(): Can't find class");
+      
+      // Synthesize an explicit cast to gain access to the ivar.
+      std::string RecName = clsDeclared->getIdentifier()->getName();
+      RecName += "_IMPL";
+      IdentifierInfo *II = &Context->Idents.get(RecName);
+      RecordDecl *RD = RecordDecl::Create(*Context, TTK_Struct, TUDecl,
+                                          SourceLocation(), SourceLocation(),
+                                          II);
+      assert(RD && "RewriteObjCIvarRefExpr(): Can't find RecordDecl");
+      QualType castT = Context->getPointerType(Context->getTagDeclType(RD));
+      CastExpr *castExpr = NoTypeInfoCStyleCastExpr(Context, castT,
+                                                    CK_BitCast,
+                                                    IV->getBase());
+      // Don't forget the parens to enforce the proper binding.
+      ParenExpr *PE = new (Context) ParenExpr(IV->getBase()->getLocStart(),
+                                              IV->getBase()->getLocEnd(), castExpr);
+      // Cannot delete IV->getBase(), since PE points to it.
+      // Replace the old base with the cast. This is important when doing
+      // embedded rewrites. For example, [newInv->_container addObject:0].
+      IV->setBase(PE);
     }
-    default:
-      break;
   }
-  // Nothing yet.
+  
+  ReplaceStmtWithRange(IV, Replacement, OldRange);
+  return Replacement;  
 }
 
-void RewriteObjC::HandleTranslationUnit(ASTContext &C) {
-  if (Diags.hasErrorOccurred())
-    return;
-
-  RewriteInclude();
-
-  // Here's a great place to add any extra declarations that may be needed.
-  // Write out meta data for each @protocol(<expr>).
-  for (llvm::SmallPtrSet<ObjCProtocolDecl *,8>::iterator I = ProtocolExprDecls.begin(),
-       E = ProtocolExprDecls.end(); I != E; ++I)
-    RewriteObjCProtocolMetaData(*I, "", "", Preamble);
-
-  InsertText(SM->getLocForStartOfFile(MainFileID), Preamble, false);
-  if (ClassImplementation.size() || CategoryImplementation.size())
-    RewriteImplementations();
-
-  // Get the buffer corresponding to MainFileID.  If we haven't changed it, then
-  // we are done.
-  if (const RewriteBuffer *RewriteBuf =
-      Rewrite.getRewriteBufferFor(MainFileID)) {
-    //printf("Changed:\n");
-    *OutFile << std::string(RewriteBuf->begin(), RewriteBuf->end());
-  } else {
-    llvm::errs() << "No changes\n";
-  }
-
-  if (ClassImplementation.size() || CategoryImplementation.size() ||
-      ProtocolExprDecls.size()) {
-    // Rewrite Objective-c meta data*
-    std::string ResultStr;
-    RewriteMetaDataIntoBuffer(ResultStr);
-    // Emit metadata.
-    *OutFile << ResultStr;
-  }
-  OutFile->flush();
-}




More information about the cfe-commits mailing list