xref: /freebsd/contrib/llvm-project/clang/lib/Frontend/Rewrite/RewriteObjC.cpp (revision 5f757f3ff9144b609b3c433dfd370cc6bdc191ad)
10b57cec5SDimitry Andric //===--- RewriteObjC.cpp - Playground for the code rewriter ---------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // Hacks and fun related to the code rewriter.
100b57cec5SDimitry Andric //
110b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
120b57cec5SDimitry Andric 
130b57cec5SDimitry Andric #include "clang/Rewrite/Frontend/ASTConsumers.h"
140b57cec5SDimitry Andric #include "clang/AST/AST.h"
150b57cec5SDimitry Andric #include "clang/AST/ASTConsumer.h"
160b57cec5SDimitry Andric #include "clang/AST/Attr.h"
170b57cec5SDimitry Andric #include "clang/AST/ParentMap.h"
180b57cec5SDimitry Andric #include "clang/Basic/CharInfo.h"
190b57cec5SDimitry Andric #include "clang/Basic/Diagnostic.h"
200b57cec5SDimitry Andric #include "clang/Basic/IdentifierTable.h"
210b57cec5SDimitry Andric #include "clang/Basic/SourceManager.h"
220b57cec5SDimitry Andric #include "clang/Config/config.h"
230b57cec5SDimitry Andric #include "clang/Lex/Lexer.h"
240b57cec5SDimitry Andric #include "clang/Rewrite/Core/Rewriter.h"
250b57cec5SDimitry Andric #include "llvm/ADT/DenseSet.h"
260b57cec5SDimitry Andric #include "llvm/ADT/SmallPtrSet.h"
270b57cec5SDimitry Andric #include "llvm/ADT/StringExtras.h"
280b57cec5SDimitry Andric #include "llvm/Support/MemoryBuffer.h"
290b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
300b57cec5SDimitry Andric #include <memory>
310b57cec5SDimitry Andric 
320b57cec5SDimitry Andric #if CLANG_ENABLE_OBJC_REWRITER
330b57cec5SDimitry Andric 
340b57cec5SDimitry Andric using namespace clang;
350b57cec5SDimitry Andric using llvm::utostr;
360b57cec5SDimitry Andric 
370b57cec5SDimitry Andric namespace {
380b57cec5SDimitry Andric   class RewriteObjC : public ASTConsumer {
390b57cec5SDimitry Andric   protected:
400b57cec5SDimitry Andric     enum {
410b57cec5SDimitry Andric       BLOCK_FIELD_IS_OBJECT   =  3,  /* id, NSObject, __attribute__((NSObject)),
420b57cec5SDimitry Andric                                         block, ... */
430b57cec5SDimitry Andric       BLOCK_FIELD_IS_BLOCK    =  7,  /* a block variable */
440b57cec5SDimitry Andric       BLOCK_FIELD_IS_BYREF    =  8,  /* the on stack structure holding the
450b57cec5SDimitry Andric                                         __block variable */
460b57cec5SDimitry Andric       BLOCK_FIELD_IS_WEAK     = 16,  /* declared __weak, only used in byref copy
470b57cec5SDimitry Andric                                         helpers */
480b57cec5SDimitry Andric       BLOCK_BYREF_CALLER      = 128, /* called from __block (byref) copy/dispose
490b57cec5SDimitry Andric                                         support routines */
500b57cec5SDimitry Andric       BLOCK_BYREF_CURRENT_MAX = 256
510b57cec5SDimitry Andric     };
520b57cec5SDimitry Andric 
530b57cec5SDimitry Andric     enum {
540b57cec5SDimitry Andric       BLOCK_NEEDS_FREE =        (1 << 24),
550b57cec5SDimitry Andric       BLOCK_HAS_COPY_DISPOSE =  (1 << 25),
560b57cec5SDimitry Andric       BLOCK_HAS_CXX_OBJ =       (1 << 26),
570b57cec5SDimitry Andric       BLOCK_IS_GC =             (1 << 27),
580b57cec5SDimitry Andric       BLOCK_IS_GLOBAL =         (1 << 28),
590b57cec5SDimitry Andric       BLOCK_HAS_DESCRIPTOR =    (1 << 29)
600b57cec5SDimitry Andric     };
610b57cec5SDimitry Andric     static const int OBJC_ABI_VERSION = 7;
620b57cec5SDimitry Andric 
630b57cec5SDimitry Andric     Rewriter Rewrite;
640b57cec5SDimitry Andric     DiagnosticsEngine &Diags;
650b57cec5SDimitry Andric     const LangOptions &LangOpts;
660b57cec5SDimitry Andric     ASTContext *Context;
670b57cec5SDimitry Andric     SourceManager *SM;
680b57cec5SDimitry Andric     TranslationUnitDecl *TUDecl;
690b57cec5SDimitry Andric     FileID MainFileID;
700b57cec5SDimitry Andric     const char *MainFileStart, *MainFileEnd;
710b57cec5SDimitry Andric     Stmt *CurrentBody;
720b57cec5SDimitry Andric     ParentMap *PropParentMap; // created lazily.
730b57cec5SDimitry Andric     std::string InFileName;
740b57cec5SDimitry Andric     std::unique_ptr<raw_ostream> OutFile;
750b57cec5SDimitry Andric     std::string Preamble;
760b57cec5SDimitry Andric 
770b57cec5SDimitry Andric     TypeDecl *ProtocolTypeDecl;
780b57cec5SDimitry Andric     VarDecl *GlobalVarDecl;
790b57cec5SDimitry Andric     unsigned RewriteFailedDiag;
800b57cec5SDimitry Andric     // ObjC string constant support.
810b57cec5SDimitry Andric     unsigned NumObjCStringLiterals;
820b57cec5SDimitry Andric     VarDecl *ConstantStringClassReference;
830b57cec5SDimitry Andric     RecordDecl *NSStringRecord;
840b57cec5SDimitry Andric 
850b57cec5SDimitry Andric     // ObjC foreach break/continue generation support.
860b57cec5SDimitry Andric     int BcLabelCount;
870b57cec5SDimitry Andric 
880b57cec5SDimitry Andric     unsigned TryFinallyContainsReturnDiag;
890b57cec5SDimitry Andric     // Needed for super.
900b57cec5SDimitry Andric     ObjCMethodDecl *CurMethodDef;
910b57cec5SDimitry Andric     RecordDecl *SuperStructDecl;
920b57cec5SDimitry Andric     RecordDecl *ConstantStringDecl;
930b57cec5SDimitry Andric 
940b57cec5SDimitry Andric     FunctionDecl *MsgSendFunctionDecl;
950b57cec5SDimitry Andric     FunctionDecl *MsgSendSuperFunctionDecl;
960b57cec5SDimitry Andric     FunctionDecl *MsgSendStretFunctionDecl;
970b57cec5SDimitry Andric     FunctionDecl *MsgSendSuperStretFunctionDecl;
980b57cec5SDimitry Andric     FunctionDecl *MsgSendFpretFunctionDecl;
990b57cec5SDimitry Andric     FunctionDecl *GetClassFunctionDecl;
1000b57cec5SDimitry Andric     FunctionDecl *GetMetaClassFunctionDecl;
1010b57cec5SDimitry Andric     FunctionDecl *GetSuperClassFunctionDecl;
1020b57cec5SDimitry Andric     FunctionDecl *SelGetUidFunctionDecl;
1030b57cec5SDimitry Andric     FunctionDecl *CFStringFunctionDecl;
1040b57cec5SDimitry Andric     FunctionDecl *SuperConstructorFunctionDecl;
1050b57cec5SDimitry Andric     FunctionDecl *CurFunctionDef;
1060b57cec5SDimitry Andric     FunctionDecl *CurFunctionDeclToDeclareForBlock;
1070b57cec5SDimitry Andric 
1080b57cec5SDimitry Andric     /* Misc. containers needed for meta-data rewrite. */
1090b57cec5SDimitry Andric     SmallVector<ObjCImplementationDecl *, 8> ClassImplementation;
1100b57cec5SDimitry Andric     SmallVector<ObjCCategoryImplDecl *, 8> CategoryImplementation;
1110b57cec5SDimitry Andric     llvm::SmallPtrSet<ObjCInterfaceDecl*, 8> ObjCSynthesizedStructs;
1120b57cec5SDimitry Andric     llvm::SmallPtrSet<ObjCProtocolDecl*, 8> ObjCSynthesizedProtocols;
1130b57cec5SDimitry Andric     llvm::SmallPtrSet<ObjCInterfaceDecl*, 8> ObjCForwardDecls;
1140b57cec5SDimitry Andric     llvm::DenseMap<ObjCMethodDecl*, std::string> MethodInternalNames;
1150b57cec5SDimitry Andric     SmallVector<Stmt *, 32> Stmts;
1160b57cec5SDimitry Andric     SmallVector<int, 8> ObjCBcLabelNo;
1170b57cec5SDimitry Andric     // Remember all the @protocol(<expr>) expressions.
1180b57cec5SDimitry Andric     llvm::SmallPtrSet<ObjCProtocolDecl *, 32> ProtocolExprDecls;
1190b57cec5SDimitry Andric 
1200b57cec5SDimitry Andric     llvm::DenseSet<uint64_t> CopyDestroyCache;
1210b57cec5SDimitry Andric 
1220b57cec5SDimitry Andric     // Block expressions.
1230b57cec5SDimitry Andric     SmallVector<BlockExpr *, 32> Blocks;
1240b57cec5SDimitry Andric     SmallVector<int, 32> InnerDeclRefsCount;
1250b57cec5SDimitry Andric     SmallVector<DeclRefExpr *, 32> InnerDeclRefs;
1260b57cec5SDimitry Andric 
1270b57cec5SDimitry Andric     SmallVector<DeclRefExpr *, 32> BlockDeclRefs;
1280b57cec5SDimitry Andric 
1290b57cec5SDimitry Andric     // Block related declarations.
1300b57cec5SDimitry Andric     SmallVector<ValueDecl *, 8> BlockByCopyDecls;
1310b57cec5SDimitry Andric     llvm::SmallPtrSet<ValueDecl *, 8> BlockByCopyDeclsPtrSet;
1320b57cec5SDimitry Andric     SmallVector<ValueDecl *, 8> BlockByRefDecls;
1330b57cec5SDimitry Andric     llvm::SmallPtrSet<ValueDecl *, 8> BlockByRefDeclsPtrSet;
1340b57cec5SDimitry Andric     llvm::DenseMap<ValueDecl *, unsigned> BlockByRefDeclNo;
1350b57cec5SDimitry Andric     llvm::SmallPtrSet<ValueDecl *, 8> ImportedBlockDecls;
1360b57cec5SDimitry Andric     llvm::SmallPtrSet<VarDecl *, 8> ImportedLocalExternalDecls;
1370b57cec5SDimitry Andric 
1380b57cec5SDimitry Andric     llvm::DenseMap<BlockExpr *, std::string> RewrittenBlockExprs;
1390b57cec5SDimitry Andric 
1400b57cec5SDimitry Andric     // This maps an original source AST to it's rewritten form. This allows
1410b57cec5SDimitry Andric     // us to avoid rewriting the same node twice (which is very uncommon).
1420b57cec5SDimitry Andric     // This is needed to support some of the exotic property rewriting.
1430b57cec5SDimitry Andric     llvm::DenseMap<Stmt *, Stmt *> ReplacedNodes;
1440b57cec5SDimitry Andric 
1450b57cec5SDimitry Andric     // Needed for header files being rewritten
1460b57cec5SDimitry Andric     bool IsHeader;
1470b57cec5SDimitry Andric     bool SilenceRewriteMacroWarning;
1480b57cec5SDimitry Andric     bool objc_impl_method;
1490b57cec5SDimitry Andric 
1500b57cec5SDimitry Andric     bool DisableReplaceStmt;
1510b57cec5SDimitry Andric     class DisableReplaceStmtScope {
1520b57cec5SDimitry Andric       RewriteObjC &R;
1530b57cec5SDimitry Andric       bool SavedValue;
1540b57cec5SDimitry Andric 
1550b57cec5SDimitry Andric     public:
1560b57cec5SDimitry Andric       DisableReplaceStmtScope(RewriteObjC &R)
1570b57cec5SDimitry Andric         : R(R), SavedValue(R.DisableReplaceStmt) {
1580b57cec5SDimitry Andric         R.DisableReplaceStmt = true;
1590b57cec5SDimitry Andric       }
1600b57cec5SDimitry Andric 
1610b57cec5SDimitry Andric       ~DisableReplaceStmtScope() {
1620b57cec5SDimitry Andric         R.DisableReplaceStmt = SavedValue;
1630b57cec5SDimitry Andric       }
1640b57cec5SDimitry Andric     };
1650b57cec5SDimitry Andric 
1660b57cec5SDimitry Andric     void InitializeCommon(ASTContext &context);
1670b57cec5SDimitry Andric 
1680b57cec5SDimitry Andric   public:
1690b57cec5SDimitry Andric     // Top Level Driver code.
1700b57cec5SDimitry Andric     bool HandleTopLevelDecl(DeclGroupRef D) override {
1710b57cec5SDimitry Andric       for (DeclGroupRef::iterator I = D.begin(), E = D.end(); I != E; ++I) {
1720b57cec5SDimitry Andric         if (ObjCInterfaceDecl *Class = dyn_cast<ObjCInterfaceDecl>(*I)) {
1730b57cec5SDimitry Andric           if (!Class->isThisDeclarationADefinition()) {
1740b57cec5SDimitry Andric             RewriteForwardClassDecl(D);
1750b57cec5SDimitry Andric             break;
1760b57cec5SDimitry Andric           }
1770b57cec5SDimitry Andric         }
1780b57cec5SDimitry Andric 
1790b57cec5SDimitry Andric         if (ObjCProtocolDecl *Proto = dyn_cast<ObjCProtocolDecl>(*I)) {
1800b57cec5SDimitry Andric           if (!Proto->isThisDeclarationADefinition()) {
1810b57cec5SDimitry Andric             RewriteForwardProtocolDecl(D);
1820b57cec5SDimitry Andric             break;
1830b57cec5SDimitry Andric           }
1840b57cec5SDimitry Andric         }
1850b57cec5SDimitry Andric 
1860b57cec5SDimitry Andric         HandleTopLevelSingleDecl(*I);
1870b57cec5SDimitry Andric       }
1880b57cec5SDimitry Andric       return true;
1890b57cec5SDimitry Andric     }
1900b57cec5SDimitry Andric 
1910b57cec5SDimitry Andric     void HandleTopLevelSingleDecl(Decl *D);
1920b57cec5SDimitry Andric     void HandleDeclInMainFile(Decl *D);
1930b57cec5SDimitry Andric     RewriteObjC(std::string inFile, std::unique_ptr<raw_ostream> OS,
1940b57cec5SDimitry Andric                 DiagnosticsEngine &D, const LangOptions &LOpts,
1950b57cec5SDimitry Andric                 bool silenceMacroWarn);
1960b57cec5SDimitry Andric 
1970b57cec5SDimitry Andric     ~RewriteObjC() override {}
1980b57cec5SDimitry Andric 
1990b57cec5SDimitry Andric     void HandleTranslationUnit(ASTContext &C) override;
2000b57cec5SDimitry Andric 
2010b57cec5SDimitry Andric     void ReplaceStmt(Stmt *Old, Stmt *New) {
2020b57cec5SDimitry Andric       ReplaceStmtWithRange(Old, New, Old->getSourceRange());
2030b57cec5SDimitry Andric     }
2040b57cec5SDimitry Andric 
2050b57cec5SDimitry Andric     void ReplaceStmtWithRange(Stmt *Old, Stmt *New, SourceRange SrcRange) {
2060b57cec5SDimitry Andric       assert(Old != nullptr && New != nullptr && "Expected non-null Stmt's");
2070b57cec5SDimitry Andric 
2080b57cec5SDimitry Andric       Stmt *ReplacingStmt = ReplacedNodes[Old];
2090b57cec5SDimitry Andric       if (ReplacingStmt)
2100b57cec5SDimitry Andric         return; // We can't rewrite the same node twice.
2110b57cec5SDimitry Andric 
2120b57cec5SDimitry Andric       if (DisableReplaceStmt)
2130b57cec5SDimitry Andric         return;
2140b57cec5SDimitry Andric 
2150b57cec5SDimitry Andric       // Measure the old text.
2160b57cec5SDimitry Andric       int Size = Rewrite.getRangeSize(SrcRange);
2170b57cec5SDimitry Andric       if (Size == -1) {
2180b57cec5SDimitry Andric         Diags.Report(Context->getFullLoc(Old->getBeginLoc()), RewriteFailedDiag)
2190b57cec5SDimitry Andric             << Old->getSourceRange();
2200b57cec5SDimitry Andric         return;
2210b57cec5SDimitry Andric       }
2220b57cec5SDimitry Andric       // Get the new text.
2230b57cec5SDimitry Andric       std::string SStr;
2240b57cec5SDimitry Andric       llvm::raw_string_ostream S(SStr);
2250b57cec5SDimitry Andric       New->printPretty(S, nullptr, PrintingPolicy(LangOpts));
2260b57cec5SDimitry Andric       const std::string &Str = S.str();
2270b57cec5SDimitry Andric 
2280b57cec5SDimitry Andric       // If replacement succeeded or warning disabled return with no warning.
2290b57cec5SDimitry Andric       if (!Rewrite.ReplaceText(SrcRange.getBegin(), Size, Str)) {
2300b57cec5SDimitry Andric         ReplacedNodes[Old] = New;
2310b57cec5SDimitry Andric         return;
2320b57cec5SDimitry Andric       }
2330b57cec5SDimitry Andric       if (SilenceRewriteMacroWarning)
2340b57cec5SDimitry Andric         return;
2350b57cec5SDimitry Andric       Diags.Report(Context->getFullLoc(Old->getBeginLoc()), RewriteFailedDiag)
2360b57cec5SDimitry Andric           << Old->getSourceRange();
2370b57cec5SDimitry Andric     }
2380b57cec5SDimitry Andric 
2390b57cec5SDimitry Andric     void InsertText(SourceLocation Loc, StringRef Str,
2400b57cec5SDimitry Andric                     bool InsertAfter = true) {
2410b57cec5SDimitry Andric       // If insertion succeeded or warning disabled return with no warning.
2420b57cec5SDimitry Andric       if (!Rewrite.InsertText(Loc, Str, InsertAfter) ||
2430b57cec5SDimitry Andric           SilenceRewriteMacroWarning)
2440b57cec5SDimitry Andric         return;
2450b57cec5SDimitry Andric 
2460b57cec5SDimitry Andric       Diags.Report(Context->getFullLoc(Loc), RewriteFailedDiag);
2470b57cec5SDimitry Andric     }
2480b57cec5SDimitry Andric 
2490b57cec5SDimitry Andric     void ReplaceText(SourceLocation Start, unsigned OrigLength,
2500b57cec5SDimitry Andric                      StringRef Str) {
2510b57cec5SDimitry Andric       // If removal succeeded or warning disabled return with no warning.
2520b57cec5SDimitry Andric       if (!Rewrite.ReplaceText(Start, OrigLength, Str) ||
2530b57cec5SDimitry Andric           SilenceRewriteMacroWarning)
2540b57cec5SDimitry Andric         return;
2550b57cec5SDimitry Andric 
2560b57cec5SDimitry Andric       Diags.Report(Context->getFullLoc(Start), RewriteFailedDiag);
2570b57cec5SDimitry Andric     }
2580b57cec5SDimitry Andric 
2590b57cec5SDimitry Andric     // Syntactic Rewriting.
2600b57cec5SDimitry Andric     void RewriteRecordBody(RecordDecl *RD);
2610b57cec5SDimitry Andric     void RewriteInclude();
2620b57cec5SDimitry Andric     void RewriteForwardClassDecl(DeclGroupRef D);
2630b57cec5SDimitry Andric     void RewriteForwardClassDecl(const SmallVectorImpl<Decl *> &DG);
2640b57cec5SDimitry Andric     void RewriteForwardClassEpilogue(ObjCInterfaceDecl *ClassDecl,
2650b57cec5SDimitry Andric                                      const std::string &typedefString);
2660b57cec5SDimitry Andric     void RewriteImplementations();
2670b57cec5SDimitry Andric     void RewritePropertyImplDecl(ObjCPropertyImplDecl *PID,
2680b57cec5SDimitry Andric                                  ObjCImplementationDecl *IMD,
2690b57cec5SDimitry Andric                                  ObjCCategoryImplDecl *CID);
2700b57cec5SDimitry Andric     void RewriteInterfaceDecl(ObjCInterfaceDecl *Dcl);
2710b57cec5SDimitry Andric     void RewriteImplementationDecl(Decl *Dcl);
2720b57cec5SDimitry Andric     void RewriteObjCMethodDecl(const ObjCInterfaceDecl *IDecl,
2730b57cec5SDimitry Andric                                ObjCMethodDecl *MDecl, std::string &ResultStr);
2740b57cec5SDimitry Andric     void RewriteTypeIntoString(QualType T, std::string &ResultStr,
2750b57cec5SDimitry Andric                                const FunctionType *&FPRetType);
2760b57cec5SDimitry Andric     void RewriteByRefString(std::string &ResultStr, const std::string &Name,
2770b57cec5SDimitry Andric                             ValueDecl *VD, bool def=false);
2780b57cec5SDimitry Andric     void RewriteCategoryDecl(ObjCCategoryDecl *Dcl);
2790b57cec5SDimitry Andric     void RewriteProtocolDecl(ObjCProtocolDecl *Dcl);
2800b57cec5SDimitry Andric     void RewriteForwardProtocolDecl(DeclGroupRef D);
2810b57cec5SDimitry Andric     void RewriteForwardProtocolDecl(const SmallVectorImpl<Decl *> &DG);
2820b57cec5SDimitry Andric     void RewriteMethodDeclaration(ObjCMethodDecl *Method);
2830b57cec5SDimitry Andric     void RewriteProperty(ObjCPropertyDecl *prop);
2840b57cec5SDimitry Andric     void RewriteFunctionDecl(FunctionDecl *FD);
2850b57cec5SDimitry Andric     void RewriteBlockPointerType(std::string& Str, QualType Type);
2860b57cec5SDimitry Andric     void RewriteBlockPointerTypeVariable(std::string& Str, ValueDecl *VD);
2870b57cec5SDimitry Andric     void RewriteBlockLiteralFunctionDecl(FunctionDecl *FD);
2880b57cec5SDimitry Andric     void RewriteObjCQualifiedInterfaceTypes(Decl *Dcl);
2890b57cec5SDimitry Andric     void RewriteTypeOfDecl(VarDecl *VD);
2900b57cec5SDimitry Andric     void RewriteObjCQualifiedInterfaceTypes(Expr *E);
2910b57cec5SDimitry Andric 
2920b57cec5SDimitry Andric     // Expression Rewriting.
2930b57cec5SDimitry Andric     Stmt *RewriteFunctionBodyOrGlobalInitializer(Stmt *S);
2940b57cec5SDimitry Andric     Stmt *RewriteAtEncode(ObjCEncodeExpr *Exp);
2950b57cec5SDimitry Andric     Stmt *RewritePropertyOrImplicitGetter(PseudoObjectExpr *Pseudo);
2960b57cec5SDimitry Andric     Stmt *RewritePropertyOrImplicitSetter(PseudoObjectExpr *Pseudo);
2970b57cec5SDimitry Andric     Stmt *RewriteAtSelector(ObjCSelectorExpr *Exp);
2980b57cec5SDimitry Andric     Stmt *RewriteMessageExpr(ObjCMessageExpr *Exp);
2990b57cec5SDimitry Andric     Stmt *RewriteObjCStringLiteral(ObjCStringLiteral *Exp);
3000b57cec5SDimitry Andric     Stmt *RewriteObjCProtocolExpr(ObjCProtocolExpr *Exp);
3010b57cec5SDimitry Andric     void RewriteTryReturnStmts(Stmt *S);
3020b57cec5SDimitry Andric     void RewriteSyncReturnStmts(Stmt *S, std::string buf);
3030b57cec5SDimitry Andric     Stmt *RewriteObjCTryStmt(ObjCAtTryStmt *S);
3040b57cec5SDimitry Andric     Stmt *RewriteObjCSynchronizedStmt(ObjCAtSynchronizedStmt *S);
3050b57cec5SDimitry Andric     Stmt *RewriteObjCThrowStmt(ObjCAtThrowStmt *S);
3060b57cec5SDimitry Andric     Stmt *RewriteObjCForCollectionStmt(ObjCForCollectionStmt *S,
3070b57cec5SDimitry Andric                                        SourceLocation OrigEnd);
3080b57cec5SDimitry Andric     Stmt *RewriteBreakStmt(BreakStmt *S);
3090b57cec5SDimitry Andric     Stmt *RewriteContinueStmt(ContinueStmt *S);
3100b57cec5SDimitry Andric     void RewriteCastExpr(CStyleCastExpr *CE);
3110b57cec5SDimitry Andric 
3120b57cec5SDimitry Andric     // Block rewriting.
3130b57cec5SDimitry Andric     void RewriteBlocksInFunctionProtoType(QualType funcType, NamedDecl *D);
3140b57cec5SDimitry Andric 
3150b57cec5SDimitry Andric     // Block specific rewrite rules.
3160b57cec5SDimitry Andric     void RewriteBlockPointerDecl(NamedDecl *VD);
3170b57cec5SDimitry Andric     void RewriteByRefVar(VarDecl *VD);
3180b57cec5SDimitry Andric     Stmt *RewriteBlockDeclRefExpr(DeclRefExpr *VD);
3190b57cec5SDimitry Andric     Stmt *RewriteLocalVariableExternalStorage(DeclRefExpr *DRE);
3200b57cec5SDimitry Andric     void RewriteBlockPointerFunctionArgs(FunctionDecl *FD);
3210b57cec5SDimitry Andric 
3220b57cec5SDimitry Andric     void RewriteObjCInternalStruct(ObjCInterfaceDecl *CDecl,
3230b57cec5SDimitry Andric                                       std::string &Result);
3240b57cec5SDimitry Andric 
3250b57cec5SDimitry Andric     void Initialize(ASTContext &context) override = 0;
3260b57cec5SDimitry Andric 
3270b57cec5SDimitry Andric     // Metadata Rewriting.
3280b57cec5SDimitry Andric     virtual void RewriteMetaDataIntoBuffer(std::string &Result) = 0;
3290b57cec5SDimitry Andric     virtual void RewriteObjCProtocolListMetaData(const ObjCList<ObjCProtocolDecl> &Prots,
3300b57cec5SDimitry Andric                                                  StringRef prefix,
3310b57cec5SDimitry Andric                                                  StringRef ClassName,
3320b57cec5SDimitry Andric                                                  std::string &Result) = 0;
3330b57cec5SDimitry Andric     virtual void RewriteObjCCategoryImplDecl(ObjCCategoryImplDecl *CDecl,
3340b57cec5SDimitry Andric                                              std::string &Result) = 0;
3350b57cec5SDimitry Andric     virtual void RewriteObjCProtocolMetaData(ObjCProtocolDecl *Protocol,
3360b57cec5SDimitry Andric                                      StringRef prefix,
3370b57cec5SDimitry Andric                                      StringRef ClassName,
3380b57cec5SDimitry Andric                                      std::string &Result) = 0;
3390b57cec5SDimitry Andric     virtual void RewriteObjCClassMetaData(ObjCImplementationDecl *IDecl,
3400b57cec5SDimitry Andric                                           std::string &Result) = 0;
3410b57cec5SDimitry Andric 
3420b57cec5SDimitry Andric     // Rewriting ivar access
3430b57cec5SDimitry Andric     virtual Stmt *RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV) = 0;
3440b57cec5SDimitry Andric     virtual void RewriteIvarOffsetComputation(ObjCIvarDecl *ivar,
3450b57cec5SDimitry Andric                                          std::string &Result) = 0;
3460b57cec5SDimitry Andric 
3470b57cec5SDimitry Andric     // Misc. AST transformation routines. Sometimes they end up calling
3480b57cec5SDimitry Andric     // rewriting routines on the new ASTs.
3490b57cec5SDimitry Andric     CallExpr *SynthesizeCallToFunctionDecl(FunctionDecl *FD,
3500b57cec5SDimitry Andric                                            ArrayRef<Expr *> Args,
3510b57cec5SDimitry Andric                                            SourceLocation StartLoc=SourceLocation(),
3520b57cec5SDimitry Andric                                            SourceLocation EndLoc=SourceLocation());
3530b57cec5SDimitry Andric     CallExpr *SynthMsgSendStretCallExpr(FunctionDecl *MsgSendStretFlavor,
3540b57cec5SDimitry Andric                                         QualType msgSendType,
3550b57cec5SDimitry Andric                                         QualType returnType,
3560b57cec5SDimitry Andric                                         SmallVectorImpl<QualType> &ArgTypes,
3570b57cec5SDimitry Andric                                         SmallVectorImpl<Expr*> &MsgExprs,
3580b57cec5SDimitry Andric                                         ObjCMethodDecl *Method);
3590b57cec5SDimitry Andric     Stmt *SynthMessageExpr(ObjCMessageExpr *Exp,
3600b57cec5SDimitry Andric                            SourceLocation StartLoc=SourceLocation(),
3610b57cec5SDimitry Andric                            SourceLocation EndLoc=SourceLocation());
3620b57cec5SDimitry Andric 
3630b57cec5SDimitry Andric     void SynthCountByEnumWithState(std::string &buf);
3640b57cec5SDimitry Andric     void SynthMsgSendFunctionDecl();
3650b57cec5SDimitry Andric     void SynthMsgSendSuperFunctionDecl();
3660b57cec5SDimitry Andric     void SynthMsgSendStretFunctionDecl();
3670b57cec5SDimitry Andric     void SynthMsgSendFpretFunctionDecl();
3680b57cec5SDimitry Andric     void SynthMsgSendSuperStretFunctionDecl();
3690b57cec5SDimitry Andric     void SynthGetClassFunctionDecl();
3700b57cec5SDimitry Andric     void SynthGetMetaClassFunctionDecl();
3710b57cec5SDimitry Andric     void SynthGetSuperClassFunctionDecl();
3720b57cec5SDimitry Andric     void SynthSelGetUidFunctionDecl();
3730b57cec5SDimitry Andric     void SynthSuperConstructorFunctionDecl();
3740b57cec5SDimitry Andric 
3750b57cec5SDimitry Andric     std::string SynthesizeByrefCopyDestroyHelper(VarDecl *VD, int flag);
3760b57cec5SDimitry Andric     std::string SynthesizeBlockHelperFuncs(BlockExpr *CE, int i,
3770b57cec5SDimitry Andric                                       StringRef funcName, std::string Tag);
3780b57cec5SDimitry Andric     std::string SynthesizeBlockFunc(BlockExpr *CE, int i,
3790b57cec5SDimitry Andric                                       StringRef funcName, std::string Tag);
3800b57cec5SDimitry Andric     std::string SynthesizeBlockImpl(BlockExpr *CE,
3810b57cec5SDimitry Andric                                     std::string Tag, std::string Desc);
3820b57cec5SDimitry Andric     std::string SynthesizeBlockDescriptor(std::string DescTag,
3830b57cec5SDimitry Andric                                           std::string ImplTag,
3840b57cec5SDimitry Andric                                           int i, StringRef funcName,
3850b57cec5SDimitry Andric                                           unsigned hasCopy);
3860b57cec5SDimitry Andric     Stmt *SynthesizeBlockCall(CallExpr *Exp, const Expr* BlockExp);
3870b57cec5SDimitry Andric     void SynthesizeBlockLiterals(SourceLocation FunLocStart,
3880b57cec5SDimitry Andric                                  StringRef FunName);
3890b57cec5SDimitry Andric     FunctionDecl *SynthBlockInitFunctionDecl(StringRef name);
3900b57cec5SDimitry Andric     Stmt *SynthBlockInitExpr(BlockExpr *Exp,
3910b57cec5SDimitry Andric             const SmallVectorImpl<DeclRefExpr *> &InnerBlockDeclRefs);
3920b57cec5SDimitry Andric 
3930b57cec5SDimitry Andric     // Misc. helper routines.
3940b57cec5SDimitry Andric     QualType getProtocolType();
3950b57cec5SDimitry Andric     void WarnAboutReturnGotoStmts(Stmt *S);
3960b57cec5SDimitry Andric     void HasReturnStmts(Stmt *S, bool &hasReturns);
3970b57cec5SDimitry Andric     void CheckFunctionPointerDecl(QualType dType, NamedDecl *ND);
3980b57cec5SDimitry Andric     void InsertBlockLiteralsWithinFunction(FunctionDecl *FD);
3990b57cec5SDimitry Andric     void InsertBlockLiteralsWithinMethod(ObjCMethodDecl *MD);
4000b57cec5SDimitry Andric 
4010b57cec5SDimitry Andric     bool IsDeclStmtInForeachHeader(DeclStmt *DS);
4020b57cec5SDimitry Andric     void CollectBlockDeclRefInfo(BlockExpr *Exp);
4030b57cec5SDimitry Andric     void GetBlockDeclRefExprs(Stmt *S);
4040b57cec5SDimitry Andric     void GetInnerBlockDeclRefExprs(Stmt *S,
4050b57cec5SDimitry Andric                 SmallVectorImpl<DeclRefExpr *> &InnerBlockDeclRefs,
4060b57cec5SDimitry Andric                 llvm::SmallPtrSetImpl<const DeclContext *> &InnerContexts);
4070b57cec5SDimitry Andric 
4080b57cec5SDimitry Andric     // We avoid calling Type::isBlockPointerType(), since it operates on the
4090b57cec5SDimitry Andric     // canonical type. We only care if the top-level type is a closure pointer.
4100b57cec5SDimitry Andric     bool isTopLevelBlockPointerType(QualType T) {
4110b57cec5SDimitry Andric       return isa<BlockPointerType>(T);
4120b57cec5SDimitry Andric     }
4130b57cec5SDimitry Andric 
4140b57cec5SDimitry Andric     /// convertBlockPointerToFunctionPointer - Converts a block-pointer type
4150b57cec5SDimitry Andric     /// to a function pointer type and upon success, returns true; false
4160b57cec5SDimitry Andric     /// otherwise.
4170b57cec5SDimitry Andric     bool convertBlockPointerToFunctionPointer(QualType &T) {
4180b57cec5SDimitry Andric       if (isTopLevelBlockPointerType(T)) {
419a7dea167SDimitry Andric         const auto *BPT = T->castAs<BlockPointerType>();
4200b57cec5SDimitry Andric         T = Context->getPointerType(BPT->getPointeeType());
4210b57cec5SDimitry Andric         return true;
4220b57cec5SDimitry Andric       }
4230b57cec5SDimitry Andric       return false;
4240b57cec5SDimitry Andric     }
4250b57cec5SDimitry Andric 
4260b57cec5SDimitry Andric     bool needToScanForQualifiers(QualType T);
4270b57cec5SDimitry Andric     QualType getSuperStructType();
4280b57cec5SDimitry Andric     QualType getConstantStringStructType();
4290b57cec5SDimitry Andric     QualType convertFunctionTypeOfBlocks(const FunctionType *FT);
4300b57cec5SDimitry Andric     bool BufferContainsPPDirectives(const char *startBuf, const char *endBuf);
4310b57cec5SDimitry Andric 
4320b57cec5SDimitry Andric     void convertToUnqualifiedObjCType(QualType &T) {
4330b57cec5SDimitry Andric       if (T->isObjCQualifiedIdType())
4340b57cec5SDimitry Andric         T = Context->getObjCIdType();
4350b57cec5SDimitry Andric       else if (T->isObjCQualifiedClassType())
4360b57cec5SDimitry Andric         T = Context->getObjCClassType();
4370b57cec5SDimitry Andric       else if (T->isObjCObjectPointerType() &&
4380b57cec5SDimitry Andric                T->getPointeeType()->isObjCQualifiedInterfaceType()) {
4390b57cec5SDimitry Andric         if (const ObjCObjectPointerType * OBJPT =
4400b57cec5SDimitry Andric               T->getAsObjCInterfacePointerType()) {
4410b57cec5SDimitry Andric           const ObjCInterfaceType *IFaceT = OBJPT->getInterfaceType();
4420b57cec5SDimitry Andric           T = QualType(IFaceT, 0);
4430b57cec5SDimitry Andric           T = Context->getPointerType(T);
4440b57cec5SDimitry Andric         }
4450b57cec5SDimitry Andric      }
4460b57cec5SDimitry Andric     }
4470b57cec5SDimitry Andric 
4480b57cec5SDimitry Andric     // FIXME: This predicate seems like it would be useful to add to ASTContext.
4490b57cec5SDimitry Andric     bool isObjCType(QualType T) {
4500b57cec5SDimitry Andric       if (!LangOpts.ObjC)
4510b57cec5SDimitry Andric         return false;
4520b57cec5SDimitry Andric 
4530b57cec5SDimitry Andric       QualType OCT = Context->getCanonicalType(T).getUnqualifiedType();
4540b57cec5SDimitry Andric 
4550b57cec5SDimitry Andric       if (OCT == Context->getCanonicalType(Context->getObjCIdType()) ||
4560b57cec5SDimitry Andric           OCT == Context->getCanonicalType(Context->getObjCClassType()))
4570b57cec5SDimitry Andric         return true;
4580b57cec5SDimitry Andric 
4590b57cec5SDimitry Andric       if (const PointerType *PT = OCT->getAs<PointerType>()) {
4600b57cec5SDimitry Andric         if (isa<ObjCInterfaceType>(PT->getPointeeType()) ||
4610b57cec5SDimitry Andric             PT->getPointeeType()->isObjCQualifiedIdType())
4620b57cec5SDimitry Andric           return true;
4630b57cec5SDimitry Andric       }
4640b57cec5SDimitry Andric       return false;
4650b57cec5SDimitry Andric     }
4660b57cec5SDimitry Andric     bool PointerTypeTakesAnyBlockArguments(QualType QT);
4670b57cec5SDimitry Andric     bool PointerTypeTakesAnyObjCQualifiedType(QualType QT);
4680b57cec5SDimitry Andric     void GetExtentOfArgList(const char *Name, const char *&LParen,
4690b57cec5SDimitry Andric                             const char *&RParen);
4700b57cec5SDimitry Andric 
4710b57cec5SDimitry Andric     void QuoteDoublequotes(std::string &From, std::string &To) {
4720b57cec5SDimitry Andric       for (unsigned i = 0; i < From.length(); i++) {
4730b57cec5SDimitry Andric         if (From[i] == '"')
4740b57cec5SDimitry Andric           To += "\\\"";
4750b57cec5SDimitry Andric         else
4760b57cec5SDimitry Andric           To += From[i];
4770b57cec5SDimitry Andric       }
4780b57cec5SDimitry Andric     }
4790b57cec5SDimitry Andric 
4800b57cec5SDimitry Andric     QualType getSimpleFunctionType(QualType result,
4810b57cec5SDimitry Andric                                    ArrayRef<QualType> args,
4820b57cec5SDimitry Andric                                    bool variadic = false) {
4830b57cec5SDimitry Andric       if (result == Context->getObjCInstanceType())
4840b57cec5SDimitry Andric         result =  Context->getObjCIdType();
4850b57cec5SDimitry Andric       FunctionProtoType::ExtProtoInfo fpi;
4860b57cec5SDimitry Andric       fpi.Variadic = variadic;
4870b57cec5SDimitry Andric       return Context->getFunctionType(result, args, fpi);
4880b57cec5SDimitry Andric     }
4890b57cec5SDimitry Andric 
4900b57cec5SDimitry Andric     // Helper function: create a CStyleCastExpr with trivial type source info.
4910b57cec5SDimitry Andric     CStyleCastExpr* NoTypeInfoCStyleCastExpr(ASTContext *Ctx, QualType Ty,
4920b57cec5SDimitry Andric                                              CastKind Kind, Expr *E) {
4930b57cec5SDimitry Andric       TypeSourceInfo *TInfo = Ctx->getTrivialTypeSourceInfo(Ty, SourceLocation());
494fe6060f1SDimitry Andric       return CStyleCastExpr::Create(*Ctx, Ty, VK_PRValue, Kind, E, nullptr,
495e8d8bef9SDimitry Andric                                     FPOptionsOverride(), TInfo,
496e8d8bef9SDimitry Andric                                     SourceLocation(), SourceLocation());
4970b57cec5SDimitry Andric     }
4980b57cec5SDimitry Andric 
4990b57cec5SDimitry Andric     StringLiteral *getStringLiteral(StringRef Str) {
5000b57cec5SDimitry Andric       QualType StrType = Context->getConstantArrayType(
501a7dea167SDimitry Andric           Context->CharTy, llvm::APInt(32, Str.size() + 1), nullptr,
502*5f757f3fSDimitry Andric           ArraySizeModifier::Normal, 0);
503*5f757f3fSDimitry Andric       return StringLiteral::Create(*Context, Str, StringLiteralKind::Ordinary,
5040b57cec5SDimitry Andric                                    /*Pascal=*/false, StrType, SourceLocation());
5050b57cec5SDimitry Andric     }
5060b57cec5SDimitry Andric   };
5070b57cec5SDimitry Andric 
5080b57cec5SDimitry Andric   class RewriteObjCFragileABI : public RewriteObjC {
5090b57cec5SDimitry Andric   public:
5100b57cec5SDimitry Andric     RewriteObjCFragileABI(std::string inFile, std::unique_ptr<raw_ostream> OS,
5110b57cec5SDimitry Andric                           DiagnosticsEngine &D, const LangOptions &LOpts,
5120b57cec5SDimitry Andric                           bool silenceMacroWarn)
5130b57cec5SDimitry Andric         : RewriteObjC(inFile, std::move(OS), D, LOpts, silenceMacroWarn) {}
5140b57cec5SDimitry Andric 
5150b57cec5SDimitry Andric     ~RewriteObjCFragileABI() override {}
5160b57cec5SDimitry Andric     void Initialize(ASTContext &context) override;
5170b57cec5SDimitry Andric 
5180b57cec5SDimitry Andric     // Rewriting metadata
5190b57cec5SDimitry Andric     template<typename MethodIterator>
5200b57cec5SDimitry Andric     void RewriteObjCMethodsMetaData(MethodIterator MethodBegin,
5210b57cec5SDimitry Andric                                     MethodIterator MethodEnd,
5220b57cec5SDimitry Andric                                     bool IsInstanceMethod,
5230b57cec5SDimitry Andric                                     StringRef prefix,
5240b57cec5SDimitry Andric                                     StringRef ClassName,
5250b57cec5SDimitry Andric                                     std::string &Result);
5260b57cec5SDimitry Andric     void RewriteObjCProtocolMetaData(ObjCProtocolDecl *Protocol,
5270b57cec5SDimitry Andric                                      StringRef prefix, StringRef ClassName,
5280b57cec5SDimitry Andric                                      std::string &Result) override;
5290b57cec5SDimitry Andric     void RewriteObjCProtocolListMetaData(
5300b57cec5SDimitry Andric           const ObjCList<ObjCProtocolDecl> &Prots,
5310b57cec5SDimitry Andric           StringRef prefix, StringRef ClassName, std::string &Result) override;
5320b57cec5SDimitry Andric     void RewriteObjCClassMetaData(ObjCImplementationDecl *IDecl,
5330b57cec5SDimitry Andric                                   std::string &Result) override;
5340b57cec5SDimitry Andric     void RewriteMetaDataIntoBuffer(std::string &Result) override;
5350b57cec5SDimitry Andric     void RewriteObjCCategoryImplDecl(ObjCCategoryImplDecl *CDecl,
5360b57cec5SDimitry Andric                                      std::string &Result) override;
5370b57cec5SDimitry Andric 
5380b57cec5SDimitry Andric     // Rewriting ivar
5390b57cec5SDimitry Andric     void RewriteIvarOffsetComputation(ObjCIvarDecl *ivar,
5400b57cec5SDimitry Andric                                       std::string &Result) override;
5410b57cec5SDimitry Andric     Stmt *RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV) override;
5420b57cec5SDimitry Andric   };
5430b57cec5SDimitry Andric } // end anonymous namespace
5440b57cec5SDimitry Andric 
5450b57cec5SDimitry Andric void RewriteObjC::RewriteBlocksInFunctionProtoType(QualType funcType,
5460b57cec5SDimitry Andric                                                    NamedDecl *D) {
5470b57cec5SDimitry Andric   if (const FunctionProtoType *fproto
5480b57cec5SDimitry Andric       = dyn_cast<FunctionProtoType>(funcType.IgnoreParens())) {
5490b57cec5SDimitry Andric     for (const auto &I : fproto->param_types())
5500b57cec5SDimitry Andric       if (isTopLevelBlockPointerType(I)) {
5510b57cec5SDimitry Andric         // All the args are checked/rewritten. Don't call twice!
5520b57cec5SDimitry Andric         RewriteBlockPointerDecl(D);
5530b57cec5SDimitry Andric         break;
5540b57cec5SDimitry Andric       }
5550b57cec5SDimitry Andric   }
5560b57cec5SDimitry Andric }
5570b57cec5SDimitry Andric 
5580b57cec5SDimitry Andric void RewriteObjC::CheckFunctionPointerDecl(QualType funcType, NamedDecl *ND) {
5590b57cec5SDimitry Andric   const PointerType *PT = funcType->getAs<PointerType>();
5600b57cec5SDimitry Andric   if (PT && PointerTypeTakesAnyBlockArguments(funcType))
5610b57cec5SDimitry Andric     RewriteBlocksInFunctionProtoType(PT->getPointeeType(), ND);
5620b57cec5SDimitry Andric }
5630b57cec5SDimitry Andric 
5640b57cec5SDimitry Andric static bool IsHeaderFile(const std::string &Filename) {
5650b57cec5SDimitry Andric   std::string::size_type DotPos = Filename.rfind('.');
5660b57cec5SDimitry Andric 
5670b57cec5SDimitry Andric   if (DotPos == std::string::npos) {
5680b57cec5SDimitry Andric     // no file extension
5690b57cec5SDimitry Andric     return false;
5700b57cec5SDimitry Andric   }
5710b57cec5SDimitry Andric 
5724824e7fdSDimitry Andric   std::string Ext = Filename.substr(DotPos + 1);
5730b57cec5SDimitry Andric   // C header: .h
5740b57cec5SDimitry Andric   // C++ header: .hh or .H;
5750b57cec5SDimitry Andric   return Ext == "h" || Ext == "hh" || Ext == "H";
5760b57cec5SDimitry Andric }
5770b57cec5SDimitry Andric 
5780b57cec5SDimitry Andric RewriteObjC::RewriteObjC(std::string inFile, std::unique_ptr<raw_ostream> OS,
5790b57cec5SDimitry Andric                          DiagnosticsEngine &D, const LangOptions &LOpts,
5800b57cec5SDimitry Andric                          bool silenceMacroWarn)
5810b57cec5SDimitry Andric     : Diags(D), LangOpts(LOpts), InFileName(inFile), OutFile(std::move(OS)),
5820b57cec5SDimitry Andric       SilenceRewriteMacroWarning(silenceMacroWarn) {
5830b57cec5SDimitry Andric   IsHeader = IsHeaderFile(inFile);
5840b57cec5SDimitry Andric   RewriteFailedDiag = Diags.getCustomDiagID(DiagnosticsEngine::Warning,
5850b57cec5SDimitry Andric                "rewriting sub-expression within a macro (may not be correct)");
5860b57cec5SDimitry Andric   TryFinallyContainsReturnDiag = Diags.getCustomDiagID(
5870b57cec5SDimitry Andric                DiagnosticsEngine::Warning,
5880b57cec5SDimitry Andric                "rewriter doesn't support user-specified control flow semantics "
5890b57cec5SDimitry Andric                "for @try/@finally (code may not execute properly)");
5900b57cec5SDimitry Andric }
5910b57cec5SDimitry Andric 
5920b57cec5SDimitry Andric std::unique_ptr<ASTConsumer>
5930b57cec5SDimitry Andric clang::CreateObjCRewriter(const std::string &InFile,
5940b57cec5SDimitry Andric                           std::unique_ptr<raw_ostream> OS,
5950b57cec5SDimitry Andric                           DiagnosticsEngine &Diags, const LangOptions &LOpts,
5960b57cec5SDimitry Andric                           bool SilenceRewriteMacroWarning) {
597a7dea167SDimitry Andric   return std::make_unique<RewriteObjCFragileABI>(
5980b57cec5SDimitry Andric       InFile, std::move(OS), Diags, LOpts, SilenceRewriteMacroWarning);
5990b57cec5SDimitry Andric }
6000b57cec5SDimitry Andric 
6010b57cec5SDimitry Andric void RewriteObjC::InitializeCommon(ASTContext &context) {
6020b57cec5SDimitry Andric   Context = &context;
6030b57cec5SDimitry Andric   SM = &Context->getSourceManager();
6040b57cec5SDimitry Andric   TUDecl = Context->getTranslationUnitDecl();
6050b57cec5SDimitry Andric   MsgSendFunctionDecl = nullptr;
6060b57cec5SDimitry Andric   MsgSendSuperFunctionDecl = nullptr;
6070b57cec5SDimitry Andric   MsgSendStretFunctionDecl = nullptr;
6080b57cec5SDimitry Andric   MsgSendSuperStretFunctionDecl = nullptr;
6090b57cec5SDimitry Andric   MsgSendFpretFunctionDecl = nullptr;
6100b57cec5SDimitry Andric   GetClassFunctionDecl = nullptr;
6110b57cec5SDimitry Andric   GetMetaClassFunctionDecl = nullptr;
6120b57cec5SDimitry Andric   GetSuperClassFunctionDecl = nullptr;
6130b57cec5SDimitry Andric   SelGetUidFunctionDecl = nullptr;
6140b57cec5SDimitry Andric   CFStringFunctionDecl = nullptr;
6150b57cec5SDimitry Andric   ConstantStringClassReference = nullptr;
6160b57cec5SDimitry Andric   NSStringRecord = nullptr;
6170b57cec5SDimitry Andric   CurMethodDef = nullptr;
6180b57cec5SDimitry Andric   CurFunctionDef = nullptr;
6190b57cec5SDimitry Andric   CurFunctionDeclToDeclareForBlock = nullptr;
6200b57cec5SDimitry Andric   GlobalVarDecl = nullptr;
6210b57cec5SDimitry Andric   SuperStructDecl = nullptr;
6220b57cec5SDimitry Andric   ProtocolTypeDecl = nullptr;
6230b57cec5SDimitry Andric   ConstantStringDecl = nullptr;
6240b57cec5SDimitry Andric   BcLabelCount = 0;
6250b57cec5SDimitry Andric   SuperConstructorFunctionDecl = nullptr;
6260b57cec5SDimitry Andric   NumObjCStringLiterals = 0;
6270b57cec5SDimitry Andric   PropParentMap = nullptr;
6280b57cec5SDimitry Andric   CurrentBody = nullptr;
6290b57cec5SDimitry Andric   DisableReplaceStmt = false;
6300b57cec5SDimitry Andric   objc_impl_method = false;
6310b57cec5SDimitry Andric 
6320b57cec5SDimitry Andric   // Get the ID and start/end of the main file.
6330b57cec5SDimitry Andric   MainFileID = SM->getMainFileID();
634e8d8bef9SDimitry Andric   llvm::MemoryBufferRef MainBuf = SM->getBufferOrFake(MainFileID);
635e8d8bef9SDimitry Andric   MainFileStart = MainBuf.getBufferStart();
636e8d8bef9SDimitry Andric   MainFileEnd = MainBuf.getBufferEnd();
6370b57cec5SDimitry Andric 
6380b57cec5SDimitry Andric   Rewrite.setSourceMgr(Context->getSourceManager(), Context->getLangOpts());
6390b57cec5SDimitry Andric }
6400b57cec5SDimitry Andric 
6410b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
6420b57cec5SDimitry Andric // Top Level Driver Code
6430b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
6440b57cec5SDimitry Andric 
6450b57cec5SDimitry Andric void RewriteObjC::HandleTopLevelSingleDecl(Decl *D) {
6460b57cec5SDimitry Andric   if (Diags.hasErrorOccurred())
6470b57cec5SDimitry Andric     return;
6480b57cec5SDimitry Andric 
6490b57cec5SDimitry Andric   // Two cases: either the decl could be in the main file, or it could be in a
6500b57cec5SDimitry Andric   // #included file.  If the former, rewrite it now.  If the later, check to see
6510b57cec5SDimitry Andric   // if we rewrote the #include/#import.
6520b57cec5SDimitry Andric   SourceLocation Loc = D->getLocation();
6530b57cec5SDimitry Andric   Loc = SM->getExpansionLoc(Loc);
6540b57cec5SDimitry Andric 
6550b57cec5SDimitry Andric   // If this is for a builtin, ignore it.
6560b57cec5SDimitry Andric   if (Loc.isInvalid()) return;
6570b57cec5SDimitry Andric 
6580b57cec5SDimitry Andric   // Look for built-in declarations that we need to refer during the rewrite.
6590b57cec5SDimitry Andric   if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
6600b57cec5SDimitry Andric     RewriteFunctionDecl(FD);
6610b57cec5SDimitry Andric   } else if (VarDecl *FVD = dyn_cast<VarDecl>(D)) {
6620b57cec5SDimitry Andric     // declared in <Foundation/NSString.h>
6630b57cec5SDimitry Andric     if (FVD->getName() == "_NSConstantStringClassReference") {
6640b57cec5SDimitry Andric       ConstantStringClassReference = FVD;
6650b57cec5SDimitry Andric       return;
6660b57cec5SDimitry Andric     }
6670b57cec5SDimitry Andric   } else if (ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(D)) {
6680b57cec5SDimitry Andric     if (ID->isThisDeclarationADefinition())
6690b57cec5SDimitry Andric       RewriteInterfaceDecl(ID);
6700b57cec5SDimitry Andric   } else if (ObjCCategoryDecl *CD = dyn_cast<ObjCCategoryDecl>(D)) {
6710b57cec5SDimitry Andric     RewriteCategoryDecl(CD);
6720b57cec5SDimitry Andric   } else if (ObjCProtocolDecl *PD = dyn_cast<ObjCProtocolDecl>(D)) {
6730b57cec5SDimitry Andric     if (PD->isThisDeclarationADefinition())
6740b57cec5SDimitry Andric       RewriteProtocolDecl(PD);
6750b57cec5SDimitry Andric   } else if (LinkageSpecDecl *LSD = dyn_cast<LinkageSpecDecl>(D)) {
6760b57cec5SDimitry Andric     // Recurse into linkage specifications
6770b57cec5SDimitry Andric     for (DeclContext::decl_iterator DI = LSD->decls_begin(),
6780b57cec5SDimitry Andric                                  DIEnd = LSD->decls_end();
6790b57cec5SDimitry Andric          DI != DIEnd; ) {
6800b57cec5SDimitry Andric       if (ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>((*DI))) {
6810b57cec5SDimitry Andric         if (!IFace->isThisDeclarationADefinition()) {
6820b57cec5SDimitry Andric           SmallVector<Decl *, 8> DG;
6830b57cec5SDimitry Andric           SourceLocation StartLoc = IFace->getBeginLoc();
6840b57cec5SDimitry Andric           do {
6850b57cec5SDimitry Andric             if (isa<ObjCInterfaceDecl>(*DI) &&
6860b57cec5SDimitry Andric                 !cast<ObjCInterfaceDecl>(*DI)->isThisDeclarationADefinition() &&
6870b57cec5SDimitry Andric                 StartLoc == (*DI)->getBeginLoc())
6880b57cec5SDimitry Andric               DG.push_back(*DI);
6890b57cec5SDimitry Andric             else
6900b57cec5SDimitry Andric               break;
6910b57cec5SDimitry Andric 
6920b57cec5SDimitry Andric             ++DI;
6930b57cec5SDimitry Andric           } while (DI != DIEnd);
6940b57cec5SDimitry Andric           RewriteForwardClassDecl(DG);
6950b57cec5SDimitry Andric           continue;
6960b57cec5SDimitry Andric         }
6970b57cec5SDimitry Andric       }
6980b57cec5SDimitry Andric 
6990b57cec5SDimitry Andric       if (ObjCProtocolDecl *Proto = dyn_cast<ObjCProtocolDecl>((*DI))) {
7000b57cec5SDimitry Andric         if (!Proto->isThisDeclarationADefinition()) {
7010b57cec5SDimitry Andric           SmallVector<Decl *, 8> DG;
7020b57cec5SDimitry Andric           SourceLocation StartLoc = Proto->getBeginLoc();
7030b57cec5SDimitry Andric           do {
7040b57cec5SDimitry Andric             if (isa<ObjCProtocolDecl>(*DI) &&
7050b57cec5SDimitry Andric                 !cast<ObjCProtocolDecl>(*DI)->isThisDeclarationADefinition() &&
7060b57cec5SDimitry Andric                 StartLoc == (*DI)->getBeginLoc())
7070b57cec5SDimitry Andric               DG.push_back(*DI);
7080b57cec5SDimitry Andric             else
7090b57cec5SDimitry Andric               break;
7100b57cec5SDimitry Andric 
7110b57cec5SDimitry Andric             ++DI;
7120b57cec5SDimitry Andric           } while (DI != DIEnd);
7130b57cec5SDimitry Andric           RewriteForwardProtocolDecl(DG);
7140b57cec5SDimitry Andric           continue;
7150b57cec5SDimitry Andric         }
7160b57cec5SDimitry Andric       }
7170b57cec5SDimitry Andric 
7180b57cec5SDimitry Andric       HandleTopLevelSingleDecl(*DI);
7190b57cec5SDimitry Andric       ++DI;
7200b57cec5SDimitry Andric     }
7210b57cec5SDimitry Andric   }
7220b57cec5SDimitry Andric   // If we have a decl in the main file, see if we should rewrite it.
7230b57cec5SDimitry Andric   if (SM->isWrittenInMainFile(Loc))
7240b57cec5SDimitry Andric     return HandleDeclInMainFile(D);
7250b57cec5SDimitry Andric }
7260b57cec5SDimitry Andric 
7270b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
7280b57cec5SDimitry Andric // Syntactic (non-AST) Rewriting Code
7290b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
7300b57cec5SDimitry Andric 
7310b57cec5SDimitry Andric void RewriteObjC::RewriteInclude() {
7320b57cec5SDimitry Andric   SourceLocation LocStart = SM->getLocForStartOfFile(MainFileID);
7330b57cec5SDimitry Andric   StringRef MainBuf = SM->getBufferData(MainFileID);
7340b57cec5SDimitry Andric   const char *MainBufStart = MainBuf.begin();
7350b57cec5SDimitry Andric   const char *MainBufEnd = MainBuf.end();
7360b57cec5SDimitry Andric   size_t ImportLen = strlen("import");
7370b57cec5SDimitry Andric 
7380b57cec5SDimitry Andric   // Loop over the whole file, looking for includes.
7390b57cec5SDimitry Andric   for (const char *BufPtr = MainBufStart; BufPtr < MainBufEnd; ++BufPtr) {
7400b57cec5SDimitry Andric     if (*BufPtr == '#') {
7410b57cec5SDimitry Andric       if (++BufPtr == MainBufEnd)
7420b57cec5SDimitry Andric         return;
7430b57cec5SDimitry Andric       while (*BufPtr == ' ' || *BufPtr == '\t')
7440b57cec5SDimitry Andric         if (++BufPtr == MainBufEnd)
7450b57cec5SDimitry Andric           return;
7460b57cec5SDimitry Andric       if (!strncmp(BufPtr, "import", ImportLen)) {
7470b57cec5SDimitry Andric         // replace import with include
7480b57cec5SDimitry Andric         SourceLocation ImportLoc =
7490b57cec5SDimitry Andric           LocStart.getLocWithOffset(BufPtr-MainBufStart);
7500b57cec5SDimitry Andric         ReplaceText(ImportLoc, ImportLen, "include");
7510b57cec5SDimitry Andric         BufPtr += ImportLen;
7520b57cec5SDimitry Andric       }
7530b57cec5SDimitry Andric     }
7540b57cec5SDimitry Andric   }
7550b57cec5SDimitry Andric }
7560b57cec5SDimitry Andric 
7570b57cec5SDimitry Andric static std::string getIvarAccessString(ObjCIvarDecl *OID) {
7580b57cec5SDimitry Andric   const ObjCInterfaceDecl *ClassDecl = OID->getContainingInterface();
7590b57cec5SDimitry Andric   std::string S;
7600b57cec5SDimitry Andric   S = "((struct ";
7610b57cec5SDimitry Andric   S += ClassDecl->getIdentifier()->getName();
7620b57cec5SDimitry Andric   S += "_IMPL *)self)->";
7630b57cec5SDimitry Andric   S += OID->getName();
7640b57cec5SDimitry Andric   return S;
7650b57cec5SDimitry Andric }
7660b57cec5SDimitry Andric 
7670b57cec5SDimitry Andric void RewriteObjC::RewritePropertyImplDecl(ObjCPropertyImplDecl *PID,
7680b57cec5SDimitry Andric                                           ObjCImplementationDecl *IMD,
7690b57cec5SDimitry Andric                                           ObjCCategoryImplDecl *CID) {
7700b57cec5SDimitry Andric   static bool objcGetPropertyDefined = false;
7710b57cec5SDimitry Andric   static bool objcSetPropertyDefined = false;
7720b57cec5SDimitry Andric   SourceLocation startLoc = PID->getBeginLoc();
7730b57cec5SDimitry Andric   InsertText(startLoc, "// ");
7740b57cec5SDimitry Andric   const char *startBuf = SM->getCharacterData(startLoc);
7750b57cec5SDimitry Andric   assert((*startBuf == '@') && "bogus @synthesize location");
7760b57cec5SDimitry Andric   const char *semiBuf = strchr(startBuf, ';');
7770b57cec5SDimitry Andric   assert((*semiBuf == ';') && "@synthesize: can't find ';'");
7780b57cec5SDimitry Andric   SourceLocation onePastSemiLoc =
7790b57cec5SDimitry Andric     startLoc.getLocWithOffset(semiBuf-startBuf+1);
7800b57cec5SDimitry Andric 
7810b57cec5SDimitry Andric   if (PID->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic)
7820b57cec5SDimitry Andric     return; // FIXME: is this correct?
7830b57cec5SDimitry Andric 
7840b57cec5SDimitry Andric   // Generate the 'getter' function.
7850b57cec5SDimitry Andric   ObjCPropertyDecl *PD = PID->getPropertyDecl();
7860b57cec5SDimitry Andric   ObjCIvarDecl *OID = PID->getPropertyIvarDecl();
7870b57cec5SDimitry Andric 
7880b57cec5SDimitry Andric   if (!OID)
7890b57cec5SDimitry Andric     return;
790480093f4SDimitry Andric 
7910b57cec5SDimitry Andric   unsigned Attributes = PD->getPropertyAttributes();
792480093f4SDimitry Andric   if (PID->getGetterMethodDecl() && !PID->getGetterMethodDecl()->isDefined()) {
7935ffd83dbSDimitry Andric     bool GenGetProperty =
7945ffd83dbSDimitry Andric         !(Attributes & ObjCPropertyAttribute::kind_nonatomic) &&
7955ffd83dbSDimitry Andric         (Attributes & (ObjCPropertyAttribute::kind_retain |
7965ffd83dbSDimitry Andric                        ObjCPropertyAttribute::kind_copy));
7970b57cec5SDimitry Andric     std::string Getr;
7980b57cec5SDimitry Andric     if (GenGetProperty && !objcGetPropertyDefined) {
7990b57cec5SDimitry Andric       objcGetPropertyDefined = true;
8000b57cec5SDimitry Andric       // FIXME. Is this attribute correct in all cases?
8010b57cec5SDimitry Andric       Getr = "\nextern \"C\" __declspec(dllimport) "
8020b57cec5SDimitry Andric             "id objc_getProperty(id, SEL, long, bool);\n";
8030b57cec5SDimitry Andric     }
8040b57cec5SDimitry Andric     RewriteObjCMethodDecl(OID->getContainingInterface(),
805480093f4SDimitry Andric                           PID->getGetterMethodDecl(), Getr);
8060b57cec5SDimitry Andric     Getr += "{ ";
8070b57cec5SDimitry Andric     // Synthesize an explicit cast to gain access to the ivar.
8080b57cec5SDimitry Andric     // See objc-act.c:objc_synthesize_new_getter() for details.
8090b57cec5SDimitry Andric     if (GenGetProperty) {
8100b57cec5SDimitry Andric       // return objc_getProperty(self, _cmd, offsetof(ClassDecl, OID), 1)
8110b57cec5SDimitry Andric       Getr += "typedef ";
8120b57cec5SDimitry Andric       const FunctionType *FPRetType = nullptr;
813480093f4SDimitry Andric       RewriteTypeIntoString(PID->getGetterMethodDecl()->getReturnType(), Getr,
8140b57cec5SDimitry Andric                             FPRetType);
8150b57cec5SDimitry Andric       Getr += " _TYPE";
8160b57cec5SDimitry Andric       if (FPRetType) {
8170b57cec5SDimitry Andric         Getr += ")"; // close the precedence "scope" for "*".
8180b57cec5SDimitry Andric 
8190b57cec5SDimitry Andric         // Now, emit the argument types (if any).
8200b57cec5SDimitry Andric         if (const FunctionProtoType *FT = dyn_cast<FunctionProtoType>(FPRetType)){
8210b57cec5SDimitry Andric           Getr += "(";
8220b57cec5SDimitry Andric           for (unsigned i = 0, e = FT->getNumParams(); i != e; ++i) {
8230b57cec5SDimitry Andric             if (i) Getr += ", ";
8240b57cec5SDimitry Andric             std::string ParamStr =
8250b57cec5SDimitry Andric                 FT->getParamType(i).getAsString(Context->getPrintingPolicy());
8260b57cec5SDimitry Andric             Getr += ParamStr;
8270b57cec5SDimitry Andric           }
8280b57cec5SDimitry Andric           if (FT->isVariadic()) {
8290b57cec5SDimitry Andric             if (FT->getNumParams())
8300b57cec5SDimitry Andric               Getr += ", ";
8310b57cec5SDimitry Andric             Getr += "...";
8320b57cec5SDimitry Andric           }
8330b57cec5SDimitry Andric           Getr += ")";
8340b57cec5SDimitry Andric         } else
8350b57cec5SDimitry Andric           Getr += "()";
8360b57cec5SDimitry Andric       }
8370b57cec5SDimitry Andric       Getr += ";\n";
8380b57cec5SDimitry Andric       Getr += "return (_TYPE)";
8390b57cec5SDimitry Andric       Getr += "objc_getProperty(self, _cmd, ";
8400b57cec5SDimitry Andric       RewriteIvarOffsetComputation(OID, Getr);
8410b57cec5SDimitry Andric       Getr += ", 1)";
8420b57cec5SDimitry Andric     }
8430b57cec5SDimitry Andric     else
8440b57cec5SDimitry Andric       Getr += "return " + getIvarAccessString(OID);
8450b57cec5SDimitry Andric     Getr += "; }";
8460b57cec5SDimitry Andric     InsertText(onePastSemiLoc, Getr);
8470b57cec5SDimitry Andric   }
8480b57cec5SDimitry Andric 
849480093f4SDimitry Andric   if (PD->isReadOnly() || !PID->getSetterMethodDecl() ||
850480093f4SDimitry Andric       PID->getSetterMethodDecl()->isDefined())
8510b57cec5SDimitry Andric     return;
8520b57cec5SDimitry Andric 
8530b57cec5SDimitry Andric   // Generate the 'setter' function.
8540b57cec5SDimitry Andric   std::string Setr;
8555ffd83dbSDimitry Andric   bool GenSetProperty = Attributes & (ObjCPropertyAttribute::kind_retain |
8565ffd83dbSDimitry Andric                                       ObjCPropertyAttribute::kind_copy);
8570b57cec5SDimitry Andric   if (GenSetProperty && !objcSetPropertyDefined) {
8580b57cec5SDimitry Andric     objcSetPropertyDefined = true;
8590b57cec5SDimitry Andric     // FIXME. Is this attribute correct in all cases?
8600b57cec5SDimitry Andric     Setr = "\nextern \"C\" __declspec(dllimport) "
8610b57cec5SDimitry Andric     "void objc_setProperty (id, SEL, long, id, bool, bool);\n";
8620b57cec5SDimitry Andric   }
8630b57cec5SDimitry Andric 
8640b57cec5SDimitry Andric   RewriteObjCMethodDecl(OID->getContainingInterface(),
865480093f4SDimitry Andric                         PID->getSetterMethodDecl(), Setr);
8660b57cec5SDimitry Andric   Setr += "{ ";
8670b57cec5SDimitry Andric   // Synthesize an explicit cast to initialize the ivar.
8680b57cec5SDimitry Andric   // See objc-act.c:objc_synthesize_new_setter() for details.
8690b57cec5SDimitry Andric   if (GenSetProperty) {
8700b57cec5SDimitry Andric     Setr += "objc_setProperty (self, _cmd, ";
8710b57cec5SDimitry Andric     RewriteIvarOffsetComputation(OID, Setr);
8720b57cec5SDimitry Andric     Setr += ", (id)";
8730b57cec5SDimitry Andric     Setr += PD->getName();
8740b57cec5SDimitry Andric     Setr += ", ";
8755ffd83dbSDimitry Andric     if (Attributes & ObjCPropertyAttribute::kind_nonatomic)
8760b57cec5SDimitry Andric       Setr += "0, ";
8770b57cec5SDimitry Andric     else
8780b57cec5SDimitry Andric       Setr += "1, ";
8795ffd83dbSDimitry Andric     if (Attributes & ObjCPropertyAttribute::kind_copy)
8800b57cec5SDimitry Andric       Setr += "1)";
8810b57cec5SDimitry Andric     else
8820b57cec5SDimitry Andric       Setr += "0)";
8830b57cec5SDimitry Andric   }
8840b57cec5SDimitry Andric   else {
8850b57cec5SDimitry Andric     Setr += getIvarAccessString(OID) + " = ";
8860b57cec5SDimitry Andric     Setr += PD->getName();
8870b57cec5SDimitry Andric   }
8880b57cec5SDimitry Andric   Setr += "; }";
8890b57cec5SDimitry Andric   InsertText(onePastSemiLoc, Setr);
8900b57cec5SDimitry Andric }
8910b57cec5SDimitry Andric 
8920b57cec5SDimitry Andric static void RewriteOneForwardClassDecl(ObjCInterfaceDecl *ForwardDecl,
8930b57cec5SDimitry Andric                                        std::string &typedefString) {
8940b57cec5SDimitry Andric   typedefString += "#ifndef _REWRITER_typedef_";
8950b57cec5SDimitry Andric   typedefString += ForwardDecl->getNameAsString();
8960b57cec5SDimitry Andric   typedefString += "\n";
8970b57cec5SDimitry Andric   typedefString += "#define _REWRITER_typedef_";
8980b57cec5SDimitry Andric   typedefString += ForwardDecl->getNameAsString();
8990b57cec5SDimitry Andric   typedefString += "\n";
9000b57cec5SDimitry Andric   typedefString += "typedef struct objc_object ";
9010b57cec5SDimitry Andric   typedefString += ForwardDecl->getNameAsString();
9020b57cec5SDimitry Andric   typedefString += ";\n#endif\n";
9030b57cec5SDimitry Andric }
9040b57cec5SDimitry Andric 
9050b57cec5SDimitry Andric void RewriteObjC::RewriteForwardClassEpilogue(ObjCInterfaceDecl *ClassDecl,
9060b57cec5SDimitry Andric                                               const std::string &typedefString) {
9070b57cec5SDimitry Andric   SourceLocation startLoc = ClassDecl->getBeginLoc();
9080b57cec5SDimitry Andric   const char *startBuf = SM->getCharacterData(startLoc);
9090b57cec5SDimitry Andric   const char *semiPtr = strchr(startBuf, ';');
9100b57cec5SDimitry Andric   // Replace the @class with typedefs corresponding to the classes.
9110b57cec5SDimitry Andric   ReplaceText(startLoc, semiPtr - startBuf + 1, typedefString);
9120b57cec5SDimitry Andric }
9130b57cec5SDimitry Andric 
9140b57cec5SDimitry Andric void RewriteObjC::RewriteForwardClassDecl(DeclGroupRef D) {
9150b57cec5SDimitry Andric   std::string typedefString;
9160b57cec5SDimitry Andric   for (DeclGroupRef::iterator I = D.begin(), E = D.end(); I != E; ++I) {
9170b57cec5SDimitry Andric     ObjCInterfaceDecl *ForwardDecl = cast<ObjCInterfaceDecl>(*I);
9180b57cec5SDimitry Andric     if (I == D.begin()) {
9190b57cec5SDimitry Andric       // Translate to typedef's that forward reference structs with the same name
9200b57cec5SDimitry Andric       // as the class. As a convenience, we include the original declaration
9210b57cec5SDimitry Andric       // as a comment.
9220b57cec5SDimitry Andric       typedefString += "// @class ";
9230b57cec5SDimitry Andric       typedefString += ForwardDecl->getNameAsString();
9240b57cec5SDimitry Andric       typedefString += ";\n";
9250b57cec5SDimitry Andric     }
9260b57cec5SDimitry Andric     RewriteOneForwardClassDecl(ForwardDecl, typedefString);
9270b57cec5SDimitry Andric   }
9280b57cec5SDimitry Andric   DeclGroupRef::iterator I = D.begin();
9290b57cec5SDimitry Andric   RewriteForwardClassEpilogue(cast<ObjCInterfaceDecl>(*I), typedefString);
9300b57cec5SDimitry Andric }
9310b57cec5SDimitry Andric 
9320b57cec5SDimitry Andric void RewriteObjC::RewriteForwardClassDecl(const SmallVectorImpl<Decl *> &D) {
9330b57cec5SDimitry Andric   std::string typedefString;
9340b57cec5SDimitry Andric   for (unsigned i = 0; i < D.size(); i++) {
9350b57cec5SDimitry Andric     ObjCInterfaceDecl *ForwardDecl = cast<ObjCInterfaceDecl>(D[i]);
9360b57cec5SDimitry Andric     if (i == 0) {
9370b57cec5SDimitry Andric       typedefString += "// @class ";
9380b57cec5SDimitry Andric       typedefString += ForwardDecl->getNameAsString();
9390b57cec5SDimitry Andric       typedefString += ";\n";
9400b57cec5SDimitry Andric     }
9410b57cec5SDimitry Andric     RewriteOneForwardClassDecl(ForwardDecl, typedefString);
9420b57cec5SDimitry Andric   }
9430b57cec5SDimitry Andric   RewriteForwardClassEpilogue(cast<ObjCInterfaceDecl>(D[0]), typedefString);
9440b57cec5SDimitry Andric }
9450b57cec5SDimitry Andric 
9460b57cec5SDimitry Andric void RewriteObjC::RewriteMethodDeclaration(ObjCMethodDecl *Method) {
9470b57cec5SDimitry Andric   // When method is a synthesized one, such as a getter/setter there is
9480b57cec5SDimitry Andric   // nothing to rewrite.
9490b57cec5SDimitry Andric   if (Method->isImplicit())
9500b57cec5SDimitry Andric     return;
9510b57cec5SDimitry Andric   SourceLocation LocStart = Method->getBeginLoc();
9520b57cec5SDimitry Andric   SourceLocation LocEnd = Method->getEndLoc();
9530b57cec5SDimitry Andric 
9540b57cec5SDimitry Andric   if (SM->getExpansionLineNumber(LocEnd) >
9550b57cec5SDimitry Andric       SM->getExpansionLineNumber(LocStart)) {
9560b57cec5SDimitry Andric     InsertText(LocStart, "#if 0\n");
9570b57cec5SDimitry Andric     ReplaceText(LocEnd, 1, ";\n#endif\n");
9580b57cec5SDimitry Andric   } else {
9590b57cec5SDimitry Andric     InsertText(LocStart, "// ");
9600b57cec5SDimitry Andric   }
9610b57cec5SDimitry Andric }
9620b57cec5SDimitry Andric 
9630b57cec5SDimitry Andric void RewriteObjC::RewriteProperty(ObjCPropertyDecl *prop) {
9640b57cec5SDimitry Andric   SourceLocation Loc = prop->getAtLoc();
9650b57cec5SDimitry Andric 
9660b57cec5SDimitry Andric   ReplaceText(Loc, 0, "// ");
9670b57cec5SDimitry Andric   // FIXME: handle properties that are declared across multiple lines.
9680b57cec5SDimitry Andric }
9690b57cec5SDimitry Andric 
9700b57cec5SDimitry Andric void RewriteObjC::RewriteCategoryDecl(ObjCCategoryDecl *CatDecl) {
9710b57cec5SDimitry Andric   SourceLocation LocStart = CatDecl->getBeginLoc();
9720b57cec5SDimitry Andric 
9730b57cec5SDimitry Andric   // FIXME: handle category headers that are declared across multiple lines.
9740b57cec5SDimitry Andric   ReplaceText(LocStart, 0, "// ");
9750b57cec5SDimitry Andric 
9760b57cec5SDimitry Andric   for (auto *I : CatDecl->instance_properties())
9770b57cec5SDimitry Andric     RewriteProperty(I);
9780b57cec5SDimitry Andric   for (auto *I : CatDecl->instance_methods())
9790b57cec5SDimitry Andric     RewriteMethodDeclaration(I);
9800b57cec5SDimitry Andric   for (auto *I : CatDecl->class_methods())
9810b57cec5SDimitry Andric     RewriteMethodDeclaration(I);
9820b57cec5SDimitry Andric 
9830b57cec5SDimitry Andric   // Lastly, comment out the @end.
9840b57cec5SDimitry Andric   ReplaceText(CatDecl->getAtEndRange().getBegin(),
9850b57cec5SDimitry Andric               strlen("@end"), "/* @end */");
9860b57cec5SDimitry Andric }
9870b57cec5SDimitry Andric 
9880b57cec5SDimitry Andric void RewriteObjC::RewriteProtocolDecl(ObjCProtocolDecl *PDecl) {
9890b57cec5SDimitry Andric   SourceLocation LocStart = PDecl->getBeginLoc();
9900b57cec5SDimitry Andric   assert(PDecl->isThisDeclarationADefinition());
9910b57cec5SDimitry Andric 
9920b57cec5SDimitry Andric   // FIXME: handle protocol headers that are declared across multiple lines.
9930b57cec5SDimitry Andric   ReplaceText(LocStart, 0, "// ");
9940b57cec5SDimitry Andric 
9950b57cec5SDimitry Andric   for (auto *I : PDecl->instance_methods())
9960b57cec5SDimitry Andric     RewriteMethodDeclaration(I);
9970b57cec5SDimitry Andric   for (auto *I : PDecl->class_methods())
9980b57cec5SDimitry Andric     RewriteMethodDeclaration(I);
9990b57cec5SDimitry Andric   for (auto *I : PDecl->instance_properties())
10000b57cec5SDimitry Andric     RewriteProperty(I);
10010b57cec5SDimitry Andric 
10020b57cec5SDimitry Andric   // Lastly, comment out the @end.
10030b57cec5SDimitry Andric   SourceLocation LocEnd = PDecl->getAtEndRange().getBegin();
10040b57cec5SDimitry Andric   ReplaceText(LocEnd, strlen("@end"), "/* @end */");
10050b57cec5SDimitry Andric 
10060b57cec5SDimitry Andric   // Must comment out @optional/@required
10070b57cec5SDimitry Andric   const char *startBuf = SM->getCharacterData(LocStart);
10080b57cec5SDimitry Andric   const char *endBuf = SM->getCharacterData(LocEnd);
10090b57cec5SDimitry Andric   for (const char *p = startBuf; p < endBuf; p++) {
10100b57cec5SDimitry Andric     if (*p == '@' && !strncmp(p+1, "optional", strlen("optional"))) {
10110b57cec5SDimitry Andric       SourceLocation OptionalLoc = LocStart.getLocWithOffset(p-startBuf);
10120b57cec5SDimitry Andric       ReplaceText(OptionalLoc, strlen("@optional"), "/* @optional */");
10130b57cec5SDimitry Andric 
10140b57cec5SDimitry Andric     }
10150b57cec5SDimitry Andric     else if (*p == '@' && !strncmp(p+1, "required", strlen("required"))) {
10160b57cec5SDimitry Andric       SourceLocation OptionalLoc = LocStart.getLocWithOffset(p-startBuf);
10170b57cec5SDimitry Andric       ReplaceText(OptionalLoc, strlen("@required"), "/* @required */");
10180b57cec5SDimitry Andric 
10190b57cec5SDimitry Andric     }
10200b57cec5SDimitry Andric   }
10210b57cec5SDimitry Andric }
10220b57cec5SDimitry Andric 
10230b57cec5SDimitry Andric void RewriteObjC::RewriteForwardProtocolDecl(DeclGroupRef D) {
10240b57cec5SDimitry Andric   SourceLocation LocStart = (*D.begin())->getBeginLoc();
10250b57cec5SDimitry Andric   if (LocStart.isInvalid())
10260b57cec5SDimitry Andric     llvm_unreachable("Invalid SourceLocation");
10270b57cec5SDimitry Andric   // FIXME: handle forward protocol that are declared across multiple lines.
10280b57cec5SDimitry Andric   ReplaceText(LocStart, 0, "// ");
10290b57cec5SDimitry Andric }
10300b57cec5SDimitry Andric 
10310b57cec5SDimitry Andric void
10320b57cec5SDimitry Andric RewriteObjC::RewriteForwardProtocolDecl(const SmallVectorImpl<Decl *> &DG) {
10330b57cec5SDimitry Andric   SourceLocation LocStart = DG[0]->getBeginLoc();
10340b57cec5SDimitry Andric   if (LocStart.isInvalid())
10350b57cec5SDimitry Andric     llvm_unreachable("Invalid SourceLocation");
10360b57cec5SDimitry Andric   // FIXME: handle forward protocol that are declared across multiple lines.
10370b57cec5SDimitry Andric   ReplaceText(LocStart, 0, "// ");
10380b57cec5SDimitry Andric }
10390b57cec5SDimitry Andric 
10400b57cec5SDimitry Andric void RewriteObjC::RewriteTypeIntoString(QualType T, std::string &ResultStr,
10410b57cec5SDimitry Andric                                         const FunctionType *&FPRetType) {
10420b57cec5SDimitry Andric   if (T->isObjCQualifiedIdType())
10430b57cec5SDimitry Andric     ResultStr += "id";
10440b57cec5SDimitry Andric   else if (T->isFunctionPointerType() ||
10450b57cec5SDimitry Andric            T->isBlockPointerType()) {
10460b57cec5SDimitry Andric     // needs special handling, since pointer-to-functions have special
10470b57cec5SDimitry Andric     // syntax (where a decaration models use).
10480b57cec5SDimitry Andric     QualType retType = T;
10490b57cec5SDimitry Andric     QualType PointeeTy;
10500b57cec5SDimitry Andric     if (const PointerType* PT = retType->getAs<PointerType>())
10510b57cec5SDimitry Andric       PointeeTy = PT->getPointeeType();
10520b57cec5SDimitry Andric     else if (const BlockPointerType *BPT = retType->getAs<BlockPointerType>())
10530b57cec5SDimitry Andric       PointeeTy = BPT->getPointeeType();
10540b57cec5SDimitry Andric     if ((FPRetType = PointeeTy->getAs<FunctionType>())) {
10550b57cec5SDimitry Andric       ResultStr +=
10560b57cec5SDimitry Andric           FPRetType->getReturnType().getAsString(Context->getPrintingPolicy());
10570b57cec5SDimitry Andric       ResultStr += "(*";
10580b57cec5SDimitry Andric     }
10590b57cec5SDimitry Andric   } else
10600b57cec5SDimitry Andric     ResultStr += T.getAsString(Context->getPrintingPolicy());
10610b57cec5SDimitry Andric }
10620b57cec5SDimitry Andric 
10630b57cec5SDimitry Andric void RewriteObjC::RewriteObjCMethodDecl(const ObjCInterfaceDecl *IDecl,
10640b57cec5SDimitry Andric                                         ObjCMethodDecl *OMD,
10650b57cec5SDimitry Andric                                         std::string &ResultStr) {
10660b57cec5SDimitry Andric   //fprintf(stderr,"In RewriteObjCMethodDecl\n");
10670b57cec5SDimitry Andric   const FunctionType *FPRetType = nullptr;
10680b57cec5SDimitry Andric   ResultStr += "\nstatic ";
10690b57cec5SDimitry Andric   RewriteTypeIntoString(OMD->getReturnType(), ResultStr, FPRetType);
10700b57cec5SDimitry Andric   ResultStr += " ";
10710b57cec5SDimitry Andric 
10720b57cec5SDimitry Andric   // Unique method name
10730b57cec5SDimitry Andric   std::string NameStr;
10740b57cec5SDimitry Andric 
10750b57cec5SDimitry Andric   if (OMD->isInstanceMethod())
10760b57cec5SDimitry Andric     NameStr += "_I_";
10770b57cec5SDimitry Andric   else
10780b57cec5SDimitry Andric     NameStr += "_C_";
10790b57cec5SDimitry Andric 
10800b57cec5SDimitry Andric   NameStr += IDecl->getNameAsString();
10810b57cec5SDimitry Andric   NameStr += "_";
10820b57cec5SDimitry Andric 
10830b57cec5SDimitry Andric   if (ObjCCategoryImplDecl *CID =
10840b57cec5SDimitry Andric       dyn_cast<ObjCCategoryImplDecl>(OMD->getDeclContext())) {
10850b57cec5SDimitry Andric     NameStr += CID->getNameAsString();
10860b57cec5SDimitry Andric     NameStr += "_";
10870b57cec5SDimitry Andric   }
10880b57cec5SDimitry Andric   // Append selector names, replacing ':' with '_'
10890b57cec5SDimitry Andric   {
10900b57cec5SDimitry Andric     std::string selString = OMD->getSelector().getAsString();
10910b57cec5SDimitry Andric     int len = selString.size();
10920b57cec5SDimitry Andric     for (int i = 0; i < len; i++)
10930b57cec5SDimitry Andric       if (selString[i] == ':')
10940b57cec5SDimitry Andric         selString[i] = '_';
10950b57cec5SDimitry Andric     NameStr += selString;
10960b57cec5SDimitry Andric   }
10970b57cec5SDimitry Andric   // Remember this name for metadata emission
10980b57cec5SDimitry Andric   MethodInternalNames[OMD] = NameStr;
10990b57cec5SDimitry Andric   ResultStr += NameStr;
11000b57cec5SDimitry Andric 
11010b57cec5SDimitry Andric   // Rewrite arguments
11020b57cec5SDimitry Andric   ResultStr += "(";
11030b57cec5SDimitry Andric 
11040b57cec5SDimitry Andric   // invisible arguments
11050b57cec5SDimitry Andric   if (OMD->isInstanceMethod()) {
11060b57cec5SDimitry Andric     QualType selfTy = Context->getObjCInterfaceType(IDecl);
11070b57cec5SDimitry Andric     selfTy = Context->getPointerType(selfTy);
11080b57cec5SDimitry Andric     if (!LangOpts.MicrosoftExt) {
11090b57cec5SDimitry Andric       if (ObjCSynthesizedStructs.count(const_cast<ObjCInterfaceDecl*>(IDecl)))
11100b57cec5SDimitry Andric         ResultStr += "struct ";
11110b57cec5SDimitry Andric     }
11120b57cec5SDimitry Andric     // When rewriting for Microsoft, explicitly omit the structure name.
11130b57cec5SDimitry Andric     ResultStr += IDecl->getNameAsString();
11140b57cec5SDimitry Andric     ResultStr += " *";
11150b57cec5SDimitry Andric   }
11160b57cec5SDimitry Andric   else
11170b57cec5SDimitry Andric     ResultStr += Context->getObjCClassType().getAsString(
11180b57cec5SDimitry Andric       Context->getPrintingPolicy());
11190b57cec5SDimitry Andric 
11200b57cec5SDimitry Andric   ResultStr += " self, ";
11210b57cec5SDimitry Andric   ResultStr += Context->getObjCSelType().getAsString(Context->getPrintingPolicy());
11220b57cec5SDimitry Andric   ResultStr += " _cmd";
11230b57cec5SDimitry Andric 
11240b57cec5SDimitry Andric   // Method arguments.
11250b57cec5SDimitry Andric   for (const auto *PDecl : OMD->parameters()) {
11260b57cec5SDimitry Andric     ResultStr += ", ";
11270b57cec5SDimitry Andric     if (PDecl->getType()->isObjCQualifiedIdType()) {
11280b57cec5SDimitry Andric       ResultStr += "id ";
11290b57cec5SDimitry Andric       ResultStr += PDecl->getNameAsString();
11300b57cec5SDimitry Andric     } else {
11310b57cec5SDimitry Andric       std::string Name = PDecl->getNameAsString();
11320b57cec5SDimitry Andric       QualType QT = PDecl->getType();
11330b57cec5SDimitry Andric       // Make sure we convert "t (^)(...)" to "t (*)(...)".
11340b57cec5SDimitry Andric       (void)convertBlockPointerToFunctionPointer(QT);
11350b57cec5SDimitry Andric       QT.getAsStringInternal(Name, Context->getPrintingPolicy());
11360b57cec5SDimitry Andric       ResultStr += Name;
11370b57cec5SDimitry Andric     }
11380b57cec5SDimitry Andric   }
11390b57cec5SDimitry Andric   if (OMD->isVariadic())
11400b57cec5SDimitry Andric     ResultStr += ", ...";
11410b57cec5SDimitry Andric   ResultStr += ") ";
11420b57cec5SDimitry Andric 
11430b57cec5SDimitry Andric   if (FPRetType) {
11440b57cec5SDimitry Andric     ResultStr += ")"; // close the precedence "scope" for "*".
11450b57cec5SDimitry Andric 
11460b57cec5SDimitry Andric     // Now, emit the argument types (if any).
11470b57cec5SDimitry Andric     if (const FunctionProtoType *FT = dyn_cast<FunctionProtoType>(FPRetType)) {
11480b57cec5SDimitry Andric       ResultStr += "(";
11490b57cec5SDimitry Andric       for (unsigned i = 0, e = FT->getNumParams(); i != e; ++i) {
11500b57cec5SDimitry Andric         if (i) ResultStr += ", ";
11510b57cec5SDimitry Andric         std::string ParamStr =
11520b57cec5SDimitry Andric             FT->getParamType(i).getAsString(Context->getPrintingPolicy());
11530b57cec5SDimitry Andric         ResultStr += ParamStr;
11540b57cec5SDimitry Andric       }
11550b57cec5SDimitry Andric       if (FT->isVariadic()) {
11560b57cec5SDimitry Andric         if (FT->getNumParams())
11570b57cec5SDimitry Andric           ResultStr += ", ";
11580b57cec5SDimitry Andric         ResultStr += "...";
11590b57cec5SDimitry Andric       }
11600b57cec5SDimitry Andric       ResultStr += ")";
11610b57cec5SDimitry Andric     } else {
11620b57cec5SDimitry Andric       ResultStr += "()";
11630b57cec5SDimitry Andric     }
11640b57cec5SDimitry Andric   }
11650b57cec5SDimitry Andric }
11660b57cec5SDimitry Andric 
11670b57cec5SDimitry Andric void RewriteObjC::RewriteImplementationDecl(Decl *OID) {
11680b57cec5SDimitry Andric   ObjCImplementationDecl *IMD = dyn_cast<ObjCImplementationDecl>(OID);
11690b57cec5SDimitry Andric   ObjCCategoryImplDecl *CID = dyn_cast<ObjCCategoryImplDecl>(OID);
1170a7dea167SDimitry Andric   assert((IMD || CID) && "Unknown ImplementationDecl");
11710b57cec5SDimitry Andric 
11720b57cec5SDimitry Andric   InsertText(IMD ? IMD->getBeginLoc() : CID->getBeginLoc(), "// ");
11730b57cec5SDimitry Andric 
11740b57cec5SDimitry Andric   for (auto *OMD : IMD ? IMD->instance_methods() : CID->instance_methods()) {
1175480093f4SDimitry Andric     if (!OMD->getBody())
1176480093f4SDimitry Andric       continue;
11770b57cec5SDimitry Andric     std::string ResultStr;
11780b57cec5SDimitry Andric     RewriteObjCMethodDecl(OMD->getClassInterface(), OMD, ResultStr);
11790b57cec5SDimitry Andric     SourceLocation LocStart = OMD->getBeginLoc();
11800b57cec5SDimitry Andric     SourceLocation LocEnd = OMD->getCompoundBody()->getBeginLoc();
11810b57cec5SDimitry Andric 
11820b57cec5SDimitry Andric     const char *startBuf = SM->getCharacterData(LocStart);
11830b57cec5SDimitry Andric     const char *endBuf = SM->getCharacterData(LocEnd);
11840b57cec5SDimitry Andric     ReplaceText(LocStart, endBuf-startBuf, ResultStr);
11850b57cec5SDimitry Andric   }
11860b57cec5SDimitry Andric 
11870b57cec5SDimitry Andric   for (auto *OMD : IMD ? IMD->class_methods() : CID->class_methods()) {
1188480093f4SDimitry Andric     if (!OMD->getBody())
1189480093f4SDimitry Andric       continue;
11900b57cec5SDimitry Andric     std::string ResultStr;
11910b57cec5SDimitry Andric     RewriteObjCMethodDecl(OMD->getClassInterface(), OMD, ResultStr);
11920b57cec5SDimitry Andric     SourceLocation LocStart = OMD->getBeginLoc();
11930b57cec5SDimitry Andric     SourceLocation LocEnd = OMD->getCompoundBody()->getBeginLoc();
11940b57cec5SDimitry Andric 
11950b57cec5SDimitry Andric     const char *startBuf = SM->getCharacterData(LocStart);
11960b57cec5SDimitry Andric     const char *endBuf = SM->getCharacterData(LocEnd);
11970b57cec5SDimitry Andric     ReplaceText(LocStart, endBuf-startBuf, ResultStr);
11980b57cec5SDimitry Andric   }
11990b57cec5SDimitry Andric   for (auto *I : IMD ? IMD->property_impls() : CID->property_impls())
12000b57cec5SDimitry Andric     RewritePropertyImplDecl(I, IMD, CID);
12010b57cec5SDimitry Andric 
12020b57cec5SDimitry Andric   InsertText(IMD ? IMD->getEndLoc() : CID->getEndLoc(), "// ");
12030b57cec5SDimitry Andric }
12040b57cec5SDimitry Andric 
12050b57cec5SDimitry Andric void RewriteObjC::RewriteInterfaceDecl(ObjCInterfaceDecl *ClassDecl) {
12060b57cec5SDimitry Andric   std::string ResultStr;
12070b57cec5SDimitry Andric   if (!ObjCForwardDecls.count(ClassDecl->getCanonicalDecl())) {
12080b57cec5SDimitry Andric     // we haven't seen a forward decl - generate a typedef.
12090b57cec5SDimitry Andric     ResultStr = "#ifndef _REWRITER_typedef_";
12100b57cec5SDimitry Andric     ResultStr += ClassDecl->getNameAsString();
12110b57cec5SDimitry Andric     ResultStr += "\n";
12120b57cec5SDimitry Andric     ResultStr += "#define _REWRITER_typedef_";
12130b57cec5SDimitry Andric     ResultStr += ClassDecl->getNameAsString();
12140b57cec5SDimitry Andric     ResultStr += "\n";
12150b57cec5SDimitry Andric     ResultStr += "typedef struct objc_object ";
12160b57cec5SDimitry Andric     ResultStr += ClassDecl->getNameAsString();
12170b57cec5SDimitry Andric     ResultStr += ";\n#endif\n";
12180b57cec5SDimitry Andric     // Mark this typedef as having been generated.
12190b57cec5SDimitry Andric     ObjCForwardDecls.insert(ClassDecl->getCanonicalDecl());
12200b57cec5SDimitry Andric   }
12210b57cec5SDimitry Andric   RewriteObjCInternalStruct(ClassDecl, ResultStr);
12220b57cec5SDimitry Andric 
12230b57cec5SDimitry Andric   for (auto *I : ClassDecl->instance_properties())
12240b57cec5SDimitry Andric     RewriteProperty(I);
12250b57cec5SDimitry Andric   for (auto *I : ClassDecl->instance_methods())
12260b57cec5SDimitry Andric     RewriteMethodDeclaration(I);
12270b57cec5SDimitry Andric   for (auto *I : ClassDecl->class_methods())
12280b57cec5SDimitry Andric     RewriteMethodDeclaration(I);
12290b57cec5SDimitry Andric 
12300b57cec5SDimitry Andric   // Lastly, comment out the @end.
12310b57cec5SDimitry Andric   ReplaceText(ClassDecl->getAtEndRange().getBegin(), strlen("@end"),
12320b57cec5SDimitry Andric               "/* @end */");
12330b57cec5SDimitry Andric }
12340b57cec5SDimitry Andric 
12350b57cec5SDimitry Andric Stmt *RewriteObjC::RewritePropertyOrImplicitSetter(PseudoObjectExpr *PseudoOp) {
12360b57cec5SDimitry Andric   SourceRange OldRange = PseudoOp->getSourceRange();
12370b57cec5SDimitry Andric 
12380b57cec5SDimitry Andric   // We just magically know some things about the structure of this
12390b57cec5SDimitry Andric   // expression.
12400b57cec5SDimitry Andric   ObjCMessageExpr *OldMsg =
12410b57cec5SDimitry Andric     cast<ObjCMessageExpr>(PseudoOp->getSemanticExpr(
12420b57cec5SDimitry Andric                             PseudoOp->getNumSemanticExprs() - 1));
12430b57cec5SDimitry Andric 
12440b57cec5SDimitry Andric   // Because the rewriter doesn't allow us to rewrite rewritten code,
12450b57cec5SDimitry Andric   // we need to suppress rewriting the sub-statements.
12460b57cec5SDimitry Andric   Expr *Base, *RHS;
12470b57cec5SDimitry Andric   {
12480b57cec5SDimitry Andric     DisableReplaceStmtScope S(*this);
12490b57cec5SDimitry Andric 
12500b57cec5SDimitry Andric     // Rebuild the base expression if we have one.
12510b57cec5SDimitry Andric     Base = nullptr;
12520b57cec5SDimitry Andric     if (OldMsg->getReceiverKind() == ObjCMessageExpr::Instance) {
12530b57cec5SDimitry Andric       Base = OldMsg->getInstanceReceiver();
12540b57cec5SDimitry Andric       Base = cast<OpaqueValueExpr>(Base)->getSourceExpr();
12550b57cec5SDimitry Andric       Base = cast<Expr>(RewriteFunctionBodyOrGlobalInitializer(Base));
12560b57cec5SDimitry Andric     }
12570b57cec5SDimitry Andric 
12580b57cec5SDimitry Andric     // Rebuild the RHS.
12590b57cec5SDimitry Andric     RHS = cast<BinaryOperator>(PseudoOp->getSyntacticForm())->getRHS();
12600b57cec5SDimitry Andric     RHS = cast<OpaqueValueExpr>(RHS)->getSourceExpr();
12610b57cec5SDimitry Andric     RHS = cast<Expr>(RewriteFunctionBodyOrGlobalInitializer(RHS));
12620b57cec5SDimitry Andric   }
12630b57cec5SDimitry Andric 
12640b57cec5SDimitry Andric   // TODO: avoid this copy.
12650b57cec5SDimitry Andric   SmallVector<SourceLocation, 1> SelLocs;
12660b57cec5SDimitry Andric   OldMsg->getSelectorLocs(SelLocs);
12670b57cec5SDimitry Andric 
12680b57cec5SDimitry Andric   ObjCMessageExpr *NewMsg = nullptr;
12690b57cec5SDimitry Andric   switch (OldMsg->getReceiverKind()) {
12700b57cec5SDimitry Andric   case ObjCMessageExpr::Class:
12710b57cec5SDimitry Andric     NewMsg = ObjCMessageExpr::Create(*Context, OldMsg->getType(),
12720b57cec5SDimitry Andric                                      OldMsg->getValueKind(),
12730b57cec5SDimitry Andric                                      OldMsg->getLeftLoc(),
12740b57cec5SDimitry Andric                                      OldMsg->getClassReceiverTypeInfo(),
12750b57cec5SDimitry Andric                                      OldMsg->getSelector(),
12760b57cec5SDimitry Andric                                      SelLocs,
12770b57cec5SDimitry Andric                                      OldMsg->getMethodDecl(),
12780b57cec5SDimitry Andric                                      RHS,
12790b57cec5SDimitry Andric                                      OldMsg->getRightLoc(),
12800b57cec5SDimitry Andric                                      OldMsg->isImplicit());
12810b57cec5SDimitry Andric     break;
12820b57cec5SDimitry Andric 
12830b57cec5SDimitry Andric   case ObjCMessageExpr::Instance:
12840b57cec5SDimitry Andric     NewMsg = ObjCMessageExpr::Create(*Context, OldMsg->getType(),
12850b57cec5SDimitry Andric                                      OldMsg->getValueKind(),
12860b57cec5SDimitry Andric                                      OldMsg->getLeftLoc(),
12870b57cec5SDimitry Andric                                      Base,
12880b57cec5SDimitry Andric                                      OldMsg->getSelector(),
12890b57cec5SDimitry Andric                                      SelLocs,
12900b57cec5SDimitry Andric                                      OldMsg->getMethodDecl(),
12910b57cec5SDimitry Andric                                      RHS,
12920b57cec5SDimitry Andric                                      OldMsg->getRightLoc(),
12930b57cec5SDimitry Andric                                      OldMsg->isImplicit());
12940b57cec5SDimitry Andric     break;
12950b57cec5SDimitry Andric 
12960b57cec5SDimitry Andric   case ObjCMessageExpr::SuperClass:
12970b57cec5SDimitry Andric   case ObjCMessageExpr::SuperInstance:
12980b57cec5SDimitry Andric     NewMsg = ObjCMessageExpr::Create(*Context, OldMsg->getType(),
12990b57cec5SDimitry Andric                                      OldMsg->getValueKind(),
13000b57cec5SDimitry Andric                                      OldMsg->getLeftLoc(),
13010b57cec5SDimitry Andric                                      OldMsg->getSuperLoc(),
13020b57cec5SDimitry Andric                  OldMsg->getReceiverKind() == ObjCMessageExpr::SuperInstance,
13030b57cec5SDimitry Andric                                      OldMsg->getSuperType(),
13040b57cec5SDimitry Andric                                      OldMsg->getSelector(),
13050b57cec5SDimitry Andric                                      SelLocs,
13060b57cec5SDimitry Andric                                      OldMsg->getMethodDecl(),
13070b57cec5SDimitry Andric                                      RHS,
13080b57cec5SDimitry Andric                                      OldMsg->getRightLoc(),
13090b57cec5SDimitry Andric                                      OldMsg->isImplicit());
13100b57cec5SDimitry Andric     break;
13110b57cec5SDimitry Andric   }
13120b57cec5SDimitry Andric 
13130b57cec5SDimitry Andric   Stmt *Replacement = SynthMessageExpr(NewMsg);
13140b57cec5SDimitry Andric   ReplaceStmtWithRange(PseudoOp, Replacement, OldRange);
13150b57cec5SDimitry Andric   return Replacement;
13160b57cec5SDimitry Andric }
13170b57cec5SDimitry Andric 
13180b57cec5SDimitry Andric Stmt *RewriteObjC::RewritePropertyOrImplicitGetter(PseudoObjectExpr *PseudoOp) {
13190b57cec5SDimitry Andric   SourceRange OldRange = PseudoOp->getSourceRange();
13200b57cec5SDimitry Andric 
13210b57cec5SDimitry Andric   // We just magically know some things about the structure of this
13220b57cec5SDimitry Andric   // expression.
13230b57cec5SDimitry Andric   ObjCMessageExpr *OldMsg =
13240b57cec5SDimitry Andric     cast<ObjCMessageExpr>(PseudoOp->getResultExpr()->IgnoreImplicit());
13250b57cec5SDimitry Andric 
13260b57cec5SDimitry Andric   // Because the rewriter doesn't allow us to rewrite rewritten code,
13270b57cec5SDimitry Andric   // we need to suppress rewriting the sub-statements.
13280b57cec5SDimitry Andric   Expr *Base = nullptr;
13290b57cec5SDimitry Andric   {
13300b57cec5SDimitry Andric     DisableReplaceStmtScope S(*this);
13310b57cec5SDimitry Andric 
13320b57cec5SDimitry Andric     // Rebuild the base expression if we have one.
13330b57cec5SDimitry Andric     if (OldMsg->getReceiverKind() == ObjCMessageExpr::Instance) {
13340b57cec5SDimitry Andric       Base = OldMsg->getInstanceReceiver();
13350b57cec5SDimitry Andric       Base = cast<OpaqueValueExpr>(Base)->getSourceExpr();
13360b57cec5SDimitry Andric       Base = cast<Expr>(RewriteFunctionBodyOrGlobalInitializer(Base));
13370b57cec5SDimitry Andric     }
13380b57cec5SDimitry Andric   }
13390b57cec5SDimitry Andric 
13400b57cec5SDimitry Andric   // Intentionally empty.
13410b57cec5SDimitry Andric   SmallVector<SourceLocation, 1> SelLocs;
13420b57cec5SDimitry Andric   SmallVector<Expr*, 1> Args;
13430b57cec5SDimitry Andric 
13440b57cec5SDimitry Andric   ObjCMessageExpr *NewMsg = nullptr;
13450b57cec5SDimitry Andric   switch (OldMsg->getReceiverKind()) {
13460b57cec5SDimitry Andric   case ObjCMessageExpr::Class:
13470b57cec5SDimitry Andric     NewMsg = ObjCMessageExpr::Create(*Context, OldMsg->getType(),
13480b57cec5SDimitry Andric                                      OldMsg->getValueKind(),
13490b57cec5SDimitry Andric                                      OldMsg->getLeftLoc(),
13500b57cec5SDimitry Andric                                      OldMsg->getClassReceiverTypeInfo(),
13510b57cec5SDimitry Andric                                      OldMsg->getSelector(),
13520b57cec5SDimitry Andric                                      SelLocs,
13530b57cec5SDimitry Andric                                      OldMsg->getMethodDecl(),
13540b57cec5SDimitry Andric                                      Args,
13550b57cec5SDimitry Andric                                      OldMsg->getRightLoc(),
13560b57cec5SDimitry Andric                                      OldMsg->isImplicit());
13570b57cec5SDimitry Andric     break;
13580b57cec5SDimitry Andric 
13590b57cec5SDimitry Andric   case ObjCMessageExpr::Instance:
13600b57cec5SDimitry Andric     NewMsg = ObjCMessageExpr::Create(*Context, OldMsg->getType(),
13610b57cec5SDimitry Andric                                      OldMsg->getValueKind(),
13620b57cec5SDimitry Andric                                      OldMsg->getLeftLoc(),
13630b57cec5SDimitry Andric                                      Base,
13640b57cec5SDimitry Andric                                      OldMsg->getSelector(),
13650b57cec5SDimitry Andric                                      SelLocs,
13660b57cec5SDimitry Andric                                      OldMsg->getMethodDecl(),
13670b57cec5SDimitry Andric                                      Args,
13680b57cec5SDimitry Andric                                      OldMsg->getRightLoc(),
13690b57cec5SDimitry Andric                                      OldMsg->isImplicit());
13700b57cec5SDimitry Andric     break;
13710b57cec5SDimitry Andric 
13720b57cec5SDimitry Andric   case ObjCMessageExpr::SuperClass:
13730b57cec5SDimitry Andric   case ObjCMessageExpr::SuperInstance:
13740b57cec5SDimitry Andric     NewMsg = ObjCMessageExpr::Create(*Context, OldMsg->getType(),
13750b57cec5SDimitry Andric                                      OldMsg->getValueKind(),
13760b57cec5SDimitry Andric                                      OldMsg->getLeftLoc(),
13770b57cec5SDimitry Andric                                      OldMsg->getSuperLoc(),
13780b57cec5SDimitry Andric                  OldMsg->getReceiverKind() == ObjCMessageExpr::SuperInstance,
13790b57cec5SDimitry Andric                                      OldMsg->getSuperType(),
13800b57cec5SDimitry Andric                                      OldMsg->getSelector(),
13810b57cec5SDimitry Andric                                      SelLocs,
13820b57cec5SDimitry Andric                                      OldMsg->getMethodDecl(),
13830b57cec5SDimitry Andric                                      Args,
13840b57cec5SDimitry Andric                                      OldMsg->getRightLoc(),
13850b57cec5SDimitry Andric                                      OldMsg->isImplicit());
13860b57cec5SDimitry Andric     break;
13870b57cec5SDimitry Andric   }
13880b57cec5SDimitry Andric 
13890b57cec5SDimitry Andric   Stmt *Replacement = SynthMessageExpr(NewMsg);
13900b57cec5SDimitry Andric   ReplaceStmtWithRange(PseudoOp, Replacement, OldRange);
13910b57cec5SDimitry Andric   return Replacement;
13920b57cec5SDimitry Andric }
13930b57cec5SDimitry Andric 
13940b57cec5SDimitry Andric /// SynthCountByEnumWithState - To print:
13950b57cec5SDimitry Andric /// ((unsigned int (*)
13960b57cec5SDimitry Andric ///  (id, SEL, struct __objcFastEnumerationState *, id *, unsigned int))
13970b57cec5SDimitry Andric ///  (void *)objc_msgSend)((id)l_collection,
13980b57cec5SDimitry Andric ///                        sel_registerName(
13990b57cec5SDimitry Andric ///                          "countByEnumeratingWithState:objects:count:"),
14000b57cec5SDimitry Andric ///                        &enumState,
14010b57cec5SDimitry Andric ///                        (id *)__rw_items, (unsigned int)16)
14020b57cec5SDimitry Andric ///
14030b57cec5SDimitry Andric void RewriteObjC::SynthCountByEnumWithState(std::string &buf) {
14040b57cec5SDimitry Andric   buf += "((unsigned int (*) (id, SEL, struct __objcFastEnumerationState *, "
14050b57cec5SDimitry Andric   "id *, unsigned int))(void *)objc_msgSend)";
14060b57cec5SDimitry Andric   buf += "\n\t\t";
14070b57cec5SDimitry Andric   buf += "((id)l_collection,\n\t\t";
14080b57cec5SDimitry Andric   buf += "sel_registerName(\"countByEnumeratingWithState:objects:count:\"),";
14090b57cec5SDimitry Andric   buf += "\n\t\t";
14100b57cec5SDimitry Andric   buf += "&enumState, "
14110b57cec5SDimitry Andric          "(id *)__rw_items, (unsigned int)16)";
14120b57cec5SDimitry Andric }
14130b57cec5SDimitry Andric 
14140b57cec5SDimitry Andric /// RewriteBreakStmt - Rewrite for a break-stmt inside an ObjC2's foreach
14150b57cec5SDimitry Andric /// statement to exit to its outer synthesized loop.
14160b57cec5SDimitry Andric ///
14170b57cec5SDimitry Andric Stmt *RewriteObjC::RewriteBreakStmt(BreakStmt *S) {
14180b57cec5SDimitry Andric   if (Stmts.empty() || !isa<ObjCForCollectionStmt>(Stmts.back()))
14190b57cec5SDimitry Andric     return S;
14200b57cec5SDimitry Andric   // replace break with goto __break_label
14210b57cec5SDimitry Andric   std::string buf;
14220b57cec5SDimitry Andric 
14230b57cec5SDimitry Andric   SourceLocation startLoc = S->getBeginLoc();
14240b57cec5SDimitry Andric   buf = "goto __break_label_";
14250b57cec5SDimitry Andric   buf += utostr(ObjCBcLabelNo.back());
14260b57cec5SDimitry Andric   ReplaceText(startLoc, strlen("break"), buf);
14270b57cec5SDimitry Andric 
14280b57cec5SDimitry Andric   return nullptr;
14290b57cec5SDimitry Andric }
14300b57cec5SDimitry Andric 
14310b57cec5SDimitry Andric /// RewriteContinueStmt - Rewrite for a continue-stmt inside an ObjC2's foreach
14320b57cec5SDimitry Andric /// statement to continue with its inner synthesized loop.
14330b57cec5SDimitry Andric ///
14340b57cec5SDimitry Andric Stmt *RewriteObjC::RewriteContinueStmt(ContinueStmt *S) {
14350b57cec5SDimitry Andric   if (Stmts.empty() || !isa<ObjCForCollectionStmt>(Stmts.back()))
14360b57cec5SDimitry Andric     return S;
14370b57cec5SDimitry Andric   // replace continue with goto __continue_label
14380b57cec5SDimitry Andric   std::string buf;
14390b57cec5SDimitry Andric 
14400b57cec5SDimitry Andric   SourceLocation startLoc = S->getBeginLoc();
14410b57cec5SDimitry Andric   buf = "goto __continue_label_";
14420b57cec5SDimitry Andric   buf += utostr(ObjCBcLabelNo.back());
14430b57cec5SDimitry Andric   ReplaceText(startLoc, strlen("continue"), buf);
14440b57cec5SDimitry Andric 
14450b57cec5SDimitry Andric   return nullptr;
14460b57cec5SDimitry Andric }
14470b57cec5SDimitry Andric 
14480b57cec5SDimitry Andric /// RewriteObjCForCollectionStmt - Rewriter for ObjC2's foreach statement.
14490b57cec5SDimitry Andric ///  It rewrites:
14500b57cec5SDimitry Andric /// for ( type elem in collection) { stmts; }
14510b57cec5SDimitry Andric 
14520b57cec5SDimitry Andric /// Into:
14530b57cec5SDimitry Andric /// {
14540b57cec5SDimitry Andric ///   type elem;
14550b57cec5SDimitry Andric ///   struct __objcFastEnumerationState enumState = { 0 };
14560b57cec5SDimitry Andric ///   id __rw_items[16];
14570b57cec5SDimitry Andric ///   id l_collection = (id)collection;
14580b57cec5SDimitry Andric ///   unsigned long limit = [l_collection countByEnumeratingWithState:&enumState
14590b57cec5SDimitry Andric ///                                       objects:__rw_items count:16];
14600b57cec5SDimitry Andric /// if (limit) {
14610b57cec5SDimitry Andric ///   unsigned long startMutations = *enumState.mutationsPtr;
14620b57cec5SDimitry Andric ///   do {
14630b57cec5SDimitry Andric ///        unsigned long counter = 0;
14640b57cec5SDimitry Andric ///        do {
14650b57cec5SDimitry Andric ///             if (startMutations != *enumState.mutationsPtr)
14660b57cec5SDimitry Andric ///               objc_enumerationMutation(l_collection);
14670b57cec5SDimitry Andric ///             elem = (type)enumState.itemsPtr[counter++];
14680b57cec5SDimitry Andric ///             stmts;
14690b57cec5SDimitry Andric ///             __continue_label: ;
14700b57cec5SDimitry Andric ///        } while (counter < limit);
14710b57cec5SDimitry Andric ///   } while (limit = [l_collection countByEnumeratingWithState:&enumState
14720b57cec5SDimitry Andric ///                                  objects:__rw_items count:16]);
14730b57cec5SDimitry Andric ///   elem = nil;
14740b57cec5SDimitry Andric ///   __break_label: ;
14750b57cec5SDimitry Andric ///  }
14760b57cec5SDimitry Andric ///  else
14770b57cec5SDimitry Andric ///       elem = nil;
14780b57cec5SDimitry Andric ///  }
14790b57cec5SDimitry Andric ///
14800b57cec5SDimitry Andric Stmt *RewriteObjC::RewriteObjCForCollectionStmt(ObjCForCollectionStmt *S,
14810b57cec5SDimitry Andric                                                 SourceLocation OrigEnd) {
14820b57cec5SDimitry Andric   assert(!Stmts.empty() && "ObjCForCollectionStmt - Statement stack empty");
14830b57cec5SDimitry Andric   assert(isa<ObjCForCollectionStmt>(Stmts.back()) &&
14840b57cec5SDimitry Andric          "ObjCForCollectionStmt Statement stack mismatch");
14850b57cec5SDimitry Andric   assert(!ObjCBcLabelNo.empty() &&
14860b57cec5SDimitry Andric          "ObjCForCollectionStmt - Label No stack empty");
14870b57cec5SDimitry Andric 
14880b57cec5SDimitry Andric   SourceLocation startLoc = S->getBeginLoc();
14890b57cec5SDimitry Andric   const char *startBuf = SM->getCharacterData(startLoc);
14900b57cec5SDimitry Andric   StringRef elementName;
14910b57cec5SDimitry Andric   std::string elementTypeAsString;
14920b57cec5SDimitry Andric   std::string buf;
14930b57cec5SDimitry Andric   buf = "\n{\n\t";
14940b57cec5SDimitry Andric   if (DeclStmt *DS = dyn_cast<DeclStmt>(S->getElement())) {
14950b57cec5SDimitry Andric     // type elem;
14960b57cec5SDimitry Andric     NamedDecl* D = cast<NamedDecl>(DS->getSingleDecl());
14970b57cec5SDimitry Andric     QualType ElementType = cast<ValueDecl>(D)->getType();
14980b57cec5SDimitry Andric     if (ElementType->isObjCQualifiedIdType() ||
14990b57cec5SDimitry Andric         ElementType->isObjCQualifiedInterfaceType())
15000b57cec5SDimitry Andric       // Simply use 'id' for all qualified types.
15010b57cec5SDimitry Andric       elementTypeAsString = "id";
15020b57cec5SDimitry Andric     else
15030b57cec5SDimitry Andric       elementTypeAsString = ElementType.getAsString(Context->getPrintingPolicy());
15040b57cec5SDimitry Andric     buf += elementTypeAsString;
15050b57cec5SDimitry Andric     buf += " ";
15060b57cec5SDimitry Andric     elementName = D->getName();
15070b57cec5SDimitry Andric     buf += elementName;
15080b57cec5SDimitry Andric     buf += ";\n\t";
15090b57cec5SDimitry Andric   }
15100b57cec5SDimitry Andric   else {
15110b57cec5SDimitry Andric     DeclRefExpr *DR = cast<DeclRefExpr>(S->getElement());
15120b57cec5SDimitry Andric     elementName = DR->getDecl()->getName();
15130b57cec5SDimitry Andric     ValueDecl *VD = DR->getDecl();
15140b57cec5SDimitry Andric     if (VD->getType()->isObjCQualifiedIdType() ||
15150b57cec5SDimitry Andric         VD->getType()->isObjCQualifiedInterfaceType())
15160b57cec5SDimitry Andric       // Simply use 'id' for all qualified types.
15170b57cec5SDimitry Andric       elementTypeAsString = "id";
15180b57cec5SDimitry Andric     else
15190b57cec5SDimitry Andric       elementTypeAsString = VD->getType().getAsString(Context->getPrintingPolicy());
15200b57cec5SDimitry Andric   }
15210b57cec5SDimitry Andric 
15220b57cec5SDimitry Andric   // struct __objcFastEnumerationState enumState = { 0 };
15230b57cec5SDimitry Andric   buf += "struct __objcFastEnumerationState enumState = { 0 };\n\t";
15240b57cec5SDimitry Andric   // id __rw_items[16];
15250b57cec5SDimitry Andric   buf += "id __rw_items[16];\n\t";
15260b57cec5SDimitry Andric   // id l_collection = (id)
15270b57cec5SDimitry Andric   buf += "id l_collection = (id)";
15280b57cec5SDimitry Andric   // Find start location of 'collection' the hard way!
15290b57cec5SDimitry Andric   const char *startCollectionBuf = startBuf;
15300b57cec5SDimitry Andric   startCollectionBuf += 3;  // skip 'for'
15310b57cec5SDimitry Andric   startCollectionBuf = strchr(startCollectionBuf, '(');
15320b57cec5SDimitry Andric   startCollectionBuf++; // skip '('
15330b57cec5SDimitry Andric   // find 'in' and skip it.
15340b57cec5SDimitry Andric   while (*startCollectionBuf != ' ' ||
15350b57cec5SDimitry Andric          *(startCollectionBuf+1) != 'i' || *(startCollectionBuf+2) != 'n' ||
15360b57cec5SDimitry Andric          (*(startCollectionBuf+3) != ' ' &&
15370b57cec5SDimitry Andric           *(startCollectionBuf+3) != '[' && *(startCollectionBuf+3) != '('))
15380b57cec5SDimitry Andric     startCollectionBuf++;
15390b57cec5SDimitry Andric   startCollectionBuf += 3;
15400b57cec5SDimitry Andric 
15410b57cec5SDimitry Andric   // Replace: "for (type element in" with string constructed thus far.
15420b57cec5SDimitry Andric   ReplaceText(startLoc, startCollectionBuf - startBuf, buf);
15430b57cec5SDimitry Andric   // Replace ')' in for '(' type elem in collection ')' with ';'
15440b57cec5SDimitry Andric   SourceLocation rightParenLoc = S->getRParenLoc();
15450b57cec5SDimitry Andric   const char *rparenBuf = SM->getCharacterData(rightParenLoc);
15460b57cec5SDimitry Andric   SourceLocation lparenLoc = startLoc.getLocWithOffset(rparenBuf-startBuf);
15470b57cec5SDimitry Andric   buf = ";\n\t";
15480b57cec5SDimitry Andric 
15490b57cec5SDimitry Andric   // unsigned long limit = [l_collection countByEnumeratingWithState:&enumState
15500b57cec5SDimitry Andric   //                                   objects:__rw_items count:16];
15510b57cec5SDimitry Andric   // which is synthesized into:
15520b57cec5SDimitry Andric   // unsigned int limit =
15530b57cec5SDimitry Andric   // ((unsigned int (*)
15540b57cec5SDimitry Andric   //  (id, SEL, struct __objcFastEnumerationState *, id *, unsigned int))
15550b57cec5SDimitry Andric   //  (void *)objc_msgSend)((id)l_collection,
15560b57cec5SDimitry Andric   //                        sel_registerName(
15570b57cec5SDimitry Andric   //                          "countByEnumeratingWithState:objects:count:"),
15580b57cec5SDimitry Andric   //                        (struct __objcFastEnumerationState *)&state,
15590b57cec5SDimitry Andric   //                        (id *)__rw_items, (unsigned int)16);
15600b57cec5SDimitry Andric   buf += "unsigned long limit =\n\t\t";
15610b57cec5SDimitry Andric   SynthCountByEnumWithState(buf);
15620b57cec5SDimitry Andric   buf += ";\n\t";
15630b57cec5SDimitry Andric   /// if (limit) {
15640b57cec5SDimitry Andric   ///   unsigned long startMutations = *enumState.mutationsPtr;
15650b57cec5SDimitry Andric   ///   do {
15660b57cec5SDimitry Andric   ///        unsigned long counter = 0;
15670b57cec5SDimitry Andric   ///        do {
15680b57cec5SDimitry Andric   ///             if (startMutations != *enumState.mutationsPtr)
15690b57cec5SDimitry Andric   ///               objc_enumerationMutation(l_collection);
15700b57cec5SDimitry Andric   ///             elem = (type)enumState.itemsPtr[counter++];
15710b57cec5SDimitry Andric   buf += "if (limit) {\n\t";
15720b57cec5SDimitry Andric   buf += "unsigned long startMutations = *enumState.mutationsPtr;\n\t";
15730b57cec5SDimitry Andric   buf += "do {\n\t\t";
15740b57cec5SDimitry Andric   buf += "unsigned long counter = 0;\n\t\t";
15750b57cec5SDimitry Andric   buf += "do {\n\t\t\t";
15760b57cec5SDimitry Andric   buf += "if (startMutations != *enumState.mutationsPtr)\n\t\t\t\t";
15770b57cec5SDimitry Andric   buf += "objc_enumerationMutation(l_collection);\n\t\t\t";
15780b57cec5SDimitry Andric   buf += elementName;
15790b57cec5SDimitry Andric   buf += " = (";
15800b57cec5SDimitry Andric   buf += elementTypeAsString;
15810b57cec5SDimitry Andric   buf += ")enumState.itemsPtr[counter++];";
15820b57cec5SDimitry Andric   // Replace ')' in for '(' type elem in collection ')' with all of these.
15830b57cec5SDimitry Andric   ReplaceText(lparenLoc, 1, buf);
15840b57cec5SDimitry Andric 
15850b57cec5SDimitry Andric   ///            __continue_label: ;
15860b57cec5SDimitry Andric   ///        } while (counter < limit);
15870b57cec5SDimitry Andric   ///   } while (limit = [l_collection countByEnumeratingWithState:&enumState
15880b57cec5SDimitry Andric   ///                                  objects:__rw_items count:16]);
15890b57cec5SDimitry Andric   ///   elem = nil;
15900b57cec5SDimitry Andric   ///   __break_label: ;
15910b57cec5SDimitry Andric   ///  }
15920b57cec5SDimitry Andric   ///  else
15930b57cec5SDimitry Andric   ///       elem = nil;
15940b57cec5SDimitry Andric   ///  }
15950b57cec5SDimitry Andric   ///
15960b57cec5SDimitry Andric   buf = ";\n\t";
15970b57cec5SDimitry Andric   buf += "__continue_label_";
15980b57cec5SDimitry Andric   buf += utostr(ObjCBcLabelNo.back());
15990b57cec5SDimitry Andric   buf += ": ;";
16000b57cec5SDimitry Andric   buf += "\n\t\t";
16010b57cec5SDimitry Andric   buf += "} while (counter < limit);\n\t";
16020b57cec5SDimitry Andric   buf += "} while (limit = ";
16030b57cec5SDimitry Andric   SynthCountByEnumWithState(buf);
16040b57cec5SDimitry Andric   buf += ");\n\t";
16050b57cec5SDimitry Andric   buf += elementName;
16060b57cec5SDimitry Andric   buf += " = ((";
16070b57cec5SDimitry Andric   buf += elementTypeAsString;
16080b57cec5SDimitry Andric   buf += ")0);\n\t";
16090b57cec5SDimitry Andric   buf += "__break_label_";
16100b57cec5SDimitry Andric   buf += utostr(ObjCBcLabelNo.back());
16110b57cec5SDimitry Andric   buf += ": ;\n\t";
16120b57cec5SDimitry Andric   buf += "}\n\t";
16130b57cec5SDimitry Andric   buf += "else\n\t\t";
16140b57cec5SDimitry Andric   buf += elementName;
16150b57cec5SDimitry Andric   buf += " = ((";
16160b57cec5SDimitry Andric   buf += elementTypeAsString;
16170b57cec5SDimitry Andric   buf += ")0);\n\t";
16180b57cec5SDimitry Andric   buf += "}\n";
16190b57cec5SDimitry Andric 
16200b57cec5SDimitry Andric   // Insert all these *after* the statement body.
16210b57cec5SDimitry Andric   // FIXME: If this should support Obj-C++, support CXXTryStmt
16220b57cec5SDimitry Andric   if (isa<CompoundStmt>(S->getBody())) {
16230b57cec5SDimitry Andric     SourceLocation endBodyLoc = OrigEnd.getLocWithOffset(1);
16240b57cec5SDimitry Andric     InsertText(endBodyLoc, buf);
16250b57cec5SDimitry Andric   } else {
16260b57cec5SDimitry Andric     /* Need to treat single statements specially. For example:
16270b57cec5SDimitry Andric      *
16280b57cec5SDimitry Andric      *     for (A *a in b) if (stuff()) break;
16290b57cec5SDimitry Andric      *     for (A *a in b) xxxyy;
16300b57cec5SDimitry Andric      *
16310b57cec5SDimitry Andric      * The following code simply scans ahead to the semi to find the actual end.
16320b57cec5SDimitry Andric      */
16330b57cec5SDimitry Andric     const char *stmtBuf = SM->getCharacterData(OrigEnd);
16340b57cec5SDimitry Andric     const char *semiBuf = strchr(stmtBuf, ';');
16350b57cec5SDimitry Andric     assert(semiBuf && "Can't find ';'");
16360b57cec5SDimitry Andric     SourceLocation endBodyLoc = OrigEnd.getLocWithOffset(semiBuf-stmtBuf+1);
16370b57cec5SDimitry Andric     InsertText(endBodyLoc, buf);
16380b57cec5SDimitry Andric   }
16390b57cec5SDimitry Andric   Stmts.pop_back();
16400b57cec5SDimitry Andric   ObjCBcLabelNo.pop_back();
16410b57cec5SDimitry Andric   return nullptr;
16420b57cec5SDimitry Andric }
16430b57cec5SDimitry Andric 
16440b57cec5SDimitry Andric /// RewriteObjCSynchronizedStmt -
16450b57cec5SDimitry Andric /// This routine rewrites @synchronized(expr) stmt;
16460b57cec5SDimitry Andric /// into:
16470b57cec5SDimitry Andric /// objc_sync_enter(expr);
16480b57cec5SDimitry Andric /// @try stmt @finally { objc_sync_exit(expr); }
16490b57cec5SDimitry Andric ///
16500b57cec5SDimitry Andric Stmt *RewriteObjC::RewriteObjCSynchronizedStmt(ObjCAtSynchronizedStmt *S) {
16510b57cec5SDimitry Andric   // Get the start location and compute the semi location.
16520b57cec5SDimitry Andric   SourceLocation startLoc = S->getBeginLoc();
16530b57cec5SDimitry Andric   const char *startBuf = SM->getCharacterData(startLoc);
16540b57cec5SDimitry Andric 
16550b57cec5SDimitry Andric   assert((*startBuf == '@') && "bogus @synchronized location");
16560b57cec5SDimitry Andric 
16570b57cec5SDimitry Andric   std::string buf;
16580b57cec5SDimitry Andric   buf = "objc_sync_enter((id)";
16590b57cec5SDimitry Andric   const char *lparenBuf = startBuf;
16600b57cec5SDimitry Andric   while (*lparenBuf != '(') lparenBuf++;
16610b57cec5SDimitry Andric   ReplaceText(startLoc, lparenBuf-startBuf+1, buf);
16620b57cec5SDimitry Andric   // We can't use S->getSynchExpr()->getEndLoc() to find the end location, since
16630b57cec5SDimitry Andric   // the sync expression is typically a message expression that's already
16640b57cec5SDimitry Andric   // been rewritten! (which implies the SourceLocation's are invalid).
16650b57cec5SDimitry Andric   SourceLocation endLoc = S->getSynchBody()->getBeginLoc();
16660b57cec5SDimitry Andric   const char *endBuf = SM->getCharacterData(endLoc);
16670b57cec5SDimitry Andric   while (*endBuf != ')') endBuf--;
16680b57cec5SDimitry Andric   SourceLocation rparenLoc = startLoc.getLocWithOffset(endBuf-startBuf);
16690b57cec5SDimitry Andric   buf = ");\n";
16700b57cec5SDimitry Andric   // declare a new scope with two variables, _stack and _rethrow.
16710b57cec5SDimitry Andric   buf += "/* @try scope begin */ \n{ struct _objc_exception_data {\n";
16720b57cec5SDimitry Andric   buf += "int buf[18/*32-bit i386*/];\n";
16730b57cec5SDimitry Andric   buf += "char *pointers[4];} _stack;\n";
16740b57cec5SDimitry Andric   buf += "id volatile _rethrow = 0;\n";
16750b57cec5SDimitry Andric   buf += "objc_exception_try_enter(&_stack);\n";
16760b57cec5SDimitry Andric   buf += "if (!_setjmp(_stack.buf)) /* @try block continue */\n";
16770b57cec5SDimitry Andric   ReplaceText(rparenLoc, 1, buf);
16780b57cec5SDimitry Andric   startLoc = S->getSynchBody()->getEndLoc();
16790b57cec5SDimitry Andric   startBuf = SM->getCharacterData(startLoc);
16800b57cec5SDimitry Andric 
16810b57cec5SDimitry Andric   assert((*startBuf == '}') && "bogus @synchronized block");
16820b57cec5SDimitry Andric   SourceLocation lastCurlyLoc = startLoc;
16830b57cec5SDimitry Andric   buf = "}\nelse {\n";
16840b57cec5SDimitry Andric   buf += "  _rethrow = objc_exception_extract(&_stack);\n";
16850b57cec5SDimitry Andric   buf += "}\n";
16860b57cec5SDimitry Andric   buf += "{ /* implicit finally clause */\n";
16870b57cec5SDimitry Andric   buf += "  if (!_rethrow) objc_exception_try_exit(&_stack);\n";
16880b57cec5SDimitry Andric 
16890b57cec5SDimitry Andric   std::string syncBuf;
16900b57cec5SDimitry Andric   syncBuf += " objc_sync_exit(";
16910b57cec5SDimitry Andric 
16920b57cec5SDimitry Andric   Expr *syncExpr = S->getSynchExpr();
16930b57cec5SDimitry Andric   CastKind CK = syncExpr->getType()->isObjCObjectPointerType()
16940b57cec5SDimitry Andric                   ? CK_BitCast :
16950b57cec5SDimitry Andric                 syncExpr->getType()->isBlockPointerType()
16960b57cec5SDimitry Andric                   ? CK_BlockPointerToObjCPointerCast
16970b57cec5SDimitry Andric                   : CK_CPointerToObjCPointerCast;
16980b57cec5SDimitry Andric   syncExpr = NoTypeInfoCStyleCastExpr(Context, Context->getObjCIdType(),
16990b57cec5SDimitry Andric                                       CK, syncExpr);
17000b57cec5SDimitry Andric   std::string syncExprBufS;
17010b57cec5SDimitry Andric   llvm::raw_string_ostream syncExprBuf(syncExprBufS);
17020b57cec5SDimitry Andric   assert(syncExpr != nullptr && "Expected non-null Expr");
17030b57cec5SDimitry Andric   syncExpr->printPretty(syncExprBuf, nullptr, PrintingPolicy(LangOpts));
17040b57cec5SDimitry Andric   syncBuf += syncExprBuf.str();
17050b57cec5SDimitry Andric   syncBuf += ");";
17060b57cec5SDimitry Andric 
17070b57cec5SDimitry Andric   buf += syncBuf;
17080b57cec5SDimitry Andric   buf += "\n  if (_rethrow) objc_exception_throw(_rethrow);\n";
17090b57cec5SDimitry Andric   buf += "}\n";
17100b57cec5SDimitry Andric   buf += "}";
17110b57cec5SDimitry Andric 
17120b57cec5SDimitry Andric   ReplaceText(lastCurlyLoc, 1, buf);
17130b57cec5SDimitry Andric 
17140b57cec5SDimitry Andric   bool hasReturns = false;
17150b57cec5SDimitry Andric   HasReturnStmts(S->getSynchBody(), hasReturns);
17160b57cec5SDimitry Andric   if (hasReturns)
17170b57cec5SDimitry Andric     RewriteSyncReturnStmts(S->getSynchBody(), syncBuf);
17180b57cec5SDimitry Andric 
17190b57cec5SDimitry Andric   return nullptr;
17200b57cec5SDimitry Andric }
17210b57cec5SDimitry Andric 
17220b57cec5SDimitry Andric void RewriteObjC::WarnAboutReturnGotoStmts(Stmt *S)
17230b57cec5SDimitry Andric {
17240b57cec5SDimitry Andric   // Perform a bottom up traversal of all children.
17250b57cec5SDimitry Andric   for (Stmt *SubStmt : S->children())
17260b57cec5SDimitry Andric     if (SubStmt)
17270b57cec5SDimitry Andric       WarnAboutReturnGotoStmts(SubStmt);
17280b57cec5SDimitry Andric 
17290b57cec5SDimitry Andric   if (isa<ReturnStmt>(S) || isa<GotoStmt>(S)) {
17300b57cec5SDimitry Andric     Diags.Report(Context->getFullLoc(S->getBeginLoc()),
17310b57cec5SDimitry Andric                  TryFinallyContainsReturnDiag);
17320b57cec5SDimitry Andric   }
17330b57cec5SDimitry Andric }
17340b57cec5SDimitry Andric 
17350b57cec5SDimitry Andric void RewriteObjC::HasReturnStmts(Stmt *S, bool &hasReturns)
17360b57cec5SDimitry Andric {
17370b57cec5SDimitry Andric   // Perform a bottom up traversal of all children.
17380b57cec5SDimitry Andric   for (Stmt *SubStmt : S->children())
17390b57cec5SDimitry Andric     if (SubStmt)
17400b57cec5SDimitry Andric       HasReturnStmts(SubStmt, hasReturns);
17410b57cec5SDimitry Andric 
17420b57cec5SDimitry Andric   if (isa<ReturnStmt>(S))
17430b57cec5SDimitry Andric     hasReturns = true;
17440b57cec5SDimitry Andric }
17450b57cec5SDimitry Andric 
17460b57cec5SDimitry Andric void RewriteObjC::RewriteTryReturnStmts(Stmt *S) {
17470b57cec5SDimitry Andric   // Perform a bottom up traversal of all children.
17480b57cec5SDimitry Andric   for (Stmt *SubStmt : S->children())
17490b57cec5SDimitry Andric     if (SubStmt) {
17500b57cec5SDimitry Andric       RewriteTryReturnStmts(SubStmt);
17510b57cec5SDimitry Andric     }
17520b57cec5SDimitry Andric   if (isa<ReturnStmt>(S)) {
17530b57cec5SDimitry Andric     SourceLocation startLoc = S->getBeginLoc();
17540b57cec5SDimitry Andric     const char *startBuf = SM->getCharacterData(startLoc);
17550b57cec5SDimitry Andric     const char *semiBuf = strchr(startBuf, ';');
17560b57cec5SDimitry Andric     assert((*semiBuf == ';') && "RewriteTryReturnStmts: can't find ';'");
17570b57cec5SDimitry Andric     SourceLocation onePastSemiLoc = startLoc.getLocWithOffset(semiBuf-startBuf+1);
17580b57cec5SDimitry Andric 
17590b57cec5SDimitry Andric     std::string buf;
17600b57cec5SDimitry Andric     buf = "{ objc_exception_try_exit(&_stack); return";
17610b57cec5SDimitry Andric 
17620b57cec5SDimitry Andric     ReplaceText(startLoc, 6, buf);
17630b57cec5SDimitry Andric     InsertText(onePastSemiLoc, "}");
17640b57cec5SDimitry Andric   }
17650b57cec5SDimitry Andric }
17660b57cec5SDimitry Andric 
17670b57cec5SDimitry Andric void RewriteObjC::RewriteSyncReturnStmts(Stmt *S, std::string syncExitBuf) {
17680b57cec5SDimitry Andric   // Perform a bottom up traversal of all children.
17690b57cec5SDimitry Andric   for (Stmt *SubStmt : S->children())
17700b57cec5SDimitry Andric     if (SubStmt) {
17710b57cec5SDimitry Andric       RewriteSyncReturnStmts(SubStmt, syncExitBuf);
17720b57cec5SDimitry Andric     }
17730b57cec5SDimitry Andric   if (isa<ReturnStmt>(S)) {
17740b57cec5SDimitry Andric     SourceLocation startLoc = S->getBeginLoc();
17750b57cec5SDimitry Andric     const char *startBuf = SM->getCharacterData(startLoc);
17760b57cec5SDimitry Andric 
17770b57cec5SDimitry Andric     const char *semiBuf = strchr(startBuf, ';');
17780b57cec5SDimitry Andric     assert((*semiBuf == ';') && "RewriteSyncReturnStmts: can't find ';'");
17790b57cec5SDimitry Andric     SourceLocation onePastSemiLoc = startLoc.getLocWithOffset(semiBuf-startBuf+1);
17800b57cec5SDimitry Andric 
17810b57cec5SDimitry Andric     std::string buf;
17820b57cec5SDimitry Andric     buf = "{ objc_exception_try_exit(&_stack);";
17830b57cec5SDimitry Andric     buf += syncExitBuf;
17840b57cec5SDimitry Andric     buf += " return";
17850b57cec5SDimitry Andric 
17860b57cec5SDimitry Andric     ReplaceText(startLoc, 6, buf);
17870b57cec5SDimitry Andric     InsertText(onePastSemiLoc, "}");
17880b57cec5SDimitry Andric   }
17890b57cec5SDimitry Andric }
17900b57cec5SDimitry Andric 
17910b57cec5SDimitry Andric Stmt *RewriteObjC::RewriteObjCTryStmt(ObjCAtTryStmt *S) {
17920b57cec5SDimitry Andric   // Get the start location and compute the semi location.
17930b57cec5SDimitry Andric   SourceLocation startLoc = S->getBeginLoc();
17940b57cec5SDimitry Andric   const char *startBuf = SM->getCharacterData(startLoc);
17950b57cec5SDimitry Andric 
17960b57cec5SDimitry Andric   assert((*startBuf == '@') && "bogus @try location");
17970b57cec5SDimitry Andric 
17980b57cec5SDimitry Andric   std::string buf;
17990b57cec5SDimitry Andric   // declare a new scope with two variables, _stack and _rethrow.
18000b57cec5SDimitry Andric   buf = "/* @try scope begin */ { struct _objc_exception_data {\n";
18010b57cec5SDimitry Andric   buf += "int buf[18/*32-bit i386*/];\n";
18020b57cec5SDimitry Andric   buf += "char *pointers[4];} _stack;\n";
18030b57cec5SDimitry Andric   buf += "id volatile _rethrow = 0;\n";
18040b57cec5SDimitry Andric   buf += "objc_exception_try_enter(&_stack);\n";
18050b57cec5SDimitry Andric   buf += "if (!_setjmp(_stack.buf)) /* @try block continue */\n";
18060b57cec5SDimitry Andric 
18070b57cec5SDimitry Andric   ReplaceText(startLoc, 4, buf);
18080b57cec5SDimitry Andric 
18090b57cec5SDimitry Andric   startLoc = S->getTryBody()->getEndLoc();
18100b57cec5SDimitry Andric   startBuf = SM->getCharacterData(startLoc);
18110b57cec5SDimitry Andric 
18120b57cec5SDimitry Andric   assert((*startBuf == '}') && "bogus @try block");
18130b57cec5SDimitry Andric 
18140b57cec5SDimitry Andric   SourceLocation lastCurlyLoc = startLoc;
18150b57cec5SDimitry Andric   if (S->getNumCatchStmts()) {
18160b57cec5SDimitry Andric     startLoc = startLoc.getLocWithOffset(1);
18170b57cec5SDimitry Andric     buf = " /* @catch begin */ else {\n";
18180b57cec5SDimitry Andric     buf += " id _caught = objc_exception_extract(&_stack);\n";
18190b57cec5SDimitry Andric     buf += " objc_exception_try_enter (&_stack);\n";
18200b57cec5SDimitry Andric     buf += " if (_setjmp(_stack.buf))\n";
18210b57cec5SDimitry Andric     buf += "   _rethrow = objc_exception_extract(&_stack);\n";
18220b57cec5SDimitry Andric     buf += " else { /* @catch continue */";
18230b57cec5SDimitry Andric 
18240b57cec5SDimitry Andric     InsertText(startLoc, buf);
18250b57cec5SDimitry Andric   } else { /* no catch list */
18260b57cec5SDimitry Andric     buf = "}\nelse {\n";
18270b57cec5SDimitry Andric     buf += "  _rethrow = objc_exception_extract(&_stack);\n";
18280b57cec5SDimitry Andric     buf += "}";
18290b57cec5SDimitry Andric     ReplaceText(lastCurlyLoc, 1, buf);
18300b57cec5SDimitry Andric   }
18310b57cec5SDimitry Andric   Stmt *lastCatchBody = nullptr;
18320b57cec5SDimitry Andric   for (unsigned I = 0, N = S->getNumCatchStmts(); I != N; ++I) {
18330b57cec5SDimitry Andric     ObjCAtCatchStmt *Catch = S->getCatchStmt(I);
18340b57cec5SDimitry Andric     VarDecl *catchDecl = Catch->getCatchParamDecl();
18350b57cec5SDimitry Andric 
18360b57cec5SDimitry Andric     if (I == 0)
18370b57cec5SDimitry Andric       buf = "if ("; // we are generating code for the first catch clause
18380b57cec5SDimitry Andric     else
18390b57cec5SDimitry Andric       buf = "else if (";
18400b57cec5SDimitry Andric     startLoc = Catch->getBeginLoc();
18410b57cec5SDimitry Andric     startBuf = SM->getCharacterData(startLoc);
18420b57cec5SDimitry Andric 
18430b57cec5SDimitry Andric     assert((*startBuf == '@') && "bogus @catch location");
18440b57cec5SDimitry Andric 
18450b57cec5SDimitry Andric     const char *lParenLoc = strchr(startBuf, '(');
18460b57cec5SDimitry Andric 
18470b57cec5SDimitry Andric     if (Catch->hasEllipsis()) {
18480b57cec5SDimitry Andric       // Now rewrite the body...
18490b57cec5SDimitry Andric       lastCatchBody = Catch->getCatchBody();
18500b57cec5SDimitry Andric       SourceLocation bodyLoc = lastCatchBody->getBeginLoc();
18510b57cec5SDimitry Andric       const char *bodyBuf = SM->getCharacterData(bodyLoc);
18520b57cec5SDimitry Andric       assert(*SM->getCharacterData(Catch->getRParenLoc()) == ')' &&
18530b57cec5SDimitry Andric              "bogus @catch paren location");
18540b57cec5SDimitry Andric       assert((*bodyBuf == '{') && "bogus @catch body location");
18550b57cec5SDimitry Andric 
18560b57cec5SDimitry Andric       buf += "1) { id _tmp = _caught;";
18570b57cec5SDimitry Andric       Rewrite.ReplaceText(startLoc, bodyBuf-startBuf+1, buf);
18580b57cec5SDimitry Andric     } else if (catchDecl) {
18590b57cec5SDimitry Andric       QualType t = catchDecl->getType();
18600b57cec5SDimitry Andric       if (t == Context->getObjCIdType()) {
18610b57cec5SDimitry Andric         buf += "1) { ";
18620b57cec5SDimitry Andric         ReplaceText(startLoc, lParenLoc-startBuf+1, buf);
18630b57cec5SDimitry Andric       } else if (const ObjCObjectPointerType *Ptr =
18640b57cec5SDimitry Andric                    t->getAs<ObjCObjectPointerType>()) {
18650b57cec5SDimitry Andric         // Should be a pointer to a class.
18660b57cec5SDimitry Andric         ObjCInterfaceDecl *IDecl = Ptr->getObjectType()->getInterface();
18670b57cec5SDimitry Andric         if (IDecl) {
18680b57cec5SDimitry Andric           buf += "objc_exception_match((struct objc_class *)objc_getClass(\"";
18690b57cec5SDimitry Andric           buf += IDecl->getNameAsString();
18700b57cec5SDimitry Andric           buf += "\"), (struct objc_object *)_caught)) { ";
18710b57cec5SDimitry Andric           ReplaceText(startLoc, lParenLoc-startBuf+1, buf);
18720b57cec5SDimitry Andric         }
18730b57cec5SDimitry Andric       }
18740b57cec5SDimitry Andric       // Now rewrite the body...
18750b57cec5SDimitry Andric       lastCatchBody = Catch->getCatchBody();
18760b57cec5SDimitry Andric       SourceLocation rParenLoc = Catch->getRParenLoc();
18770b57cec5SDimitry Andric       SourceLocation bodyLoc = lastCatchBody->getBeginLoc();
18780b57cec5SDimitry Andric       const char *bodyBuf = SM->getCharacterData(bodyLoc);
18790b57cec5SDimitry Andric       const char *rParenBuf = SM->getCharacterData(rParenLoc);
18800b57cec5SDimitry Andric       assert((*rParenBuf == ')') && "bogus @catch paren location");
18810b57cec5SDimitry Andric       assert((*bodyBuf == '{') && "bogus @catch body location");
18820b57cec5SDimitry Andric 
18830b57cec5SDimitry Andric       // Here we replace ") {" with "= _caught;" (which initializes and
18840b57cec5SDimitry Andric       // declares the @catch parameter).
18850b57cec5SDimitry Andric       ReplaceText(rParenLoc, bodyBuf-rParenBuf+1, " = _caught;");
18860b57cec5SDimitry Andric     } else {
18870b57cec5SDimitry Andric       llvm_unreachable("@catch rewrite bug");
18880b57cec5SDimitry Andric     }
18890b57cec5SDimitry Andric   }
18900b57cec5SDimitry Andric   // Complete the catch list...
18910b57cec5SDimitry Andric   if (lastCatchBody) {
18920b57cec5SDimitry Andric     SourceLocation bodyLoc = lastCatchBody->getEndLoc();
18930b57cec5SDimitry Andric     assert(*SM->getCharacterData(bodyLoc) == '}' &&
18940b57cec5SDimitry Andric            "bogus @catch body location");
18950b57cec5SDimitry Andric 
18960b57cec5SDimitry Andric     // Insert the last (implicit) else clause *before* the right curly brace.
18970b57cec5SDimitry Andric     bodyLoc = bodyLoc.getLocWithOffset(-1);
18980b57cec5SDimitry Andric     buf = "} /* last catch end */\n";
18990b57cec5SDimitry Andric     buf += "else {\n";
19000b57cec5SDimitry Andric     buf += " _rethrow = _caught;\n";
19010b57cec5SDimitry Andric     buf += " objc_exception_try_exit(&_stack);\n";
19020b57cec5SDimitry Andric     buf += "} } /* @catch end */\n";
19030b57cec5SDimitry Andric     if (!S->getFinallyStmt())
19040b57cec5SDimitry Andric       buf += "}\n";
19050b57cec5SDimitry Andric     InsertText(bodyLoc, buf);
19060b57cec5SDimitry Andric 
19070b57cec5SDimitry Andric     // Set lastCurlyLoc
19080b57cec5SDimitry Andric     lastCurlyLoc = lastCatchBody->getEndLoc();
19090b57cec5SDimitry Andric   }
19100b57cec5SDimitry Andric   if (ObjCAtFinallyStmt *finalStmt = S->getFinallyStmt()) {
19110b57cec5SDimitry Andric     startLoc = finalStmt->getBeginLoc();
19120b57cec5SDimitry Andric     startBuf = SM->getCharacterData(startLoc);
19130b57cec5SDimitry Andric     assert((*startBuf == '@') && "bogus @finally start");
19140b57cec5SDimitry Andric 
19150b57cec5SDimitry Andric     ReplaceText(startLoc, 8, "/* @finally */");
19160b57cec5SDimitry Andric 
19170b57cec5SDimitry Andric     Stmt *body = finalStmt->getFinallyBody();
19180b57cec5SDimitry Andric     SourceLocation startLoc = body->getBeginLoc();
19190b57cec5SDimitry Andric     SourceLocation endLoc = body->getEndLoc();
19200b57cec5SDimitry Andric     assert(*SM->getCharacterData(startLoc) == '{' &&
19210b57cec5SDimitry Andric            "bogus @finally body location");
19220b57cec5SDimitry Andric     assert(*SM->getCharacterData(endLoc) == '}' &&
19230b57cec5SDimitry Andric            "bogus @finally body location");
19240b57cec5SDimitry Andric 
19250b57cec5SDimitry Andric     startLoc = startLoc.getLocWithOffset(1);
19260b57cec5SDimitry Andric     InsertText(startLoc, " if (!_rethrow) objc_exception_try_exit(&_stack);\n");
19270b57cec5SDimitry Andric     endLoc = endLoc.getLocWithOffset(-1);
19280b57cec5SDimitry Andric     InsertText(endLoc, " if (_rethrow) objc_exception_throw(_rethrow);\n");
19290b57cec5SDimitry Andric 
19300b57cec5SDimitry Andric     // Set lastCurlyLoc
19310b57cec5SDimitry Andric     lastCurlyLoc = body->getEndLoc();
19320b57cec5SDimitry Andric 
19330b57cec5SDimitry Andric     // Now check for any return/continue/go statements within the @try.
19340b57cec5SDimitry Andric     WarnAboutReturnGotoStmts(S->getTryBody());
19350b57cec5SDimitry Andric   } else { /* no finally clause - make sure we synthesize an implicit one */
19360b57cec5SDimitry Andric     buf = "{ /* implicit finally clause */\n";
19370b57cec5SDimitry Andric     buf += " if (!_rethrow) objc_exception_try_exit(&_stack);\n";
19380b57cec5SDimitry Andric     buf += " if (_rethrow) objc_exception_throw(_rethrow);\n";
19390b57cec5SDimitry Andric     buf += "}";
19400b57cec5SDimitry Andric     ReplaceText(lastCurlyLoc, 1, buf);
19410b57cec5SDimitry Andric 
19420b57cec5SDimitry Andric     // Now check for any return/continue/go statements within the @try.
19430b57cec5SDimitry Andric     // The implicit finally clause won't called if the @try contains any
19440b57cec5SDimitry Andric     // jump statements.
19450b57cec5SDimitry Andric     bool hasReturns = false;
19460b57cec5SDimitry Andric     HasReturnStmts(S->getTryBody(), hasReturns);
19470b57cec5SDimitry Andric     if (hasReturns)
19480b57cec5SDimitry Andric       RewriteTryReturnStmts(S->getTryBody());
19490b57cec5SDimitry Andric   }
19500b57cec5SDimitry Andric   // Now emit the final closing curly brace...
19510b57cec5SDimitry Andric   lastCurlyLoc = lastCurlyLoc.getLocWithOffset(1);
19520b57cec5SDimitry Andric   InsertText(lastCurlyLoc, " } /* @try scope end */\n");
19530b57cec5SDimitry Andric   return nullptr;
19540b57cec5SDimitry Andric }
19550b57cec5SDimitry Andric 
19560b57cec5SDimitry Andric // This can't be done with ReplaceStmt(S, ThrowExpr), since
19570b57cec5SDimitry Andric // the throw expression is typically a message expression that's already
19580b57cec5SDimitry Andric // been rewritten! (which implies the SourceLocation's are invalid).
19590b57cec5SDimitry Andric Stmt *RewriteObjC::RewriteObjCThrowStmt(ObjCAtThrowStmt *S) {
19600b57cec5SDimitry Andric   // Get the start location and compute the semi location.
19610b57cec5SDimitry Andric   SourceLocation startLoc = S->getBeginLoc();
19620b57cec5SDimitry Andric   const char *startBuf = SM->getCharacterData(startLoc);
19630b57cec5SDimitry Andric 
19640b57cec5SDimitry Andric   assert((*startBuf == '@') && "bogus @throw location");
19650b57cec5SDimitry Andric 
19660b57cec5SDimitry Andric   std::string buf;
19670b57cec5SDimitry Andric   /* void objc_exception_throw(id) __attribute__((noreturn)); */
19680b57cec5SDimitry Andric   if (S->getThrowExpr())
19690b57cec5SDimitry Andric     buf = "objc_exception_throw(";
19700b57cec5SDimitry Andric   else // add an implicit argument
19710b57cec5SDimitry Andric     buf = "objc_exception_throw(_caught";
19720b57cec5SDimitry Andric 
19730b57cec5SDimitry Andric   // handle "@  throw" correctly.
19740b57cec5SDimitry Andric   const char *wBuf = strchr(startBuf, 'w');
19750b57cec5SDimitry Andric   assert((*wBuf == 'w') && "@throw: can't find 'w'");
19760b57cec5SDimitry Andric   ReplaceText(startLoc, wBuf-startBuf+1, buf);
19770b57cec5SDimitry Andric 
19780b57cec5SDimitry Andric   const char *semiBuf = strchr(startBuf, ';');
19790b57cec5SDimitry Andric   assert((*semiBuf == ';') && "@throw: can't find ';'");
19800b57cec5SDimitry Andric   SourceLocation semiLoc = startLoc.getLocWithOffset(semiBuf-startBuf);
19810b57cec5SDimitry Andric   ReplaceText(semiLoc, 1, ");");
19820b57cec5SDimitry Andric   return nullptr;
19830b57cec5SDimitry Andric }
19840b57cec5SDimitry Andric 
19850b57cec5SDimitry Andric Stmt *RewriteObjC::RewriteAtEncode(ObjCEncodeExpr *Exp) {
19860b57cec5SDimitry Andric   // Create a new string expression.
19870b57cec5SDimitry Andric   std::string StrEncoding;
19880b57cec5SDimitry Andric   Context->getObjCEncodingForType(Exp->getEncodedType(), StrEncoding);
19890b57cec5SDimitry Andric   Expr *Replacement = getStringLiteral(StrEncoding);
19900b57cec5SDimitry Andric   ReplaceStmt(Exp, Replacement);
19910b57cec5SDimitry Andric 
19920b57cec5SDimitry Andric   // Replace this subexpr in the parent.
19930b57cec5SDimitry Andric   // delete Exp; leak for now, see RewritePropertyOrImplicitSetter() usage for more info.
19940b57cec5SDimitry Andric   return Replacement;
19950b57cec5SDimitry Andric }
19960b57cec5SDimitry Andric 
19970b57cec5SDimitry Andric Stmt *RewriteObjC::RewriteAtSelector(ObjCSelectorExpr *Exp) {
19980b57cec5SDimitry Andric   if (!SelGetUidFunctionDecl)
19990b57cec5SDimitry Andric     SynthSelGetUidFunctionDecl();
20000b57cec5SDimitry Andric   assert(SelGetUidFunctionDecl && "Can't find sel_registerName() decl");
20010b57cec5SDimitry Andric   // Create a call to sel_registerName("selName").
20020b57cec5SDimitry Andric   SmallVector<Expr*, 8> SelExprs;
20030b57cec5SDimitry Andric   SelExprs.push_back(getStringLiteral(Exp->getSelector().getAsString()));
20040b57cec5SDimitry Andric   CallExpr *SelExp = SynthesizeCallToFunctionDecl(SelGetUidFunctionDecl,
20050b57cec5SDimitry Andric                                                   SelExprs);
20060b57cec5SDimitry Andric   ReplaceStmt(Exp, SelExp);
20070b57cec5SDimitry Andric   // delete Exp; leak for now, see RewritePropertyOrImplicitSetter() usage for more info.
20080b57cec5SDimitry Andric   return SelExp;
20090b57cec5SDimitry Andric }
20100b57cec5SDimitry Andric 
20110b57cec5SDimitry Andric CallExpr *
20120b57cec5SDimitry Andric RewriteObjC::SynthesizeCallToFunctionDecl(FunctionDecl *FD,
20130b57cec5SDimitry Andric                                           ArrayRef<Expr *> Args,
20140b57cec5SDimitry Andric                                           SourceLocation StartLoc,
20150b57cec5SDimitry Andric                                           SourceLocation EndLoc) {
20160b57cec5SDimitry Andric   // Get the type, we will need to reference it in a couple spots.
20170b57cec5SDimitry Andric   QualType msgSendType = FD->getType();
20180b57cec5SDimitry Andric 
20190b57cec5SDimitry Andric   // Create a reference to the objc_msgSend() declaration.
20200b57cec5SDimitry Andric   DeclRefExpr *DRE = new (Context) DeclRefExpr(*Context, FD, false, msgSendType,
20210b57cec5SDimitry Andric                                                VK_LValue, SourceLocation());
20220b57cec5SDimitry Andric 
20230b57cec5SDimitry Andric   // Now, we cast the reference to a pointer to the objc_msgSend type.
20240b57cec5SDimitry Andric   QualType pToFunc = Context->getPointerType(msgSendType);
20250b57cec5SDimitry Andric   ImplicitCastExpr *ICE =
20260b57cec5SDimitry Andric       ImplicitCastExpr::Create(*Context, pToFunc, CK_FunctionToPointerDecay,
2027fe6060f1SDimitry Andric                                DRE, nullptr, VK_PRValue, FPOptionsOverride());
20280b57cec5SDimitry Andric 
2029a7dea167SDimitry Andric   const auto *FT = msgSendType->castAs<FunctionType>();
20300b57cec5SDimitry Andric 
2031e8d8bef9SDimitry Andric   CallExpr *Exp =
2032e8d8bef9SDimitry Andric       CallExpr::Create(*Context, ICE, Args, FT->getCallResultType(*Context),
2033fe6060f1SDimitry Andric                        VK_PRValue, EndLoc, FPOptionsOverride());
20340b57cec5SDimitry Andric   return Exp;
20350b57cec5SDimitry Andric }
20360b57cec5SDimitry Andric 
20370b57cec5SDimitry Andric static bool scanForProtocolRefs(const char *startBuf, const char *endBuf,
20380b57cec5SDimitry Andric                                 const char *&startRef, const char *&endRef) {
20390b57cec5SDimitry Andric   while (startBuf < endBuf) {
20400b57cec5SDimitry Andric     if (*startBuf == '<')
20410b57cec5SDimitry Andric       startRef = startBuf; // mark the start.
20420b57cec5SDimitry Andric     if (*startBuf == '>') {
20430b57cec5SDimitry Andric       if (startRef && *startRef == '<') {
20440b57cec5SDimitry Andric         endRef = startBuf; // mark the end.
20450b57cec5SDimitry Andric         return true;
20460b57cec5SDimitry Andric       }
20470b57cec5SDimitry Andric       return false;
20480b57cec5SDimitry Andric     }
20490b57cec5SDimitry Andric     startBuf++;
20500b57cec5SDimitry Andric   }
20510b57cec5SDimitry Andric   return false;
20520b57cec5SDimitry Andric }
20530b57cec5SDimitry Andric 
20540b57cec5SDimitry Andric static void scanToNextArgument(const char *&argRef) {
20550b57cec5SDimitry Andric   int angle = 0;
20560b57cec5SDimitry Andric   while (*argRef != ')' && (*argRef != ',' || angle > 0)) {
20570b57cec5SDimitry Andric     if (*argRef == '<')
20580b57cec5SDimitry Andric       angle++;
20590b57cec5SDimitry Andric     else if (*argRef == '>')
20600b57cec5SDimitry Andric       angle--;
20610b57cec5SDimitry Andric     argRef++;
20620b57cec5SDimitry Andric   }
20630b57cec5SDimitry Andric   assert(angle == 0 && "scanToNextArgument - bad protocol type syntax");
20640b57cec5SDimitry Andric }
20650b57cec5SDimitry Andric 
20660b57cec5SDimitry Andric bool RewriteObjC::needToScanForQualifiers(QualType T) {
20670b57cec5SDimitry Andric   if (T->isObjCQualifiedIdType())
20680b57cec5SDimitry Andric     return true;
20690b57cec5SDimitry Andric   if (const PointerType *PT = T->getAs<PointerType>()) {
20700b57cec5SDimitry Andric     if (PT->getPointeeType()->isObjCQualifiedIdType())
20710b57cec5SDimitry Andric       return true;
20720b57cec5SDimitry Andric   }
20730b57cec5SDimitry Andric   if (T->isObjCObjectPointerType()) {
20740b57cec5SDimitry Andric     T = T->getPointeeType();
20750b57cec5SDimitry Andric     return T->isObjCQualifiedInterfaceType();
20760b57cec5SDimitry Andric   }
20770b57cec5SDimitry Andric   if (T->isArrayType()) {
20780b57cec5SDimitry Andric     QualType ElemTy = Context->getBaseElementType(T);
20790b57cec5SDimitry Andric     return needToScanForQualifiers(ElemTy);
20800b57cec5SDimitry Andric   }
20810b57cec5SDimitry Andric   return false;
20820b57cec5SDimitry Andric }
20830b57cec5SDimitry Andric 
20840b57cec5SDimitry Andric void RewriteObjC::RewriteObjCQualifiedInterfaceTypes(Expr *E) {
20850b57cec5SDimitry Andric   QualType Type = E->getType();
20860b57cec5SDimitry Andric   if (needToScanForQualifiers(Type)) {
20870b57cec5SDimitry Andric     SourceLocation Loc, EndLoc;
20880b57cec5SDimitry Andric 
20890b57cec5SDimitry Andric     if (const CStyleCastExpr *ECE = dyn_cast<CStyleCastExpr>(E)) {
20900b57cec5SDimitry Andric       Loc = ECE->getLParenLoc();
20910b57cec5SDimitry Andric       EndLoc = ECE->getRParenLoc();
20920b57cec5SDimitry Andric     } else {
20930b57cec5SDimitry Andric       Loc = E->getBeginLoc();
20940b57cec5SDimitry Andric       EndLoc = E->getEndLoc();
20950b57cec5SDimitry Andric     }
20960b57cec5SDimitry Andric     // This will defend against trying to rewrite synthesized expressions.
20970b57cec5SDimitry Andric     if (Loc.isInvalid() || EndLoc.isInvalid())
20980b57cec5SDimitry Andric       return;
20990b57cec5SDimitry Andric 
21000b57cec5SDimitry Andric     const char *startBuf = SM->getCharacterData(Loc);
21010b57cec5SDimitry Andric     const char *endBuf = SM->getCharacterData(EndLoc);
21020b57cec5SDimitry Andric     const char *startRef = nullptr, *endRef = nullptr;
21030b57cec5SDimitry Andric     if (scanForProtocolRefs(startBuf, endBuf, startRef, endRef)) {
21040b57cec5SDimitry Andric       // Get the locations of the startRef, endRef.
21050b57cec5SDimitry Andric       SourceLocation LessLoc = Loc.getLocWithOffset(startRef-startBuf);
21060b57cec5SDimitry Andric       SourceLocation GreaterLoc = Loc.getLocWithOffset(endRef-startBuf+1);
21070b57cec5SDimitry Andric       // Comment out the protocol references.
21080b57cec5SDimitry Andric       InsertText(LessLoc, "/*");
21090b57cec5SDimitry Andric       InsertText(GreaterLoc, "*/");
21100b57cec5SDimitry Andric     }
21110b57cec5SDimitry Andric   }
21120b57cec5SDimitry Andric }
21130b57cec5SDimitry Andric 
21140b57cec5SDimitry Andric void RewriteObjC::RewriteObjCQualifiedInterfaceTypes(Decl *Dcl) {
21150b57cec5SDimitry Andric   SourceLocation Loc;
21160b57cec5SDimitry Andric   QualType Type;
21170b57cec5SDimitry Andric   const FunctionProtoType *proto = nullptr;
21180b57cec5SDimitry Andric   if (VarDecl *VD = dyn_cast<VarDecl>(Dcl)) {
21190b57cec5SDimitry Andric     Loc = VD->getLocation();
21200b57cec5SDimitry Andric     Type = VD->getType();
21210b57cec5SDimitry Andric   }
21220b57cec5SDimitry Andric   else if (FunctionDecl *FD = dyn_cast<FunctionDecl>(Dcl)) {
21230b57cec5SDimitry Andric     Loc = FD->getLocation();
21240b57cec5SDimitry Andric     // Check for ObjC 'id' and class types that have been adorned with protocol
21250b57cec5SDimitry Andric     // information (id<p>, C<p>*). The protocol references need to be rewritten!
21260b57cec5SDimitry Andric     const FunctionType *funcType = FD->getType()->getAs<FunctionType>();
21270b57cec5SDimitry Andric     assert(funcType && "missing function type");
21280b57cec5SDimitry Andric     proto = dyn_cast<FunctionProtoType>(funcType);
21290b57cec5SDimitry Andric     if (!proto)
21300b57cec5SDimitry Andric       return;
21310b57cec5SDimitry Andric     Type = proto->getReturnType();
21320b57cec5SDimitry Andric   }
21330b57cec5SDimitry Andric   else if (FieldDecl *FD = dyn_cast<FieldDecl>(Dcl)) {
21340b57cec5SDimitry Andric     Loc = FD->getLocation();
21350b57cec5SDimitry Andric     Type = FD->getType();
21360b57cec5SDimitry Andric   }
21370b57cec5SDimitry Andric   else
21380b57cec5SDimitry Andric     return;
21390b57cec5SDimitry Andric 
21400b57cec5SDimitry Andric   if (needToScanForQualifiers(Type)) {
21410b57cec5SDimitry Andric     // Since types are unique, we need to scan the buffer.
21420b57cec5SDimitry Andric 
21430b57cec5SDimitry Andric     const char *endBuf = SM->getCharacterData(Loc);
21440b57cec5SDimitry Andric     const char *startBuf = endBuf;
21450b57cec5SDimitry Andric     while (*startBuf != ';' && *startBuf != '<' && startBuf != MainFileStart)
21460b57cec5SDimitry Andric       startBuf--; // scan backward (from the decl location) for return type.
21470b57cec5SDimitry Andric     const char *startRef = nullptr, *endRef = nullptr;
21480b57cec5SDimitry Andric     if (scanForProtocolRefs(startBuf, endBuf, startRef, endRef)) {
21490b57cec5SDimitry Andric       // Get the locations of the startRef, endRef.
21500b57cec5SDimitry Andric       SourceLocation LessLoc = Loc.getLocWithOffset(startRef-endBuf);
21510b57cec5SDimitry Andric       SourceLocation GreaterLoc = Loc.getLocWithOffset(endRef-endBuf+1);
21520b57cec5SDimitry Andric       // Comment out the protocol references.
21530b57cec5SDimitry Andric       InsertText(LessLoc, "/*");
21540b57cec5SDimitry Andric       InsertText(GreaterLoc, "*/");
21550b57cec5SDimitry Andric     }
21560b57cec5SDimitry Andric   }
21570b57cec5SDimitry Andric   if (!proto)
21580b57cec5SDimitry Andric       return; // most likely, was a variable
21590b57cec5SDimitry Andric   // Now check arguments.
21600b57cec5SDimitry Andric   const char *startBuf = SM->getCharacterData(Loc);
21610b57cec5SDimitry Andric   const char *startFuncBuf = startBuf;
21620b57cec5SDimitry Andric   for (unsigned i = 0; i < proto->getNumParams(); i++) {
21630b57cec5SDimitry Andric     if (needToScanForQualifiers(proto->getParamType(i))) {
21640b57cec5SDimitry Andric       // Since types are unique, we need to scan the buffer.
21650b57cec5SDimitry Andric 
21660b57cec5SDimitry Andric       const char *endBuf = startBuf;
21670b57cec5SDimitry Andric       // scan forward (from the decl location) for argument types.
21680b57cec5SDimitry Andric       scanToNextArgument(endBuf);
21690b57cec5SDimitry Andric       const char *startRef = nullptr, *endRef = nullptr;
21700b57cec5SDimitry Andric       if (scanForProtocolRefs(startBuf, endBuf, startRef, endRef)) {
21710b57cec5SDimitry Andric         // Get the locations of the startRef, endRef.
21720b57cec5SDimitry Andric         SourceLocation LessLoc =
21730b57cec5SDimitry Andric           Loc.getLocWithOffset(startRef-startFuncBuf);
21740b57cec5SDimitry Andric         SourceLocation GreaterLoc =
21750b57cec5SDimitry Andric           Loc.getLocWithOffset(endRef-startFuncBuf+1);
21760b57cec5SDimitry Andric         // Comment out the protocol references.
21770b57cec5SDimitry Andric         InsertText(LessLoc, "/*");
21780b57cec5SDimitry Andric         InsertText(GreaterLoc, "*/");
21790b57cec5SDimitry Andric       }
21800b57cec5SDimitry Andric       startBuf = ++endBuf;
21810b57cec5SDimitry Andric     }
21820b57cec5SDimitry Andric     else {
21830b57cec5SDimitry Andric       // If the function name is derived from a macro expansion, then the
21840b57cec5SDimitry Andric       // argument buffer will not follow the name. Need to speak with Chris.
21850b57cec5SDimitry Andric       while (*startBuf && *startBuf != ')' && *startBuf != ',')
21860b57cec5SDimitry Andric         startBuf++; // scan forward (from the decl location) for argument types.
21870b57cec5SDimitry Andric       startBuf++;
21880b57cec5SDimitry Andric     }
21890b57cec5SDimitry Andric   }
21900b57cec5SDimitry Andric }
21910b57cec5SDimitry Andric 
21920b57cec5SDimitry Andric void RewriteObjC::RewriteTypeOfDecl(VarDecl *ND) {
21930b57cec5SDimitry Andric   QualType QT = ND->getType();
21940b57cec5SDimitry Andric   const Type* TypePtr = QT->getAs<Type>();
21950b57cec5SDimitry Andric   if (!isa<TypeOfExprType>(TypePtr))
21960b57cec5SDimitry Andric     return;
21970b57cec5SDimitry Andric   while (isa<TypeOfExprType>(TypePtr)) {
21980b57cec5SDimitry Andric     const TypeOfExprType *TypeOfExprTypePtr = cast<TypeOfExprType>(TypePtr);
21990b57cec5SDimitry Andric     QT = TypeOfExprTypePtr->getUnderlyingExpr()->getType();
22000b57cec5SDimitry Andric     TypePtr = QT->getAs<Type>();
22010b57cec5SDimitry Andric   }
22020b57cec5SDimitry Andric   // FIXME. This will not work for multiple declarators; as in:
22030b57cec5SDimitry Andric   // __typeof__(a) b,c,d;
22040b57cec5SDimitry Andric   std::string TypeAsString(QT.getAsString(Context->getPrintingPolicy()));
22050b57cec5SDimitry Andric   SourceLocation DeclLoc = ND->getTypeSpecStartLoc();
22060b57cec5SDimitry Andric   const char *startBuf = SM->getCharacterData(DeclLoc);
22070b57cec5SDimitry Andric   if (ND->getInit()) {
22080b57cec5SDimitry Andric     std::string Name(ND->getNameAsString());
22090b57cec5SDimitry Andric     TypeAsString += " " + Name + " = ";
22100b57cec5SDimitry Andric     Expr *E = ND->getInit();
22110b57cec5SDimitry Andric     SourceLocation startLoc;
22120b57cec5SDimitry Andric     if (const CStyleCastExpr *ECE = dyn_cast<CStyleCastExpr>(E))
22130b57cec5SDimitry Andric       startLoc = ECE->getLParenLoc();
22140b57cec5SDimitry Andric     else
22150b57cec5SDimitry Andric       startLoc = E->getBeginLoc();
22160b57cec5SDimitry Andric     startLoc = SM->getExpansionLoc(startLoc);
22170b57cec5SDimitry Andric     const char *endBuf = SM->getCharacterData(startLoc);
22180b57cec5SDimitry Andric     ReplaceText(DeclLoc, endBuf-startBuf-1, TypeAsString);
22190b57cec5SDimitry Andric   }
22200b57cec5SDimitry Andric   else {
22210b57cec5SDimitry Andric     SourceLocation X = ND->getEndLoc();
22220b57cec5SDimitry Andric     X = SM->getExpansionLoc(X);
22230b57cec5SDimitry Andric     const char *endBuf = SM->getCharacterData(X);
22240b57cec5SDimitry Andric     ReplaceText(DeclLoc, endBuf-startBuf-1, TypeAsString);
22250b57cec5SDimitry Andric   }
22260b57cec5SDimitry Andric }
22270b57cec5SDimitry Andric 
22280b57cec5SDimitry Andric // SynthSelGetUidFunctionDecl - SEL sel_registerName(const char *str);
22290b57cec5SDimitry Andric void RewriteObjC::SynthSelGetUidFunctionDecl() {
22300b57cec5SDimitry Andric   IdentifierInfo *SelGetUidIdent = &Context->Idents.get("sel_registerName");
22310b57cec5SDimitry Andric   SmallVector<QualType, 16> ArgTys;
22320b57cec5SDimitry Andric   ArgTys.push_back(Context->getPointerType(Context->CharTy.withConst()));
22330b57cec5SDimitry Andric   QualType getFuncType =
22340b57cec5SDimitry Andric     getSimpleFunctionType(Context->getObjCSelType(), ArgTys);
22350b57cec5SDimitry Andric   SelGetUidFunctionDecl = FunctionDecl::Create(*Context, TUDecl,
22360b57cec5SDimitry Andric                                                SourceLocation(),
22370b57cec5SDimitry Andric                                                SourceLocation(),
22380b57cec5SDimitry Andric                                                SelGetUidIdent, getFuncType,
22390b57cec5SDimitry Andric                                                nullptr, SC_Extern);
22400b57cec5SDimitry Andric }
22410b57cec5SDimitry Andric 
22420b57cec5SDimitry Andric void RewriteObjC::RewriteFunctionDecl(FunctionDecl *FD) {
22430b57cec5SDimitry Andric   // declared in <objc/objc.h>
22440b57cec5SDimitry Andric   if (FD->getIdentifier() &&
22450b57cec5SDimitry Andric       FD->getName() == "sel_registerName") {
22460b57cec5SDimitry Andric     SelGetUidFunctionDecl = FD;
22470b57cec5SDimitry Andric     return;
22480b57cec5SDimitry Andric   }
22490b57cec5SDimitry Andric   RewriteObjCQualifiedInterfaceTypes(FD);
22500b57cec5SDimitry Andric }
22510b57cec5SDimitry Andric 
22520b57cec5SDimitry Andric void RewriteObjC::RewriteBlockPointerType(std::string& Str, QualType Type) {
22530b57cec5SDimitry Andric   std::string TypeString(Type.getAsString(Context->getPrintingPolicy()));
22540b57cec5SDimitry Andric   const char *argPtr = TypeString.c_str();
22550b57cec5SDimitry Andric   if (!strchr(argPtr, '^')) {
22560b57cec5SDimitry Andric     Str += TypeString;
22570b57cec5SDimitry Andric     return;
22580b57cec5SDimitry Andric   }
22590b57cec5SDimitry Andric   while (*argPtr) {
22600b57cec5SDimitry Andric     Str += (*argPtr == '^' ? '*' : *argPtr);
22610b57cec5SDimitry Andric     argPtr++;
22620b57cec5SDimitry Andric   }
22630b57cec5SDimitry Andric }
22640b57cec5SDimitry Andric 
22650b57cec5SDimitry Andric // FIXME. Consolidate this routine with RewriteBlockPointerType.
22660b57cec5SDimitry Andric void RewriteObjC::RewriteBlockPointerTypeVariable(std::string& Str,
22670b57cec5SDimitry Andric                                                   ValueDecl *VD) {
22680b57cec5SDimitry Andric   QualType Type = VD->getType();
22690b57cec5SDimitry Andric   std::string TypeString(Type.getAsString(Context->getPrintingPolicy()));
22700b57cec5SDimitry Andric   const char *argPtr = TypeString.c_str();
22710b57cec5SDimitry Andric   int paren = 0;
22720b57cec5SDimitry Andric   while (*argPtr) {
22730b57cec5SDimitry Andric     switch (*argPtr) {
22740b57cec5SDimitry Andric       case '(':
22750b57cec5SDimitry Andric         Str += *argPtr;
22760b57cec5SDimitry Andric         paren++;
22770b57cec5SDimitry Andric         break;
22780b57cec5SDimitry Andric       case ')':
22790b57cec5SDimitry Andric         Str += *argPtr;
22800b57cec5SDimitry Andric         paren--;
22810b57cec5SDimitry Andric         break;
22820b57cec5SDimitry Andric       case '^':
22830b57cec5SDimitry Andric         Str += '*';
22840b57cec5SDimitry Andric         if (paren == 1)
22850b57cec5SDimitry Andric           Str += VD->getNameAsString();
22860b57cec5SDimitry Andric         break;
22870b57cec5SDimitry Andric       default:
22880b57cec5SDimitry Andric         Str += *argPtr;
22890b57cec5SDimitry Andric         break;
22900b57cec5SDimitry Andric     }
22910b57cec5SDimitry Andric     argPtr++;
22920b57cec5SDimitry Andric   }
22930b57cec5SDimitry Andric }
22940b57cec5SDimitry Andric 
22950b57cec5SDimitry Andric void RewriteObjC::RewriteBlockLiteralFunctionDecl(FunctionDecl *FD) {
22960b57cec5SDimitry Andric   SourceLocation FunLocStart = FD->getTypeSpecStartLoc();
22970b57cec5SDimitry Andric   const FunctionType *funcType = FD->getType()->getAs<FunctionType>();
2298a7dea167SDimitry Andric   const FunctionProtoType *proto = dyn_cast_or_null<FunctionProtoType>(funcType);
22990b57cec5SDimitry Andric   if (!proto)
23000b57cec5SDimitry Andric     return;
23010b57cec5SDimitry Andric   QualType Type = proto->getReturnType();
23020b57cec5SDimitry Andric   std::string FdStr = Type.getAsString(Context->getPrintingPolicy());
23030b57cec5SDimitry Andric   FdStr += " ";
23040b57cec5SDimitry Andric   FdStr += FD->getName();
23050b57cec5SDimitry Andric   FdStr +=  "(";
23060b57cec5SDimitry Andric   unsigned numArgs = proto->getNumParams();
23070b57cec5SDimitry Andric   for (unsigned i = 0; i < numArgs; i++) {
23080b57cec5SDimitry Andric     QualType ArgType = proto->getParamType(i);
23090b57cec5SDimitry Andric     RewriteBlockPointerType(FdStr, ArgType);
23100b57cec5SDimitry Andric     if (i+1 < numArgs)
23110b57cec5SDimitry Andric       FdStr += ", ";
23120b57cec5SDimitry Andric   }
23130b57cec5SDimitry Andric   FdStr +=  ");\n";
23140b57cec5SDimitry Andric   InsertText(FunLocStart, FdStr);
23150b57cec5SDimitry Andric   CurFunctionDeclToDeclareForBlock = nullptr;
23160b57cec5SDimitry Andric }
23170b57cec5SDimitry Andric 
23180b57cec5SDimitry Andric // SynthSuperConstructorFunctionDecl - id objc_super(id obj, id super);
23190b57cec5SDimitry Andric void RewriteObjC::SynthSuperConstructorFunctionDecl() {
23200b57cec5SDimitry Andric   if (SuperConstructorFunctionDecl)
23210b57cec5SDimitry Andric     return;
23220b57cec5SDimitry Andric   IdentifierInfo *msgSendIdent = &Context->Idents.get("__rw_objc_super");
23230b57cec5SDimitry Andric   SmallVector<QualType, 16> ArgTys;
23240b57cec5SDimitry Andric   QualType argT = Context->getObjCIdType();
23250b57cec5SDimitry Andric   assert(!argT.isNull() && "Can't find 'id' type");
23260b57cec5SDimitry Andric   ArgTys.push_back(argT);
23270b57cec5SDimitry Andric   ArgTys.push_back(argT);
23280b57cec5SDimitry Andric   QualType msgSendType = getSimpleFunctionType(Context->getObjCIdType(),
23290b57cec5SDimitry Andric                                                ArgTys);
23300b57cec5SDimitry Andric   SuperConstructorFunctionDecl = FunctionDecl::Create(*Context, TUDecl,
23310b57cec5SDimitry Andric                                                      SourceLocation(),
23320b57cec5SDimitry Andric                                                      SourceLocation(),
23330b57cec5SDimitry Andric                                                      msgSendIdent, msgSendType,
23340b57cec5SDimitry Andric                                                      nullptr, SC_Extern);
23350b57cec5SDimitry Andric }
23360b57cec5SDimitry Andric 
23370b57cec5SDimitry Andric // SynthMsgSendFunctionDecl - id objc_msgSend(id self, SEL op, ...);
23380b57cec5SDimitry Andric void RewriteObjC::SynthMsgSendFunctionDecl() {
23390b57cec5SDimitry Andric   IdentifierInfo *msgSendIdent = &Context->Idents.get("objc_msgSend");
23400b57cec5SDimitry Andric   SmallVector<QualType, 16> ArgTys;
23410b57cec5SDimitry Andric   QualType argT = Context->getObjCIdType();
23420b57cec5SDimitry Andric   assert(!argT.isNull() && "Can't find 'id' type");
23430b57cec5SDimitry Andric   ArgTys.push_back(argT);
23440b57cec5SDimitry Andric   argT = Context->getObjCSelType();
23450b57cec5SDimitry Andric   assert(!argT.isNull() && "Can't find 'SEL' type");
23460b57cec5SDimitry Andric   ArgTys.push_back(argT);
23470b57cec5SDimitry Andric   QualType msgSendType = getSimpleFunctionType(Context->getObjCIdType(),
23480b57cec5SDimitry Andric                                                ArgTys, /*variadic=*/true);
23490b57cec5SDimitry Andric   MsgSendFunctionDecl = FunctionDecl::Create(*Context, TUDecl,
23500b57cec5SDimitry Andric                                              SourceLocation(),
23510b57cec5SDimitry Andric                                              SourceLocation(),
23520b57cec5SDimitry Andric                                              msgSendIdent, msgSendType,
23530b57cec5SDimitry Andric                                              nullptr, SC_Extern);
23540b57cec5SDimitry Andric }
23550b57cec5SDimitry Andric 
23560b57cec5SDimitry Andric // SynthMsgSendSuperFunctionDecl - id objc_msgSendSuper(struct objc_super *, SEL op, ...);
23570b57cec5SDimitry Andric void RewriteObjC::SynthMsgSendSuperFunctionDecl() {
23580b57cec5SDimitry Andric   IdentifierInfo *msgSendIdent = &Context->Idents.get("objc_msgSendSuper");
23590b57cec5SDimitry Andric   SmallVector<QualType, 16> ArgTys;
2360*5f757f3fSDimitry Andric   RecordDecl *RD = RecordDecl::Create(*Context, TagTypeKind::Struct, TUDecl,
23610b57cec5SDimitry Andric                                       SourceLocation(), SourceLocation(),
23620b57cec5SDimitry Andric                                       &Context->Idents.get("objc_super"));
23630b57cec5SDimitry Andric   QualType argT = Context->getPointerType(Context->getTagDeclType(RD));
23640b57cec5SDimitry Andric   assert(!argT.isNull() && "Can't build 'struct objc_super *' type");
23650b57cec5SDimitry Andric   ArgTys.push_back(argT);
23660b57cec5SDimitry Andric   argT = Context->getObjCSelType();
23670b57cec5SDimitry Andric   assert(!argT.isNull() && "Can't find 'SEL' type");
23680b57cec5SDimitry Andric   ArgTys.push_back(argT);
23690b57cec5SDimitry Andric   QualType msgSendType = getSimpleFunctionType(Context->getObjCIdType(),
23700b57cec5SDimitry Andric                                                ArgTys, /*variadic=*/true);
23710b57cec5SDimitry Andric   MsgSendSuperFunctionDecl = FunctionDecl::Create(*Context, TUDecl,
23720b57cec5SDimitry Andric                                                   SourceLocation(),
23730b57cec5SDimitry Andric                                                   SourceLocation(),
23740b57cec5SDimitry Andric                                                   msgSendIdent, msgSendType,
23750b57cec5SDimitry Andric                                                   nullptr, SC_Extern);
23760b57cec5SDimitry Andric }
23770b57cec5SDimitry Andric 
23780b57cec5SDimitry Andric // SynthMsgSendStretFunctionDecl - id objc_msgSend_stret(id self, SEL op, ...);
23790b57cec5SDimitry Andric void RewriteObjC::SynthMsgSendStretFunctionDecl() {
23800b57cec5SDimitry Andric   IdentifierInfo *msgSendIdent = &Context->Idents.get("objc_msgSend_stret");
23810b57cec5SDimitry Andric   SmallVector<QualType, 16> ArgTys;
23820b57cec5SDimitry Andric   QualType argT = Context->getObjCIdType();
23830b57cec5SDimitry Andric   assert(!argT.isNull() && "Can't find 'id' type");
23840b57cec5SDimitry Andric   ArgTys.push_back(argT);
23850b57cec5SDimitry Andric   argT = Context->getObjCSelType();
23860b57cec5SDimitry Andric   assert(!argT.isNull() && "Can't find 'SEL' type");
23870b57cec5SDimitry Andric   ArgTys.push_back(argT);
23880b57cec5SDimitry Andric   QualType msgSendType = getSimpleFunctionType(Context->getObjCIdType(),
23890b57cec5SDimitry Andric                                                ArgTys, /*variadic=*/true);
23900b57cec5SDimitry Andric   MsgSendStretFunctionDecl = FunctionDecl::Create(*Context, TUDecl,
23910b57cec5SDimitry Andric                                                   SourceLocation(),
23920b57cec5SDimitry Andric                                                   SourceLocation(),
23930b57cec5SDimitry Andric                                                   msgSendIdent, msgSendType,
23940b57cec5SDimitry Andric                                                   nullptr, SC_Extern);
23950b57cec5SDimitry Andric }
23960b57cec5SDimitry Andric 
23970b57cec5SDimitry Andric // SynthMsgSendSuperStretFunctionDecl -
23980b57cec5SDimitry Andric // id objc_msgSendSuper_stret(struct objc_super *, SEL op, ...);
23990b57cec5SDimitry Andric void RewriteObjC::SynthMsgSendSuperStretFunctionDecl() {
24000b57cec5SDimitry Andric   IdentifierInfo *msgSendIdent =
24010b57cec5SDimitry Andric     &Context->Idents.get("objc_msgSendSuper_stret");
24020b57cec5SDimitry Andric   SmallVector<QualType, 16> ArgTys;
2403*5f757f3fSDimitry Andric   RecordDecl *RD = RecordDecl::Create(*Context, TagTypeKind::Struct, TUDecl,
24040b57cec5SDimitry Andric                                       SourceLocation(), SourceLocation(),
24050b57cec5SDimitry Andric                                       &Context->Idents.get("objc_super"));
24060b57cec5SDimitry Andric   QualType argT = Context->getPointerType(Context->getTagDeclType(RD));
24070b57cec5SDimitry Andric   assert(!argT.isNull() && "Can't build 'struct objc_super *' type");
24080b57cec5SDimitry Andric   ArgTys.push_back(argT);
24090b57cec5SDimitry Andric   argT = Context->getObjCSelType();
24100b57cec5SDimitry Andric   assert(!argT.isNull() && "Can't find 'SEL' type");
24110b57cec5SDimitry Andric   ArgTys.push_back(argT);
24120b57cec5SDimitry Andric   QualType msgSendType = getSimpleFunctionType(Context->getObjCIdType(),
24130b57cec5SDimitry Andric                                                ArgTys, /*variadic=*/true);
24140b57cec5SDimitry Andric   MsgSendSuperStretFunctionDecl = FunctionDecl::Create(*Context, TUDecl,
24150b57cec5SDimitry Andric                                                        SourceLocation(),
24160b57cec5SDimitry Andric                                                        SourceLocation(),
24170b57cec5SDimitry Andric                                                        msgSendIdent,
24180b57cec5SDimitry Andric                                                        msgSendType, nullptr,
24190b57cec5SDimitry Andric                                                        SC_Extern);
24200b57cec5SDimitry Andric }
24210b57cec5SDimitry Andric 
24220b57cec5SDimitry Andric // SynthMsgSendFpretFunctionDecl - double objc_msgSend_fpret(id self, SEL op, ...);
24230b57cec5SDimitry Andric void RewriteObjC::SynthMsgSendFpretFunctionDecl() {
24240b57cec5SDimitry Andric   IdentifierInfo *msgSendIdent = &Context->Idents.get("objc_msgSend_fpret");
24250b57cec5SDimitry Andric   SmallVector<QualType, 16> ArgTys;
24260b57cec5SDimitry Andric   QualType argT = Context->getObjCIdType();
24270b57cec5SDimitry Andric   assert(!argT.isNull() && "Can't find 'id' type");
24280b57cec5SDimitry Andric   ArgTys.push_back(argT);
24290b57cec5SDimitry Andric   argT = Context->getObjCSelType();
24300b57cec5SDimitry Andric   assert(!argT.isNull() && "Can't find 'SEL' type");
24310b57cec5SDimitry Andric   ArgTys.push_back(argT);
24320b57cec5SDimitry Andric   QualType msgSendType = getSimpleFunctionType(Context->DoubleTy,
24330b57cec5SDimitry Andric                                                ArgTys, /*variadic=*/true);
24340b57cec5SDimitry Andric   MsgSendFpretFunctionDecl = FunctionDecl::Create(*Context, TUDecl,
24350b57cec5SDimitry Andric                                                   SourceLocation(),
24360b57cec5SDimitry Andric                                                   SourceLocation(),
24370b57cec5SDimitry Andric                                                   msgSendIdent, msgSendType,
24380b57cec5SDimitry Andric                                                   nullptr, SC_Extern);
24390b57cec5SDimitry Andric }
24400b57cec5SDimitry Andric 
24410b57cec5SDimitry Andric // SynthGetClassFunctionDecl - id objc_getClass(const char *name);
24420b57cec5SDimitry Andric void RewriteObjC::SynthGetClassFunctionDecl() {
24430b57cec5SDimitry Andric   IdentifierInfo *getClassIdent = &Context->Idents.get("objc_getClass");
24440b57cec5SDimitry Andric   SmallVector<QualType, 16> ArgTys;
24450b57cec5SDimitry Andric   ArgTys.push_back(Context->getPointerType(Context->CharTy.withConst()));
24460b57cec5SDimitry Andric   QualType getClassType = getSimpleFunctionType(Context->getObjCIdType(),
24470b57cec5SDimitry Andric                                                 ArgTys);
24480b57cec5SDimitry Andric   GetClassFunctionDecl = FunctionDecl::Create(*Context, TUDecl,
24490b57cec5SDimitry Andric                                               SourceLocation(),
24500b57cec5SDimitry Andric                                               SourceLocation(),
24510b57cec5SDimitry Andric                                               getClassIdent, getClassType,
24520b57cec5SDimitry Andric                                               nullptr, SC_Extern);
24530b57cec5SDimitry Andric }
24540b57cec5SDimitry Andric 
24550b57cec5SDimitry Andric // SynthGetSuperClassFunctionDecl - Class class_getSuperclass(Class cls);
24560b57cec5SDimitry Andric void RewriteObjC::SynthGetSuperClassFunctionDecl() {
24570b57cec5SDimitry Andric   IdentifierInfo *getSuperClassIdent =
24580b57cec5SDimitry Andric     &Context->Idents.get("class_getSuperclass");
24590b57cec5SDimitry Andric   SmallVector<QualType, 16> ArgTys;
24600b57cec5SDimitry Andric   ArgTys.push_back(Context->getObjCClassType());
24610b57cec5SDimitry Andric   QualType getClassType = getSimpleFunctionType(Context->getObjCClassType(),
24620b57cec5SDimitry Andric                                                 ArgTys);
24630b57cec5SDimitry Andric   GetSuperClassFunctionDecl = FunctionDecl::Create(*Context, TUDecl,
24640b57cec5SDimitry Andric                                                    SourceLocation(),
24650b57cec5SDimitry Andric                                                    SourceLocation(),
24660b57cec5SDimitry Andric                                                    getSuperClassIdent,
24670b57cec5SDimitry Andric                                                    getClassType, nullptr,
24680b57cec5SDimitry Andric                                                    SC_Extern);
24690b57cec5SDimitry Andric }
24700b57cec5SDimitry Andric 
24710b57cec5SDimitry Andric // SynthGetMetaClassFunctionDecl - id objc_getMetaClass(const char *name);
24720b57cec5SDimitry Andric void RewriteObjC::SynthGetMetaClassFunctionDecl() {
24730b57cec5SDimitry Andric   IdentifierInfo *getClassIdent = &Context->Idents.get("objc_getMetaClass");
24740b57cec5SDimitry Andric   SmallVector<QualType, 16> ArgTys;
24750b57cec5SDimitry Andric   ArgTys.push_back(Context->getPointerType(Context->CharTy.withConst()));
24760b57cec5SDimitry Andric   QualType getClassType = getSimpleFunctionType(Context->getObjCIdType(),
24770b57cec5SDimitry Andric                                                 ArgTys);
24780b57cec5SDimitry Andric   GetMetaClassFunctionDecl = FunctionDecl::Create(*Context, TUDecl,
24790b57cec5SDimitry Andric                                                   SourceLocation(),
24800b57cec5SDimitry Andric                                                   SourceLocation(),
24810b57cec5SDimitry Andric                                                   getClassIdent, getClassType,
24820b57cec5SDimitry Andric                                                   nullptr, SC_Extern);
24830b57cec5SDimitry Andric }
24840b57cec5SDimitry Andric 
24850b57cec5SDimitry Andric Stmt *RewriteObjC::RewriteObjCStringLiteral(ObjCStringLiteral *Exp) {
24860b57cec5SDimitry Andric   assert(Exp != nullptr && "Expected non-null ObjCStringLiteral");
24870b57cec5SDimitry Andric   QualType strType = getConstantStringStructType();
24880b57cec5SDimitry Andric 
24890b57cec5SDimitry Andric   std::string S = "__NSConstantStringImpl_";
24900b57cec5SDimitry Andric 
24910b57cec5SDimitry Andric   std::string tmpName = InFileName;
24920b57cec5SDimitry Andric   unsigned i;
24930b57cec5SDimitry Andric   for (i=0; i < tmpName.length(); i++) {
24940b57cec5SDimitry Andric     char c = tmpName.at(i);
24950b57cec5SDimitry Andric     // replace any non-alphanumeric characters with '_'.
24960b57cec5SDimitry Andric     if (!isAlphanumeric(c))
24970b57cec5SDimitry Andric       tmpName[i] = '_';
24980b57cec5SDimitry Andric   }
24990b57cec5SDimitry Andric   S += tmpName;
25000b57cec5SDimitry Andric   S += "_";
25010b57cec5SDimitry Andric   S += utostr(NumObjCStringLiterals++);
25020b57cec5SDimitry Andric 
25030b57cec5SDimitry Andric   Preamble += "static __NSConstantStringImpl " + S;
25040b57cec5SDimitry Andric   Preamble += " __attribute__ ((section (\"__DATA, __cfstring\"))) = {__CFConstantStringClassReference,";
25050b57cec5SDimitry Andric   Preamble += "0x000007c8,"; // utf8_str
25060b57cec5SDimitry Andric   // The pretty printer for StringLiteral handles escape characters properly.
25070b57cec5SDimitry Andric   std::string prettyBufS;
25080b57cec5SDimitry Andric   llvm::raw_string_ostream prettyBuf(prettyBufS);
25090b57cec5SDimitry Andric   Exp->getString()->printPretty(prettyBuf, nullptr, PrintingPolicy(LangOpts));
25100b57cec5SDimitry Andric   Preamble += prettyBuf.str();
25110b57cec5SDimitry Andric   Preamble += ",";
25120b57cec5SDimitry Andric   Preamble += utostr(Exp->getString()->getByteLength()) + "};\n";
25130b57cec5SDimitry Andric 
25140b57cec5SDimitry Andric   VarDecl *NewVD = VarDecl::Create(*Context, TUDecl, SourceLocation(),
25150b57cec5SDimitry Andric                                    SourceLocation(), &Context->Idents.get(S),
25160b57cec5SDimitry Andric                                    strType, nullptr, SC_Static);
25170b57cec5SDimitry Andric   DeclRefExpr *DRE = new (Context)
25180b57cec5SDimitry Andric       DeclRefExpr(*Context, NewVD, false, strType, VK_LValue, SourceLocation());
25195ffd83dbSDimitry Andric   Expr *Unop = UnaryOperator::Create(
25205ffd83dbSDimitry Andric       const_cast<ASTContext &>(*Context), DRE, UO_AddrOf,
2521fe6060f1SDimitry Andric       Context->getPointerType(DRE->getType()), VK_PRValue, OK_Ordinary,
25225ffd83dbSDimitry Andric       SourceLocation(), false, FPOptionsOverride());
25230b57cec5SDimitry Andric   // cast to NSConstantString *
25240b57cec5SDimitry Andric   CastExpr *cast = NoTypeInfoCStyleCastExpr(Context, Exp->getType(),
25250b57cec5SDimitry Andric                                             CK_CPointerToObjCPointerCast, Unop);
25260b57cec5SDimitry Andric   ReplaceStmt(Exp, cast);
25270b57cec5SDimitry Andric   // delete Exp; leak for now, see RewritePropertyOrImplicitSetter() usage for more info.
25280b57cec5SDimitry Andric   return cast;
25290b57cec5SDimitry Andric }
25300b57cec5SDimitry Andric 
25310b57cec5SDimitry Andric // struct objc_super { struct objc_object *receiver; struct objc_class *super; };
25320b57cec5SDimitry Andric QualType RewriteObjC::getSuperStructType() {
25330b57cec5SDimitry Andric   if (!SuperStructDecl) {
2534*5f757f3fSDimitry Andric     SuperStructDecl = RecordDecl::Create(*Context, TagTypeKind::Struct, TUDecl,
25350b57cec5SDimitry Andric                                          SourceLocation(), SourceLocation(),
25360b57cec5SDimitry Andric                                          &Context->Idents.get("objc_super"));
25370b57cec5SDimitry Andric     QualType FieldTypes[2];
25380b57cec5SDimitry Andric 
25390b57cec5SDimitry Andric     // struct objc_object *receiver;
25400b57cec5SDimitry Andric     FieldTypes[0] = Context->getObjCIdType();
25410b57cec5SDimitry Andric     // struct objc_class *super;
25420b57cec5SDimitry Andric     FieldTypes[1] = Context->getObjCClassType();
25430b57cec5SDimitry Andric 
25440b57cec5SDimitry Andric     // Create fields
25450b57cec5SDimitry Andric     for (unsigned i = 0; i < 2; ++i) {
25460b57cec5SDimitry Andric       SuperStructDecl->addDecl(FieldDecl::Create(*Context, SuperStructDecl,
25470b57cec5SDimitry Andric                                                  SourceLocation(),
25480b57cec5SDimitry Andric                                                  SourceLocation(), nullptr,
25490b57cec5SDimitry Andric                                                  FieldTypes[i], nullptr,
25500b57cec5SDimitry Andric                                                  /*BitWidth=*/nullptr,
25510b57cec5SDimitry Andric                                                  /*Mutable=*/false,
25520b57cec5SDimitry Andric                                                  ICIS_NoInit));
25530b57cec5SDimitry Andric     }
25540b57cec5SDimitry Andric 
25550b57cec5SDimitry Andric     SuperStructDecl->completeDefinition();
25560b57cec5SDimitry Andric   }
25570b57cec5SDimitry Andric   return Context->getTagDeclType(SuperStructDecl);
25580b57cec5SDimitry Andric }
25590b57cec5SDimitry Andric 
25600b57cec5SDimitry Andric QualType RewriteObjC::getConstantStringStructType() {
25610b57cec5SDimitry Andric   if (!ConstantStringDecl) {
2562*5f757f3fSDimitry Andric     ConstantStringDecl = RecordDecl::Create(
2563*5f757f3fSDimitry Andric         *Context, TagTypeKind::Struct, TUDecl, SourceLocation(),
2564*5f757f3fSDimitry Andric         SourceLocation(), &Context->Idents.get("__NSConstantStringImpl"));
25650b57cec5SDimitry Andric     QualType FieldTypes[4];
25660b57cec5SDimitry Andric 
25670b57cec5SDimitry Andric     // struct objc_object *receiver;
25680b57cec5SDimitry Andric     FieldTypes[0] = Context->getObjCIdType();
25690b57cec5SDimitry Andric     // int flags;
25700b57cec5SDimitry Andric     FieldTypes[1] = Context->IntTy;
25710b57cec5SDimitry Andric     // char *str;
25720b57cec5SDimitry Andric     FieldTypes[2] = Context->getPointerType(Context->CharTy);
25730b57cec5SDimitry Andric     // long length;
25740b57cec5SDimitry Andric     FieldTypes[3] = Context->LongTy;
25750b57cec5SDimitry Andric 
25760b57cec5SDimitry Andric     // Create fields
25770b57cec5SDimitry Andric     for (unsigned i = 0; i < 4; ++i) {
25780b57cec5SDimitry Andric       ConstantStringDecl->addDecl(FieldDecl::Create(*Context,
25790b57cec5SDimitry Andric                                                     ConstantStringDecl,
25800b57cec5SDimitry Andric                                                     SourceLocation(),
25810b57cec5SDimitry Andric                                                     SourceLocation(), nullptr,
25820b57cec5SDimitry Andric                                                     FieldTypes[i], nullptr,
25830b57cec5SDimitry Andric                                                     /*BitWidth=*/nullptr,
25840b57cec5SDimitry Andric                                                     /*Mutable=*/true,
25850b57cec5SDimitry Andric                                                     ICIS_NoInit));
25860b57cec5SDimitry Andric     }
25870b57cec5SDimitry Andric 
25880b57cec5SDimitry Andric     ConstantStringDecl->completeDefinition();
25890b57cec5SDimitry Andric   }
25900b57cec5SDimitry Andric   return Context->getTagDeclType(ConstantStringDecl);
25910b57cec5SDimitry Andric }
25920b57cec5SDimitry Andric 
25930b57cec5SDimitry Andric CallExpr *RewriteObjC::SynthMsgSendStretCallExpr(FunctionDecl *MsgSendStretFlavor,
25940b57cec5SDimitry Andric                                                 QualType msgSendType,
25950b57cec5SDimitry Andric                                                 QualType returnType,
25960b57cec5SDimitry Andric                                                 SmallVectorImpl<QualType> &ArgTypes,
25970b57cec5SDimitry Andric                                                 SmallVectorImpl<Expr*> &MsgExprs,
25980b57cec5SDimitry Andric                                                 ObjCMethodDecl *Method) {
25990b57cec5SDimitry Andric   // Create a reference to the objc_msgSend_stret() declaration.
26000b57cec5SDimitry Andric   DeclRefExpr *STDRE =
26010b57cec5SDimitry Andric       new (Context) DeclRefExpr(*Context, MsgSendStretFlavor, false,
26020b57cec5SDimitry Andric                                 msgSendType, VK_LValue, SourceLocation());
26030b57cec5SDimitry Andric   // Need to cast objc_msgSend_stret to "void *" (see above comment).
26040b57cec5SDimitry Andric   CastExpr *cast = NoTypeInfoCStyleCastExpr(Context,
26050b57cec5SDimitry Andric                                   Context->getPointerType(Context->VoidTy),
26060b57cec5SDimitry Andric                                   CK_BitCast, STDRE);
26070b57cec5SDimitry Andric   // Now do the "normal" pointer to function cast.
26080b57cec5SDimitry Andric   QualType castType = getSimpleFunctionType(returnType, ArgTypes,
26090b57cec5SDimitry Andric                                             Method ? Method->isVariadic()
26100b57cec5SDimitry Andric                                                    : false);
26110b57cec5SDimitry Andric   castType = Context->getPointerType(castType);
26120b57cec5SDimitry Andric   cast = NoTypeInfoCStyleCastExpr(Context, castType, CK_BitCast,
26130b57cec5SDimitry Andric                                             cast);
26140b57cec5SDimitry Andric 
26150b57cec5SDimitry Andric   // Don't forget the parens to enforce the proper binding.
26160b57cec5SDimitry Andric   ParenExpr *PE = new (Context) ParenExpr(SourceLocation(), SourceLocation(), cast);
26170b57cec5SDimitry Andric 
2618a7dea167SDimitry Andric   const auto *FT = msgSendType->castAs<FunctionType>();
2619e8d8bef9SDimitry Andric   CallExpr *STCE =
2620fe6060f1SDimitry Andric       CallExpr::Create(*Context, PE, MsgExprs, FT->getReturnType(), VK_PRValue,
2621e8d8bef9SDimitry Andric                        SourceLocation(), FPOptionsOverride());
26220b57cec5SDimitry Andric   return STCE;
26230b57cec5SDimitry Andric }
26240b57cec5SDimitry Andric 
26250b57cec5SDimitry Andric Stmt *RewriteObjC::SynthMessageExpr(ObjCMessageExpr *Exp,
26260b57cec5SDimitry Andric                                     SourceLocation StartLoc,
26270b57cec5SDimitry Andric                                     SourceLocation EndLoc) {
26280b57cec5SDimitry Andric   if (!SelGetUidFunctionDecl)
26290b57cec5SDimitry Andric     SynthSelGetUidFunctionDecl();
26300b57cec5SDimitry Andric   if (!MsgSendFunctionDecl)
26310b57cec5SDimitry Andric     SynthMsgSendFunctionDecl();
26320b57cec5SDimitry Andric   if (!MsgSendSuperFunctionDecl)
26330b57cec5SDimitry Andric     SynthMsgSendSuperFunctionDecl();
26340b57cec5SDimitry Andric   if (!MsgSendStretFunctionDecl)
26350b57cec5SDimitry Andric     SynthMsgSendStretFunctionDecl();
26360b57cec5SDimitry Andric   if (!MsgSendSuperStretFunctionDecl)
26370b57cec5SDimitry Andric     SynthMsgSendSuperStretFunctionDecl();
26380b57cec5SDimitry Andric   if (!MsgSendFpretFunctionDecl)
26390b57cec5SDimitry Andric     SynthMsgSendFpretFunctionDecl();
26400b57cec5SDimitry Andric   if (!GetClassFunctionDecl)
26410b57cec5SDimitry Andric     SynthGetClassFunctionDecl();
26420b57cec5SDimitry Andric   if (!GetSuperClassFunctionDecl)
26430b57cec5SDimitry Andric     SynthGetSuperClassFunctionDecl();
26440b57cec5SDimitry Andric   if (!GetMetaClassFunctionDecl)
26450b57cec5SDimitry Andric     SynthGetMetaClassFunctionDecl();
26460b57cec5SDimitry Andric 
26470b57cec5SDimitry Andric   // default to objc_msgSend().
26480b57cec5SDimitry Andric   FunctionDecl *MsgSendFlavor = MsgSendFunctionDecl;
26490b57cec5SDimitry Andric   // May need to use objc_msgSend_stret() as well.
26500b57cec5SDimitry Andric   FunctionDecl *MsgSendStretFlavor = nullptr;
26510b57cec5SDimitry Andric   if (ObjCMethodDecl *mDecl = Exp->getMethodDecl()) {
26520b57cec5SDimitry Andric     QualType resultType = mDecl->getReturnType();
26530b57cec5SDimitry Andric     if (resultType->isRecordType())
26540b57cec5SDimitry Andric       MsgSendStretFlavor = MsgSendStretFunctionDecl;
26550b57cec5SDimitry Andric     else if (resultType->isRealFloatingType())
26560b57cec5SDimitry Andric       MsgSendFlavor = MsgSendFpretFunctionDecl;
26570b57cec5SDimitry Andric   }
26580b57cec5SDimitry Andric 
26590b57cec5SDimitry Andric   // Synthesize a call to objc_msgSend().
26600b57cec5SDimitry Andric   SmallVector<Expr*, 8> MsgExprs;
26610b57cec5SDimitry Andric   switch (Exp->getReceiverKind()) {
26620b57cec5SDimitry Andric   case ObjCMessageExpr::SuperClass: {
26630b57cec5SDimitry Andric     MsgSendFlavor = MsgSendSuperFunctionDecl;
26640b57cec5SDimitry Andric     if (MsgSendStretFlavor)
26650b57cec5SDimitry Andric       MsgSendStretFlavor = MsgSendSuperStretFunctionDecl;
26660b57cec5SDimitry Andric     assert(MsgSendFlavor && "MsgSendFlavor is NULL!");
26670b57cec5SDimitry Andric 
26680b57cec5SDimitry Andric     ObjCInterfaceDecl *ClassDecl = CurMethodDef->getClassInterface();
26690b57cec5SDimitry Andric 
26700b57cec5SDimitry Andric     SmallVector<Expr*, 4> InitExprs;
26710b57cec5SDimitry Andric 
26720b57cec5SDimitry Andric     // set the receiver to self, the first argument to all methods.
2673fe6060f1SDimitry Andric     InitExprs.push_back(NoTypeInfoCStyleCastExpr(
2674fe6060f1SDimitry Andric         Context, Context->getObjCIdType(), CK_BitCast,
2675fe6060f1SDimitry Andric         new (Context) DeclRefExpr(*Context, CurMethodDef->getSelfDecl(), false,
2676fe6060f1SDimitry Andric                                   Context->getObjCIdType(), VK_PRValue,
2677fe6060f1SDimitry Andric                                   SourceLocation()))); // set the 'receiver'.
26780b57cec5SDimitry Andric 
26790b57cec5SDimitry Andric     // (id)class_getSuperclass((Class)objc_getClass("CurrentClass"))
26800b57cec5SDimitry Andric     SmallVector<Expr*, 8> ClsExprs;
26810b57cec5SDimitry Andric     ClsExprs.push_back(getStringLiteral(ClassDecl->getIdentifier()->getName()));
26820b57cec5SDimitry Andric     CallExpr *Cls = SynthesizeCallToFunctionDecl(GetMetaClassFunctionDecl,
26830b57cec5SDimitry Andric                                                  ClsExprs, StartLoc, EndLoc);
26840b57cec5SDimitry Andric     // (Class)objc_getClass("CurrentClass")
26850b57cec5SDimitry Andric     CastExpr *ArgExpr = NoTypeInfoCStyleCastExpr(Context,
26860b57cec5SDimitry Andric                                              Context->getObjCClassType(),
26870b57cec5SDimitry Andric                                              CK_BitCast, Cls);
26880b57cec5SDimitry Andric     ClsExprs.clear();
26890b57cec5SDimitry Andric     ClsExprs.push_back(ArgExpr);
26900b57cec5SDimitry Andric     Cls = SynthesizeCallToFunctionDecl(GetSuperClassFunctionDecl, ClsExprs,
26910b57cec5SDimitry Andric                                        StartLoc, EndLoc);
26920b57cec5SDimitry Andric     // (id)class_getSuperclass((Class)objc_getClass("CurrentClass"))
26930b57cec5SDimitry Andric     // To turn off a warning, type-cast to 'id'
26940b57cec5SDimitry Andric     InitExprs.push_back( // set 'super class', using class_getSuperclass().
26950b57cec5SDimitry Andric                         NoTypeInfoCStyleCastExpr(Context,
26960b57cec5SDimitry Andric                                                  Context->getObjCIdType(),
26970b57cec5SDimitry Andric                                                  CK_BitCast, Cls));
26980b57cec5SDimitry Andric     // struct objc_super
26990b57cec5SDimitry Andric     QualType superType = getSuperStructType();
27000b57cec5SDimitry Andric     Expr *SuperRep;
27010b57cec5SDimitry Andric 
27020b57cec5SDimitry Andric     if (LangOpts.MicrosoftExt) {
27030b57cec5SDimitry Andric       SynthSuperConstructorFunctionDecl();
27040b57cec5SDimitry Andric       // Simulate a constructor call...
27050b57cec5SDimitry Andric       DeclRefExpr *DRE = new (Context)
27060b57cec5SDimitry Andric           DeclRefExpr(*Context, SuperConstructorFunctionDecl, false, superType,
27070b57cec5SDimitry Andric                       VK_LValue, SourceLocation());
2708e8d8bef9SDimitry Andric       SuperRep =
2709e8d8bef9SDimitry Andric           CallExpr::Create(*Context, DRE, InitExprs, superType, VK_LValue,
2710e8d8bef9SDimitry Andric                            SourceLocation(), FPOptionsOverride());
27110b57cec5SDimitry Andric       // The code for super is a little tricky to prevent collision with
27120b57cec5SDimitry Andric       // the structure definition in the header. The rewriter has it's own
27130b57cec5SDimitry Andric       // internal definition (__rw_objc_super) that is uses. This is why
27140b57cec5SDimitry Andric       // we need the cast below. For example:
27150b57cec5SDimitry Andric       // (struct objc_super *)&__rw_objc_super((id)self, (id)objc_getClass("SUPER"))
27160b57cec5SDimitry Andric       //
27175ffd83dbSDimitry Andric       SuperRep = UnaryOperator::Create(
27185ffd83dbSDimitry Andric           const_cast<ASTContext &>(*Context), SuperRep, UO_AddrOf,
2719fe6060f1SDimitry Andric           Context->getPointerType(SuperRep->getType()), VK_PRValue, OK_Ordinary,
27205ffd83dbSDimitry Andric           SourceLocation(), false, FPOptionsOverride());
27210b57cec5SDimitry Andric       SuperRep = NoTypeInfoCStyleCastExpr(Context,
27220b57cec5SDimitry Andric                                           Context->getPointerType(superType),
27230b57cec5SDimitry Andric                                           CK_BitCast, SuperRep);
27240b57cec5SDimitry Andric     } else {
27250b57cec5SDimitry Andric       // (struct objc_super) { <exprs from above> }
27260b57cec5SDimitry Andric       InitListExpr *ILE =
27270b57cec5SDimitry Andric         new (Context) InitListExpr(*Context, SourceLocation(), InitExprs,
27280b57cec5SDimitry Andric                                    SourceLocation());
27290b57cec5SDimitry Andric       TypeSourceInfo *superTInfo
27300b57cec5SDimitry Andric         = Context->getTrivialTypeSourceInfo(superType);
27310b57cec5SDimitry Andric       SuperRep = new (Context) CompoundLiteralExpr(SourceLocation(), superTInfo,
27320b57cec5SDimitry Andric                                                    superType, VK_LValue,
27330b57cec5SDimitry Andric                                                    ILE, false);
27340b57cec5SDimitry Andric       // struct objc_super *
27355ffd83dbSDimitry Andric       SuperRep = UnaryOperator::Create(
27365ffd83dbSDimitry Andric           const_cast<ASTContext &>(*Context), SuperRep, UO_AddrOf,
2737fe6060f1SDimitry Andric           Context->getPointerType(SuperRep->getType()), VK_PRValue, OK_Ordinary,
27385ffd83dbSDimitry Andric           SourceLocation(), false, FPOptionsOverride());
27390b57cec5SDimitry Andric     }
27400b57cec5SDimitry Andric     MsgExprs.push_back(SuperRep);
27410b57cec5SDimitry Andric     break;
27420b57cec5SDimitry Andric   }
27430b57cec5SDimitry Andric 
27440b57cec5SDimitry Andric   case ObjCMessageExpr::Class: {
27450b57cec5SDimitry Andric     SmallVector<Expr*, 8> ClsExprs;
2746a7dea167SDimitry Andric     auto *Class =
2747a7dea167SDimitry Andric         Exp->getClassReceiver()->castAs<ObjCObjectType>()->getInterface();
27480b57cec5SDimitry Andric     IdentifierInfo *clsName = Class->getIdentifier();
27490b57cec5SDimitry Andric     ClsExprs.push_back(getStringLiteral(clsName->getName()));
27500b57cec5SDimitry Andric     CallExpr *Cls = SynthesizeCallToFunctionDecl(GetClassFunctionDecl, ClsExprs,
27510b57cec5SDimitry Andric                                                  StartLoc, EndLoc);
27520b57cec5SDimitry Andric     MsgExprs.push_back(Cls);
27530b57cec5SDimitry Andric     break;
27540b57cec5SDimitry Andric   }
27550b57cec5SDimitry Andric 
27560b57cec5SDimitry Andric   case ObjCMessageExpr::SuperInstance:{
27570b57cec5SDimitry Andric     MsgSendFlavor = MsgSendSuperFunctionDecl;
27580b57cec5SDimitry Andric     if (MsgSendStretFlavor)
27590b57cec5SDimitry Andric       MsgSendStretFlavor = MsgSendSuperStretFunctionDecl;
27600b57cec5SDimitry Andric     assert(MsgSendFlavor && "MsgSendFlavor is NULL!");
27610b57cec5SDimitry Andric     ObjCInterfaceDecl *ClassDecl = CurMethodDef->getClassInterface();
27620b57cec5SDimitry Andric     SmallVector<Expr*, 4> InitExprs;
27630b57cec5SDimitry Andric 
2764fe6060f1SDimitry Andric     InitExprs.push_back(NoTypeInfoCStyleCastExpr(
2765fe6060f1SDimitry Andric         Context, Context->getObjCIdType(), CK_BitCast,
2766fe6060f1SDimitry Andric         new (Context) DeclRefExpr(*Context, CurMethodDef->getSelfDecl(), false,
2767fe6060f1SDimitry Andric                                   Context->getObjCIdType(), VK_PRValue,
2768fe6060f1SDimitry Andric                                   SourceLocation()))); // set the 'receiver'.
27690b57cec5SDimitry Andric 
27700b57cec5SDimitry Andric     // (id)class_getSuperclass((Class)objc_getClass("CurrentClass"))
27710b57cec5SDimitry Andric     SmallVector<Expr*, 8> ClsExprs;
27720b57cec5SDimitry Andric     ClsExprs.push_back(getStringLiteral(ClassDecl->getIdentifier()->getName()));
27730b57cec5SDimitry Andric     CallExpr *Cls = SynthesizeCallToFunctionDecl(GetClassFunctionDecl, ClsExprs,
27740b57cec5SDimitry Andric                                                  StartLoc, EndLoc);
27750b57cec5SDimitry Andric     // (Class)objc_getClass("CurrentClass")
27760b57cec5SDimitry Andric     CastExpr *ArgExpr = NoTypeInfoCStyleCastExpr(Context,
27770b57cec5SDimitry Andric                                                  Context->getObjCClassType(),
27780b57cec5SDimitry Andric                                                  CK_BitCast, Cls);
27790b57cec5SDimitry Andric     ClsExprs.clear();
27800b57cec5SDimitry Andric     ClsExprs.push_back(ArgExpr);
27810b57cec5SDimitry Andric     Cls = SynthesizeCallToFunctionDecl(GetSuperClassFunctionDecl, ClsExprs,
27820b57cec5SDimitry Andric                                        StartLoc, EndLoc);
27830b57cec5SDimitry Andric 
27840b57cec5SDimitry Andric     // (id)class_getSuperclass((Class)objc_getClass("CurrentClass"))
27850b57cec5SDimitry Andric     // To turn off a warning, type-cast to 'id'
27860b57cec5SDimitry Andric     InitExprs.push_back(
27870b57cec5SDimitry Andric       // set 'super class', using class_getSuperclass().
27880b57cec5SDimitry Andric       NoTypeInfoCStyleCastExpr(Context, Context->getObjCIdType(),
27890b57cec5SDimitry Andric                                CK_BitCast, Cls));
27900b57cec5SDimitry Andric     // struct objc_super
27910b57cec5SDimitry Andric     QualType superType = getSuperStructType();
27920b57cec5SDimitry Andric     Expr *SuperRep;
27930b57cec5SDimitry Andric 
27940b57cec5SDimitry Andric     if (LangOpts.MicrosoftExt) {
27950b57cec5SDimitry Andric       SynthSuperConstructorFunctionDecl();
27960b57cec5SDimitry Andric       // Simulate a constructor call...
27970b57cec5SDimitry Andric       DeclRefExpr *DRE = new (Context)
27980b57cec5SDimitry Andric           DeclRefExpr(*Context, SuperConstructorFunctionDecl, false, superType,
27990b57cec5SDimitry Andric                       VK_LValue, SourceLocation());
2800e8d8bef9SDimitry Andric       SuperRep =
2801e8d8bef9SDimitry Andric           CallExpr::Create(*Context, DRE, InitExprs, superType, VK_LValue,
2802e8d8bef9SDimitry Andric                            SourceLocation(), FPOptionsOverride());
28030b57cec5SDimitry Andric       // The code for super is a little tricky to prevent collision with
28040b57cec5SDimitry Andric       // the structure definition in the header. The rewriter has it's own
28050b57cec5SDimitry Andric       // internal definition (__rw_objc_super) that is uses. This is why
28060b57cec5SDimitry Andric       // we need the cast below. For example:
28070b57cec5SDimitry Andric       // (struct objc_super *)&__rw_objc_super((id)self, (id)objc_getClass("SUPER"))
28080b57cec5SDimitry Andric       //
28095ffd83dbSDimitry Andric       SuperRep = UnaryOperator::Create(
28105ffd83dbSDimitry Andric           const_cast<ASTContext &>(*Context), SuperRep, UO_AddrOf,
2811fe6060f1SDimitry Andric           Context->getPointerType(SuperRep->getType()), VK_PRValue, OK_Ordinary,
28125ffd83dbSDimitry Andric           SourceLocation(), false, FPOptionsOverride());
28130b57cec5SDimitry Andric       SuperRep = NoTypeInfoCStyleCastExpr(Context,
28140b57cec5SDimitry Andric                                Context->getPointerType(superType),
28150b57cec5SDimitry Andric                                CK_BitCast, SuperRep);
28160b57cec5SDimitry Andric     } else {
28170b57cec5SDimitry Andric       // (struct objc_super) { <exprs from above> }
28180b57cec5SDimitry Andric       InitListExpr *ILE =
28190b57cec5SDimitry Andric         new (Context) InitListExpr(*Context, SourceLocation(), InitExprs,
28200b57cec5SDimitry Andric                                    SourceLocation());
28210b57cec5SDimitry Andric       TypeSourceInfo *superTInfo
28220b57cec5SDimitry Andric         = Context->getTrivialTypeSourceInfo(superType);
2823fe6060f1SDimitry Andric       SuperRep = new (Context) CompoundLiteralExpr(
2824fe6060f1SDimitry Andric           SourceLocation(), superTInfo, superType, VK_PRValue, ILE, false);
28250b57cec5SDimitry Andric     }
28260b57cec5SDimitry Andric     MsgExprs.push_back(SuperRep);
28270b57cec5SDimitry Andric     break;
28280b57cec5SDimitry Andric   }
28290b57cec5SDimitry Andric 
28300b57cec5SDimitry Andric   case ObjCMessageExpr::Instance: {
28310b57cec5SDimitry Andric     // Remove all type-casts because it may contain objc-style types; e.g.
28320b57cec5SDimitry Andric     // Foo<Proto> *.
28330b57cec5SDimitry Andric     Expr *recExpr = Exp->getInstanceReceiver();
28340b57cec5SDimitry Andric     while (CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(recExpr))
28350b57cec5SDimitry Andric       recExpr = CE->getSubExpr();
28360b57cec5SDimitry Andric     CastKind CK = recExpr->getType()->isObjCObjectPointerType()
28370b57cec5SDimitry Andric                     ? CK_BitCast : recExpr->getType()->isBlockPointerType()
28380b57cec5SDimitry Andric                                      ? CK_BlockPointerToObjCPointerCast
28390b57cec5SDimitry Andric                                      : CK_CPointerToObjCPointerCast;
28400b57cec5SDimitry Andric 
28410b57cec5SDimitry Andric     recExpr = NoTypeInfoCStyleCastExpr(Context, Context->getObjCIdType(),
28420b57cec5SDimitry Andric                                        CK, recExpr);
28430b57cec5SDimitry Andric     MsgExprs.push_back(recExpr);
28440b57cec5SDimitry Andric     break;
28450b57cec5SDimitry Andric   }
28460b57cec5SDimitry Andric   }
28470b57cec5SDimitry Andric 
28480b57cec5SDimitry Andric   // Create a call to sel_registerName("selName"), it will be the 2nd argument.
28490b57cec5SDimitry Andric   SmallVector<Expr*, 8> SelExprs;
28500b57cec5SDimitry Andric   SelExprs.push_back(getStringLiteral(Exp->getSelector().getAsString()));
28510b57cec5SDimitry Andric   CallExpr *SelExp = SynthesizeCallToFunctionDecl(SelGetUidFunctionDecl,
28520b57cec5SDimitry Andric                                                   SelExprs, StartLoc, EndLoc);
28530b57cec5SDimitry Andric   MsgExprs.push_back(SelExp);
28540b57cec5SDimitry Andric 
28550b57cec5SDimitry Andric   // Now push any user supplied arguments.
28560b57cec5SDimitry Andric   for (unsigned i = 0; i < Exp->getNumArgs(); i++) {
28570b57cec5SDimitry Andric     Expr *userExpr = Exp->getArg(i);
28580b57cec5SDimitry Andric     // Make all implicit casts explicit...ICE comes in handy:-)
28590b57cec5SDimitry Andric     if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(userExpr)) {
28600b57cec5SDimitry Andric       // Reuse the ICE type, it is exactly what the doctor ordered.
28610b57cec5SDimitry Andric       QualType type = ICE->getType();
28620b57cec5SDimitry Andric       if (needToScanForQualifiers(type))
28630b57cec5SDimitry Andric         type = Context->getObjCIdType();
28640b57cec5SDimitry Andric       // Make sure we convert "type (^)(...)" to "type (*)(...)".
28650b57cec5SDimitry Andric       (void)convertBlockPointerToFunctionPointer(type);
28660b57cec5SDimitry Andric       const Expr *SubExpr = ICE->IgnoreParenImpCasts();
28670b57cec5SDimitry Andric       CastKind CK;
28680b57cec5SDimitry Andric       if (SubExpr->getType()->isIntegralType(*Context) &&
28690b57cec5SDimitry Andric           type->isBooleanType()) {
28700b57cec5SDimitry Andric         CK = CK_IntegralToBoolean;
28710b57cec5SDimitry Andric       } else if (type->isObjCObjectPointerType()) {
28720b57cec5SDimitry Andric         if (SubExpr->getType()->isBlockPointerType()) {
28730b57cec5SDimitry Andric           CK = CK_BlockPointerToObjCPointerCast;
28740b57cec5SDimitry Andric         } else if (SubExpr->getType()->isPointerType()) {
28750b57cec5SDimitry Andric           CK = CK_CPointerToObjCPointerCast;
28760b57cec5SDimitry Andric         } else {
28770b57cec5SDimitry Andric           CK = CK_BitCast;
28780b57cec5SDimitry Andric         }
28790b57cec5SDimitry Andric       } else {
28800b57cec5SDimitry Andric         CK = CK_BitCast;
28810b57cec5SDimitry Andric       }
28820b57cec5SDimitry Andric 
28830b57cec5SDimitry Andric       userExpr = NoTypeInfoCStyleCastExpr(Context, type, CK, userExpr);
28840b57cec5SDimitry Andric     }
28850b57cec5SDimitry Andric     // Make id<P...> cast into an 'id' cast.
28860b57cec5SDimitry Andric     else if (CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(userExpr)) {
28870b57cec5SDimitry Andric       if (CE->getType()->isObjCQualifiedIdType()) {
28880b57cec5SDimitry Andric         while ((CE = dyn_cast<CStyleCastExpr>(userExpr)))
28890b57cec5SDimitry Andric           userExpr = CE->getSubExpr();
28900b57cec5SDimitry Andric         CastKind CK;
28910b57cec5SDimitry Andric         if (userExpr->getType()->isIntegralType(*Context)) {
28920b57cec5SDimitry Andric           CK = CK_IntegralToPointer;
28930b57cec5SDimitry Andric         } else if (userExpr->getType()->isBlockPointerType()) {
28940b57cec5SDimitry Andric           CK = CK_BlockPointerToObjCPointerCast;
28950b57cec5SDimitry Andric         } else if (userExpr->getType()->isPointerType()) {
28960b57cec5SDimitry Andric           CK = CK_CPointerToObjCPointerCast;
28970b57cec5SDimitry Andric         } else {
28980b57cec5SDimitry Andric           CK = CK_BitCast;
28990b57cec5SDimitry Andric         }
29000b57cec5SDimitry Andric         userExpr = NoTypeInfoCStyleCastExpr(Context, Context->getObjCIdType(),
29010b57cec5SDimitry Andric                                             CK, userExpr);
29020b57cec5SDimitry Andric       }
29030b57cec5SDimitry Andric     }
29040b57cec5SDimitry Andric     MsgExprs.push_back(userExpr);
29050b57cec5SDimitry Andric     // We've transferred the ownership to MsgExprs. For now, we *don't* null
29060b57cec5SDimitry Andric     // out the argument in the original expression (since we aren't deleting
29070b57cec5SDimitry Andric     // the ObjCMessageExpr). See RewritePropertyOrImplicitSetter() usage for more info.
29080b57cec5SDimitry Andric     //Exp->setArg(i, 0);
29090b57cec5SDimitry Andric   }
29100b57cec5SDimitry Andric   // Generate the funky cast.
29110b57cec5SDimitry Andric   CastExpr *cast;
29120b57cec5SDimitry Andric   SmallVector<QualType, 8> ArgTypes;
29130b57cec5SDimitry Andric   QualType returnType;
29140b57cec5SDimitry Andric 
29150b57cec5SDimitry Andric   // Push 'id' and 'SEL', the 2 implicit arguments.
29160b57cec5SDimitry Andric   if (MsgSendFlavor == MsgSendSuperFunctionDecl)
29170b57cec5SDimitry Andric     ArgTypes.push_back(Context->getPointerType(getSuperStructType()));
29180b57cec5SDimitry Andric   else
29190b57cec5SDimitry Andric     ArgTypes.push_back(Context->getObjCIdType());
29200b57cec5SDimitry Andric   ArgTypes.push_back(Context->getObjCSelType());
29210b57cec5SDimitry Andric   if (ObjCMethodDecl *OMD = Exp->getMethodDecl()) {
29220b57cec5SDimitry Andric     // Push any user argument types.
29230b57cec5SDimitry Andric     for (const auto *PI : OMD->parameters()) {
29240b57cec5SDimitry Andric       QualType t = PI->getType()->isObjCQualifiedIdType()
29250b57cec5SDimitry Andric                      ? Context->getObjCIdType()
29260b57cec5SDimitry Andric                      : PI->getType();
29270b57cec5SDimitry Andric       // Make sure we convert "t (^)(...)" to "t (*)(...)".
29280b57cec5SDimitry Andric       (void)convertBlockPointerToFunctionPointer(t);
29290b57cec5SDimitry Andric       ArgTypes.push_back(t);
29300b57cec5SDimitry Andric     }
29310b57cec5SDimitry Andric     returnType = Exp->getType();
29320b57cec5SDimitry Andric     convertToUnqualifiedObjCType(returnType);
29330b57cec5SDimitry Andric     (void)convertBlockPointerToFunctionPointer(returnType);
29340b57cec5SDimitry Andric   } else {
29350b57cec5SDimitry Andric     returnType = Context->getObjCIdType();
29360b57cec5SDimitry Andric   }
29370b57cec5SDimitry Andric   // Get the type, we will need to reference it in a couple spots.
29380b57cec5SDimitry Andric   QualType msgSendType = MsgSendFlavor->getType();
29390b57cec5SDimitry Andric 
29400b57cec5SDimitry Andric   // Create a reference to the objc_msgSend() declaration.
29410b57cec5SDimitry Andric   DeclRefExpr *DRE = new (Context) DeclRefExpr(
29420b57cec5SDimitry Andric       *Context, MsgSendFlavor, false, msgSendType, VK_LValue, SourceLocation());
29430b57cec5SDimitry Andric 
29440b57cec5SDimitry Andric   // Need to cast objc_msgSend to "void *" (to workaround a GCC bandaid).
29450b57cec5SDimitry Andric   // If we don't do this cast, we get the following bizarre warning/note:
29460b57cec5SDimitry Andric   // xx.m:13: warning: function called through a non-compatible type
29470b57cec5SDimitry Andric   // xx.m:13: note: if this code is reached, the program will abort
29480b57cec5SDimitry Andric   cast = NoTypeInfoCStyleCastExpr(Context,
29490b57cec5SDimitry Andric                                   Context->getPointerType(Context->VoidTy),
29500b57cec5SDimitry Andric                                   CK_BitCast, DRE);
29510b57cec5SDimitry Andric 
29520b57cec5SDimitry Andric   // Now do the "normal" pointer to function cast.
29530b57cec5SDimitry Andric   // If we don't have a method decl, force a variadic cast.
29540b57cec5SDimitry Andric   const ObjCMethodDecl *MD = Exp->getMethodDecl();
29550b57cec5SDimitry Andric   QualType castType =
29560b57cec5SDimitry Andric     getSimpleFunctionType(returnType, ArgTypes, MD ? MD->isVariadic() : true);
29570b57cec5SDimitry Andric   castType = Context->getPointerType(castType);
29580b57cec5SDimitry Andric   cast = NoTypeInfoCStyleCastExpr(Context, castType, CK_BitCast,
29590b57cec5SDimitry Andric                                   cast);
29600b57cec5SDimitry Andric 
29610b57cec5SDimitry Andric   // Don't forget the parens to enforce the proper binding.
29620b57cec5SDimitry Andric   ParenExpr *PE = new (Context) ParenExpr(StartLoc, EndLoc, cast);
29630b57cec5SDimitry Andric 
2964a7dea167SDimitry Andric   const auto *FT = msgSendType->castAs<FunctionType>();
29650b57cec5SDimitry Andric   CallExpr *CE = CallExpr::Create(*Context, PE, MsgExprs, FT->getReturnType(),
2966fe6060f1SDimitry Andric                                   VK_PRValue, EndLoc, FPOptionsOverride());
29670b57cec5SDimitry Andric   Stmt *ReplacingStmt = CE;
29680b57cec5SDimitry Andric   if (MsgSendStretFlavor) {
29690b57cec5SDimitry Andric     // We have the method which returns a struct/union. Must also generate
29700b57cec5SDimitry Andric     // call to objc_msgSend_stret and hang both varieties on a conditional
29710b57cec5SDimitry Andric     // expression which dictate which one to envoke depending on size of
29720b57cec5SDimitry Andric     // method's return type.
29730b57cec5SDimitry Andric 
29740b57cec5SDimitry Andric     CallExpr *STCE = SynthMsgSendStretCallExpr(MsgSendStretFlavor,
29750b57cec5SDimitry Andric                                                msgSendType, returnType,
29760b57cec5SDimitry Andric                                                ArgTypes, MsgExprs,
29770b57cec5SDimitry Andric                                                Exp->getMethodDecl());
29780b57cec5SDimitry Andric 
29790b57cec5SDimitry Andric     // Build sizeof(returnType)
29800b57cec5SDimitry Andric     UnaryExprOrTypeTraitExpr *sizeofExpr =
29810b57cec5SDimitry Andric        new (Context) UnaryExprOrTypeTraitExpr(UETT_SizeOf,
29820b57cec5SDimitry Andric                                  Context->getTrivialTypeSourceInfo(returnType),
29830b57cec5SDimitry Andric                                  Context->getSizeType(), SourceLocation(),
29840b57cec5SDimitry Andric                                  SourceLocation());
29850b57cec5SDimitry Andric     // (sizeof(returnType) <= 8 ? objc_msgSend(...) : objc_msgSend_stret(...))
29860b57cec5SDimitry Andric     // FIXME: Value of 8 is base on ppc32/x86 ABI for the most common cases.
29870b57cec5SDimitry Andric     // For X86 it is more complicated and some kind of target specific routine
29880b57cec5SDimitry Andric     // is needed to decide what to do.
29890b57cec5SDimitry Andric     unsigned IntSize =
29900b57cec5SDimitry Andric       static_cast<unsigned>(Context->getTypeSize(Context->IntTy));
29910b57cec5SDimitry Andric     IntegerLiteral *limit = IntegerLiteral::Create(*Context,
29920b57cec5SDimitry Andric                                                    llvm::APInt(IntSize, 8),
29930b57cec5SDimitry Andric                                                    Context->IntTy,
29940b57cec5SDimitry Andric                                                    SourceLocation());
29955ffd83dbSDimitry Andric     BinaryOperator *lessThanExpr = BinaryOperator::Create(
2996fe6060f1SDimitry Andric         *Context, sizeofExpr, limit, BO_LE, Context->IntTy, VK_PRValue,
29975ffd83dbSDimitry Andric         OK_Ordinary, SourceLocation(), FPOptionsOverride());
29980b57cec5SDimitry Andric     // (sizeof(returnType) <= 8 ? objc_msgSend(...) : objc_msgSend_stret(...))
2999fe6060f1SDimitry Andric     ConditionalOperator *CondExpr = new (Context) ConditionalOperator(
3000fe6060f1SDimitry Andric         lessThanExpr, SourceLocation(), CE, SourceLocation(), STCE, returnType,
3001fe6060f1SDimitry Andric         VK_PRValue, OK_Ordinary);
30020b57cec5SDimitry Andric     ReplacingStmt = new (Context) ParenExpr(SourceLocation(), SourceLocation(),
30030b57cec5SDimitry Andric                                             CondExpr);
30040b57cec5SDimitry Andric   }
30050b57cec5SDimitry Andric   // delete Exp; leak for now, see RewritePropertyOrImplicitSetter() usage for more info.
30060b57cec5SDimitry Andric   return ReplacingStmt;
30070b57cec5SDimitry Andric }
30080b57cec5SDimitry Andric 
30090b57cec5SDimitry Andric Stmt *RewriteObjC::RewriteMessageExpr(ObjCMessageExpr *Exp) {
30100b57cec5SDimitry Andric   Stmt *ReplacingStmt =
30110b57cec5SDimitry Andric       SynthMessageExpr(Exp, Exp->getBeginLoc(), Exp->getEndLoc());
30120b57cec5SDimitry Andric 
30130b57cec5SDimitry Andric   // Now do the actual rewrite.
30140b57cec5SDimitry Andric   ReplaceStmt(Exp, ReplacingStmt);
30150b57cec5SDimitry Andric 
30160b57cec5SDimitry Andric   // delete Exp; leak for now, see RewritePropertyOrImplicitSetter() usage for more info.
30170b57cec5SDimitry Andric   return ReplacingStmt;
30180b57cec5SDimitry Andric }
30190b57cec5SDimitry Andric 
30200b57cec5SDimitry Andric // typedef struct objc_object Protocol;
30210b57cec5SDimitry Andric QualType RewriteObjC::getProtocolType() {
30220b57cec5SDimitry Andric   if (!ProtocolTypeDecl) {
30230b57cec5SDimitry Andric     TypeSourceInfo *TInfo
30240b57cec5SDimitry Andric       = Context->getTrivialTypeSourceInfo(Context->getObjCIdType());
30250b57cec5SDimitry Andric     ProtocolTypeDecl = TypedefDecl::Create(*Context, TUDecl,
30260b57cec5SDimitry Andric                                            SourceLocation(), SourceLocation(),
30270b57cec5SDimitry Andric                                            &Context->Idents.get("Protocol"),
30280b57cec5SDimitry Andric                                            TInfo);
30290b57cec5SDimitry Andric   }
30300b57cec5SDimitry Andric   return Context->getTypeDeclType(ProtocolTypeDecl);
30310b57cec5SDimitry Andric }
30320b57cec5SDimitry Andric 
30330b57cec5SDimitry Andric /// RewriteObjCProtocolExpr - Rewrite a protocol expression into
30340b57cec5SDimitry Andric /// a synthesized/forward data reference (to the protocol's metadata).
30350b57cec5SDimitry Andric /// The forward references (and metadata) are generated in
30360b57cec5SDimitry Andric /// RewriteObjC::HandleTranslationUnit().
30370b57cec5SDimitry Andric Stmt *RewriteObjC::RewriteObjCProtocolExpr(ObjCProtocolExpr *Exp) {
30380b57cec5SDimitry Andric   std::string Name = "_OBJC_PROTOCOL_" + Exp->getProtocol()->getNameAsString();
30390b57cec5SDimitry Andric   IdentifierInfo *ID = &Context->Idents.get(Name);
30400b57cec5SDimitry Andric   VarDecl *VD = VarDecl::Create(*Context, TUDecl, SourceLocation(),
30410b57cec5SDimitry Andric                                 SourceLocation(), ID, getProtocolType(),
30420b57cec5SDimitry Andric                                 nullptr, SC_Extern);
30430b57cec5SDimitry Andric   DeclRefExpr *DRE = new (Context) DeclRefExpr(
30440b57cec5SDimitry Andric       *Context, VD, false, getProtocolType(), VK_LValue, SourceLocation());
30455ffd83dbSDimitry Andric   Expr *DerefExpr = UnaryOperator::Create(
30465ffd83dbSDimitry Andric       const_cast<ASTContext &>(*Context), DRE, UO_AddrOf,
3047fe6060f1SDimitry Andric       Context->getPointerType(DRE->getType()), VK_PRValue, OK_Ordinary,
30485ffd83dbSDimitry Andric       SourceLocation(), false, FPOptionsOverride());
30490b57cec5SDimitry Andric   CastExpr *castExpr = NoTypeInfoCStyleCastExpr(Context, DerefExpr->getType(),
30500b57cec5SDimitry Andric                                                 CK_BitCast,
30510b57cec5SDimitry Andric                                                 DerefExpr);
30520b57cec5SDimitry Andric   ReplaceStmt(Exp, castExpr);
30530b57cec5SDimitry Andric   ProtocolExprDecls.insert(Exp->getProtocol()->getCanonicalDecl());
30540b57cec5SDimitry Andric   // delete Exp; leak for now, see RewritePropertyOrImplicitSetter() usage for more info.
30550b57cec5SDimitry Andric   return castExpr;
30560b57cec5SDimitry Andric }
30570b57cec5SDimitry Andric 
30580b57cec5SDimitry Andric bool RewriteObjC::BufferContainsPPDirectives(const char *startBuf,
30590b57cec5SDimitry Andric                                              const char *endBuf) {
30600b57cec5SDimitry Andric   while (startBuf < endBuf) {
30610b57cec5SDimitry Andric     if (*startBuf == '#') {
30620b57cec5SDimitry Andric       // Skip whitespace.
30630b57cec5SDimitry Andric       for (++startBuf; startBuf[0] == ' ' || startBuf[0] == '\t'; ++startBuf)
30640b57cec5SDimitry Andric         ;
30650b57cec5SDimitry Andric       if (!strncmp(startBuf, "if", strlen("if")) ||
30660b57cec5SDimitry Andric           !strncmp(startBuf, "ifdef", strlen("ifdef")) ||
30670b57cec5SDimitry Andric           !strncmp(startBuf, "ifndef", strlen("ifndef")) ||
30680b57cec5SDimitry Andric           !strncmp(startBuf, "define", strlen("define")) ||
30690b57cec5SDimitry Andric           !strncmp(startBuf, "undef", strlen("undef")) ||
30700b57cec5SDimitry Andric           !strncmp(startBuf, "else", strlen("else")) ||
30710b57cec5SDimitry Andric           !strncmp(startBuf, "elif", strlen("elif")) ||
30720b57cec5SDimitry Andric           !strncmp(startBuf, "endif", strlen("endif")) ||
30730b57cec5SDimitry Andric           !strncmp(startBuf, "pragma", strlen("pragma")) ||
30740b57cec5SDimitry Andric           !strncmp(startBuf, "include", strlen("include")) ||
30750b57cec5SDimitry Andric           !strncmp(startBuf, "import", strlen("import")) ||
30760b57cec5SDimitry Andric           !strncmp(startBuf, "include_next", strlen("include_next")))
30770b57cec5SDimitry Andric         return true;
30780b57cec5SDimitry Andric     }
30790b57cec5SDimitry Andric     startBuf++;
30800b57cec5SDimitry Andric   }
30810b57cec5SDimitry Andric   return false;
30820b57cec5SDimitry Andric }
30830b57cec5SDimitry Andric 
30840b57cec5SDimitry Andric /// RewriteObjCInternalStruct - Rewrite one internal struct corresponding to
30850b57cec5SDimitry Andric /// an objective-c class with ivars.
30860b57cec5SDimitry Andric void RewriteObjC::RewriteObjCInternalStruct(ObjCInterfaceDecl *CDecl,
30870b57cec5SDimitry Andric                                                std::string &Result) {
30880b57cec5SDimitry Andric   assert(CDecl && "Class missing in SynthesizeObjCInternalStruct");
30890b57cec5SDimitry Andric   assert(CDecl->getName() != "" &&
30900b57cec5SDimitry Andric          "Name missing in SynthesizeObjCInternalStruct");
30910b57cec5SDimitry Andric   // Do not synthesize more than once.
30920b57cec5SDimitry Andric   if (ObjCSynthesizedStructs.count(CDecl))
30930b57cec5SDimitry Andric     return;
30940b57cec5SDimitry Andric   ObjCInterfaceDecl *RCDecl = CDecl->getSuperClass();
30950b57cec5SDimitry Andric   int NumIvars = CDecl->ivar_size();
30960b57cec5SDimitry Andric   SourceLocation LocStart = CDecl->getBeginLoc();
30970b57cec5SDimitry Andric   SourceLocation LocEnd = CDecl->getEndOfDefinitionLoc();
30980b57cec5SDimitry Andric 
30990b57cec5SDimitry Andric   const char *startBuf = SM->getCharacterData(LocStart);
31000b57cec5SDimitry Andric   const char *endBuf = SM->getCharacterData(LocEnd);
31010b57cec5SDimitry Andric 
31020b57cec5SDimitry Andric   // If no ivars and no root or if its root, directly or indirectly,
31030b57cec5SDimitry Andric   // have no ivars (thus not synthesized) then no need to synthesize this class.
31040b57cec5SDimitry Andric   if ((!CDecl->isThisDeclarationADefinition() || NumIvars == 0) &&
31050b57cec5SDimitry Andric       (!RCDecl || !ObjCSynthesizedStructs.count(RCDecl))) {
31060b57cec5SDimitry Andric     endBuf += Lexer::MeasureTokenLength(LocEnd, *SM, LangOpts);
31070b57cec5SDimitry Andric     ReplaceText(LocStart, endBuf-startBuf, Result);
31080b57cec5SDimitry Andric     return;
31090b57cec5SDimitry Andric   }
31100b57cec5SDimitry Andric 
31110b57cec5SDimitry Andric   // FIXME: This has potential of causing problem. If
31120b57cec5SDimitry Andric   // SynthesizeObjCInternalStruct is ever called recursively.
31130b57cec5SDimitry Andric   Result += "\nstruct ";
31140b57cec5SDimitry Andric   Result += CDecl->getNameAsString();
31150b57cec5SDimitry Andric   if (LangOpts.MicrosoftExt)
31160b57cec5SDimitry Andric     Result += "_IMPL";
31170b57cec5SDimitry Andric 
31180b57cec5SDimitry Andric   if (NumIvars > 0) {
31190b57cec5SDimitry Andric     const char *cursor = strchr(startBuf, '{');
31200b57cec5SDimitry Andric     assert((cursor && endBuf)
31210b57cec5SDimitry Andric            && "SynthesizeObjCInternalStruct - malformed @interface");
31220b57cec5SDimitry Andric     // If the buffer contains preprocessor directives, we do more fine-grained
31230b57cec5SDimitry Andric     // rewrites. This is intended to fix code that looks like (which occurs in
31240b57cec5SDimitry Andric     // NSURL.h, for example):
31250b57cec5SDimitry Andric     //
31260b57cec5SDimitry Andric     // #ifdef XYZ
31270b57cec5SDimitry Andric     // @interface Foo : NSObject
31280b57cec5SDimitry Andric     // #else
31290b57cec5SDimitry Andric     // @interface FooBar : NSObject
31300b57cec5SDimitry Andric     // #endif
31310b57cec5SDimitry Andric     // {
31320b57cec5SDimitry Andric     //    int i;
31330b57cec5SDimitry Andric     // }
31340b57cec5SDimitry Andric     // @end
31350b57cec5SDimitry Andric     //
31360b57cec5SDimitry Andric     // This clause is segregated to avoid breaking the common case.
31370b57cec5SDimitry Andric     if (BufferContainsPPDirectives(startBuf, cursor)) {
31380b57cec5SDimitry Andric       SourceLocation L = RCDecl ? CDecl->getSuperClassLoc() :
31390b57cec5SDimitry Andric                                   CDecl->getAtStartLoc();
31400b57cec5SDimitry Andric       const char *endHeader = SM->getCharacterData(L);
31410b57cec5SDimitry Andric       endHeader += Lexer::MeasureTokenLength(L, *SM, LangOpts);
31420b57cec5SDimitry Andric 
31430b57cec5SDimitry Andric       if (CDecl->protocol_begin() != CDecl->protocol_end()) {
31440b57cec5SDimitry Andric         // advance to the end of the referenced protocols.
31450b57cec5SDimitry Andric         while (endHeader < cursor && *endHeader != '>') endHeader++;
31460b57cec5SDimitry Andric         endHeader++;
31470b57cec5SDimitry Andric       }
31480b57cec5SDimitry Andric       // rewrite the original header
31490b57cec5SDimitry Andric       ReplaceText(LocStart, endHeader-startBuf, Result);
31500b57cec5SDimitry Andric     } else {
31510b57cec5SDimitry Andric       // rewrite the original header *without* disturbing the '{'
31520b57cec5SDimitry Andric       ReplaceText(LocStart, cursor-startBuf, Result);
31530b57cec5SDimitry Andric     }
31540b57cec5SDimitry Andric     if (RCDecl && ObjCSynthesizedStructs.count(RCDecl)) {
31550b57cec5SDimitry Andric       Result = "\n    struct ";
31560b57cec5SDimitry Andric       Result += RCDecl->getNameAsString();
31570b57cec5SDimitry Andric       Result += "_IMPL ";
31580b57cec5SDimitry Andric       Result += RCDecl->getNameAsString();
31590b57cec5SDimitry Andric       Result += "_IVARS;\n";
31600b57cec5SDimitry Andric 
31610b57cec5SDimitry Andric       // insert the super class structure definition.
31620b57cec5SDimitry Andric       SourceLocation OnePastCurly =
31630b57cec5SDimitry Andric         LocStart.getLocWithOffset(cursor-startBuf+1);
31640b57cec5SDimitry Andric       InsertText(OnePastCurly, Result);
31650b57cec5SDimitry Andric     }
31660b57cec5SDimitry Andric     cursor++; // past '{'
31670b57cec5SDimitry Andric 
31680b57cec5SDimitry Andric     // Now comment out any visibility specifiers.
31690b57cec5SDimitry Andric     while (cursor < endBuf) {
31700b57cec5SDimitry Andric       if (*cursor == '@') {
31710b57cec5SDimitry Andric         SourceLocation atLoc = LocStart.getLocWithOffset(cursor-startBuf);
31720b57cec5SDimitry Andric         // Skip whitespace.
31730b57cec5SDimitry Andric         for (++cursor; cursor[0] == ' ' || cursor[0] == '\t'; ++cursor)
31740b57cec5SDimitry Andric           /*scan*/;
31750b57cec5SDimitry Andric 
31760b57cec5SDimitry Andric         // FIXME: presence of @public, etc. inside comment results in
31770b57cec5SDimitry Andric         // this transformation as well, which is still correct c-code.
31780b57cec5SDimitry Andric         if (!strncmp(cursor, "public", strlen("public")) ||
31790b57cec5SDimitry Andric             !strncmp(cursor, "private", strlen("private")) ||
31800b57cec5SDimitry Andric             !strncmp(cursor, "package", strlen("package")) ||
31810b57cec5SDimitry Andric             !strncmp(cursor, "protected", strlen("protected")))
31820b57cec5SDimitry Andric           InsertText(atLoc, "// ");
31830b57cec5SDimitry Andric       }
31840b57cec5SDimitry Andric       // FIXME: If there are cases where '<' is used in ivar declaration part
31850b57cec5SDimitry Andric       // of user code, then scan the ivar list and use needToScanForQualifiers
31860b57cec5SDimitry Andric       // for type checking.
31870b57cec5SDimitry Andric       else if (*cursor == '<') {
31880b57cec5SDimitry Andric         SourceLocation atLoc = LocStart.getLocWithOffset(cursor-startBuf);
31890b57cec5SDimitry Andric         InsertText(atLoc, "/* ");
31900b57cec5SDimitry Andric         cursor = strchr(cursor, '>');
31910b57cec5SDimitry Andric         cursor++;
31920b57cec5SDimitry Andric         atLoc = LocStart.getLocWithOffset(cursor-startBuf);
31930b57cec5SDimitry Andric         InsertText(atLoc, " */");
31940b57cec5SDimitry Andric       } else if (*cursor == '^') { // rewrite block specifier.
31950b57cec5SDimitry Andric         SourceLocation caretLoc = LocStart.getLocWithOffset(cursor-startBuf);
31960b57cec5SDimitry Andric         ReplaceText(caretLoc, 1, "*");
31970b57cec5SDimitry Andric       }
31980b57cec5SDimitry Andric       cursor++;
31990b57cec5SDimitry Andric     }
32000b57cec5SDimitry Andric     // Don't forget to add a ';'!!
32010b57cec5SDimitry Andric     InsertText(LocEnd.getLocWithOffset(1), ";");
32020b57cec5SDimitry Andric   } else { // we don't have any instance variables - insert super struct.
32030b57cec5SDimitry Andric     endBuf += Lexer::MeasureTokenLength(LocEnd, *SM, LangOpts);
32040b57cec5SDimitry Andric     Result += " {\n    struct ";
32050b57cec5SDimitry Andric     Result += RCDecl->getNameAsString();
32060b57cec5SDimitry Andric     Result += "_IMPL ";
32070b57cec5SDimitry Andric     Result += RCDecl->getNameAsString();
32080b57cec5SDimitry Andric     Result += "_IVARS;\n};\n";
32090b57cec5SDimitry Andric     ReplaceText(LocStart, endBuf-startBuf, Result);
32100b57cec5SDimitry Andric   }
32110b57cec5SDimitry Andric   // Mark this struct as having been generated.
32120b57cec5SDimitry Andric   if (!ObjCSynthesizedStructs.insert(CDecl).second)
32130b57cec5SDimitry Andric     llvm_unreachable("struct already synthesize- SynthesizeObjCInternalStruct");
32140b57cec5SDimitry Andric }
32150b57cec5SDimitry Andric 
32160b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
32170b57cec5SDimitry Andric // Meta Data Emission
32180b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
32190b57cec5SDimitry Andric 
32200b57cec5SDimitry Andric /// RewriteImplementations - This routine rewrites all method implementations
32210b57cec5SDimitry Andric /// and emits meta-data.
32220b57cec5SDimitry Andric 
32230b57cec5SDimitry Andric void RewriteObjC::RewriteImplementations() {
32240b57cec5SDimitry Andric   int ClsDefCount = ClassImplementation.size();
32250b57cec5SDimitry Andric   int CatDefCount = CategoryImplementation.size();
32260b57cec5SDimitry Andric 
32270b57cec5SDimitry Andric   // Rewrite implemented methods
32280b57cec5SDimitry Andric   for (int i = 0; i < ClsDefCount; i++)
32290b57cec5SDimitry Andric     RewriteImplementationDecl(ClassImplementation[i]);
32300b57cec5SDimitry Andric 
32310b57cec5SDimitry Andric   for (int i = 0; i < CatDefCount; i++)
32320b57cec5SDimitry Andric     RewriteImplementationDecl(CategoryImplementation[i]);
32330b57cec5SDimitry Andric }
32340b57cec5SDimitry Andric 
32350b57cec5SDimitry Andric void RewriteObjC::RewriteByRefString(std::string &ResultStr,
32360b57cec5SDimitry Andric                                      const std::string &Name,
32370b57cec5SDimitry Andric                                      ValueDecl *VD, bool def) {
32380b57cec5SDimitry Andric   assert(BlockByRefDeclNo.count(VD) &&
32390b57cec5SDimitry Andric          "RewriteByRefString: ByRef decl missing");
32400b57cec5SDimitry Andric   if (def)
32410b57cec5SDimitry Andric     ResultStr += "struct ";
32420b57cec5SDimitry Andric   ResultStr += "__Block_byref_" + Name +
32430b57cec5SDimitry Andric     "_" + utostr(BlockByRefDeclNo[VD]) ;
32440b57cec5SDimitry Andric }
32450b57cec5SDimitry Andric 
32460b57cec5SDimitry Andric static bool HasLocalVariableExternalStorage(ValueDecl *VD) {
32470b57cec5SDimitry Andric   if (VarDecl *Var = dyn_cast<VarDecl>(VD))
32480b57cec5SDimitry Andric     return (Var->isFunctionOrMethodVarDecl() && !Var->hasLocalStorage());
32490b57cec5SDimitry Andric   return false;
32500b57cec5SDimitry Andric }
32510b57cec5SDimitry Andric 
32520b57cec5SDimitry Andric std::string RewriteObjC::SynthesizeBlockFunc(BlockExpr *CE, int i,
32530b57cec5SDimitry Andric                                                    StringRef funcName,
32540b57cec5SDimitry Andric                                                    std::string Tag) {
32550b57cec5SDimitry Andric   const FunctionType *AFT = CE->getFunctionType();
32560b57cec5SDimitry Andric   QualType RT = AFT->getReturnType();
32570b57cec5SDimitry Andric   std::string StructRef = "struct " + Tag;
32580b57cec5SDimitry Andric   std::string S = "static " + RT.getAsString(Context->getPrintingPolicy()) + " __" +
32590b57cec5SDimitry Andric                   funcName.str() + "_" + "block_func_" + utostr(i);
32600b57cec5SDimitry Andric 
32610b57cec5SDimitry Andric   BlockDecl *BD = CE->getBlockDecl();
32620b57cec5SDimitry Andric 
32630b57cec5SDimitry Andric   if (isa<FunctionNoProtoType>(AFT)) {
32640b57cec5SDimitry Andric     // No user-supplied arguments. Still need to pass in a pointer to the
32650b57cec5SDimitry Andric     // block (to reference imported block decl refs).
32660b57cec5SDimitry Andric     S += "(" + StructRef + " *__cself)";
32670b57cec5SDimitry Andric   } else if (BD->param_empty()) {
32680b57cec5SDimitry Andric     S += "(" + StructRef + " *__cself)";
32690b57cec5SDimitry Andric   } else {
32700b57cec5SDimitry Andric     const FunctionProtoType *FT = cast<FunctionProtoType>(AFT);
32710b57cec5SDimitry Andric     assert(FT && "SynthesizeBlockFunc: No function proto");
32720b57cec5SDimitry Andric     S += '(';
32730b57cec5SDimitry Andric     // first add the implicit argument.
32740b57cec5SDimitry Andric     S += StructRef + " *__cself, ";
32750b57cec5SDimitry Andric     std::string ParamStr;
32760b57cec5SDimitry Andric     for (BlockDecl::param_iterator AI = BD->param_begin(),
32770b57cec5SDimitry Andric          E = BD->param_end(); AI != E; ++AI) {
32780b57cec5SDimitry Andric       if (AI != BD->param_begin()) S += ", ";
32790b57cec5SDimitry Andric       ParamStr = (*AI)->getNameAsString();
32800b57cec5SDimitry Andric       QualType QT = (*AI)->getType();
32810b57cec5SDimitry Andric       (void)convertBlockPointerToFunctionPointer(QT);
32820b57cec5SDimitry Andric       QT.getAsStringInternal(ParamStr, Context->getPrintingPolicy());
32830b57cec5SDimitry Andric       S += ParamStr;
32840b57cec5SDimitry Andric     }
32850b57cec5SDimitry Andric     if (FT->isVariadic()) {
32860b57cec5SDimitry Andric       if (!BD->param_empty()) S += ", ";
32870b57cec5SDimitry Andric       S += "...";
32880b57cec5SDimitry Andric     }
32890b57cec5SDimitry Andric     S += ')';
32900b57cec5SDimitry Andric   }
32910b57cec5SDimitry Andric   S += " {\n";
32920b57cec5SDimitry Andric 
32930b57cec5SDimitry Andric   // Create local declarations to avoid rewriting all closure decl ref exprs.
32940b57cec5SDimitry Andric   // First, emit a declaration for all "by ref" decls.
32950b57cec5SDimitry Andric   for (SmallVectorImpl<ValueDecl *>::iterator I = BlockByRefDecls.begin(),
32960b57cec5SDimitry Andric        E = BlockByRefDecls.end(); I != E; ++I) {
32970b57cec5SDimitry Andric     S += "  ";
32980b57cec5SDimitry Andric     std::string Name = (*I)->getNameAsString();
32990b57cec5SDimitry Andric     std::string TypeString;
33000b57cec5SDimitry Andric     RewriteByRefString(TypeString, Name, (*I));
33010b57cec5SDimitry Andric     TypeString += " *";
33020b57cec5SDimitry Andric     Name = TypeString + Name;
33030b57cec5SDimitry Andric     S += Name + " = __cself->" + (*I)->getNameAsString() + "; // bound by ref\n";
33040b57cec5SDimitry Andric   }
33050b57cec5SDimitry Andric   // Next, emit a declaration for all "by copy" declarations.
33060b57cec5SDimitry Andric   for (SmallVectorImpl<ValueDecl *>::iterator I = BlockByCopyDecls.begin(),
33070b57cec5SDimitry Andric        E = BlockByCopyDecls.end(); I != E; ++I) {
33080b57cec5SDimitry Andric     S += "  ";
33090b57cec5SDimitry Andric     // Handle nested closure invocation. For example:
33100b57cec5SDimitry Andric     //
33110b57cec5SDimitry Andric     //   void (^myImportedClosure)(void);
33120b57cec5SDimitry Andric     //   myImportedClosure  = ^(void) { setGlobalInt(x + y); };
33130b57cec5SDimitry Andric     //
33140b57cec5SDimitry Andric     //   void (^anotherClosure)(void);
33150b57cec5SDimitry Andric     //   anotherClosure = ^(void) {
33160b57cec5SDimitry Andric     //     myImportedClosure(); // import and invoke the closure
33170b57cec5SDimitry Andric     //   };
33180b57cec5SDimitry Andric     //
33190b57cec5SDimitry Andric     if (isTopLevelBlockPointerType((*I)->getType())) {
33200b57cec5SDimitry Andric       RewriteBlockPointerTypeVariable(S, (*I));
33210b57cec5SDimitry Andric       S += " = (";
33220b57cec5SDimitry Andric       RewriteBlockPointerType(S, (*I)->getType());
33230b57cec5SDimitry Andric       S += ")";
33240b57cec5SDimitry Andric       S += "__cself->" + (*I)->getNameAsString() + "; // bound by copy\n";
33250b57cec5SDimitry Andric     }
33260b57cec5SDimitry Andric     else {
33270b57cec5SDimitry Andric       std::string Name = (*I)->getNameAsString();
33280b57cec5SDimitry Andric       QualType QT = (*I)->getType();
33290b57cec5SDimitry Andric       if (HasLocalVariableExternalStorage(*I))
33300b57cec5SDimitry Andric         QT = Context->getPointerType(QT);
33310b57cec5SDimitry Andric       QT.getAsStringInternal(Name, Context->getPrintingPolicy());
33320b57cec5SDimitry Andric       S += Name + " = __cself->" +
33330b57cec5SDimitry Andric                               (*I)->getNameAsString() + "; // bound by copy\n";
33340b57cec5SDimitry Andric     }
33350b57cec5SDimitry Andric   }
33360b57cec5SDimitry Andric   std::string RewrittenStr = RewrittenBlockExprs[CE];
33370b57cec5SDimitry Andric   const char *cstr = RewrittenStr.c_str();
33380b57cec5SDimitry Andric   while (*cstr++ != '{') ;
33390b57cec5SDimitry Andric   S += cstr;
33400b57cec5SDimitry Andric   S += "\n";
33410b57cec5SDimitry Andric   return S;
33420b57cec5SDimitry Andric }
33430b57cec5SDimitry Andric 
33440b57cec5SDimitry Andric std::string RewriteObjC::SynthesizeBlockHelperFuncs(BlockExpr *CE, int i,
33450b57cec5SDimitry Andric                                                    StringRef funcName,
33460b57cec5SDimitry Andric                                                    std::string Tag) {
33470b57cec5SDimitry Andric   std::string StructRef = "struct " + Tag;
33480b57cec5SDimitry Andric   std::string S = "static void __";
33490b57cec5SDimitry Andric 
33500b57cec5SDimitry Andric   S += funcName;
33510b57cec5SDimitry Andric   S += "_block_copy_" + utostr(i);
33520b57cec5SDimitry Andric   S += "(" + StructRef;
33530b57cec5SDimitry Andric   S += "*dst, " + StructRef;
33540b57cec5SDimitry Andric   S += "*src) {";
33550b57cec5SDimitry Andric   for (ValueDecl *VD : ImportedBlockDecls) {
33560b57cec5SDimitry Andric     S += "_Block_object_assign((void*)&dst->";
33570b57cec5SDimitry Andric     S += VD->getNameAsString();
33580b57cec5SDimitry Andric     S += ", (void*)src->";
33590b57cec5SDimitry Andric     S += VD->getNameAsString();
33600b57cec5SDimitry Andric     if (BlockByRefDeclsPtrSet.count(VD))
33610b57cec5SDimitry Andric       S += ", " + utostr(BLOCK_FIELD_IS_BYREF) + "/*BLOCK_FIELD_IS_BYREF*/);";
33620b57cec5SDimitry Andric     else if (VD->getType()->isBlockPointerType())
33630b57cec5SDimitry Andric       S += ", " + utostr(BLOCK_FIELD_IS_BLOCK) + "/*BLOCK_FIELD_IS_BLOCK*/);";
33640b57cec5SDimitry Andric     else
33650b57cec5SDimitry Andric       S += ", " + utostr(BLOCK_FIELD_IS_OBJECT) + "/*BLOCK_FIELD_IS_OBJECT*/);";
33660b57cec5SDimitry Andric   }
33670b57cec5SDimitry Andric   S += "}\n";
33680b57cec5SDimitry Andric 
33690b57cec5SDimitry Andric   S += "\nstatic void __";
33700b57cec5SDimitry Andric   S += funcName;
33710b57cec5SDimitry Andric   S += "_block_dispose_" + utostr(i);
33720b57cec5SDimitry Andric   S += "(" + StructRef;
33730b57cec5SDimitry Andric   S += "*src) {";
33740b57cec5SDimitry Andric   for (ValueDecl *VD : ImportedBlockDecls) {
33750b57cec5SDimitry Andric     S += "_Block_object_dispose((void*)src->";
33760b57cec5SDimitry Andric     S += VD->getNameAsString();
33770b57cec5SDimitry Andric     if (BlockByRefDeclsPtrSet.count(VD))
33780b57cec5SDimitry Andric       S += ", " + utostr(BLOCK_FIELD_IS_BYREF) + "/*BLOCK_FIELD_IS_BYREF*/);";
33790b57cec5SDimitry Andric     else if (VD->getType()->isBlockPointerType())
33800b57cec5SDimitry Andric       S += ", " + utostr(BLOCK_FIELD_IS_BLOCK) + "/*BLOCK_FIELD_IS_BLOCK*/);";
33810b57cec5SDimitry Andric     else
33820b57cec5SDimitry Andric       S += ", " + utostr(BLOCK_FIELD_IS_OBJECT) + "/*BLOCK_FIELD_IS_OBJECT*/);";
33830b57cec5SDimitry Andric   }
33840b57cec5SDimitry Andric   S += "}\n";
33850b57cec5SDimitry Andric   return S;
33860b57cec5SDimitry Andric }
33870b57cec5SDimitry Andric 
33880b57cec5SDimitry Andric std::string RewriteObjC::SynthesizeBlockImpl(BlockExpr *CE, std::string Tag,
33890b57cec5SDimitry Andric                                              std::string Desc) {
33900b57cec5SDimitry Andric   std::string S = "\nstruct " + Tag;
33910b57cec5SDimitry Andric   std::string Constructor = "  " + Tag;
33920b57cec5SDimitry Andric 
33930b57cec5SDimitry Andric   S += " {\n  struct __block_impl impl;\n";
33940b57cec5SDimitry Andric   S += "  struct " + Desc;
33950b57cec5SDimitry Andric   S += "* Desc;\n";
33960b57cec5SDimitry Andric 
33970b57cec5SDimitry Andric   Constructor += "(void *fp, "; // Invoke function pointer.
33980b57cec5SDimitry Andric   Constructor += "struct " + Desc; // Descriptor pointer.
33990b57cec5SDimitry Andric   Constructor += " *desc";
34000b57cec5SDimitry Andric 
34010b57cec5SDimitry Andric   if (BlockDeclRefs.size()) {
34020b57cec5SDimitry Andric     // Output all "by copy" declarations.
34030b57cec5SDimitry Andric     for (SmallVectorImpl<ValueDecl *>::iterator I = BlockByCopyDecls.begin(),
34040b57cec5SDimitry Andric          E = BlockByCopyDecls.end(); I != E; ++I) {
34050b57cec5SDimitry Andric       S += "  ";
34060b57cec5SDimitry Andric       std::string FieldName = (*I)->getNameAsString();
34070b57cec5SDimitry Andric       std::string ArgName = "_" + FieldName;
34080b57cec5SDimitry Andric       // Handle nested closure invocation. For example:
34090b57cec5SDimitry Andric       //
34100b57cec5SDimitry Andric       //   void (^myImportedBlock)(void);
34110b57cec5SDimitry Andric       //   myImportedBlock  = ^(void) { setGlobalInt(x + y); };
34120b57cec5SDimitry Andric       //
34130b57cec5SDimitry Andric       //   void (^anotherBlock)(void);
34140b57cec5SDimitry Andric       //   anotherBlock = ^(void) {
34150b57cec5SDimitry Andric       //     myImportedBlock(); // import and invoke the closure
34160b57cec5SDimitry Andric       //   };
34170b57cec5SDimitry Andric       //
34180b57cec5SDimitry Andric       if (isTopLevelBlockPointerType((*I)->getType())) {
34190b57cec5SDimitry Andric         S += "struct __block_impl *";
34200b57cec5SDimitry Andric         Constructor += ", void *" + ArgName;
34210b57cec5SDimitry Andric       } else {
34220b57cec5SDimitry Andric         QualType QT = (*I)->getType();
34230b57cec5SDimitry Andric         if (HasLocalVariableExternalStorage(*I))
34240b57cec5SDimitry Andric           QT = Context->getPointerType(QT);
34250b57cec5SDimitry Andric         QT.getAsStringInternal(FieldName, Context->getPrintingPolicy());
34260b57cec5SDimitry Andric         QT.getAsStringInternal(ArgName, Context->getPrintingPolicy());
34270b57cec5SDimitry Andric         Constructor += ", " + ArgName;
34280b57cec5SDimitry Andric       }
34290b57cec5SDimitry Andric       S += FieldName + ";\n";
34300b57cec5SDimitry Andric     }
34310b57cec5SDimitry Andric     // Output all "by ref" declarations.
34320b57cec5SDimitry Andric     for (SmallVectorImpl<ValueDecl *>::iterator I = BlockByRefDecls.begin(),
34330b57cec5SDimitry Andric          E = BlockByRefDecls.end(); I != E; ++I) {
34340b57cec5SDimitry Andric       S += "  ";
34350b57cec5SDimitry Andric       std::string FieldName = (*I)->getNameAsString();
34360b57cec5SDimitry Andric       std::string ArgName = "_" + FieldName;
34370b57cec5SDimitry Andric       {
34380b57cec5SDimitry Andric         std::string TypeString;
34390b57cec5SDimitry Andric         RewriteByRefString(TypeString, FieldName, (*I));
34400b57cec5SDimitry Andric         TypeString += " *";
34410b57cec5SDimitry Andric         FieldName = TypeString + FieldName;
34420b57cec5SDimitry Andric         ArgName = TypeString + ArgName;
34430b57cec5SDimitry Andric         Constructor += ", " + ArgName;
34440b57cec5SDimitry Andric       }
34450b57cec5SDimitry Andric       S += FieldName + "; // by ref\n";
34460b57cec5SDimitry Andric     }
34470b57cec5SDimitry Andric     // Finish writing the constructor.
34480b57cec5SDimitry Andric     Constructor += ", int flags=0)";
34490b57cec5SDimitry Andric     // Initialize all "by copy" arguments.
34500b57cec5SDimitry Andric     bool firsTime = true;
34510b57cec5SDimitry Andric     for (SmallVectorImpl<ValueDecl *>::iterator I = BlockByCopyDecls.begin(),
34520b57cec5SDimitry Andric          E = BlockByCopyDecls.end(); I != E; ++I) {
34530b57cec5SDimitry Andric       std::string Name = (*I)->getNameAsString();
34540b57cec5SDimitry Andric         if (firsTime) {
34550b57cec5SDimitry Andric           Constructor += " : ";
34560b57cec5SDimitry Andric           firsTime = false;
34570b57cec5SDimitry Andric         }
34580b57cec5SDimitry Andric         else
34590b57cec5SDimitry Andric           Constructor += ", ";
34600b57cec5SDimitry Andric         if (isTopLevelBlockPointerType((*I)->getType()))
34610b57cec5SDimitry Andric           Constructor += Name + "((struct __block_impl *)_" + Name + ")";
34620b57cec5SDimitry Andric         else
34630b57cec5SDimitry Andric           Constructor += Name + "(_" + Name + ")";
34640b57cec5SDimitry Andric     }
34650b57cec5SDimitry Andric     // Initialize all "by ref" arguments.
34660b57cec5SDimitry Andric     for (SmallVectorImpl<ValueDecl *>::iterator I = BlockByRefDecls.begin(),
34670b57cec5SDimitry Andric          E = BlockByRefDecls.end(); I != E; ++I) {
34680b57cec5SDimitry Andric       std::string Name = (*I)->getNameAsString();
34690b57cec5SDimitry Andric       if (firsTime) {
34700b57cec5SDimitry Andric         Constructor += " : ";
34710b57cec5SDimitry Andric         firsTime = false;
34720b57cec5SDimitry Andric       }
34730b57cec5SDimitry Andric       else
34740b57cec5SDimitry Andric         Constructor += ", ";
34750b57cec5SDimitry Andric       Constructor += Name + "(_" + Name + "->__forwarding)";
34760b57cec5SDimitry Andric     }
34770b57cec5SDimitry Andric 
34780b57cec5SDimitry Andric     Constructor += " {\n";
34790b57cec5SDimitry Andric     if (GlobalVarDecl)
34800b57cec5SDimitry Andric       Constructor += "    impl.isa = &_NSConcreteGlobalBlock;\n";
34810b57cec5SDimitry Andric     else
34820b57cec5SDimitry Andric       Constructor += "    impl.isa = &_NSConcreteStackBlock;\n";
34830b57cec5SDimitry Andric     Constructor += "    impl.Flags = flags;\n    impl.FuncPtr = fp;\n";
34840b57cec5SDimitry Andric 
34850b57cec5SDimitry Andric     Constructor += "    Desc = desc;\n";
34860b57cec5SDimitry Andric   } else {
34870b57cec5SDimitry Andric     // Finish writing the constructor.
34880b57cec5SDimitry Andric     Constructor += ", int flags=0) {\n";
34890b57cec5SDimitry Andric     if (GlobalVarDecl)
34900b57cec5SDimitry Andric       Constructor += "    impl.isa = &_NSConcreteGlobalBlock;\n";
34910b57cec5SDimitry Andric     else
34920b57cec5SDimitry Andric       Constructor += "    impl.isa = &_NSConcreteStackBlock;\n";
34930b57cec5SDimitry Andric     Constructor += "    impl.Flags = flags;\n    impl.FuncPtr = fp;\n";
34940b57cec5SDimitry Andric     Constructor += "    Desc = desc;\n";
34950b57cec5SDimitry Andric   }
34960b57cec5SDimitry Andric   Constructor += "  ";
34970b57cec5SDimitry Andric   Constructor += "}\n";
34980b57cec5SDimitry Andric   S += Constructor;
34990b57cec5SDimitry Andric   S += "};\n";
35000b57cec5SDimitry Andric   return S;
35010b57cec5SDimitry Andric }
35020b57cec5SDimitry Andric 
35030b57cec5SDimitry Andric std::string RewriteObjC::SynthesizeBlockDescriptor(std::string DescTag,
35040b57cec5SDimitry Andric                                                    std::string ImplTag, int i,
35050b57cec5SDimitry Andric                                                    StringRef FunName,
35060b57cec5SDimitry Andric                                                    unsigned hasCopy) {
35070b57cec5SDimitry Andric   std::string S = "\nstatic struct " + DescTag;
35080b57cec5SDimitry Andric 
35090b57cec5SDimitry Andric   S += " {\n  unsigned long reserved;\n";
35100b57cec5SDimitry Andric   S += "  unsigned long Block_size;\n";
35110b57cec5SDimitry Andric   if (hasCopy) {
35120b57cec5SDimitry Andric     S += "  void (*copy)(struct ";
35130b57cec5SDimitry Andric     S += ImplTag; S += "*, struct ";
35140b57cec5SDimitry Andric     S += ImplTag; S += "*);\n";
35150b57cec5SDimitry Andric 
35160b57cec5SDimitry Andric     S += "  void (*dispose)(struct ";
35170b57cec5SDimitry Andric     S += ImplTag; S += "*);\n";
35180b57cec5SDimitry Andric   }
35190b57cec5SDimitry Andric   S += "} ";
35200b57cec5SDimitry Andric 
35210b57cec5SDimitry Andric   S += DescTag + "_DATA = { 0, sizeof(struct ";
35220b57cec5SDimitry Andric   S += ImplTag + ")";
35230b57cec5SDimitry Andric   if (hasCopy) {
35240b57cec5SDimitry Andric     S += ", __" + FunName.str() + "_block_copy_" + utostr(i);
35250b57cec5SDimitry Andric     S += ", __" + FunName.str() + "_block_dispose_" + utostr(i);
35260b57cec5SDimitry Andric   }
35270b57cec5SDimitry Andric   S += "};\n";
35280b57cec5SDimitry Andric   return S;
35290b57cec5SDimitry Andric }
35300b57cec5SDimitry Andric 
35310b57cec5SDimitry Andric void RewriteObjC::SynthesizeBlockLiterals(SourceLocation FunLocStart,
35320b57cec5SDimitry Andric                                           StringRef FunName) {
35330b57cec5SDimitry Andric   // Insert declaration for the function in which block literal is used.
35340b57cec5SDimitry Andric   if (CurFunctionDeclToDeclareForBlock && !Blocks.empty())
35350b57cec5SDimitry Andric     RewriteBlockLiteralFunctionDecl(CurFunctionDeclToDeclareForBlock);
35360b57cec5SDimitry Andric   bool RewriteSC = (GlobalVarDecl &&
35370b57cec5SDimitry Andric                     !Blocks.empty() &&
35380b57cec5SDimitry Andric                     GlobalVarDecl->getStorageClass() == SC_Static &&
35390b57cec5SDimitry Andric                     GlobalVarDecl->getType().getCVRQualifiers());
35400b57cec5SDimitry Andric   if (RewriteSC) {
35410b57cec5SDimitry Andric     std::string SC(" void __");
35420b57cec5SDimitry Andric     SC += GlobalVarDecl->getNameAsString();
35430b57cec5SDimitry Andric     SC += "() {}";
35440b57cec5SDimitry Andric     InsertText(FunLocStart, SC);
35450b57cec5SDimitry Andric   }
35460b57cec5SDimitry Andric 
35470b57cec5SDimitry Andric   // Insert closures that were part of the function.
35480b57cec5SDimitry Andric   for (unsigned i = 0, count=0; i < Blocks.size(); i++) {
35490b57cec5SDimitry Andric     CollectBlockDeclRefInfo(Blocks[i]);
35500b57cec5SDimitry Andric     // Need to copy-in the inner copied-in variables not actually used in this
35510b57cec5SDimitry Andric     // block.
35520b57cec5SDimitry Andric     for (int j = 0; j < InnerDeclRefsCount[i]; j++) {
35530b57cec5SDimitry Andric       DeclRefExpr *Exp = InnerDeclRefs[count++];
35540b57cec5SDimitry Andric       ValueDecl *VD = Exp->getDecl();
35550b57cec5SDimitry Andric       BlockDeclRefs.push_back(Exp);
35560b57cec5SDimitry Andric       if (!VD->hasAttr<BlocksAttr>() && !BlockByCopyDeclsPtrSet.count(VD)) {
35570b57cec5SDimitry Andric         BlockByCopyDeclsPtrSet.insert(VD);
35580b57cec5SDimitry Andric         BlockByCopyDecls.push_back(VD);
35590b57cec5SDimitry Andric       }
35600b57cec5SDimitry Andric       if (VD->hasAttr<BlocksAttr>() && !BlockByRefDeclsPtrSet.count(VD)) {
35610b57cec5SDimitry Andric         BlockByRefDeclsPtrSet.insert(VD);
35620b57cec5SDimitry Andric         BlockByRefDecls.push_back(VD);
35630b57cec5SDimitry Andric       }
35640b57cec5SDimitry Andric       // imported objects in the inner blocks not used in the outer
35650b57cec5SDimitry Andric       // blocks must be copied/disposed in the outer block as well.
35660b57cec5SDimitry Andric       if (VD->hasAttr<BlocksAttr>() ||
35670b57cec5SDimitry Andric           VD->getType()->isObjCObjectPointerType() ||
35680b57cec5SDimitry Andric           VD->getType()->isBlockPointerType())
35690b57cec5SDimitry Andric         ImportedBlockDecls.insert(VD);
35700b57cec5SDimitry Andric     }
35710b57cec5SDimitry Andric 
35720b57cec5SDimitry Andric     std::string ImplTag = "__" + FunName.str() + "_block_impl_" + utostr(i);
35730b57cec5SDimitry Andric     std::string DescTag = "__" + FunName.str() + "_block_desc_" + utostr(i);
35740b57cec5SDimitry Andric 
35750b57cec5SDimitry Andric     std::string CI = SynthesizeBlockImpl(Blocks[i], ImplTag, DescTag);
35760b57cec5SDimitry Andric 
35770b57cec5SDimitry Andric     InsertText(FunLocStart, CI);
35780b57cec5SDimitry Andric 
35790b57cec5SDimitry Andric     std::string CF = SynthesizeBlockFunc(Blocks[i], i, FunName, ImplTag);
35800b57cec5SDimitry Andric 
35810b57cec5SDimitry Andric     InsertText(FunLocStart, CF);
35820b57cec5SDimitry Andric 
35830b57cec5SDimitry Andric     if (ImportedBlockDecls.size()) {
35840b57cec5SDimitry Andric       std::string HF = SynthesizeBlockHelperFuncs(Blocks[i], i, FunName, ImplTag);
35850b57cec5SDimitry Andric       InsertText(FunLocStart, HF);
35860b57cec5SDimitry Andric     }
35870b57cec5SDimitry Andric     std::string BD = SynthesizeBlockDescriptor(DescTag, ImplTag, i, FunName,
35880b57cec5SDimitry Andric                                                ImportedBlockDecls.size() > 0);
35890b57cec5SDimitry Andric     InsertText(FunLocStart, BD);
35900b57cec5SDimitry Andric 
35910b57cec5SDimitry Andric     BlockDeclRefs.clear();
35920b57cec5SDimitry Andric     BlockByRefDecls.clear();
35930b57cec5SDimitry Andric     BlockByRefDeclsPtrSet.clear();
35940b57cec5SDimitry Andric     BlockByCopyDecls.clear();
35950b57cec5SDimitry Andric     BlockByCopyDeclsPtrSet.clear();
35960b57cec5SDimitry Andric     ImportedBlockDecls.clear();
35970b57cec5SDimitry Andric   }
35980b57cec5SDimitry Andric   if (RewriteSC) {
35990b57cec5SDimitry Andric     // Must insert any 'const/volatile/static here. Since it has been
36000b57cec5SDimitry Andric     // removed as result of rewriting of block literals.
36010b57cec5SDimitry Andric     std::string SC;
36020b57cec5SDimitry Andric     if (GlobalVarDecl->getStorageClass() == SC_Static)
36030b57cec5SDimitry Andric       SC = "static ";
36040b57cec5SDimitry Andric     if (GlobalVarDecl->getType().isConstQualified())
36050b57cec5SDimitry Andric       SC += "const ";
36060b57cec5SDimitry Andric     if (GlobalVarDecl->getType().isVolatileQualified())
36070b57cec5SDimitry Andric       SC += "volatile ";
36080b57cec5SDimitry Andric     if (GlobalVarDecl->getType().isRestrictQualified())
36090b57cec5SDimitry Andric       SC += "restrict ";
36100b57cec5SDimitry Andric     InsertText(FunLocStart, SC);
36110b57cec5SDimitry Andric   }
36120b57cec5SDimitry Andric 
36130b57cec5SDimitry Andric   Blocks.clear();
36140b57cec5SDimitry Andric   InnerDeclRefsCount.clear();
36150b57cec5SDimitry Andric   InnerDeclRefs.clear();
36160b57cec5SDimitry Andric   RewrittenBlockExprs.clear();
36170b57cec5SDimitry Andric }
36180b57cec5SDimitry Andric 
36190b57cec5SDimitry Andric void RewriteObjC::InsertBlockLiteralsWithinFunction(FunctionDecl *FD) {
36200b57cec5SDimitry Andric   SourceLocation FunLocStart = FD->getTypeSpecStartLoc();
36210b57cec5SDimitry Andric   StringRef FuncName = FD->getName();
36220b57cec5SDimitry Andric 
36230b57cec5SDimitry Andric   SynthesizeBlockLiterals(FunLocStart, FuncName);
36240b57cec5SDimitry Andric }
36250b57cec5SDimitry Andric 
36260b57cec5SDimitry Andric static void BuildUniqueMethodName(std::string &Name,
36270b57cec5SDimitry Andric                                   ObjCMethodDecl *MD) {
36280b57cec5SDimitry Andric   ObjCInterfaceDecl *IFace = MD->getClassInterface();
36295ffd83dbSDimitry Andric   Name = std::string(IFace->getName());
36300b57cec5SDimitry Andric   Name += "__" + MD->getSelector().getAsString();
36310b57cec5SDimitry Andric   // Convert colons to underscores.
36320b57cec5SDimitry Andric   std::string::size_type loc = 0;
36330b57cec5SDimitry Andric   while ((loc = Name.find(':', loc)) != std::string::npos)
36340b57cec5SDimitry Andric     Name.replace(loc, 1, "_");
36350b57cec5SDimitry Andric }
36360b57cec5SDimitry Andric 
36370b57cec5SDimitry Andric void RewriteObjC::InsertBlockLiteralsWithinMethod(ObjCMethodDecl *MD) {
36380b57cec5SDimitry Andric   // fprintf(stderr,"In InsertBlockLiteralsWitinMethod\n");
36390b57cec5SDimitry Andric   // SourceLocation FunLocStart = MD->getBeginLoc();
36400b57cec5SDimitry Andric   SourceLocation FunLocStart = MD->getBeginLoc();
36410b57cec5SDimitry Andric   std::string FuncName;
36420b57cec5SDimitry Andric   BuildUniqueMethodName(FuncName, MD);
36430b57cec5SDimitry Andric   SynthesizeBlockLiterals(FunLocStart, FuncName);
36440b57cec5SDimitry Andric }
36450b57cec5SDimitry Andric 
36460b57cec5SDimitry Andric void RewriteObjC::GetBlockDeclRefExprs(Stmt *S) {
36470b57cec5SDimitry Andric   for (Stmt *SubStmt : S->children())
36480b57cec5SDimitry Andric     if (SubStmt) {
36490b57cec5SDimitry Andric       if (BlockExpr *CBE = dyn_cast<BlockExpr>(SubStmt))
36500b57cec5SDimitry Andric         GetBlockDeclRefExprs(CBE->getBody());
36510b57cec5SDimitry Andric       else
36520b57cec5SDimitry Andric         GetBlockDeclRefExprs(SubStmt);
36530b57cec5SDimitry Andric     }
36540b57cec5SDimitry Andric   // Handle specific things.
36550b57cec5SDimitry Andric   if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(S))
36560b57cec5SDimitry Andric     if (DRE->refersToEnclosingVariableOrCapture() ||
36570b57cec5SDimitry Andric         HasLocalVariableExternalStorage(DRE->getDecl()))
36580b57cec5SDimitry Andric       // FIXME: Handle enums.
36590b57cec5SDimitry Andric       BlockDeclRefs.push_back(DRE);
36600b57cec5SDimitry Andric }
36610b57cec5SDimitry Andric 
36620b57cec5SDimitry Andric void RewriteObjC::GetInnerBlockDeclRefExprs(Stmt *S,
36630b57cec5SDimitry Andric                 SmallVectorImpl<DeclRefExpr *> &InnerBlockDeclRefs,
36640b57cec5SDimitry Andric                 llvm::SmallPtrSetImpl<const DeclContext *> &InnerContexts) {
36650b57cec5SDimitry Andric   for (Stmt *SubStmt : S->children())
36660b57cec5SDimitry Andric     if (SubStmt) {
36670b57cec5SDimitry Andric       if (BlockExpr *CBE = dyn_cast<BlockExpr>(SubStmt)) {
36680b57cec5SDimitry Andric         InnerContexts.insert(cast<DeclContext>(CBE->getBlockDecl()));
36690b57cec5SDimitry Andric         GetInnerBlockDeclRefExprs(CBE->getBody(),
36700b57cec5SDimitry Andric                                   InnerBlockDeclRefs,
36710b57cec5SDimitry Andric                                   InnerContexts);
36720b57cec5SDimitry Andric       }
36730b57cec5SDimitry Andric       else
36740b57cec5SDimitry Andric         GetInnerBlockDeclRefExprs(SubStmt, InnerBlockDeclRefs, InnerContexts);
36750b57cec5SDimitry Andric     }
36760b57cec5SDimitry Andric   // Handle specific things.
36770b57cec5SDimitry Andric   if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(S)) {
36780b57cec5SDimitry Andric     if (DRE->refersToEnclosingVariableOrCapture() ||
36790b57cec5SDimitry Andric         HasLocalVariableExternalStorage(DRE->getDecl())) {
36800b57cec5SDimitry Andric       if (!InnerContexts.count(DRE->getDecl()->getDeclContext()))
36810b57cec5SDimitry Andric         InnerBlockDeclRefs.push_back(DRE);
36820b57cec5SDimitry Andric       if (VarDecl *Var = cast<VarDecl>(DRE->getDecl()))
36830b57cec5SDimitry Andric         if (Var->isFunctionOrMethodVarDecl())
36840b57cec5SDimitry Andric           ImportedLocalExternalDecls.insert(Var);
36850b57cec5SDimitry Andric     }
36860b57cec5SDimitry Andric   }
36870b57cec5SDimitry Andric }
36880b57cec5SDimitry Andric 
36890b57cec5SDimitry Andric /// convertFunctionTypeOfBlocks - This routine converts a function type
36900b57cec5SDimitry Andric /// whose result type may be a block pointer or whose argument type(s)
36910b57cec5SDimitry Andric /// might be block pointers to an equivalent function type replacing
36920b57cec5SDimitry Andric /// all block pointers to function pointers.
36930b57cec5SDimitry Andric QualType RewriteObjC::convertFunctionTypeOfBlocks(const FunctionType *FT) {
36940b57cec5SDimitry Andric   const FunctionProtoType *FTP = dyn_cast<FunctionProtoType>(FT);
36950b57cec5SDimitry Andric   // FTP will be null for closures that don't take arguments.
36960b57cec5SDimitry Andric   // Generate a funky cast.
36970b57cec5SDimitry Andric   SmallVector<QualType, 8> ArgTypes;
36980b57cec5SDimitry Andric   QualType Res = FT->getReturnType();
36990b57cec5SDimitry Andric   bool HasBlockType = convertBlockPointerToFunctionPointer(Res);
37000b57cec5SDimitry Andric 
37010b57cec5SDimitry Andric   if (FTP) {
37020b57cec5SDimitry Andric     for (auto &I : FTP->param_types()) {
37030b57cec5SDimitry Andric       QualType t = I;
37040b57cec5SDimitry Andric       // Make sure we convert "t (^)(...)" to "t (*)(...)".
37050b57cec5SDimitry Andric       if (convertBlockPointerToFunctionPointer(t))
37060b57cec5SDimitry Andric         HasBlockType = true;
37070b57cec5SDimitry Andric       ArgTypes.push_back(t);
37080b57cec5SDimitry Andric     }
37090b57cec5SDimitry Andric   }
37100b57cec5SDimitry Andric   QualType FuncType;
37110b57cec5SDimitry Andric   // FIXME. Does this work if block takes no argument but has a return type
37120b57cec5SDimitry Andric   // which is of block type?
37130b57cec5SDimitry Andric   if (HasBlockType)
37140b57cec5SDimitry Andric     FuncType = getSimpleFunctionType(Res, ArgTypes);
37150b57cec5SDimitry Andric   else FuncType = QualType(FT, 0);
37160b57cec5SDimitry Andric   return FuncType;
37170b57cec5SDimitry Andric }
37180b57cec5SDimitry Andric 
37190b57cec5SDimitry Andric Stmt *RewriteObjC::SynthesizeBlockCall(CallExpr *Exp, const Expr *BlockExp) {
37200b57cec5SDimitry Andric   // Navigate to relevant type information.
37210b57cec5SDimitry Andric   const BlockPointerType *CPT = nullptr;
37220b57cec5SDimitry Andric 
37230b57cec5SDimitry Andric   if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(BlockExp)) {
37240b57cec5SDimitry Andric     CPT = DRE->getType()->getAs<BlockPointerType>();
37250b57cec5SDimitry Andric   } else if (const MemberExpr *MExpr = dyn_cast<MemberExpr>(BlockExp)) {
37260b57cec5SDimitry Andric     CPT = MExpr->getType()->getAs<BlockPointerType>();
37270b57cec5SDimitry Andric   }
37280b57cec5SDimitry Andric   else if (const ParenExpr *PRE = dyn_cast<ParenExpr>(BlockExp)) {
37290b57cec5SDimitry Andric     return SynthesizeBlockCall(Exp, PRE->getSubExpr());
37300b57cec5SDimitry Andric   }
37310b57cec5SDimitry Andric   else if (const ImplicitCastExpr *IEXPR = dyn_cast<ImplicitCastExpr>(BlockExp))
37320b57cec5SDimitry Andric     CPT = IEXPR->getType()->getAs<BlockPointerType>();
37330b57cec5SDimitry Andric   else if (const ConditionalOperator *CEXPR =
37340b57cec5SDimitry Andric             dyn_cast<ConditionalOperator>(BlockExp)) {
37350b57cec5SDimitry Andric     Expr *LHSExp = CEXPR->getLHS();
37360b57cec5SDimitry Andric     Stmt *LHSStmt = SynthesizeBlockCall(Exp, LHSExp);
37370b57cec5SDimitry Andric     Expr *RHSExp = CEXPR->getRHS();
37380b57cec5SDimitry Andric     Stmt *RHSStmt = SynthesizeBlockCall(Exp, RHSExp);
37390b57cec5SDimitry Andric     Expr *CONDExp = CEXPR->getCond();
3740fe6060f1SDimitry Andric     ConditionalOperator *CondExpr = new (Context) ConditionalOperator(
3741fe6060f1SDimitry Andric         CONDExp, SourceLocation(), cast<Expr>(LHSStmt), SourceLocation(),
3742fe6060f1SDimitry Andric         cast<Expr>(RHSStmt), Exp->getType(), VK_PRValue, OK_Ordinary);
37430b57cec5SDimitry Andric     return CondExpr;
37440b57cec5SDimitry Andric   } else if (const ObjCIvarRefExpr *IRE = dyn_cast<ObjCIvarRefExpr>(BlockExp)) {
37450b57cec5SDimitry Andric     CPT = IRE->getType()->getAs<BlockPointerType>();
37460b57cec5SDimitry Andric   } else if (const PseudoObjectExpr *POE
37470b57cec5SDimitry Andric                = dyn_cast<PseudoObjectExpr>(BlockExp)) {
37480b57cec5SDimitry Andric     CPT = POE->getType()->castAs<BlockPointerType>();
37490b57cec5SDimitry Andric   } else {
37500b57cec5SDimitry Andric     assert(false && "RewriteBlockClass: Bad type");
37510b57cec5SDimitry Andric   }
37520b57cec5SDimitry Andric   assert(CPT && "RewriteBlockClass: Bad type");
37530b57cec5SDimitry Andric   const FunctionType *FT = CPT->getPointeeType()->getAs<FunctionType>();
37540b57cec5SDimitry Andric   assert(FT && "RewriteBlockClass: Bad type");
37550b57cec5SDimitry Andric   const FunctionProtoType *FTP = dyn_cast<FunctionProtoType>(FT);
37560b57cec5SDimitry Andric   // FTP will be null for closures that don't take arguments.
37570b57cec5SDimitry Andric 
3758*5f757f3fSDimitry Andric   RecordDecl *RD = RecordDecl::Create(*Context, TagTypeKind::Struct, TUDecl,
37590b57cec5SDimitry Andric                                       SourceLocation(), SourceLocation(),
37600b57cec5SDimitry Andric                                       &Context->Idents.get("__block_impl"));
37610b57cec5SDimitry Andric   QualType PtrBlock = Context->getPointerType(Context->getTagDeclType(RD));
37620b57cec5SDimitry Andric 
37630b57cec5SDimitry Andric   // Generate a funky cast.
37640b57cec5SDimitry Andric   SmallVector<QualType, 8> ArgTypes;
37650b57cec5SDimitry Andric 
37660b57cec5SDimitry Andric   // Push the block argument type.
37670b57cec5SDimitry Andric   ArgTypes.push_back(PtrBlock);
37680b57cec5SDimitry Andric   if (FTP) {
37690b57cec5SDimitry Andric     for (auto &I : FTP->param_types()) {
37700b57cec5SDimitry Andric       QualType t = I;
37710b57cec5SDimitry Andric       // Make sure we convert "t (^)(...)" to "t (*)(...)".
37720b57cec5SDimitry Andric       if (!convertBlockPointerToFunctionPointer(t))
37730b57cec5SDimitry Andric         convertToUnqualifiedObjCType(t);
37740b57cec5SDimitry Andric       ArgTypes.push_back(t);
37750b57cec5SDimitry Andric     }
37760b57cec5SDimitry Andric   }
37770b57cec5SDimitry Andric   // Now do the pointer to function cast.
37780b57cec5SDimitry Andric   QualType PtrToFuncCastType = getSimpleFunctionType(Exp->getType(), ArgTypes);
37790b57cec5SDimitry Andric 
37800b57cec5SDimitry Andric   PtrToFuncCastType = Context->getPointerType(PtrToFuncCastType);
37810b57cec5SDimitry Andric 
37820b57cec5SDimitry Andric   CastExpr *BlkCast = NoTypeInfoCStyleCastExpr(Context, PtrBlock,
37830b57cec5SDimitry Andric                                                CK_BitCast,
37840b57cec5SDimitry Andric                                                const_cast<Expr*>(BlockExp));
37850b57cec5SDimitry Andric   // Don't forget the parens to enforce the proper binding.
37860b57cec5SDimitry Andric   ParenExpr *PE = new (Context) ParenExpr(SourceLocation(), SourceLocation(),
37870b57cec5SDimitry Andric                                           BlkCast);
37880b57cec5SDimitry Andric   //PE->dump();
37890b57cec5SDimitry Andric 
37900b57cec5SDimitry Andric   FieldDecl *FD = FieldDecl::Create(*Context, nullptr, SourceLocation(),
37910b57cec5SDimitry Andric                                     SourceLocation(),
37920b57cec5SDimitry Andric                                     &Context->Idents.get("FuncPtr"),
37930b57cec5SDimitry Andric                                     Context->VoidPtrTy, nullptr,
37940b57cec5SDimitry Andric                                     /*BitWidth=*/nullptr, /*Mutable=*/true,
37950b57cec5SDimitry Andric                                     ICIS_NoInit);
37960b57cec5SDimitry Andric   MemberExpr *ME = MemberExpr::CreateImplicit(
37970b57cec5SDimitry Andric       *Context, PE, true, FD, FD->getType(), VK_LValue, OK_Ordinary);
37980b57cec5SDimitry Andric 
37990b57cec5SDimitry Andric   CastExpr *FunkCast = NoTypeInfoCStyleCastExpr(Context, PtrToFuncCastType,
38000b57cec5SDimitry Andric                                                 CK_BitCast, ME);
38010b57cec5SDimitry Andric   PE = new (Context) ParenExpr(SourceLocation(), SourceLocation(), FunkCast);
38020b57cec5SDimitry Andric 
38030b57cec5SDimitry Andric   SmallVector<Expr*, 8> BlkExprs;
38040b57cec5SDimitry Andric   // Add the implicit argument.
38050b57cec5SDimitry Andric   BlkExprs.push_back(BlkCast);
38060b57cec5SDimitry Andric   // Add the user arguments.
38070b57cec5SDimitry Andric   for (CallExpr::arg_iterator I = Exp->arg_begin(),
38080b57cec5SDimitry Andric        E = Exp->arg_end(); I != E; ++I) {
38090b57cec5SDimitry Andric     BlkExprs.push_back(*I);
38100b57cec5SDimitry Andric   }
3811e8d8bef9SDimitry Andric   CallExpr *CE =
3812fe6060f1SDimitry Andric       CallExpr::Create(*Context, PE, BlkExprs, Exp->getType(), VK_PRValue,
3813e8d8bef9SDimitry Andric                        SourceLocation(), FPOptionsOverride());
38140b57cec5SDimitry Andric   return CE;
38150b57cec5SDimitry Andric }
38160b57cec5SDimitry Andric 
38170b57cec5SDimitry Andric // We need to return the rewritten expression to handle cases where the
38180b57cec5SDimitry Andric // BlockDeclRefExpr is embedded in another expression being rewritten.
38190b57cec5SDimitry Andric // For example:
38200b57cec5SDimitry Andric //
38210b57cec5SDimitry Andric // int main() {
38220b57cec5SDimitry Andric //    __block Foo *f;
38230b57cec5SDimitry Andric //    __block int i;
38240b57cec5SDimitry Andric //
38250b57cec5SDimitry Andric //    void (^myblock)() = ^() {
38260b57cec5SDimitry Andric //        [f test]; // f is a BlockDeclRefExpr embedded in a message (which is being rewritten).
38270b57cec5SDimitry Andric //        i = 77;
38280b57cec5SDimitry Andric //    };
38290b57cec5SDimitry Andric //}
38300b57cec5SDimitry Andric Stmt *RewriteObjC::RewriteBlockDeclRefExpr(DeclRefExpr *DeclRefExp) {
38310b57cec5SDimitry Andric   // Rewrite the byref variable into BYREFVAR->__forwarding->BYREFVAR
38320b57cec5SDimitry Andric   // for each DeclRefExp where BYREFVAR is name of the variable.
38330b57cec5SDimitry Andric   ValueDecl *VD = DeclRefExp->getDecl();
38340b57cec5SDimitry Andric   bool isArrow = DeclRefExp->refersToEnclosingVariableOrCapture() ||
38350b57cec5SDimitry Andric                  HasLocalVariableExternalStorage(DeclRefExp->getDecl());
38360b57cec5SDimitry Andric 
38370b57cec5SDimitry Andric   FieldDecl *FD = FieldDecl::Create(*Context, nullptr, SourceLocation(),
38380b57cec5SDimitry Andric                                     SourceLocation(),
38390b57cec5SDimitry Andric                                     &Context->Idents.get("__forwarding"),
38400b57cec5SDimitry Andric                                     Context->VoidPtrTy, nullptr,
38410b57cec5SDimitry Andric                                     /*BitWidth=*/nullptr, /*Mutable=*/true,
38420b57cec5SDimitry Andric                                     ICIS_NoInit);
38430b57cec5SDimitry Andric   MemberExpr *ME =
38440b57cec5SDimitry Andric       MemberExpr::CreateImplicit(*Context, DeclRefExp, isArrow, FD,
38450b57cec5SDimitry Andric                                  FD->getType(), VK_LValue, OK_Ordinary);
38460b57cec5SDimitry Andric 
38470b57cec5SDimitry Andric   StringRef Name = VD->getName();
38480b57cec5SDimitry Andric   FD = FieldDecl::Create(*Context, nullptr, SourceLocation(), SourceLocation(),
38490b57cec5SDimitry Andric                          &Context->Idents.get(Name),
38500b57cec5SDimitry Andric                          Context->VoidPtrTy, nullptr,
38510b57cec5SDimitry Andric                          /*BitWidth=*/nullptr, /*Mutable=*/true,
38520b57cec5SDimitry Andric                          ICIS_NoInit);
38530b57cec5SDimitry Andric   ME = MemberExpr::CreateImplicit(*Context, ME, true, FD, DeclRefExp->getType(),
38540b57cec5SDimitry Andric                                   VK_LValue, OK_Ordinary);
38550b57cec5SDimitry Andric 
38560b57cec5SDimitry Andric   // Need parens to enforce precedence.
38570b57cec5SDimitry Andric   ParenExpr *PE = new (Context) ParenExpr(DeclRefExp->getExprLoc(),
38580b57cec5SDimitry Andric                                           DeclRefExp->getExprLoc(),
38590b57cec5SDimitry Andric                                           ME);
38600b57cec5SDimitry Andric   ReplaceStmt(DeclRefExp, PE);
38610b57cec5SDimitry Andric   return PE;
38620b57cec5SDimitry Andric }
38630b57cec5SDimitry Andric 
38640b57cec5SDimitry Andric // Rewrites the imported local variable V with external storage
38650b57cec5SDimitry Andric // (static, extern, etc.) as *V
38660b57cec5SDimitry Andric //
38670b57cec5SDimitry Andric Stmt *RewriteObjC::RewriteLocalVariableExternalStorage(DeclRefExpr *DRE) {
38680b57cec5SDimitry Andric   ValueDecl *VD = DRE->getDecl();
38690b57cec5SDimitry Andric   if (VarDecl *Var = dyn_cast<VarDecl>(VD))
38700b57cec5SDimitry Andric     if (!ImportedLocalExternalDecls.count(Var))
38710b57cec5SDimitry Andric       return DRE;
38725ffd83dbSDimitry Andric   Expr *Exp = UnaryOperator::Create(
38735ffd83dbSDimitry Andric       const_cast<ASTContext &>(*Context), DRE, UO_Deref, DRE->getType(),
38745ffd83dbSDimitry Andric       VK_LValue, OK_Ordinary, DRE->getLocation(), false, FPOptionsOverride());
38750b57cec5SDimitry Andric   // Need parens to enforce precedence.
38760b57cec5SDimitry Andric   ParenExpr *PE = new (Context) ParenExpr(SourceLocation(), SourceLocation(),
38770b57cec5SDimitry Andric                                           Exp);
38780b57cec5SDimitry Andric   ReplaceStmt(DRE, PE);
38790b57cec5SDimitry Andric   return PE;
38800b57cec5SDimitry Andric }
38810b57cec5SDimitry Andric 
38820b57cec5SDimitry Andric void RewriteObjC::RewriteCastExpr(CStyleCastExpr *CE) {
38830b57cec5SDimitry Andric   SourceLocation LocStart = CE->getLParenLoc();
38840b57cec5SDimitry Andric   SourceLocation LocEnd = CE->getRParenLoc();
38850b57cec5SDimitry Andric 
38860b57cec5SDimitry Andric   // Need to avoid trying to rewrite synthesized casts.
38870b57cec5SDimitry Andric   if (LocStart.isInvalid())
38880b57cec5SDimitry Andric     return;
38890b57cec5SDimitry Andric   // Need to avoid trying to rewrite casts contained in macros.
38900b57cec5SDimitry Andric   if (!Rewriter::isRewritable(LocStart) || !Rewriter::isRewritable(LocEnd))
38910b57cec5SDimitry Andric     return;
38920b57cec5SDimitry Andric 
38930b57cec5SDimitry Andric   const char *startBuf = SM->getCharacterData(LocStart);
38940b57cec5SDimitry Andric   const char *endBuf = SM->getCharacterData(LocEnd);
38950b57cec5SDimitry Andric   QualType QT = CE->getType();
38960b57cec5SDimitry Andric   const Type* TypePtr = QT->getAs<Type>();
38970b57cec5SDimitry Andric   if (isa<TypeOfExprType>(TypePtr)) {
38980b57cec5SDimitry Andric     const TypeOfExprType *TypeOfExprTypePtr = cast<TypeOfExprType>(TypePtr);
38990b57cec5SDimitry Andric     QT = TypeOfExprTypePtr->getUnderlyingExpr()->getType();
39000b57cec5SDimitry Andric     std::string TypeAsString = "(";
39010b57cec5SDimitry Andric     RewriteBlockPointerType(TypeAsString, QT);
39020b57cec5SDimitry Andric     TypeAsString += ")";
39030b57cec5SDimitry Andric     ReplaceText(LocStart, endBuf-startBuf+1, TypeAsString);
39040b57cec5SDimitry Andric     return;
39050b57cec5SDimitry Andric   }
39060b57cec5SDimitry Andric   // advance the location to startArgList.
39070b57cec5SDimitry Andric   const char *argPtr = startBuf;
39080b57cec5SDimitry Andric 
39090b57cec5SDimitry Andric   while (*argPtr++ && (argPtr < endBuf)) {
39100b57cec5SDimitry Andric     switch (*argPtr) {
39110b57cec5SDimitry Andric     case '^':
39120b57cec5SDimitry Andric       // Replace the '^' with '*'.
39130b57cec5SDimitry Andric       LocStart = LocStart.getLocWithOffset(argPtr-startBuf);
39140b57cec5SDimitry Andric       ReplaceText(LocStart, 1, "*");
39150b57cec5SDimitry Andric       break;
39160b57cec5SDimitry Andric     }
39170b57cec5SDimitry Andric   }
39180b57cec5SDimitry Andric }
39190b57cec5SDimitry Andric 
39200b57cec5SDimitry Andric void RewriteObjC::RewriteBlockPointerFunctionArgs(FunctionDecl *FD) {
39210b57cec5SDimitry Andric   SourceLocation DeclLoc = FD->getLocation();
39220b57cec5SDimitry Andric   unsigned parenCount = 0;
39230b57cec5SDimitry Andric 
39240b57cec5SDimitry Andric   // We have 1 or more arguments that have closure pointers.
39250b57cec5SDimitry Andric   const char *startBuf = SM->getCharacterData(DeclLoc);
39260b57cec5SDimitry Andric   const char *startArgList = strchr(startBuf, '(');
39270b57cec5SDimitry Andric 
39280b57cec5SDimitry Andric   assert((*startArgList == '(') && "Rewriter fuzzy parser confused");
39290b57cec5SDimitry Andric 
39300b57cec5SDimitry Andric   parenCount++;
39310b57cec5SDimitry Andric   // advance the location to startArgList.
39320b57cec5SDimitry Andric   DeclLoc = DeclLoc.getLocWithOffset(startArgList-startBuf);
39330b57cec5SDimitry Andric   assert((DeclLoc.isValid()) && "Invalid DeclLoc");
39340b57cec5SDimitry Andric 
39350b57cec5SDimitry Andric   const char *argPtr = startArgList;
39360b57cec5SDimitry Andric 
39370b57cec5SDimitry Andric   while (*argPtr++ && parenCount) {
39380b57cec5SDimitry Andric     switch (*argPtr) {
39390b57cec5SDimitry Andric     case '^':
39400b57cec5SDimitry Andric       // Replace the '^' with '*'.
39410b57cec5SDimitry Andric       DeclLoc = DeclLoc.getLocWithOffset(argPtr-startArgList);
39420b57cec5SDimitry Andric       ReplaceText(DeclLoc, 1, "*");
39430b57cec5SDimitry Andric       break;
39440b57cec5SDimitry Andric     case '(':
39450b57cec5SDimitry Andric       parenCount++;
39460b57cec5SDimitry Andric       break;
39470b57cec5SDimitry Andric     case ')':
39480b57cec5SDimitry Andric       parenCount--;
39490b57cec5SDimitry Andric       break;
39500b57cec5SDimitry Andric     }
39510b57cec5SDimitry Andric   }
39520b57cec5SDimitry Andric }
39530b57cec5SDimitry Andric 
39540b57cec5SDimitry Andric bool RewriteObjC::PointerTypeTakesAnyBlockArguments(QualType QT) {
39550b57cec5SDimitry Andric   const FunctionProtoType *FTP;
39560b57cec5SDimitry Andric   const PointerType *PT = QT->getAs<PointerType>();
39570b57cec5SDimitry Andric   if (PT) {
39580b57cec5SDimitry Andric     FTP = PT->getPointeeType()->getAs<FunctionProtoType>();
39590b57cec5SDimitry Andric   } else {
39600b57cec5SDimitry Andric     const BlockPointerType *BPT = QT->getAs<BlockPointerType>();
39610b57cec5SDimitry Andric     assert(BPT && "BlockPointerTypeTakeAnyBlockArguments(): not a block pointer type");
39620b57cec5SDimitry Andric     FTP = BPT->getPointeeType()->getAs<FunctionProtoType>();
39630b57cec5SDimitry Andric   }
39640b57cec5SDimitry Andric   if (FTP) {
39650b57cec5SDimitry Andric     for (const auto &I : FTP->param_types())
39660b57cec5SDimitry Andric       if (isTopLevelBlockPointerType(I))
39670b57cec5SDimitry Andric         return true;
39680b57cec5SDimitry Andric   }
39690b57cec5SDimitry Andric   return false;
39700b57cec5SDimitry Andric }
39710b57cec5SDimitry Andric 
39720b57cec5SDimitry Andric bool RewriteObjC::PointerTypeTakesAnyObjCQualifiedType(QualType QT) {
39730b57cec5SDimitry Andric   const FunctionProtoType *FTP;
39740b57cec5SDimitry Andric   const PointerType *PT = QT->getAs<PointerType>();
39750b57cec5SDimitry Andric   if (PT) {
39760b57cec5SDimitry Andric     FTP = PT->getPointeeType()->getAs<FunctionProtoType>();
39770b57cec5SDimitry Andric   } else {
39780b57cec5SDimitry Andric     const BlockPointerType *BPT = QT->getAs<BlockPointerType>();
39790b57cec5SDimitry Andric     assert(BPT && "BlockPointerTypeTakeAnyBlockArguments(): not a block pointer type");
39800b57cec5SDimitry Andric     FTP = BPT->getPointeeType()->getAs<FunctionProtoType>();
39810b57cec5SDimitry Andric   }
39820b57cec5SDimitry Andric   if (FTP) {
39830b57cec5SDimitry Andric     for (const auto &I : FTP->param_types()) {
39840b57cec5SDimitry Andric       if (I->isObjCQualifiedIdType())
39850b57cec5SDimitry Andric         return true;
39860b57cec5SDimitry Andric       if (I->isObjCObjectPointerType() &&
39870b57cec5SDimitry Andric           I->getPointeeType()->isObjCQualifiedInterfaceType())
39880b57cec5SDimitry Andric         return true;
39890b57cec5SDimitry Andric     }
39900b57cec5SDimitry Andric 
39910b57cec5SDimitry Andric   }
39920b57cec5SDimitry Andric   return false;
39930b57cec5SDimitry Andric }
39940b57cec5SDimitry Andric 
39950b57cec5SDimitry Andric void RewriteObjC::GetExtentOfArgList(const char *Name, const char *&LParen,
39960b57cec5SDimitry Andric                                      const char *&RParen) {
39970b57cec5SDimitry Andric   const char *argPtr = strchr(Name, '(');
39980b57cec5SDimitry Andric   assert((*argPtr == '(') && "Rewriter fuzzy parser confused");
39990b57cec5SDimitry Andric 
40000b57cec5SDimitry Andric   LParen = argPtr; // output the start.
40010b57cec5SDimitry Andric   argPtr++; // skip past the left paren.
40020b57cec5SDimitry Andric   unsigned parenCount = 1;
40030b57cec5SDimitry Andric 
40040b57cec5SDimitry Andric   while (*argPtr && parenCount) {
40050b57cec5SDimitry Andric     switch (*argPtr) {
40060b57cec5SDimitry Andric     case '(': parenCount++; break;
40070b57cec5SDimitry Andric     case ')': parenCount--; break;
40080b57cec5SDimitry Andric     default: break;
40090b57cec5SDimitry Andric     }
40100b57cec5SDimitry Andric     if (parenCount) argPtr++;
40110b57cec5SDimitry Andric   }
40120b57cec5SDimitry Andric   assert((*argPtr == ')') && "Rewriter fuzzy parser confused");
40130b57cec5SDimitry Andric   RParen = argPtr; // output the end
40140b57cec5SDimitry Andric }
40150b57cec5SDimitry Andric 
40160b57cec5SDimitry Andric void RewriteObjC::RewriteBlockPointerDecl(NamedDecl *ND) {
40170b57cec5SDimitry Andric   if (FunctionDecl *FD = dyn_cast<FunctionDecl>(ND)) {
40180b57cec5SDimitry Andric     RewriteBlockPointerFunctionArgs(FD);
40190b57cec5SDimitry Andric     return;
40200b57cec5SDimitry Andric   }
40210b57cec5SDimitry Andric   // Handle Variables and Typedefs.
40220b57cec5SDimitry Andric   SourceLocation DeclLoc = ND->getLocation();
40230b57cec5SDimitry Andric   QualType DeclT;
40240b57cec5SDimitry Andric   if (VarDecl *VD = dyn_cast<VarDecl>(ND))
40250b57cec5SDimitry Andric     DeclT = VD->getType();
40260b57cec5SDimitry Andric   else if (TypedefNameDecl *TDD = dyn_cast<TypedefNameDecl>(ND))
40270b57cec5SDimitry Andric     DeclT = TDD->getUnderlyingType();
40280b57cec5SDimitry Andric   else if (FieldDecl *FD = dyn_cast<FieldDecl>(ND))
40290b57cec5SDimitry Andric     DeclT = FD->getType();
40300b57cec5SDimitry Andric   else
40310b57cec5SDimitry Andric     llvm_unreachable("RewriteBlockPointerDecl(): Decl type not yet handled");
40320b57cec5SDimitry Andric 
40330b57cec5SDimitry Andric   const char *startBuf = SM->getCharacterData(DeclLoc);
40340b57cec5SDimitry Andric   const char *endBuf = startBuf;
40350b57cec5SDimitry Andric   // scan backward (from the decl location) for the end of the previous decl.
40360b57cec5SDimitry Andric   while (*startBuf != '^' && *startBuf != ';' && startBuf != MainFileStart)
40370b57cec5SDimitry Andric     startBuf--;
40380b57cec5SDimitry Andric   SourceLocation Start = DeclLoc.getLocWithOffset(startBuf-endBuf);
40390b57cec5SDimitry Andric   std::string buf;
40400b57cec5SDimitry Andric   unsigned OrigLength=0;
40410b57cec5SDimitry Andric   // *startBuf != '^' if we are dealing with a pointer to function that
40420b57cec5SDimitry Andric   // may take block argument types (which will be handled below).
40430b57cec5SDimitry Andric   if (*startBuf == '^') {
40440b57cec5SDimitry Andric     // Replace the '^' with '*', computing a negative offset.
40450b57cec5SDimitry Andric     buf = '*';
40460b57cec5SDimitry Andric     startBuf++;
40470b57cec5SDimitry Andric     OrigLength++;
40480b57cec5SDimitry Andric   }
40490b57cec5SDimitry Andric   while (*startBuf != ')') {
40500b57cec5SDimitry Andric     buf += *startBuf;
40510b57cec5SDimitry Andric     startBuf++;
40520b57cec5SDimitry Andric     OrigLength++;
40530b57cec5SDimitry Andric   }
40540b57cec5SDimitry Andric   buf += ')';
40550b57cec5SDimitry Andric   OrigLength++;
40560b57cec5SDimitry Andric 
40570b57cec5SDimitry Andric   if (PointerTypeTakesAnyBlockArguments(DeclT) ||
40580b57cec5SDimitry Andric       PointerTypeTakesAnyObjCQualifiedType(DeclT)) {
40590b57cec5SDimitry Andric     // Replace the '^' with '*' for arguments.
40600b57cec5SDimitry Andric     // Replace id<P> with id/*<>*/
40610b57cec5SDimitry Andric     DeclLoc = ND->getLocation();
40620b57cec5SDimitry Andric     startBuf = SM->getCharacterData(DeclLoc);
40630b57cec5SDimitry Andric     const char *argListBegin, *argListEnd;
40640b57cec5SDimitry Andric     GetExtentOfArgList(startBuf, argListBegin, argListEnd);
40650b57cec5SDimitry Andric     while (argListBegin < argListEnd) {
40660b57cec5SDimitry Andric       if (*argListBegin == '^')
40670b57cec5SDimitry Andric         buf += '*';
40680b57cec5SDimitry Andric       else if (*argListBegin ==  '<') {
40690b57cec5SDimitry Andric         buf += "/*";
40700b57cec5SDimitry Andric         buf += *argListBegin++;
40710b57cec5SDimitry Andric         OrigLength++;
40720b57cec5SDimitry Andric         while (*argListBegin != '>') {
40730b57cec5SDimitry Andric           buf += *argListBegin++;
40740b57cec5SDimitry Andric           OrigLength++;
40750b57cec5SDimitry Andric         }
40760b57cec5SDimitry Andric         buf += *argListBegin;
40770b57cec5SDimitry Andric         buf += "*/";
40780b57cec5SDimitry Andric       }
40790b57cec5SDimitry Andric       else
40800b57cec5SDimitry Andric         buf += *argListBegin;
40810b57cec5SDimitry Andric       argListBegin++;
40820b57cec5SDimitry Andric       OrigLength++;
40830b57cec5SDimitry Andric     }
40840b57cec5SDimitry Andric     buf += ')';
40850b57cec5SDimitry Andric     OrigLength++;
40860b57cec5SDimitry Andric   }
40870b57cec5SDimitry Andric   ReplaceText(Start, OrigLength, buf);
40880b57cec5SDimitry Andric }
40890b57cec5SDimitry Andric 
40900b57cec5SDimitry Andric /// SynthesizeByrefCopyDestroyHelper - This routine synthesizes:
40910b57cec5SDimitry Andric /// void __Block_byref_id_object_copy(struct Block_byref_id_object *dst,
40920b57cec5SDimitry Andric ///                    struct Block_byref_id_object *src) {
40930b57cec5SDimitry Andric ///  _Block_object_assign (&_dest->object, _src->object,
40940b57cec5SDimitry Andric ///                        BLOCK_BYREF_CALLER | BLOCK_FIELD_IS_OBJECT
40950b57cec5SDimitry Andric ///                        [|BLOCK_FIELD_IS_WEAK]) // object
40960b57cec5SDimitry Andric ///  _Block_object_assign(&_dest->object, _src->object,
40970b57cec5SDimitry Andric ///                       BLOCK_BYREF_CALLER | BLOCK_FIELD_IS_BLOCK
40980b57cec5SDimitry Andric ///                       [|BLOCK_FIELD_IS_WEAK]) // block
40990b57cec5SDimitry Andric /// }
41000b57cec5SDimitry Andric /// And:
41010b57cec5SDimitry Andric /// void __Block_byref_id_object_dispose(struct Block_byref_id_object *_src) {
41020b57cec5SDimitry Andric ///  _Block_object_dispose(_src->object,
41030b57cec5SDimitry Andric ///                        BLOCK_BYREF_CALLER | BLOCK_FIELD_IS_OBJECT
41040b57cec5SDimitry Andric ///                        [|BLOCK_FIELD_IS_WEAK]) // object
41050b57cec5SDimitry Andric ///  _Block_object_dispose(_src->object,
41060b57cec5SDimitry Andric ///                         BLOCK_BYREF_CALLER | BLOCK_FIELD_IS_BLOCK
41070b57cec5SDimitry Andric ///                         [|BLOCK_FIELD_IS_WEAK]) // block
41080b57cec5SDimitry Andric /// }
41090b57cec5SDimitry Andric 
41100b57cec5SDimitry Andric std::string RewriteObjC::SynthesizeByrefCopyDestroyHelper(VarDecl *VD,
41110b57cec5SDimitry Andric                                                           int flag) {
41120b57cec5SDimitry Andric   std::string S;
41130b57cec5SDimitry Andric   if (CopyDestroyCache.count(flag))
41140b57cec5SDimitry Andric     return S;
41150b57cec5SDimitry Andric   CopyDestroyCache.insert(flag);
41160b57cec5SDimitry Andric   S = "static void __Block_byref_id_object_copy_";
41170b57cec5SDimitry Andric   S += utostr(flag);
41180b57cec5SDimitry Andric   S += "(void *dst, void *src) {\n";
41190b57cec5SDimitry Andric 
41200b57cec5SDimitry Andric   // offset into the object pointer is computed as:
41210b57cec5SDimitry Andric   // void * + void* + int + int + void* + void *
41220b57cec5SDimitry Andric   unsigned IntSize =
41230b57cec5SDimitry Andric   static_cast<unsigned>(Context->getTypeSize(Context->IntTy));
41240b57cec5SDimitry Andric   unsigned VoidPtrSize =
41250b57cec5SDimitry Andric   static_cast<unsigned>(Context->getTypeSize(Context->VoidPtrTy));
41260b57cec5SDimitry Andric 
41270b57cec5SDimitry Andric   unsigned offset = (VoidPtrSize*4 + IntSize + IntSize)/Context->getCharWidth();
41280b57cec5SDimitry Andric   S += " _Block_object_assign((char*)dst + ";
41290b57cec5SDimitry Andric   S += utostr(offset);
41300b57cec5SDimitry Andric   S += ", *(void * *) ((char*)src + ";
41310b57cec5SDimitry Andric   S += utostr(offset);
41320b57cec5SDimitry Andric   S += "), ";
41330b57cec5SDimitry Andric   S += utostr(flag);
41340b57cec5SDimitry Andric   S += ");\n}\n";
41350b57cec5SDimitry Andric 
41360b57cec5SDimitry Andric   S += "static void __Block_byref_id_object_dispose_";
41370b57cec5SDimitry Andric   S += utostr(flag);
41380b57cec5SDimitry Andric   S += "(void *src) {\n";
41390b57cec5SDimitry Andric   S += " _Block_object_dispose(*(void * *) ((char*)src + ";
41400b57cec5SDimitry Andric   S += utostr(offset);
41410b57cec5SDimitry Andric   S += "), ";
41420b57cec5SDimitry Andric   S += utostr(flag);
41430b57cec5SDimitry Andric   S += ");\n}\n";
41440b57cec5SDimitry Andric   return S;
41450b57cec5SDimitry Andric }
41460b57cec5SDimitry Andric 
41470b57cec5SDimitry Andric /// RewriteByRefVar - For each __block typex ND variable this routine transforms
41480b57cec5SDimitry Andric /// the declaration into:
41490b57cec5SDimitry Andric /// struct __Block_byref_ND {
41500b57cec5SDimitry Andric /// void *__isa;                  // NULL for everything except __weak pointers
41510b57cec5SDimitry Andric /// struct __Block_byref_ND *__forwarding;
41520b57cec5SDimitry Andric /// int32_t __flags;
41530b57cec5SDimitry Andric /// int32_t __size;
41540b57cec5SDimitry Andric /// void *__Block_byref_id_object_copy; // If variable is __block ObjC object
41550b57cec5SDimitry Andric /// void *__Block_byref_id_object_dispose; // If variable is __block ObjC object
41560b57cec5SDimitry Andric /// typex ND;
41570b57cec5SDimitry Andric /// };
41580b57cec5SDimitry Andric ///
41590b57cec5SDimitry Andric /// It then replaces declaration of ND variable with:
41600b57cec5SDimitry Andric /// struct __Block_byref_ND ND = {__isa=0B, __forwarding=&ND, __flags=some_flag,
41610b57cec5SDimitry Andric ///                               __size=sizeof(struct __Block_byref_ND),
41620b57cec5SDimitry Andric ///                               ND=initializer-if-any};
41630b57cec5SDimitry Andric ///
41640b57cec5SDimitry Andric ///
41650b57cec5SDimitry Andric void RewriteObjC::RewriteByRefVar(VarDecl *ND) {
41660b57cec5SDimitry Andric   // Insert declaration for the function in which block literal is
41670b57cec5SDimitry Andric   // used.
41680b57cec5SDimitry Andric   if (CurFunctionDeclToDeclareForBlock)
41690b57cec5SDimitry Andric     RewriteBlockLiteralFunctionDecl(CurFunctionDeclToDeclareForBlock);
41700b57cec5SDimitry Andric   int flag = 0;
41710b57cec5SDimitry Andric   int isa = 0;
41720b57cec5SDimitry Andric   SourceLocation DeclLoc = ND->getTypeSpecStartLoc();
41730b57cec5SDimitry Andric   if (DeclLoc.isInvalid())
41740b57cec5SDimitry Andric     // If type location is missing, it is because of missing type (a warning).
41750b57cec5SDimitry Andric     // Use variable's location which is good for this case.
41760b57cec5SDimitry Andric     DeclLoc = ND->getLocation();
41770b57cec5SDimitry Andric   const char *startBuf = SM->getCharacterData(DeclLoc);
41780b57cec5SDimitry Andric   SourceLocation X = ND->getEndLoc();
41790b57cec5SDimitry Andric   X = SM->getExpansionLoc(X);
41800b57cec5SDimitry Andric   const char *endBuf = SM->getCharacterData(X);
41810b57cec5SDimitry Andric   std::string Name(ND->getNameAsString());
41820b57cec5SDimitry Andric   std::string ByrefType;
41830b57cec5SDimitry Andric   RewriteByRefString(ByrefType, Name, ND, true);
41840b57cec5SDimitry Andric   ByrefType += " {\n";
41850b57cec5SDimitry Andric   ByrefType += "  void *__isa;\n";
41860b57cec5SDimitry Andric   RewriteByRefString(ByrefType, Name, ND);
41870b57cec5SDimitry Andric   ByrefType += " *__forwarding;\n";
41880b57cec5SDimitry Andric   ByrefType += " int __flags;\n";
41890b57cec5SDimitry Andric   ByrefType += " int __size;\n";
41900b57cec5SDimitry Andric   // Add void *__Block_byref_id_object_copy;
41910b57cec5SDimitry Andric   // void *__Block_byref_id_object_dispose; if needed.
41920b57cec5SDimitry Andric   QualType Ty = ND->getType();
41930b57cec5SDimitry Andric   bool HasCopyAndDispose = Context->BlockRequiresCopying(Ty, ND);
41940b57cec5SDimitry Andric   if (HasCopyAndDispose) {
41950b57cec5SDimitry Andric     ByrefType += " void (*__Block_byref_id_object_copy)(void*, void*);\n";
41960b57cec5SDimitry Andric     ByrefType += " void (*__Block_byref_id_object_dispose)(void*);\n";
41970b57cec5SDimitry Andric   }
41980b57cec5SDimitry Andric 
41990b57cec5SDimitry Andric   QualType T = Ty;
42000b57cec5SDimitry Andric   (void)convertBlockPointerToFunctionPointer(T);
42010b57cec5SDimitry Andric   T.getAsStringInternal(Name, Context->getPrintingPolicy());
42020b57cec5SDimitry Andric 
42030b57cec5SDimitry Andric   ByrefType += " " + Name + ";\n";
42040b57cec5SDimitry Andric   ByrefType += "};\n";
42050b57cec5SDimitry Andric   // Insert this type in global scope. It is needed by helper function.
42060b57cec5SDimitry Andric   SourceLocation FunLocStart;
42070b57cec5SDimitry Andric   if (CurFunctionDef)
42080b57cec5SDimitry Andric      FunLocStart = CurFunctionDef->getTypeSpecStartLoc();
42090b57cec5SDimitry Andric   else {
42100b57cec5SDimitry Andric     assert(CurMethodDef && "RewriteByRefVar - CurMethodDef is null");
42110b57cec5SDimitry Andric     FunLocStart = CurMethodDef->getBeginLoc();
42120b57cec5SDimitry Andric   }
42130b57cec5SDimitry Andric   InsertText(FunLocStart, ByrefType);
42140b57cec5SDimitry Andric   if (Ty.isObjCGCWeak()) {
42150b57cec5SDimitry Andric     flag |= BLOCK_FIELD_IS_WEAK;
42160b57cec5SDimitry Andric     isa = 1;
42170b57cec5SDimitry Andric   }
42180b57cec5SDimitry Andric 
42190b57cec5SDimitry Andric   if (HasCopyAndDispose) {
42200b57cec5SDimitry Andric     flag = BLOCK_BYREF_CALLER;
42210b57cec5SDimitry Andric     QualType Ty = ND->getType();
42220b57cec5SDimitry Andric     // FIXME. Handle __weak variable (BLOCK_FIELD_IS_WEAK) as well.
42230b57cec5SDimitry Andric     if (Ty->isBlockPointerType())
42240b57cec5SDimitry Andric       flag |= BLOCK_FIELD_IS_BLOCK;
42250b57cec5SDimitry Andric     else
42260b57cec5SDimitry Andric       flag |= BLOCK_FIELD_IS_OBJECT;
42270b57cec5SDimitry Andric     std::string HF = SynthesizeByrefCopyDestroyHelper(ND, flag);
42280b57cec5SDimitry Andric     if (!HF.empty())
42290b57cec5SDimitry Andric       InsertText(FunLocStart, HF);
42300b57cec5SDimitry Andric   }
42310b57cec5SDimitry Andric 
42320b57cec5SDimitry Andric   // struct __Block_byref_ND ND =
42330b57cec5SDimitry Andric   // {0, &ND, some_flag, __size=sizeof(struct __Block_byref_ND),
42340b57cec5SDimitry Andric   //  initializer-if-any};
42350b57cec5SDimitry Andric   bool hasInit = (ND->getInit() != nullptr);
42360b57cec5SDimitry Andric   unsigned flags = 0;
42370b57cec5SDimitry Andric   if (HasCopyAndDispose)
42380b57cec5SDimitry Andric     flags |= BLOCK_HAS_COPY_DISPOSE;
42390b57cec5SDimitry Andric   Name = ND->getNameAsString();
42400b57cec5SDimitry Andric   ByrefType.clear();
42410b57cec5SDimitry Andric   RewriteByRefString(ByrefType, Name, ND);
42420b57cec5SDimitry Andric   std::string ForwardingCastType("(");
42430b57cec5SDimitry Andric   ForwardingCastType += ByrefType + " *)";
42440b57cec5SDimitry Andric   if (!hasInit) {
42450b57cec5SDimitry Andric     ByrefType += " " + Name + " = {(void*)";
42460b57cec5SDimitry Andric     ByrefType += utostr(isa);
42470b57cec5SDimitry Andric     ByrefType += "," +  ForwardingCastType + "&" + Name + ", ";
42480b57cec5SDimitry Andric     ByrefType += utostr(flags);
42490b57cec5SDimitry Andric     ByrefType += ", ";
42500b57cec5SDimitry Andric     ByrefType += "sizeof(";
42510b57cec5SDimitry Andric     RewriteByRefString(ByrefType, Name, ND);
42520b57cec5SDimitry Andric     ByrefType += ")";
42530b57cec5SDimitry Andric     if (HasCopyAndDispose) {
42540b57cec5SDimitry Andric       ByrefType += ", __Block_byref_id_object_copy_";
42550b57cec5SDimitry Andric       ByrefType += utostr(flag);
42560b57cec5SDimitry Andric       ByrefType += ", __Block_byref_id_object_dispose_";
42570b57cec5SDimitry Andric       ByrefType += utostr(flag);
42580b57cec5SDimitry Andric     }
42590b57cec5SDimitry Andric     ByrefType += "};\n";
42600b57cec5SDimitry Andric     unsigned nameSize = Name.size();
42610b57cec5SDimitry Andric     // for block or function pointer declaration. Name is already
42620b57cec5SDimitry Andric     // part of the declaration.
42630b57cec5SDimitry Andric     if (Ty->isBlockPointerType() || Ty->isFunctionPointerType())
42640b57cec5SDimitry Andric       nameSize = 1;
42650b57cec5SDimitry Andric     ReplaceText(DeclLoc, endBuf-startBuf+nameSize, ByrefType);
42660b57cec5SDimitry Andric   }
42670b57cec5SDimitry Andric   else {
42680b57cec5SDimitry Andric     SourceLocation startLoc;
42690b57cec5SDimitry Andric     Expr *E = ND->getInit();
42700b57cec5SDimitry Andric     if (const CStyleCastExpr *ECE = dyn_cast<CStyleCastExpr>(E))
42710b57cec5SDimitry Andric       startLoc = ECE->getLParenLoc();
42720b57cec5SDimitry Andric     else
42730b57cec5SDimitry Andric       startLoc = E->getBeginLoc();
42740b57cec5SDimitry Andric     startLoc = SM->getExpansionLoc(startLoc);
42750b57cec5SDimitry Andric     endBuf = SM->getCharacterData(startLoc);
42760b57cec5SDimitry Andric     ByrefType += " " + Name;
42770b57cec5SDimitry Andric     ByrefType += " = {(void*)";
42780b57cec5SDimitry Andric     ByrefType += utostr(isa);
42790b57cec5SDimitry Andric     ByrefType += "," +  ForwardingCastType + "&" + Name + ", ";
42800b57cec5SDimitry Andric     ByrefType += utostr(flags);
42810b57cec5SDimitry Andric     ByrefType += ", ";
42820b57cec5SDimitry Andric     ByrefType += "sizeof(";
42830b57cec5SDimitry Andric     RewriteByRefString(ByrefType, Name, ND);
42840b57cec5SDimitry Andric     ByrefType += "), ";
42850b57cec5SDimitry Andric     if (HasCopyAndDispose) {
42860b57cec5SDimitry Andric       ByrefType += "__Block_byref_id_object_copy_";
42870b57cec5SDimitry Andric       ByrefType += utostr(flag);
42880b57cec5SDimitry Andric       ByrefType += ", __Block_byref_id_object_dispose_";
42890b57cec5SDimitry Andric       ByrefType += utostr(flag);
42900b57cec5SDimitry Andric       ByrefType += ", ";
42910b57cec5SDimitry Andric     }
42920b57cec5SDimitry Andric     ReplaceText(DeclLoc, endBuf-startBuf, ByrefType);
42930b57cec5SDimitry Andric 
42940b57cec5SDimitry Andric     // Complete the newly synthesized compound expression by inserting a right
42950b57cec5SDimitry Andric     // curly brace before the end of the declaration.
42960b57cec5SDimitry Andric     // FIXME: This approach avoids rewriting the initializer expression. It
42970b57cec5SDimitry Andric     // also assumes there is only one declarator. For example, the following
42980b57cec5SDimitry Andric     // isn't currently supported by this routine (in general):
42990b57cec5SDimitry Andric     //
43000b57cec5SDimitry Andric     // double __block BYREFVAR = 1.34, BYREFVAR2 = 1.37;
43010b57cec5SDimitry Andric     //
43020b57cec5SDimitry Andric     const char *startInitializerBuf = SM->getCharacterData(startLoc);
43030b57cec5SDimitry Andric     const char *semiBuf = strchr(startInitializerBuf, ';');
43040b57cec5SDimitry Andric     assert((*semiBuf == ';') && "RewriteByRefVar: can't find ';'");
43050b57cec5SDimitry Andric     SourceLocation semiLoc =
43060b57cec5SDimitry Andric       startLoc.getLocWithOffset(semiBuf-startInitializerBuf);
43070b57cec5SDimitry Andric 
43080b57cec5SDimitry Andric     InsertText(semiLoc, "}");
43090b57cec5SDimitry Andric   }
43100b57cec5SDimitry Andric }
43110b57cec5SDimitry Andric 
43120b57cec5SDimitry Andric void RewriteObjC::CollectBlockDeclRefInfo(BlockExpr *Exp) {
43130b57cec5SDimitry Andric   // Add initializers for any closure decl refs.
43140b57cec5SDimitry Andric   GetBlockDeclRefExprs(Exp->getBody());
43150b57cec5SDimitry Andric   if (BlockDeclRefs.size()) {
43160b57cec5SDimitry Andric     // Unique all "by copy" declarations.
43170b57cec5SDimitry Andric     for (unsigned i = 0; i < BlockDeclRefs.size(); i++)
43180b57cec5SDimitry Andric       if (!BlockDeclRefs[i]->getDecl()->hasAttr<BlocksAttr>()) {
43190b57cec5SDimitry Andric         if (!BlockByCopyDeclsPtrSet.count(BlockDeclRefs[i]->getDecl())) {
43200b57cec5SDimitry Andric           BlockByCopyDeclsPtrSet.insert(BlockDeclRefs[i]->getDecl());
43210b57cec5SDimitry Andric           BlockByCopyDecls.push_back(BlockDeclRefs[i]->getDecl());
43220b57cec5SDimitry Andric         }
43230b57cec5SDimitry Andric       }
43240b57cec5SDimitry Andric     // Unique all "by ref" declarations.
43250b57cec5SDimitry Andric     for (unsigned i = 0; i < BlockDeclRefs.size(); i++)
43260b57cec5SDimitry Andric       if (BlockDeclRefs[i]->getDecl()->hasAttr<BlocksAttr>()) {
43270b57cec5SDimitry Andric         if (!BlockByRefDeclsPtrSet.count(BlockDeclRefs[i]->getDecl())) {
43280b57cec5SDimitry Andric           BlockByRefDeclsPtrSet.insert(BlockDeclRefs[i]->getDecl());
43290b57cec5SDimitry Andric           BlockByRefDecls.push_back(BlockDeclRefs[i]->getDecl());
43300b57cec5SDimitry Andric         }
43310b57cec5SDimitry Andric       }
43320b57cec5SDimitry Andric     // Find any imported blocks...they will need special attention.
43330b57cec5SDimitry Andric     for (unsigned i = 0; i < BlockDeclRefs.size(); i++)
43340b57cec5SDimitry Andric       if (BlockDeclRefs[i]->getDecl()->hasAttr<BlocksAttr>() ||
43350b57cec5SDimitry Andric           BlockDeclRefs[i]->getType()->isObjCObjectPointerType() ||
43360b57cec5SDimitry Andric           BlockDeclRefs[i]->getType()->isBlockPointerType())
43370b57cec5SDimitry Andric         ImportedBlockDecls.insert(BlockDeclRefs[i]->getDecl());
43380b57cec5SDimitry Andric   }
43390b57cec5SDimitry Andric }
43400b57cec5SDimitry Andric 
43410b57cec5SDimitry Andric FunctionDecl *RewriteObjC::SynthBlockInitFunctionDecl(StringRef name) {
43420b57cec5SDimitry Andric   IdentifierInfo *ID = &Context->Idents.get(name);
43430b57cec5SDimitry Andric   QualType FType = Context->getFunctionNoProtoType(Context->VoidPtrTy);
43440b57cec5SDimitry Andric   return FunctionDecl::Create(*Context, TUDecl, SourceLocation(),
43450b57cec5SDimitry Andric                               SourceLocation(), ID, FType, nullptr, SC_Extern,
43460b57cec5SDimitry Andric                               false, false);
43470b57cec5SDimitry Andric }
43480b57cec5SDimitry Andric 
43490b57cec5SDimitry Andric Stmt *RewriteObjC::SynthBlockInitExpr(BlockExpr *Exp,
43500b57cec5SDimitry Andric                      const SmallVectorImpl<DeclRefExpr *> &InnerBlockDeclRefs) {
43510b57cec5SDimitry Andric   const BlockDecl *block = Exp->getBlockDecl();
43520b57cec5SDimitry Andric   Blocks.push_back(Exp);
43530b57cec5SDimitry Andric 
43540b57cec5SDimitry Andric   CollectBlockDeclRefInfo(Exp);
43550b57cec5SDimitry Andric 
43560b57cec5SDimitry Andric   // Add inner imported variables now used in current block.
43570b57cec5SDimitry Andric  int countOfInnerDecls = 0;
43580b57cec5SDimitry Andric   if (!InnerBlockDeclRefs.empty()) {
43590b57cec5SDimitry Andric     for (unsigned i = 0; i < InnerBlockDeclRefs.size(); i++) {
43600b57cec5SDimitry Andric       DeclRefExpr *Exp = InnerBlockDeclRefs[i];
43610b57cec5SDimitry Andric       ValueDecl *VD = Exp->getDecl();
43620b57cec5SDimitry Andric       if (!VD->hasAttr<BlocksAttr>() && !BlockByCopyDeclsPtrSet.count(VD)) {
43630b57cec5SDimitry Andric       // We need to save the copied-in variables in nested
43640b57cec5SDimitry Andric       // blocks because it is needed at the end for some of the API generations.
43650b57cec5SDimitry Andric       // See SynthesizeBlockLiterals routine.
43660b57cec5SDimitry Andric         InnerDeclRefs.push_back(Exp); countOfInnerDecls++;
43670b57cec5SDimitry Andric         BlockDeclRefs.push_back(Exp);
43680b57cec5SDimitry Andric         BlockByCopyDeclsPtrSet.insert(VD);
43690b57cec5SDimitry Andric         BlockByCopyDecls.push_back(VD);
43700b57cec5SDimitry Andric       }
43710b57cec5SDimitry Andric       if (VD->hasAttr<BlocksAttr>() && !BlockByRefDeclsPtrSet.count(VD)) {
43720b57cec5SDimitry Andric         InnerDeclRefs.push_back(Exp); countOfInnerDecls++;
43730b57cec5SDimitry Andric         BlockDeclRefs.push_back(Exp);
43740b57cec5SDimitry Andric         BlockByRefDeclsPtrSet.insert(VD);
43750b57cec5SDimitry Andric         BlockByRefDecls.push_back(VD);
43760b57cec5SDimitry Andric       }
43770b57cec5SDimitry Andric     }
43780b57cec5SDimitry Andric     // Find any imported blocks...they will need special attention.
43790b57cec5SDimitry Andric     for (unsigned i = 0; i < InnerBlockDeclRefs.size(); i++)
43800b57cec5SDimitry Andric       if (InnerBlockDeclRefs[i]->getDecl()->hasAttr<BlocksAttr>() ||
43810b57cec5SDimitry Andric           InnerBlockDeclRefs[i]->getType()->isObjCObjectPointerType() ||
43820b57cec5SDimitry Andric           InnerBlockDeclRefs[i]->getType()->isBlockPointerType())
43830b57cec5SDimitry Andric         ImportedBlockDecls.insert(InnerBlockDeclRefs[i]->getDecl());
43840b57cec5SDimitry Andric   }
43850b57cec5SDimitry Andric   InnerDeclRefsCount.push_back(countOfInnerDecls);
43860b57cec5SDimitry Andric 
43870b57cec5SDimitry Andric   std::string FuncName;
43880b57cec5SDimitry Andric 
43890b57cec5SDimitry Andric   if (CurFunctionDef)
43900b57cec5SDimitry Andric     FuncName = CurFunctionDef->getNameAsString();
43910b57cec5SDimitry Andric   else if (CurMethodDef)
43920b57cec5SDimitry Andric     BuildUniqueMethodName(FuncName, CurMethodDef);
43930b57cec5SDimitry Andric   else if (GlobalVarDecl)
43940b57cec5SDimitry Andric     FuncName = std::string(GlobalVarDecl->getNameAsString());
43950b57cec5SDimitry Andric 
43960b57cec5SDimitry Andric   std::string BlockNumber = utostr(Blocks.size()-1);
43970b57cec5SDimitry Andric 
43980b57cec5SDimitry Andric   std::string Tag = "__" + FuncName + "_block_impl_" + BlockNumber;
43990b57cec5SDimitry Andric   std::string Func = "__" + FuncName + "_block_func_" + BlockNumber;
44000b57cec5SDimitry Andric 
44010b57cec5SDimitry Andric   // Get a pointer to the function type so we can cast appropriately.
44020b57cec5SDimitry Andric   QualType BFT = convertFunctionTypeOfBlocks(Exp->getFunctionType());
44030b57cec5SDimitry Andric   QualType FType = Context->getPointerType(BFT);
44040b57cec5SDimitry Andric 
44050b57cec5SDimitry Andric   FunctionDecl *FD;
44060b57cec5SDimitry Andric   Expr *NewRep;
44070b57cec5SDimitry Andric 
44080b57cec5SDimitry Andric   // Simulate a constructor call...
44090b57cec5SDimitry Andric   FD = SynthBlockInitFunctionDecl(Tag);
44100b57cec5SDimitry Andric   DeclRefExpr *DRE = new (Context)
4411fe6060f1SDimitry Andric       DeclRefExpr(*Context, FD, false, FType, VK_PRValue, SourceLocation());
44120b57cec5SDimitry Andric 
44130b57cec5SDimitry Andric   SmallVector<Expr*, 4> InitExprs;
44140b57cec5SDimitry Andric 
44150b57cec5SDimitry Andric   // Initialize the block function.
44160b57cec5SDimitry Andric   FD = SynthBlockInitFunctionDecl(Func);
44170b57cec5SDimitry Andric   DeclRefExpr *Arg = new (Context) DeclRefExpr(
44180b57cec5SDimitry Andric       *Context, FD, false, FD->getType(), VK_LValue, SourceLocation());
44190b57cec5SDimitry Andric   CastExpr *castExpr =
44200b57cec5SDimitry Andric       NoTypeInfoCStyleCastExpr(Context, Context->VoidPtrTy, CK_BitCast, Arg);
44210b57cec5SDimitry Andric   InitExprs.push_back(castExpr);
44220b57cec5SDimitry Andric 
44230b57cec5SDimitry Andric   // Initialize the block descriptor.
44240b57cec5SDimitry Andric   std::string DescData = "__" + FuncName + "_block_desc_" + BlockNumber + "_DATA";
44250b57cec5SDimitry Andric 
44260b57cec5SDimitry Andric   VarDecl *NewVD = VarDecl::Create(
44270b57cec5SDimitry Andric       *Context, TUDecl, SourceLocation(), SourceLocation(),
44280b57cec5SDimitry Andric       &Context->Idents.get(DescData), Context->VoidPtrTy, nullptr, SC_Static);
44295ffd83dbSDimitry Andric   UnaryOperator *DescRefExpr = UnaryOperator::Create(
44305ffd83dbSDimitry Andric       const_cast<ASTContext &>(*Context),
44310b57cec5SDimitry Andric       new (Context) DeclRefExpr(*Context, NewVD, false, Context->VoidPtrTy,
44320b57cec5SDimitry Andric                                 VK_LValue, SourceLocation()),
4433fe6060f1SDimitry Andric       UO_AddrOf, Context->getPointerType(Context->VoidPtrTy), VK_PRValue,
44345ffd83dbSDimitry Andric       OK_Ordinary, SourceLocation(), false, FPOptionsOverride());
44350b57cec5SDimitry Andric   InitExprs.push_back(DescRefExpr);
44360b57cec5SDimitry Andric 
44370b57cec5SDimitry Andric   // Add initializers for any closure decl refs.
44380b57cec5SDimitry Andric   if (BlockDeclRefs.size()) {
44390b57cec5SDimitry Andric     Expr *Exp;
44400b57cec5SDimitry Andric     // Output all "by copy" declarations.
44410b57cec5SDimitry Andric     for (SmallVectorImpl<ValueDecl *>::iterator I = BlockByCopyDecls.begin(),
44420b57cec5SDimitry Andric          E = BlockByCopyDecls.end(); I != E; ++I) {
44430b57cec5SDimitry Andric       if (isObjCType((*I)->getType())) {
44440b57cec5SDimitry Andric         // FIXME: Conform to ABI ([[obj retain] autorelease]).
44450b57cec5SDimitry Andric         FD = SynthBlockInitFunctionDecl((*I)->getName());
44460b57cec5SDimitry Andric         Exp = new (Context) DeclRefExpr(*Context, FD, false, FD->getType(),
44470b57cec5SDimitry Andric                                         VK_LValue, SourceLocation());
44480b57cec5SDimitry Andric         if (HasLocalVariableExternalStorage(*I)) {
44490b57cec5SDimitry Andric           QualType QT = (*I)->getType();
44500b57cec5SDimitry Andric           QT = Context->getPointerType(QT);
4451fe6060f1SDimitry Andric           Exp = UnaryOperator::Create(const_cast<ASTContext &>(*Context), Exp,
4452fe6060f1SDimitry Andric                                       UO_AddrOf, QT, VK_PRValue, OK_Ordinary,
4453fe6060f1SDimitry Andric                                       SourceLocation(), false,
4454fe6060f1SDimitry Andric                                       FPOptionsOverride());
44550b57cec5SDimitry Andric         }
44560b57cec5SDimitry Andric       } else if (isTopLevelBlockPointerType((*I)->getType())) {
44570b57cec5SDimitry Andric         FD = SynthBlockInitFunctionDecl((*I)->getName());
44580b57cec5SDimitry Andric         Arg = new (Context) DeclRefExpr(*Context, FD, false, FD->getType(),
44590b57cec5SDimitry Andric                                         VK_LValue, SourceLocation());
44600b57cec5SDimitry Andric         Exp = NoTypeInfoCStyleCastExpr(Context, Context->VoidPtrTy, CK_BitCast,
44610b57cec5SDimitry Andric                                        Arg);
44620b57cec5SDimitry Andric       } else {
44630b57cec5SDimitry Andric         FD = SynthBlockInitFunctionDecl((*I)->getName());
44640b57cec5SDimitry Andric         Exp = new (Context) DeclRefExpr(*Context, FD, false, FD->getType(),
44650b57cec5SDimitry Andric                                         VK_LValue, SourceLocation());
44660b57cec5SDimitry Andric         if (HasLocalVariableExternalStorage(*I)) {
44670b57cec5SDimitry Andric           QualType QT = (*I)->getType();
44680b57cec5SDimitry Andric           QT = Context->getPointerType(QT);
4469fe6060f1SDimitry Andric           Exp = UnaryOperator::Create(const_cast<ASTContext &>(*Context), Exp,
4470fe6060f1SDimitry Andric                                       UO_AddrOf, QT, VK_PRValue, OK_Ordinary,
4471fe6060f1SDimitry Andric                                       SourceLocation(), false,
4472fe6060f1SDimitry Andric                                       FPOptionsOverride());
44730b57cec5SDimitry Andric         }
44740b57cec5SDimitry Andric       }
44750b57cec5SDimitry Andric       InitExprs.push_back(Exp);
44760b57cec5SDimitry Andric     }
44770b57cec5SDimitry Andric     // Output all "by ref" declarations.
44780b57cec5SDimitry Andric     for (SmallVectorImpl<ValueDecl *>::iterator I = BlockByRefDecls.begin(),
44790b57cec5SDimitry Andric          E = BlockByRefDecls.end(); I != E; ++I) {
44800b57cec5SDimitry Andric       ValueDecl *ND = (*I);
44810b57cec5SDimitry Andric       std::string Name(ND->getNameAsString());
44820b57cec5SDimitry Andric       std::string RecName;
44830b57cec5SDimitry Andric       RewriteByRefString(RecName, Name, ND, true);
44840b57cec5SDimitry Andric       IdentifierInfo *II = &Context->Idents.get(RecName.c_str()
44850b57cec5SDimitry Andric                                                 + sizeof("struct"));
4486*5f757f3fSDimitry Andric       RecordDecl *RD =
4487*5f757f3fSDimitry Andric           RecordDecl::Create(*Context, TagTypeKind::Struct, TUDecl,
4488*5f757f3fSDimitry Andric                              SourceLocation(), SourceLocation(), II);
44890b57cec5SDimitry Andric       assert(RD && "SynthBlockInitExpr(): Can't find RecordDecl");
44900b57cec5SDimitry Andric       QualType castT = Context->getPointerType(Context->getTagDeclType(RD));
44910b57cec5SDimitry Andric 
44920b57cec5SDimitry Andric       FD = SynthBlockInitFunctionDecl((*I)->getName());
44930b57cec5SDimitry Andric       Exp = new (Context) DeclRefExpr(*Context, FD, false, FD->getType(),
44940b57cec5SDimitry Andric                                       VK_LValue, SourceLocation());
44950b57cec5SDimitry Andric       bool isNestedCapturedVar = false;
44960b57cec5SDimitry Andric       if (block)
44970b57cec5SDimitry Andric         for (const auto &CI : block->captures()) {
44980b57cec5SDimitry Andric           const VarDecl *variable = CI.getVariable();
44990b57cec5SDimitry Andric           if (variable == ND && CI.isNested()) {
45000b57cec5SDimitry Andric             assert (CI.isByRef() &&
45010b57cec5SDimitry Andric                     "SynthBlockInitExpr - captured block variable is not byref");
45020b57cec5SDimitry Andric             isNestedCapturedVar = true;
45030b57cec5SDimitry Andric             break;
45040b57cec5SDimitry Andric           }
45050b57cec5SDimitry Andric         }
45060b57cec5SDimitry Andric       // captured nested byref variable has its address passed. Do not take
45070b57cec5SDimitry Andric       // its address again.
45080b57cec5SDimitry Andric       if (!isNestedCapturedVar)
45095ffd83dbSDimitry Andric         Exp = UnaryOperator::Create(
45105ffd83dbSDimitry Andric             const_cast<ASTContext &>(*Context), Exp, UO_AddrOf,
4511fe6060f1SDimitry Andric             Context->getPointerType(Exp->getType()), VK_PRValue, OK_Ordinary,
45125ffd83dbSDimitry Andric             SourceLocation(), false, FPOptionsOverride());
45130b57cec5SDimitry Andric       Exp = NoTypeInfoCStyleCastExpr(Context, castT, CK_BitCast, Exp);
45140b57cec5SDimitry Andric       InitExprs.push_back(Exp);
45150b57cec5SDimitry Andric     }
45160b57cec5SDimitry Andric   }
45170b57cec5SDimitry Andric   if (ImportedBlockDecls.size()) {
45180b57cec5SDimitry Andric     // generate BLOCK_HAS_COPY_DISPOSE(have helper funcs) | BLOCK_HAS_DESCRIPTOR
45190b57cec5SDimitry Andric     int flag = (BLOCK_HAS_COPY_DISPOSE | BLOCK_HAS_DESCRIPTOR);
45200b57cec5SDimitry Andric     unsigned IntSize =
45210b57cec5SDimitry Andric       static_cast<unsigned>(Context->getTypeSize(Context->IntTy));
45220b57cec5SDimitry Andric     Expr *FlagExp = IntegerLiteral::Create(*Context, llvm::APInt(IntSize, flag),
45230b57cec5SDimitry Andric                                            Context->IntTy, SourceLocation());
45240b57cec5SDimitry Andric     InitExprs.push_back(FlagExp);
45250b57cec5SDimitry Andric   }
45260b57cec5SDimitry Andric   NewRep = CallExpr::Create(*Context, DRE, InitExprs, FType, VK_LValue,
4527e8d8bef9SDimitry Andric                             SourceLocation(), FPOptionsOverride());
45285ffd83dbSDimitry Andric   NewRep = UnaryOperator::Create(
45295ffd83dbSDimitry Andric       const_cast<ASTContext &>(*Context), NewRep, UO_AddrOf,
4530fe6060f1SDimitry Andric       Context->getPointerType(NewRep->getType()), VK_PRValue, OK_Ordinary,
45315ffd83dbSDimitry Andric       SourceLocation(), false, FPOptionsOverride());
45320b57cec5SDimitry Andric   NewRep = NoTypeInfoCStyleCastExpr(Context, FType, CK_BitCast,
45330b57cec5SDimitry Andric                                     NewRep);
45340b57cec5SDimitry Andric   BlockDeclRefs.clear();
45350b57cec5SDimitry Andric   BlockByRefDecls.clear();
45360b57cec5SDimitry Andric   BlockByRefDeclsPtrSet.clear();
45370b57cec5SDimitry Andric   BlockByCopyDecls.clear();
45380b57cec5SDimitry Andric   BlockByCopyDeclsPtrSet.clear();
45390b57cec5SDimitry Andric   ImportedBlockDecls.clear();
45400b57cec5SDimitry Andric   return NewRep;
45410b57cec5SDimitry Andric }
45420b57cec5SDimitry Andric 
45430b57cec5SDimitry Andric bool RewriteObjC::IsDeclStmtInForeachHeader(DeclStmt *DS) {
45440b57cec5SDimitry Andric   if (const ObjCForCollectionStmt * CS =
45450b57cec5SDimitry Andric       dyn_cast<ObjCForCollectionStmt>(Stmts.back()))
45460b57cec5SDimitry Andric         return CS->getElement() == DS;
45470b57cec5SDimitry Andric   return false;
45480b57cec5SDimitry Andric }
45490b57cec5SDimitry Andric 
45500b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
45510b57cec5SDimitry Andric // Function Body / Expression rewriting
45520b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
45530b57cec5SDimitry Andric 
45540b57cec5SDimitry Andric Stmt *RewriteObjC::RewriteFunctionBodyOrGlobalInitializer(Stmt *S) {
45550b57cec5SDimitry Andric   if (isa<SwitchStmt>(S) || isa<WhileStmt>(S) ||
45560b57cec5SDimitry Andric       isa<DoStmt>(S) || isa<ForStmt>(S))
45570b57cec5SDimitry Andric     Stmts.push_back(S);
45580b57cec5SDimitry Andric   else if (isa<ObjCForCollectionStmt>(S)) {
45590b57cec5SDimitry Andric     Stmts.push_back(S);
45600b57cec5SDimitry Andric     ObjCBcLabelNo.push_back(++BcLabelCount);
45610b57cec5SDimitry Andric   }
45620b57cec5SDimitry Andric 
45630b57cec5SDimitry Andric   // Pseudo-object operations and ivar references need special
45640b57cec5SDimitry Andric   // treatment because we're going to recursively rewrite them.
45650b57cec5SDimitry Andric   if (PseudoObjectExpr *PseudoOp = dyn_cast<PseudoObjectExpr>(S)) {
45660b57cec5SDimitry Andric     if (isa<BinaryOperator>(PseudoOp->getSyntacticForm())) {
45670b57cec5SDimitry Andric       return RewritePropertyOrImplicitSetter(PseudoOp);
45680b57cec5SDimitry Andric     } else {
45690b57cec5SDimitry Andric       return RewritePropertyOrImplicitGetter(PseudoOp);
45700b57cec5SDimitry Andric     }
45710b57cec5SDimitry Andric   } else if (ObjCIvarRefExpr *IvarRefExpr = dyn_cast<ObjCIvarRefExpr>(S)) {
45720b57cec5SDimitry Andric     return RewriteObjCIvarRefExpr(IvarRefExpr);
45730b57cec5SDimitry Andric   }
45740b57cec5SDimitry Andric 
45750b57cec5SDimitry Andric   SourceRange OrigStmtRange = S->getSourceRange();
45760b57cec5SDimitry Andric 
45770b57cec5SDimitry Andric   // Perform a bottom up rewrite of all children.
45780b57cec5SDimitry Andric   for (Stmt *&childStmt : S->children())
45790b57cec5SDimitry Andric     if (childStmt) {
45800b57cec5SDimitry Andric       Stmt *newStmt = RewriteFunctionBodyOrGlobalInitializer(childStmt);
45810b57cec5SDimitry Andric       if (newStmt) {
45820b57cec5SDimitry Andric         childStmt = newStmt;
45830b57cec5SDimitry Andric       }
45840b57cec5SDimitry Andric     }
45850b57cec5SDimitry Andric 
45860b57cec5SDimitry Andric   if (BlockExpr *BE = dyn_cast<BlockExpr>(S)) {
45870b57cec5SDimitry Andric     SmallVector<DeclRefExpr *, 8> InnerBlockDeclRefs;
45880b57cec5SDimitry Andric     llvm::SmallPtrSet<const DeclContext *, 8> InnerContexts;
45890b57cec5SDimitry Andric     InnerContexts.insert(BE->getBlockDecl());
45900b57cec5SDimitry Andric     ImportedLocalExternalDecls.clear();
45910b57cec5SDimitry Andric     GetInnerBlockDeclRefExprs(BE->getBody(),
45920b57cec5SDimitry Andric                               InnerBlockDeclRefs, InnerContexts);
45930b57cec5SDimitry Andric     // Rewrite the block body in place.
45940b57cec5SDimitry Andric     Stmt *SaveCurrentBody = CurrentBody;
45950b57cec5SDimitry Andric     CurrentBody = BE->getBody();
45960b57cec5SDimitry Andric     PropParentMap = nullptr;
45970b57cec5SDimitry Andric     // block literal on rhs of a property-dot-sytax assignment
45980b57cec5SDimitry Andric     // must be replaced by its synthesize ast so getRewrittenText
45990b57cec5SDimitry Andric     // works as expected. In this case, what actually ends up on RHS
46000b57cec5SDimitry Andric     // is the blockTranscribed which is the helper function for the
46010b57cec5SDimitry Andric     // block literal; as in: self.c = ^() {[ace ARR];};
46020b57cec5SDimitry Andric     bool saveDisableReplaceStmt = DisableReplaceStmt;
46030b57cec5SDimitry Andric     DisableReplaceStmt = false;
46040b57cec5SDimitry Andric     RewriteFunctionBodyOrGlobalInitializer(BE->getBody());
46050b57cec5SDimitry Andric     DisableReplaceStmt = saveDisableReplaceStmt;
46060b57cec5SDimitry Andric     CurrentBody = SaveCurrentBody;
46070b57cec5SDimitry Andric     PropParentMap = nullptr;
46080b57cec5SDimitry Andric     ImportedLocalExternalDecls.clear();
46090b57cec5SDimitry Andric     // Now we snarf the rewritten text and stash it away for later use.
46100b57cec5SDimitry Andric     std::string Str = Rewrite.getRewrittenText(BE->getSourceRange());
46110b57cec5SDimitry Andric     RewrittenBlockExprs[BE] = Str;
46120b57cec5SDimitry Andric 
46130b57cec5SDimitry Andric     Stmt *blockTranscribed = SynthBlockInitExpr(BE, InnerBlockDeclRefs);
46140b57cec5SDimitry Andric 
46150b57cec5SDimitry Andric     //blockTranscribed->dump();
46160b57cec5SDimitry Andric     ReplaceStmt(S, blockTranscribed);
46170b57cec5SDimitry Andric     return blockTranscribed;
46180b57cec5SDimitry Andric   }
46190b57cec5SDimitry Andric   // Handle specific things.
46200b57cec5SDimitry Andric   if (ObjCEncodeExpr *AtEncode = dyn_cast<ObjCEncodeExpr>(S))
46210b57cec5SDimitry Andric     return RewriteAtEncode(AtEncode);
46220b57cec5SDimitry Andric 
46230b57cec5SDimitry Andric   if (ObjCSelectorExpr *AtSelector = dyn_cast<ObjCSelectorExpr>(S))
46240b57cec5SDimitry Andric     return RewriteAtSelector(AtSelector);
46250b57cec5SDimitry Andric 
46260b57cec5SDimitry Andric   if (ObjCStringLiteral *AtString = dyn_cast<ObjCStringLiteral>(S))
46270b57cec5SDimitry Andric     return RewriteObjCStringLiteral(AtString);
46280b57cec5SDimitry Andric 
46290b57cec5SDimitry Andric   if (ObjCMessageExpr *MessExpr = dyn_cast<ObjCMessageExpr>(S)) {
46300b57cec5SDimitry Andric #if 0
46310b57cec5SDimitry Andric     // Before we rewrite it, put the original message expression in a comment.
46320b57cec5SDimitry Andric     SourceLocation startLoc = MessExpr->getBeginLoc();
46330b57cec5SDimitry Andric     SourceLocation endLoc = MessExpr->getEndLoc();
46340b57cec5SDimitry Andric 
46350b57cec5SDimitry Andric     const char *startBuf = SM->getCharacterData(startLoc);
46360b57cec5SDimitry Andric     const char *endBuf = SM->getCharacterData(endLoc);
46370b57cec5SDimitry Andric 
46380b57cec5SDimitry Andric     std::string messString;
46390b57cec5SDimitry Andric     messString += "// ";
46400b57cec5SDimitry Andric     messString.append(startBuf, endBuf-startBuf+1);
46410b57cec5SDimitry Andric     messString += "\n";
46420b57cec5SDimitry Andric 
46430b57cec5SDimitry Andric     // FIXME: Missing definition of
46440b57cec5SDimitry Andric     // InsertText(clang::SourceLocation, char const*, unsigned int).
46450b57cec5SDimitry Andric     // InsertText(startLoc, messString);
46460b57cec5SDimitry Andric     // Tried this, but it didn't work either...
46470b57cec5SDimitry Andric     // ReplaceText(startLoc, 0, messString.c_str(), messString.size());
46480b57cec5SDimitry Andric #endif
46490b57cec5SDimitry Andric     return RewriteMessageExpr(MessExpr);
46500b57cec5SDimitry Andric   }
46510b57cec5SDimitry Andric 
46520b57cec5SDimitry Andric   if (ObjCAtTryStmt *StmtTry = dyn_cast<ObjCAtTryStmt>(S))
46530b57cec5SDimitry Andric     return RewriteObjCTryStmt(StmtTry);
46540b57cec5SDimitry Andric 
46550b57cec5SDimitry Andric   if (ObjCAtSynchronizedStmt *StmtTry = dyn_cast<ObjCAtSynchronizedStmt>(S))
46560b57cec5SDimitry Andric     return RewriteObjCSynchronizedStmt(StmtTry);
46570b57cec5SDimitry Andric 
46580b57cec5SDimitry Andric   if (ObjCAtThrowStmt *StmtThrow = dyn_cast<ObjCAtThrowStmt>(S))
46590b57cec5SDimitry Andric     return RewriteObjCThrowStmt(StmtThrow);
46600b57cec5SDimitry Andric 
46610b57cec5SDimitry Andric   if (ObjCProtocolExpr *ProtocolExp = dyn_cast<ObjCProtocolExpr>(S))
46620b57cec5SDimitry Andric     return RewriteObjCProtocolExpr(ProtocolExp);
46630b57cec5SDimitry Andric 
46640b57cec5SDimitry Andric   if (ObjCForCollectionStmt *StmtForCollection =
46650b57cec5SDimitry Andric         dyn_cast<ObjCForCollectionStmt>(S))
46660b57cec5SDimitry Andric     return RewriteObjCForCollectionStmt(StmtForCollection,
46670b57cec5SDimitry Andric                                         OrigStmtRange.getEnd());
46680b57cec5SDimitry Andric   if (BreakStmt *StmtBreakStmt =
46690b57cec5SDimitry Andric       dyn_cast<BreakStmt>(S))
46700b57cec5SDimitry Andric     return RewriteBreakStmt(StmtBreakStmt);
46710b57cec5SDimitry Andric   if (ContinueStmt *StmtContinueStmt =
46720b57cec5SDimitry Andric       dyn_cast<ContinueStmt>(S))
46730b57cec5SDimitry Andric     return RewriteContinueStmt(StmtContinueStmt);
46740b57cec5SDimitry Andric 
46750b57cec5SDimitry Andric   // Need to check for protocol refs (id <P>, Foo <P> *) in variable decls
46760b57cec5SDimitry Andric   // and cast exprs.
46770b57cec5SDimitry Andric   if (DeclStmt *DS = dyn_cast<DeclStmt>(S)) {
46780b57cec5SDimitry Andric     // FIXME: What we're doing here is modifying the type-specifier that
46790b57cec5SDimitry Andric     // precedes the first Decl.  In the future the DeclGroup should have
46800b57cec5SDimitry Andric     // a separate type-specifier that we can rewrite.
46810b57cec5SDimitry Andric     // NOTE: We need to avoid rewriting the DeclStmt if it is within
46820b57cec5SDimitry Andric     // the context of an ObjCForCollectionStmt. For example:
46830b57cec5SDimitry Andric     //   NSArray *someArray;
46840b57cec5SDimitry Andric     //   for (id <FooProtocol> index in someArray) ;
46850b57cec5SDimitry Andric     // This is because RewriteObjCForCollectionStmt() does textual rewriting
46860b57cec5SDimitry Andric     // and it depends on the original text locations/positions.
46870b57cec5SDimitry Andric     if (Stmts.empty() || !IsDeclStmtInForeachHeader(DS))
46880b57cec5SDimitry Andric       RewriteObjCQualifiedInterfaceTypes(*DS->decl_begin());
46890b57cec5SDimitry Andric 
46900b57cec5SDimitry Andric     // Blocks rewrite rules.
46910b57cec5SDimitry Andric     for (auto *SD : DS->decls()) {
46920b57cec5SDimitry Andric       if (ValueDecl *ND = dyn_cast<ValueDecl>(SD)) {
46930b57cec5SDimitry Andric         if (isTopLevelBlockPointerType(ND->getType()))
46940b57cec5SDimitry Andric           RewriteBlockPointerDecl(ND);
46950b57cec5SDimitry Andric         else if (ND->getType()->isFunctionPointerType())
46960b57cec5SDimitry Andric           CheckFunctionPointerDecl(ND->getType(), ND);
46970b57cec5SDimitry Andric         if (VarDecl *VD = dyn_cast<VarDecl>(SD)) {
46980b57cec5SDimitry Andric           if (VD->hasAttr<BlocksAttr>()) {
46990b57cec5SDimitry Andric             static unsigned uniqueByrefDeclCount = 0;
47000b57cec5SDimitry Andric             assert(!BlockByRefDeclNo.count(ND) &&
47010b57cec5SDimitry Andric               "RewriteFunctionBodyOrGlobalInitializer: Duplicate byref decl");
47020b57cec5SDimitry Andric             BlockByRefDeclNo[ND] = uniqueByrefDeclCount++;
47030b57cec5SDimitry Andric             RewriteByRefVar(VD);
47040b57cec5SDimitry Andric           }
47050b57cec5SDimitry Andric           else
47060b57cec5SDimitry Andric             RewriteTypeOfDecl(VD);
47070b57cec5SDimitry Andric         }
47080b57cec5SDimitry Andric       }
47090b57cec5SDimitry Andric       if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(SD)) {
47100b57cec5SDimitry Andric         if (isTopLevelBlockPointerType(TD->getUnderlyingType()))
47110b57cec5SDimitry Andric           RewriteBlockPointerDecl(TD);
47120b57cec5SDimitry Andric         else if (TD->getUnderlyingType()->isFunctionPointerType())
47130b57cec5SDimitry Andric           CheckFunctionPointerDecl(TD->getUnderlyingType(), TD);
47140b57cec5SDimitry Andric       }
47150b57cec5SDimitry Andric     }
47160b57cec5SDimitry Andric   }
47170b57cec5SDimitry Andric 
47180b57cec5SDimitry Andric   if (CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(S))
47190b57cec5SDimitry Andric     RewriteObjCQualifiedInterfaceTypes(CE);
47200b57cec5SDimitry Andric 
47210b57cec5SDimitry Andric   if (isa<SwitchStmt>(S) || isa<WhileStmt>(S) ||
47220b57cec5SDimitry Andric       isa<DoStmt>(S) || isa<ForStmt>(S)) {
47230b57cec5SDimitry Andric     assert(!Stmts.empty() && "Statement stack is empty");
47240b57cec5SDimitry Andric     assert ((isa<SwitchStmt>(Stmts.back()) || isa<WhileStmt>(Stmts.back()) ||
47250b57cec5SDimitry Andric              isa<DoStmt>(Stmts.back()) || isa<ForStmt>(Stmts.back()))
47260b57cec5SDimitry Andric             && "Statement stack mismatch");
47270b57cec5SDimitry Andric     Stmts.pop_back();
47280b57cec5SDimitry Andric   }
47290b57cec5SDimitry Andric   // Handle blocks rewriting.
47300b57cec5SDimitry Andric   if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(S)) {
47310b57cec5SDimitry Andric     ValueDecl *VD = DRE->getDecl();
47320b57cec5SDimitry Andric     if (VD->hasAttr<BlocksAttr>())
47330b57cec5SDimitry Andric       return RewriteBlockDeclRefExpr(DRE);
47340b57cec5SDimitry Andric     if (HasLocalVariableExternalStorage(VD))
47350b57cec5SDimitry Andric       return RewriteLocalVariableExternalStorage(DRE);
47360b57cec5SDimitry Andric   }
47370b57cec5SDimitry Andric 
47380b57cec5SDimitry Andric   if (CallExpr *CE = dyn_cast<CallExpr>(S)) {
47390b57cec5SDimitry Andric     if (CE->getCallee()->getType()->isBlockPointerType()) {
47400b57cec5SDimitry Andric       Stmt *BlockCall = SynthesizeBlockCall(CE, CE->getCallee());
47410b57cec5SDimitry Andric       ReplaceStmt(S, BlockCall);
47420b57cec5SDimitry Andric       return BlockCall;
47430b57cec5SDimitry Andric     }
47440b57cec5SDimitry Andric   }
47450b57cec5SDimitry Andric   if (CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(S)) {
47460b57cec5SDimitry Andric     RewriteCastExpr(CE);
47470b57cec5SDimitry Andric   }
47480b57cec5SDimitry Andric #if 0
47490b57cec5SDimitry Andric   if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(S)) {
47500b57cec5SDimitry Andric     CastExpr *Replacement = new (Context) CastExpr(ICE->getType(),
47510b57cec5SDimitry Andric                                                    ICE->getSubExpr(),
47520b57cec5SDimitry Andric                                                    SourceLocation());
47530b57cec5SDimitry Andric     // Get the new text.
47540b57cec5SDimitry Andric     std::string SStr;
47550b57cec5SDimitry Andric     llvm::raw_string_ostream Buf(SStr);
47560b57cec5SDimitry Andric     Replacement->printPretty(Buf);
47570b57cec5SDimitry Andric     const std::string &Str = Buf.str();
47580b57cec5SDimitry Andric 
47590b57cec5SDimitry Andric     printf("CAST = %s\n", &Str[0]);
47600b57cec5SDimitry Andric     InsertText(ICE->getSubExpr()->getBeginLoc(), Str);
47610b57cec5SDimitry Andric     delete S;
47620b57cec5SDimitry Andric     return Replacement;
47630b57cec5SDimitry Andric   }
47640b57cec5SDimitry Andric #endif
47650b57cec5SDimitry Andric   // Return this stmt unmodified.
47660b57cec5SDimitry Andric   return S;
47670b57cec5SDimitry Andric }
47680b57cec5SDimitry Andric 
47690b57cec5SDimitry Andric void RewriteObjC::RewriteRecordBody(RecordDecl *RD) {
47700b57cec5SDimitry Andric   for (auto *FD : RD->fields()) {
47710b57cec5SDimitry Andric     if (isTopLevelBlockPointerType(FD->getType()))
47720b57cec5SDimitry Andric       RewriteBlockPointerDecl(FD);
47730b57cec5SDimitry Andric     if (FD->getType()->isObjCQualifiedIdType() ||
47740b57cec5SDimitry Andric         FD->getType()->isObjCQualifiedInterfaceType())
47750b57cec5SDimitry Andric       RewriteObjCQualifiedInterfaceTypes(FD);
47760b57cec5SDimitry Andric   }
47770b57cec5SDimitry Andric }
47780b57cec5SDimitry Andric 
47790b57cec5SDimitry Andric /// HandleDeclInMainFile - This is called for each top-level decl defined in the
47800b57cec5SDimitry Andric /// main file of the input.
47810b57cec5SDimitry Andric void RewriteObjC::HandleDeclInMainFile(Decl *D) {
47820b57cec5SDimitry Andric   switch (D->getKind()) {
47830b57cec5SDimitry Andric     case Decl::Function: {
47840b57cec5SDimitry Andric       FunctionDecl *FD = cast<FunctionDecl>(D);
47850b57cec5SDimitry Andric       if (FD->isOverloadedOperator())
47860b57cec5SDimitry Andric         return;
47870b57cec5SDimitry Andric 
47880b57cec5SDimitry Andric       // Since function prototypes don't have ParmDecl's, we check the function
47890b57cec5SDimitry Andric       // prototype. This enables us to rewrite function declarations and
47900b57cec5SDimitry Andric       // definitions using the same code.
47910b57cec5SDimitry Andric       RewriteBlocksInFunctionProtoType(FD->getType(), FD);
47920b57cec5SDimitry Andric 
47930b57cec5SDimitry Andric       if (!FD->isThisDeclarationADefinition())
47940b57cec5SDimitry Andric         break;
47950b57cec5SDimitry Andric 
47960b57cec5SDimitry Andric       // FIXME: If this should support Obj-C++, support CXXTryStmt
47970b57cec5SDimitry Andric       if (CompoundStmt *Body = dyn_cast_or_null<CompoundStmt>(FD->getBody())) {
47980b57cec5SDimitry Andric         CurFunctionDef = FD;
47990b57cec5SDimitry Andric         CurFunctionDeclToDeclareForBlock = FD;
48000b57cec5SDimitry Andric         CurrentBody = Body;
48010b57cec5SDimitry Andric         Body =
48020b57cec5SDimitry Andric         cast_or_null<CompoundStmt>(RewriteFunctionBodyOrGlobalInitializer(Body));
48030b57cec5SDimitry Andric         FD->setBody(Body);
48040b57cec5SDimitry Andric         CurrentBody = nullptr;
48050b57cec5SDimitry Andric         if (PropParentMap) {
48060b57cec5SDimitry Andric           delete PropParentMap;
48070b57cec5SDimitry Andric           PropParentMap = nullptr;
48080b57cec5SDimitry Andric         }
48090b57cec5SDimitry Andric         // This synthesizes and inserts the block "impl" struct, invoke function,
48100b57cec5SDimitry Andric         // and any copy/dispose helper functions.
48110b57cec5SDimitry Andric         InsertBlockLiteralsWithinFunction(FD);
48120b57cec5SDimitry Andric         CurFunctionDef = nullptr;
48130b57cec5SDimitry Andric         CurFunctionDeclToDeclareForBlock = nullptr;
48140b57cec5SDimitry Andric       }
48150b57cec5SDimitry Andric       break;
48160b57cec5SDimitry Andric     }
48170b57cec5SDimitry Andric     case Decl::ObjCMethod: {
48180b57cec5SDimitry Andric       ObjCMethodDecl *MD = cast<ObjCMethodDecl>(D);
48190b57cec5SDimitry Andric       if (CompoundStmt *Body = MD->getCompoundBody()) {
48200b57cec5SDimitry Andric         CurMethodDef = MD;
48210b57cec5SDimitry Andric         CurrentBody = Body;
48220b57cec5SDimitry Andric         Body =
48230b57cec5SDimitry Andric           cast_or_null<CompoundStmt>(RewriteFunctionBodyOrGlobalInitializer(Body));
48240b57cec5SDimitry Andric         MD->setBody(Body);
48250b57cec5SDimitry Andric         CurrentBody = nullptr;
48260b57cec5SDimitry Andric         if (PropParentMap) {
48270b57cec5SDimitry Andric           delete PropParentMap;
48280b57cec5SDimitry Andric           PropParentMap = nullptr;
48290b57cec5SDimitry Andric         }
48300b57cec5SDimitry Andric         InsertBlockLiteralsWithinMethod(MD);
48310b57cec5SDimitry Andric         CurMethodDef = nullptr;
48320b57cec5SDimitry Andric       }
48330b57cec5SDimitry Andric       break;
48340b57cec5SDimitry Andric     }
48350b57cec5SDimitry Andric     case Decl::ObjCImplementation: {
48360b57cec5SDimitry Andric       ObjCImplementationDecl *CI = cast<ObjCImplementationDecl>(D);
48370b57cec5SDimitry Andric       ClassImplementation.push_back(CI);
48380b57cec5SDimitry Andric       break;
48390b57cec5SDimitry Andric     }
48400b57cec5SDimitry Andric     case Decl::ObjCCategoryImpl: {
48410b57cec5SDimitry Andric       ObjCCategoryImplDecl *CI = cast<ObjCCategoryImplDecl>(D);
48420b57cec5SDimitry Andric       CategoryImplementation.push_back(CI);
48430b57cec5SDimitry Andric       break;
48440b57cec5SDimitry Andric     }
48450b57cec5SDimitry Andric     case Decl::Var: {
48460b57cec5SDimitry Andric       VarDecl *VD = cast<VarDecl>(D);
48470b57cec5SDimitry Andric       RewriteObjCQualifiedInterfaceTypes(VD);
48480b57cec5SDimitry Andric       if (isTopLevelBlockPointerType(VD->getType()))
48490b57cec5SDimitry Andric         RewriteBlockPointerDecl(VD);
48500b57cec5SDimitry Andric       else if (VD->getType()->isFunctionPointerType()) {
48510b57cec5SDimitry Andric         CheckFunctionPointerDecl(VD->getType(), VD);
48520b57cec5SDimitry Andric         if (VD->getInit()) {
48530b57cec5SDimitry Andric           if (CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(VD->getInit())) {
48540b57cec5SDimitry Andric             RewriteCastExpr(CE);
48550b57cec5SDimitry Andric           }
48560b57cec5SDimitry Andric         }
48570b57cec5SDimitry Andric       } else if (VD->getType()->isRecordType()) {
4858a7dea167SDimitry Andric         RecordDecl *RD = VD->getType()->castAs<RecordType>()->getDecl();
48590b57cec5SDimitry Andric         if (RD->isCompleteDefinition())
48600b57cec5SDimitry Andric           RewriteRecordBody(RD);
48610b57cec5SDimitry Andric       }
48620b57cec5SDimitry Andric       if (VD->getInit()) {
48630b57cec5SDimitry Andric         GlobalVarDecl = VD;
48640b57cec5SDimitry Andric         CurrentBody = VD->getInit();
48650b57cec5SDimitry Andric         RewriteFunctionBodyOrGlobalInitializer(VD->getInit());
48660b57cec5SDimitry Andric         CurrentBody = nullptr;
48670b57cec5SDimitry Andric         if (PropParentMap) {
48680b57cec5SDimitry Andric           delete PropParentMap;
48690b57cec5SDimitry Andric           PropParentMap = nullptr;
48700b57cec5SDimitry Andric         }
48710b57cec5SDimitry Andric         SynthesizeBlockLiterals(VD->getTypeSpecStartLoc(), VD->getName());
48720b57cec5SDimitry Andric         GlobalVarDecl = nullptr;
48730b57cec5SDimitry Andric 
48740b57cec5SDimitry Andric         // This is needed for blocks.
48750b57cec5SDimitry Andric         if (CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(VD->getInit())) {
48760b57cec5SDimitry Andric             RewriteCastExpr(CE);
48770b57cec5SDimitry Andric         }
48780b57cec5SDimitry Andric       }
48790b57cec5SDimitry Andric       break;
48800b57cec5SDimitry Andric     }
48810b57cec5SDimitry Andric     case Decl::TypeAlias:
48820b57cec5SDimitry Andric     case Decl::Typedef: {
48830b57cec5SDimitry Andric       if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(D)) {
48840b57cec5SDimitry Andric         if (isTopLevelBlockPointerType(TD->getUnderlyingType()))
48850b57cec5SDimitry Andric           RewriteBlockPointerDecl(TD);
48860b57cec5SDimitry Andric         else if (TD->getUnderlyingType()->isFunctionPointerType())
48870b57cec5SDimitry Andric           CheckFunctionPointerDecl(TD->getUnderlyingType(), TD);
48880b57cec5SDimitry Andric       }
48890b57cec5SDimitry Andric       break;
48900b57cec5SDimitry Andric     }
48910b57cec5SDimitry Andric     case Decl::CXXRecord:
48920b57cec5SDimitry Andric     case Decl::Record: {
48930b57cec5SDimitry Andric       RecordDecl *RD = cast<RecordDecl>(D);
48940b57cec5SDimitry Andric       if (RD->isCompleteDefinition())
48950b57cec5SDimitry Andric         RewriteRecordBody(RD);
48960b57cec5SDimitry Andric       break;
48970b57cec5SDimitry Andric     }
48980b57cec5SDimitry Andric     default:
48990b57cec5SDimitry Andric       break;
49000b57cec5SDimitry Andric   }
49010b57cec5SDimitry Andric   // Nothing yet.
49020b57cec5SDimitry Andric }
49030b57cec5SDimitry Andric 
49040b57cec5SDimitry Andric void RewriteObjC::HandleTranslationUnit(ASTContext &C) {
49050b57cec5SDimitry Andric   if (Diags.hasErrorOccurred())
49060b57cec5SDimitry Andric     return;
49070b57cec5SDimitry Andric 
49080b57cec5SDimitry Andric   RewriteInclude();
49090b57cec5SDimitry Andric 
49100b57cec5SDimitry Andric   // Here's a great place to add any extra declarations that may be needed.
49110b57cec5SDimitry Andric   // Write out meta data for each @protocol(<expr>).
49120b57cec5SDimitry Andric   for (ObjCProtocolDecl *ProtDecl : ProtocolExprDecls)
49130b57cec5SDimitry Andric     RewriteObjCProtocolMetaData(ProtDecl, "", "", Preamble);
49140b57cec5SDimitry Andric 
49150b57cec5SDimitry Andric   InsertText(SM->getLocForStartOfFile(MainFileID), Preamble, false);
49160b57cec5SDimitry Andric   if (ClassImplementation.size() || CategoryImplementation.size())
49170b57cec5SDimitry Andric     RewriteImplementations();
49180b57cec5SDimitry Andric 
49190b57cec5SDimitry Andric   // Get the buffer corresponding to MainFileID.  If we haven't changed it, then
49200b57cec5SDimitry Andric   // we are done.
49210b57cec5SDimitry Andric   if (const RewriteBuffer *RewriteBuf =
49220b57cec5SDimitry Andric       Rewrite.getRewriteBufferFor(MainFileID)) {
49230b57cec5SDimitry Andric     //printf("Changed:\n");
49240b57cec5SDimitry Andric     *OutFile << std::string(RewriteBuf->begin(), RewriteBuf->end());
49250b57cec5SDimitry Andric   } else {
49260b57cec5SDimitry Andric     llvm::errs() << "No changes\n";
49270b57cec5SDimitry Andric   }
49280b57cec5SDimitry Andric 
49290b57cec5SDimitry Andric   if (ClassImplementation.size() || CategoryImplementation.size() ||
49300b57cec5SDimitry Andric       ProtocolExprDecls.size()) {
49310b57cec5SDimitry Andric     // Rewrite Objective-c meta data*
49320b57cec5SDimitry Andric     std::string ResultStr;
49330b57cec5SDimitry Andric     RewriteMetaDataIntoBuffer(ResultStr);
49340b57cec5SDimitry Andric     // Emit metadata.
49350b57cec5SDimitry Andric     *OutFile << ResultStr;
49360b57cec5SDimitry Andric   }
49370b57cec5SDimitry Andric   OutFile->flush();
49380b57cec5SDimitry Andric }
49390b57cec5SDimitry Andric 
49400b57cec5SDimitry Andric void RewriteObjCFragileABI::Initialize(ASTContext &context) {
49410b57cec5SDimitry Andric   InitializeCommon(context);
49420b57cec5SDimitry Andric 
49430b57cec5SDimitry Andric   // declaring objc_selector outside the parameter list removes a silly
49440b57cec5SDimitry Andric   // scope related warning...
49450b57cec5SDimitry Andric   if (IsHeader)
49460b57cec5SDimitry Andric     Preamble = "#pragma once\n";
49470b57cec5SDimitry Andric   Preamble += "struct objc_selector; struct objc_class;\n";
49480b57cec5SDimitry Andric   Preamble += "struct __rw_objc_super { struct objc_object *object; ";
49490b57cec5SDimitry Andric   Preamble += "struct objc_object *superClass; ";
49500b57cec5SDimitry Andric   if (LangOpts.MicrosoftExt) {
49510b57cec5SDimitry Andric     // Add a constructor for creating temporary objects.
49520b57cec5SDimitry Andric     Preamble += "__rw_objc_super(struct objc_object *o, struct objc_object *s) "
49530b57cec5SDimitry Andric     ": ";
49540b57cec5SDimitry Andric     Preamble += "object(o), superClass(s) {} ";
49550b57cec5SDimitry Andric   }
49560b57cec5SDimitry Andric   Preamble += "};\n";
49570b57cec5SDimitry Andric   Preamble += "#ifndef _REWRITER_typedef_Protocol\n";
49580b57cec5SDimitry Andric   Preamble += "typedef struct objc_object Protocol;\n";
49590b57cec5SDimitry Andric   Preamble += "#define _REWRITER_typedef_Protocol\n";
49600b57cec5SDimitry Andric   Preamble += "#endif\n";
49610b57cec5SDimitry Andric   if (LangOpts.MicrosoftExt) {
49620b57cec5SDimitry Andric     Preamble += "#define __OBJC_RW_DLLIMPORT extern \"C\" __declspec(dllimport)\n";
49630b57cec5SDimitry Andric     Preamble += "#define __OBJC_RW_STATICIMPORT extern \"C\"\n";
49640b57cec5SDimitry Andric   } else
49650b57cec5SDimitry Andric     Preamble += "#define __OBJC_RW_DLLIMPORT extern\n";
49660b57cec5SDimitry Andric   Preamble += "__OBJC_RW_DLLIMPORT struct objc_object *objc_msgSend";
49670b57cec5SDimitry Andric   Preamble += "(struct objc_object *, struct objc_selector *, ...);\n";
49680b57cec5SDimitry Andric   Preamble += "__OBJC_RW_DLLIMPORT struct objc_object *objc_msgSendSuper";
49690b57cec5SDimitry Andric   Preamble += "(struct objc_super *, struct objc_selector *, ...);\n";
49700b57cec5SDimitry Andric   Preamble += "__OBJC_RW_DLLIMPORT struct objc_object* objc_msgSend_stret";
49710b57cec5SDimitry Andric   Preamble += "(struct objc_object *, struct objc_selector *, ...);\n";
49720b57cec5SDimitry Andric   Preamble += "__OBJC_RW_DLLIMPORT struct objc_object* objc_msgSendSuper_stret";
49730b57cec5SDimitry Andric   Preamble += "(struct objc_super *, struct objc_selector *, ...);\n";
49740b57cec5SDimitry Andric   Preamble += "__OBJC_RW_DLLIMPORT double objc_msgSend_fpret";
49750b57cec5SDimitry Andric   Preamble += "(struct objc_object *, struct objc_selector *, ...);\n";
49760b57cec5SDimitry Andric   Preamble += "__OBJC_RW_DLLIMPORT struct objc_object *objc_getClass";
49770b57cec5SDimitry Andric   Preamble += "(const char *);\n";
49780b57cec5SDimitry Andric   Preamble += "__OBJC_RW_DLLIMPORT struct objc_class *class_getSuperclass";
49790b57cec5SDimitry Andric   Preamble += "(struct objc_class *);\n";
49800b57cec5SDimitry Andric   Preamble += "__OBJC_RW_DLLIMPORT struct objc_object *objc_getMetaClass";
49810b57cec5SDimitry Andric   Preamble += "(const char *);\n";
49820b57cec5SDimitry Andric   Preamble += "__OBJC_RW_DLLIMPORT void objc_exception_throw(struct objc_object *);\n";
49830b57cec5SDimitry Andric   Preamble += "__OBJC_RW_DLLIMPORT void objc_exception_try_enter(void *);\n";
49840b57cec5SDimitry Andric   Preamble += "__OBJC_RW_DLLIMPORT void objc_exception_try_exit(void *);\n";
49850b57cec5SDimitry Andric   Preamble += "__OBJC_RW_DLLIMPORT struct objc_object *objc_exception_extract(void *);\n";
49860b57cec5SDimitry Andric   Preamble += "__OBJC_RW_DLLIMPORT int objc_exception_match";
49870b57cec5SDimitry Andric   Preamble += "(struct objc_class *, struct objc_object *);\n";
49880b57cec5SDimitry Andric   // @synchronized hooks.
49890b57cec5SDimitry Andric   Preamble += "__OBJC_RW_DLLIMPORT int objc_sync_enter(struct objc_object *);\n";
49900b57cec5SDimitry Andric   Preamble += "__OBJC_RW_DLLIMPORT int objc_sync_exit(struct objc_object *);\n";
49910b57cec5SDimitry Andric   Preamble += "__OBJC_RW_DLLIMPORT Protocol *objc_getProtocol(const char *);\n";
49920b57cec5SDimitry Andric   Preamble += "#ifndef __FASTENUMERATIONSTATE\n";
49930b57cec5SDimitry Andric   Preamble += "struct __objcFastEnumerationState {\n\t";
49940b57cec5SDimitry Andric   Preamble += "unsigned long state;\n\t";
49950b57cec5SDimitry Andric   Preamble += "void **itemsPtr;\n\t";
49960b57cec5SDimitry Andric   Preamble += "unsigned long *mutationsPtr;\n\t";
49970b57cec5SDimitry Andric   Preamble += "unsigned long extra[5];\n};\n";
49980b57cec5SDimitry Andric   Preamble += "__OBJC_RW_DLLIMPORT void objc_enumerationMutation(struct objc_object *);\n";
49990b57cec5SDimitry Andric   Preamble += "#define __FASTENUMERATIONSTATE\n";
50000b57cec5SDimitry Andric   Preamble += "#endif\n";
50010b57cec5SDimitry Andric   Preamble += "#ifndef __NSCONSTANTSTRINGIMPL\n";
50020b57cec5SDimitry Andric   Preamble += "struct __NSConstantStringImpl {\n";
50030b57cec5SDimitry Andric   Preamble += "  int *isa;\n";
50040b57cec5SDimitry Andric   Preamble += "  int flags;\n";
50050b57cec5SDimitry Andric   Preamble += "  char *str;\n";
50060b57cec5SDimitry Andric   Preamble += "  long length;\n";
50070b57cec5SDimitry Andric   Preamble += "};\n";
50080b57cec5SDimitry Andric   Preamble += "#ifdef CF_EXPORT_CONSTANT_STRING\n";
50090b57cec5SDimitry Andric   Preamble += "extern \"C\" __declspec(dllexport) int __CFConstantStringClassReference[];\n";
50100b57cec5SDimitry Andric   Preamble += "#else\n";
50110b57cec5SDimitry Andric   Preamble += "__OBJC_RW_DLLIMPORT int __CFConstantStringClassReference[];\n";
50120b57cec5SDimitry Andric   Preamble += "#endif\n";
50130b57cec5SDimitry Andric   Preamble += "#define __NSCONSTANTSTRINGIMPL\n";
50140b57cec5SDimitry Andric   Preamble += "#endif\n";
50150b57cec5SDimitry Andric   // Blocks preamble.
50160b57cec5SDimitry Andric   Preamble += "#ifndef BLOCK_IMPL\n";
50170b57cec5SDimitry Andric   Preamble += "#define BLOCK_IMPL\n";
50180b57cec5SDimitry Andric   Preamble += "struct __block_impl {\n";
50190b57cec5SDimitry Andric   Preamble += "  void *isa;\n";
50200b57cec5SDimitry Andric   Preamble += "  int Flags;\n";
50210b57cec5SDimitry Andric   Preamble += "  int Reserved;\n";
50220b57cec5SDimitry Andric   Preamble += "  void *FuncPtr;\n";
50230b57cec5SDimitry Andric   Preamble += "};\n";
50240b57cec5SDimitry Andric   Preamble += "// Runtime copy/destroy helper functions (from Block_private.h)\n";
50250b57cec5SDimitry Andric   Preamble += "#ifdef __OBJC_EXPORT_BLOCKS\n";
50260b57cec5SDimitry Andric   Preamble += "extern \"C\" __declspec(dllexport) "
50270b57cec5SDimitry Andric   "void _Block_object_assign(void *, const void *, const int);\n";
50280b57cec5SDimitry Andric   Preamble += "extern \"C\" __declspec(dllexport) void _Block_object_dispose(const void *, const int);\n";
50290b57cec5SDimitry Andric   Preamble += "extern \"C\" __declspec(dllexport) void *_NSConcreteGlobalBlock[32];\n";
50300b57cec5SDimitry Andric   Preamble += "extern \"C\" __declspec(dllexport) void *_NSConcreteStackBlock[32];\n";
50310b57cec5SDimitry Andric   Preamble += "#else\n";
50320b57cec5SDimitry Andric   Preamble += "__OBJC_RW_DLLIMPORT void _Block_object_assign(void *, const void *, const int);\n";
50330b57cec5SDimitry Andric   Preamble += "__OBJC_RW_DLLIMPORT void _Block_object_dispose(const void *, const int);\n";
50340b57cec5SDimitry Andric   Preamble += "__OBJC_RW_DLLIMPORT void *_NSConcreteGlobalBlock[32];\n";
50350b57cec5SDimitry Andric   Preamble += "__OBJC_RW_DLLIMPORT void *_NSConcreteStackBlock[32];\n";
50360b57cec5SDimitry Andric   Preamble += "#endif\n";
50370b57cec5SDimitry Andric   Preamble += "#endif\n";
50380b57cec5SDimitry Andric   if (LangOpts.MicrosoftExt) {
50390b57cec5SDimitry Andric     Preamble += "#undef __OBJC_RW_DLLIMPORT\n";
50400b57cec5SDimitry Andric     Preamble += "#undef __OBJC_RW_STATICIMPORT\n";
50410b57cec5SDimitry Andric     Preamble += "#ifndef KEEP_ATTRIBUTES\n";  // We use this for clang tests.
50420b57cec5SDimitry Andric     Preamble += "#define __attribute__(X)\n";
50430b57cec5SDimitry Andric     Preamble += "#endif\n";
50440b57cec5SDimitry Andric     Preamble += "#define __weak\n";
50450b57cec5SDimitry Andric   }
50460b57cec5SDimitry Andric   else {
50470b57cec5SDimitry Andric     Preamble += "#define __block\n";
50480b57cec5SDimitry Andric     Preamble += "#define __weak\n";
50490b57cec5SDimitry Andric   }
50500b57cec5SDimitry Andric   // NOTE! Windows uses LLP64 for 64bit mode. So, cast pointer to long long
50510b57cec5SDimitry Andric   // as this avoids warning in any 64bit/32bit compilation model.
50520b57cec5SDimitry Andric   Preamble += "\n#define __OFFSETOFIVAR__(TYPE, MEMBER) ((long long) &((TYPE *)0)->MEMBER)\n";
50530b57cec5SDimitry Andric }
50540b57cec5SDimitry Andric 
50550b57cec5SDimitry Andric /// RewriteIvarOffsetComputation - This routine synthesizes computation of
50560b57cec5SDimitry Andric /// ivar offset.
50570b57cec5SDimitry Andric void RewriteObjCFragileABI::RewriteIvarOffsetComputation(ObjCIvarDecl *ivar,
50580b57cec5SDimitry Andric                                                          std::string &Result) {
50590b57cec5SDimitry Andric   if (ivar->isBitField()) {
50600b57cec5SDimitry Andric     // FIXME: The hack below doesn't work for bitfields. For now, we simply
50610b57cec5SDimitry Andric     // place all bitfields at offset 0.
50620b57cec5SDimitry Andric     Result += "0";
50630b57cec5SDimitry Andric   } else {
50640b57cec5SDimitry Andric     Result += "__OFFSETOFIVAR__(struct ";
50650b57cec5SDimitry Andric     Result += ivar->getContainingInterface()->getNameAsString();
50660b57cec5SDimitry Andric     if (LangOpts.MicrosoftExt)
50670b57cec5SDimitry Andric       Result += "_IMPL";
50680b57cec5SDimitry Andric     Result += ", ";
50690b57cec5SDimitry Andric     Result += ivar->getNameAsString();
50700b57cec5SDimitry Andric     Result += ")";
50710b57cec5SDimitry Andric   }
50720b57cec5SDimitry Andric }
50730b57cec5SDimitry Andric 
50740b57cec5SDimitry Andric /// RewriteObjCProtocolMetaData - Rewrite protocols meta-data.
50750b57cec5SDimitry Andric void RewriteObjCFragileABI::RewriteObjCProtocolMetaData(
50760b57cec5SDimitry Andric                             ObjCProtocolDecl *PDecl, StringRef prefix,
50770b57cec5SDimitry Andric                             StringRef ClassName, std::string &Result) {
50780b57cec5SDimitry Andric   static bool objc_protocol_methods = false;
50790b57cec5SDimitry Andric 
50800b57cec5SDimitry Andric   // Output struct protocol_methods holder of method selector and type.
50810b57cec5SDimitry Andric   if (!objc_protocol_methods && PDecl->hasDefinition()) {
50820b57cec5SDimitry Andric     /* struct protocol_methods {
50830b57cec5SDimitry Andric      SEL _cmd;
50840b57cec5SDimitry Andric      char *method_types;
50850b57cec5SDimitry Andric      }
50860b57cec5SDimitry Andric      */
50870b57cec5SDimitry Andric     Result += "\nstruct _protocol_methods {\n";
50880b57cec5SDimitry Andric     Result += "\tstruct objc_selector *_cmd;\n";
50890b57cec5SDimitry Andric     Result += "\tchar *method_types;\n";
50900b57cec5SDimitry Andric     Result += "};\n";
50910b57cec5SDimitry Andric 
50920b57cec5SDimitry Andric     objc_protocol_methods = true;
50930b57cec5SDimitry Andric   }
50940b57cec5SDimitry Andric   // Do not synthesize the protocol more than once.
50950b57cec5SDimitry Andric   if (ObjCSynthesizedProtocols.count(PDecl->getCanonicalDecl()))
50960b57cec5SDimitry Andric     return;
50970b57cec5SDimitry Andric 
50980b57cec5SDimitry Andric   if (ObjCProtocolDecl *Def = PDecl->getDefinition())
50990b57cec5SDimitry Andric     PDecl = Def;
51000b57cec5SDimitry Andric 
51010b57cec5SDimitry Andric   if (PDecl->instmeth_begin() != PDecl->instmeth_end()) {
51020b57cec5SDimitry Andric     unsigned NumMethods = std::distance(PDecl->instmeth_begin(),
51030b57cec5SDimitry Andric                                         PDecl->instmeth_end());
51040b57cec5SDimitry Andric     /* struct _objc_protocol_method_list {
51050b57cec5SDimitry Andric      int protocol_method_count;
51060b57cec5SDimitry Andric      struct protocol_methods protocols[];
51070b57cec5SDimitry Andric      }
51080b57cec5SDimitry Andric      */
51090b57cec5SDimitry Andric     Result += "\nstatic struct {\n";
51100b57cec5SDimitry Andric     Result += "\tint protocol_method_count;\n";
51110b57cec5SDimitry Andric     Result += "\tstruct _protocol_methods protocol_methods[";
51120b57cec5SDimitry Andric     Result += utostr(NumMethods);
51130b57cec5SDimitry Andric     Result += "];\n} _OBJC_PROTOCOL_INSTANCE_METHODS_";
51140b57cec5SDimitry Andric     Result += PDecl->getNameAsString();
51150b57cec5SDimitry Andric     Result += " __attribute__ ((used, section (\"__OBJC, __cat_inst_meth\")))= "
51160b57cec5SDimitry Andric     "{\n\t" + utostr(NumMethods) + "\n";
51170b57cec5SDimitry Andric 
51180b57cec5SDimitry Andric     // Output instance methods declared in this protocol.
51190b57cec5SDimitry Andric     for (ObjCProtocolDecl::instmeth_iterator
51200b57cec5SDimitry Andric          I = PDecl->instmeth_begin(), E = PDecl->instmeth_end();
51210b57cec5SDimitry Andric          I != E; ++I) {
51220b57cec5SDimitry Andric       if (I == PDecl->instmeth_begin())
51230b57cec5SDimitry Andric         Result += "\t  ,{{(struct objc_selector *)\"";
51240b57cec5SDimitry Andric       else
51250b57cec5SDimitry Andric         Result += "\t  ,{(struct objc_selector *)\"";
51260b57cec5SDimitry Andric       Result += (*I)->getSelector().getAsString();
51270b57cec5SDimitry Andric       std::string MethodTypeString = Context->getObjCEncodingForMethodDecl(*I);
51280b57cec5SDimitry Andric       Result += "\", \"";
51290b57cec5SDimitry Andric       Result += MethodTypeString;
51300b57cec5SDimitry Andric       Result += "\"}\n";
51310b57cec5SDimitry Andric     }
51320b57cec5SDimitry Andric     Result += "\t }\n};\n";
51330b57cec5SDimitry Andric   }
51340b57cec5SDimitry Andric 
51350b57cec5SDimitry Andric   // Output class methods declared in this protocol.
51360b57cec5SDimitry Andric   unsigned NumMethods = std::distance(PDecl->classmeth_begin(),
51370b57cec5SDimitry Andric                                       PDecl->classmeth_end());
51380b57cec5SDimitry Andric   if (NumMethods > 0) {
51390b57cec5SDimitry Andric     /* struct _objc_protocol_method_list {
51400b57cec5SDimitry Andric      int protocol_method_count;
51410b57cec5SDimitry Andric      struct protocol_methods protocols[];
51420b57cec5SDimitry Andric      }
51430b57cec5SDimitry Andric      */
51440b57cec5SDimitry Andric     Result += "\nstatic struct {\n";
51450b57cec5SDimitry Andric     Result += "\tint protocol_method_count;\n";
51460b57cec5SDimitry Andric     Result += "\tstruct _protocol_methods protocol_methods[";
51470b57cec5SDimitry Andric     Result += utostr(NumMethods);
51480b57cec5SDimitry Andric     Result += "];\n} _OBJC_PROTOCOL_CLASS_METHODS_";
51490b57cec5SDimitry Andric     Result += PDecl->getNameAsString();
51500b57cec5SDimitry Andric     Result += " __attribute__ ((used, section (\"__OBJC, __cat_cls_meth\")))= "
51510b57cec5SDimitry Andric     "{\n\t";
51520b57cec5SDimitry Andric     Result += utostr(NumMethods);
51530b57cec5SDimitry Andric     Result += "\n";
51540b57cec5SDimitry Andric 
51550b57cec5SDimitry Andric     // Output instance methods declared in this protocol.
51560b57cec5SDimitry Andric     for (ObjCProtocolDecl::classmeth_iterator
51570b57cec5SDimitry Andric          I = PDecl->classmeth_begin(), E = PDecl->classmeth_end();
51580b57cec5SDimitry Andric          I != E; ++I) {
51590b57cec5SDimitry Andric       if (I == PDecl->classmeth_begin())
51600b57cec5SDimitry Andric         Result += "\t  ,{{(struct objc_selector *)\"";
51610b57cec5SDimitry Andric       else
51620b57cec5SDimitry Andric         Result += "\t  ,{(struct objc_selector *)\"";
51630b57cec5SDimitry Andric       Result += (*I)->getSelector().getAsString();
51640b57cec5SDimitry Andric       std::string MethodTypeString = Context->getObjCEncodingForMethodDecl(*I);
51650b57cec5SDimitry Andric       Result += "\", \"";
51660b57cec5SDimitry Andric       Result += MethodTypeString;
51670b57cec5SDimitry Andric       Result += "\"}\n";
51680b57cec5SDimitry Andric     }
51690b57cec5SDimitry Andric     Result += "\t }\n};\n";
51700b57cec5SDimitry Andric   }
51710b57cec5SDimitry Andric 
51720b57cec5SDimitry Andric   // Output:
51730b57cec5SDimitry Andric   /* struct _objc_protocol {
51740b57cec5SDimitry Andric    // Objective-C 1.0 extensions
51750b57cec5SDimitry Andric    struct _objc_protocol_extension *isa;
51760b57cec5SDimitry Andric    char *protocol_name;
51770b57cec5SDimitry Andric    struct _objc_protocol **protocol_list;
51780b57cec5SDimitry Andric    struct _objc_protocol_method_list *instance_methods;
51790b57cec5SDimitry Andric    struct _objc_protocol_method_list *class_methods;
51800b57cec5SDimitry Andric    };
51810b57cec5SDimitry Andric    */
51820b57cec5SDimitry Andric   static bool objc_protocol = false;
51830b57cec5SDimitry Andric   if (!objc_protocol) {
51840b57cec5SDimitry Andric     Result += "\nstruct _objc_protocol {\n";
51850b57cec5SDimitry Andric     Result += "\tstruct _objc_protocol_extension *isa;\n";
51860b57cec5SDimitry Andric     Result += "\tchar *protocol_name;\n";
51870b57cec5SDimitry Andric     Result += "\tstruct _objc_protocol **protocol_list;\n";
51880b57cec5SDimitry Andric     Result += "\tstruct _objc_protocol_method_list *instance_methods;\n";
51890b57cec5SDimitry Andric     Result += "\tstruct _objc_protocol_method_list *class_methods;\n";
51900b57cec5SDimitry Andric     Result += "};\n";
51910b57cec5SDimitry Andric 
51920b57cec5SDimitry Andric     objc_protocol = true;
51930b57cec5SDimitry Andric   }
51940b57cec5SDimitry Andric 
51950b57cec5SDimitry Andric   Result += "\nstatic struct _objc_protocol _OBJC_PROTOCOL_";
51960b57cec5SDimitry Andric   Result += PDecl->getNameAsString();
51970b57cec5SDimitry Andric   Result += " __attribute__ ((used, section (\"__OBJC, __protocol\")))= "
51980b57cec5SDimitry Andric   "{\n\t0, \"";
51990b57cec5SDimitry Andric   Result += PDecl->getNameAsString();
52000b57cec5SDimitry Andric   Result += "\", 0, ";
52010b57cec5SDimitry Andric   if (PDecl->instmeth_begin() != PDecl->instmeth_end()) {
52020b57cec5SDimitry Andric     Result += "(struct _objc_protocol_method_list *)&_OBJC_PROTOCOL_INSTANCE_METHODS_";
52030b57cec5SDimitry Andric     Result += PDecl->getNameAsString();
52040b57cec5SDimitry Andric     Result += ", ";
52050b57cec5SDimitry Andric   }
52060b57cec5SDimitry Andric   else
52070b57cec5SDimitry Andric     Result += "0, ";
52080b57cec5SDimitry Andric   if (PDecl->classmeth_begin() != PDecl->classmeth_end()) {
52090b57cec5SDimitry Andric     Result += "(struct _objc_protocol_method_list *)&_OBJC_PROTOCOL_CLASS_METHODS_";
52100b57cec5SDimitry Andric     Result += PDecl->getNameAsString();
52110b57cec5SDimitry Andric     Result += "\n";
52120b57cec5SDimitry Andric   }
52130b57cec5SDimitry Andric   else
52140b57cec5SDimitry Andric     Result += "0\n";
52150b57cec5SDimitry Andric   Result += "};\n";
52160b57cec5SDimitry Andric 
52170b57cec5SDimitry Andric   // Mark this protocol as having been generated.
52180b57cec5SDimitry Andric   if (!ObjCSynthesizedProtocols.insert(PDecl->getCanonicalDecl()).second)
52190b57cec5SDimitry Andric     llvm_unreachable("protocol already synthesized");
52200b57cec5SDimitry Andric }
52210b57cec5SDimitry Andric 
52220b57cec5SDimitry Andric void RewriteObjCFragileABI::RewriteObjCProtocolListMetaData(
52230b57cec5SDimitry Andric                                 const ObjCList<ObjCProtocolDecl> &Protocols,
52240b57cec5SDimitry Andric                                 StringRef prefix, StringRef ClassName,
52250b57cec5SDimitry Andric                                 std::string &Result) {
52260b57cec5SDimitry Andric   if (Protocols.empty()) return;
52270b57cec5SDimitry Andric 
52280b57cec5SDimitry Andric   for (unsigned i = 0; i != Protocols.size(); i++)
52290b57cec5SDimitry Andric     RewriteObjCProtocolMetaData(Protocols[i], prefix, ClassName, Result);
52300b57cec5SDimitry Andric 
52310b57cec5SDimitry Andric   // Output the top lovel protocol meta-data for the class.
52320b57cec5SDimitry Andric   /* struct _objc_protocol_list {
52330b57cec5SDimitry Andric    struct _objc_protocol_list *next;
52340b57cec5SDimitry Andric    int    protocol_count;
52350b57cec5SDimitry Andric    struct _objc_protocol *class_protocols[];
52360b57cec5SDimitry Andric    }
52370b57cec5SDimitry Andric    */
52380b57cec5SDimitry Andric   Result += "\nstatic struct {\n";
52390b57cec5SDimitry Andric   Result += "\tstruct _objc_protocol_list *next;\n";
52400b57cec5SDimitry Andric   Result += "\tint    protocol_count;\n";
52410b57cec5SDimitry Andric   Result += "\tstruct _objc_protocol *class_protocols[";
52420b57cec5SDimitry Andric   Result += utostr(Protocols.size());
52430b57cec5SDimitry Andric   Result += "];\n} _OBJC_";
52440b57cec5SDimitry Andric   Result += prefix;
52450b57cec5SDimitry Andric   Result += "_PROTOCOLS_";
52460b57cec5SDimitry Andric   Result += ClassName;
52470b57cec5SDimitry Andric   Result += " __attribute__ ((used, section (\"__OBJC, __cat_cls_meth\")))= "
52480b57cec5SDimitry Andric   "{\n\t0, ";
52490b57cec5SDimitry Andric   Result += utostr(Protocols.size());
52500b57cec5SDimitry Andric   Result += "\n";
52510b57cec5SDimitry Andric 
52520b57cec5SDimitry Andric   Result += "\t,{&_OBJC_PROTOCOL_";
52530b57cec5SDimitry Andric   Result += Protocols[0]->getNameAsString();
52540b57cec5SDimitry Andric   Result += " \n";
52550b57cec5SDimitry Andric 
52560b57cec5SDimitry Andric   for (unsigned i = 1; i != Protocols.size(); i++) {
52570b57cec5SDimitry Andric     Result += "\t ,&_OBJC_PROTOCOL_";
52580b57cec5SDimitry Andric     Result += Protocols[i]->getNameAsString();
52590b57cec5SDimitry Andric     Result += "\n";
52600b57cec5SDimitry Andric   }
52610b57cec5SDimitry Andric   Result += "\t }\n};\n";
52620b57cec5SDimitry Andric }
52630b57cec5SDimitry Andric 
52640b57cec5SDimitry Andric void RewriteObjCFragileABI::RewriteObjCClassMetaData(ObjCImplementationDecl *IDecl,
52650b57cec5SDimitry Andric                                            std::string &Result) {
52660b57cec5SDimitry Andric   ObjCInterfaceDecl *CDecl = IDecl->getClassInterface();
52670b57cec5SDimitry Andric 
52680b57cec5SDimitry Andric   // Explicitly declared @interface's are already synthesized.
52690b57cec5SDimitry Andric   if (CDecl->isImplicitInterfaceDecl()) {
52700b57cec5SDimitry Andric     // FIXME: Implementation of a class with no @interface (legacy) does not
52710b57cec5SDimitry Andric     // produce correct synthesis as yet.
52720b57cec5SDimitry Andric     RewriteObjCInternalStruct(CDecl, Result);
52730b57cec5SDimitry Andric   }
52740b57cec5SDimitry Andric 
52750b57cec5SDimitry Andric   // Build _objc_ivar_list metadata for classes ivars if needed
5276e8d8bef9SDimitry Andric   unsigned NumIvars =
5277e8d8bef9SDimitry Andric       !IDecl->ivar_empty() ? IDecl->ivar_size() : CDecl->ivar_size();
52780b57cec5SDimitry Andric   if (NumIvars > 0) {
52790b57cec5SDimitry Andric     static bool objc_ivar = false;
52800b57cec5SDimitry Andric     if (!objc_ivar) {
52810b57cec5SDimitry Andric       /* struct _objc_ivar {
52820b57cec5SDimitry Andric        char *ivar_name;
52830b57cec5SDimitry Andric        char *ivar_type;
52840b57cec5SDimitry Andric        int ivar_offset;
52850b57cec5SDimitry Andric        };
52860b57cec5SDimitry Andric        */
52870b57cec5SDimitry Andric       Result += "\nstruct _objc_ivar {\n";
52880b57cec5SDimitry Andric       Result += "\tchar *ivar_name;\n";
52890b57cec5SDimitry Andric       Result += "\tchar *ivar_type;\n";
52900b57cec5SDimitry Andric       Result += "\tint ivar_offset;\n";
52910b57cec5SDimitry Andric       Result += "};\n";
52920b57cec5SDimitry Andric 
52930b57cec5SDimitry Andric       objc_ivar = true;
52940b57cec5SDimitry Andric     }
52950b57cec5SDimitry Andric 
52960b57cec5SDimitry Andric     /* struct {
52970b57cec5SDimitry Andric      int ivar_count;
52980b57cec5SDimitry Andric      struct _objc_ivar ivar_list[nIvars];
52990b57cec5SDimitry Andric      };
53000b57cec5SDimitry Andric      */
53010b57cec5SDimitry Andric     Result += "\nstatic struct {\n";
53020b57cec5SDimitry Andric     Result += "\tint ivar_count;\n";
53030b57cec5SDimitry Andric     Result += "\tstruct _objc_ivar ivar_list[";
53040b57cec5SDimitry Andric     Result += utostr(NumIvars);
53050b57cec5SDimitry Andric     Result += "];\n} _OBJC_INSTANCE_VARIABLES_";
53060b57cec5SDimitry Andric     Result += IDecl->getNameAsString();
53070b57cec5SDimitry Andric     Result += " __attribute__ ((used, section (\"__OBJC, __instance_vars\")))= "
53080b57cec5SDimitry Andric     "{\n\t";
53090b57cec5SDimitry Andric     Result += utostr(NumIvars);
53100b57cec5SDimitry Andric     Result += "\n";
53110b57cec5SDimitry Andric 
53120b57cec5SDimitry Andric     ObjCInterfaceDecl::ivar_iterator IVI, IVE;
53130b57cec5SDimitry Andric     SmallVector<ObjCIvarDecl *, 8> IVars;
53140b57cec5SDimitry Andric     if (!IDecl->ivar_empty()) {
53150b57cec5SDimitry Andric       for (auto *IV : IDecl->ivars())
53160b57cec5SDimitry Andric         IVars.push_back(IV);
53170b57cec5SDimitry Andric       IVI = IDecl->ivar_begin();
53180b57cec5SDimitry Andric       IVE = IDecl->ivar_end();
53190b57cec5SDimitry Andric     } else {
53200b57cec5SDimitry Andric       IVI = CDecl->ivar_begin();
53210b57cec5SDimitry Andric       IVE = CDecl->ivar_end();
53220b57cec5SDimitry Andric     }
53230b57cec5SDimitry Andric     Result += "\t,{{\"";
53240b57cec5SDimitry Andric     Result += IVI->getNameAsString();
53250b57cec5SDimitry Andric     Result += "\", \"";
53260b57cec5SDimitry Andric     std::string TmpString, StrEncoding;
53270b57cec5SDimitry Andric     Context->getObjCEncodingForType(IVI->getType(), TmpString, *IVI);
53280b57cec5SDimitry Andric     QuoteDoublequotes(TmpString, StrEncoding);
53290b57cec5SDimitry Andric     Result += StrEncoding;
53300b57cec5SDimitry Andric     Result += "\", ";
53310b57cec5SDimitry Andric     RewriteIvarOffsetComputation(*IVI, Result);
53320b57cec5SDimitry Andric     Result += "}\n";
53330b57cec5SDimitry Andric     for (++IVI; IVI != IVE; ++IVI) {
53340b57cec5SDimitry Andric       Result += "\t  ,{\"";
53350b57cec5SDimitry Andric       Result += IVI->getNameAsString();
53360b57cec5SDimitry Andric       Result += "\", \"";
53370b57cec5SDimitry Andric       std::string TmpString, StrEncoding;
53380b57cec5SDimitry Andric       Context->getObjCEncodingForType(IVI->getType(), TmpString, *IVI);
53390b57cec5SDimitry Andric       QuoteDoublequotes(TmpString, StrEncoding);
53400b57cec5SDimitry Andric       Result += StrEncoding;
53410b57cec5SDimitry Andric       Result += "\", ";
53420b57cec5SDimitry Andric       RewriteIvarOffsetComputation(*IVI, Result);
53430b57cec5SDimitry Andric       Result += "}\n";
53440b57cec5SDimitry Andric     }
53450b57cec5SDimitry Andric 
53460b57cec5SDimitry Andric     Result += "\t }\n};\n";
53470b57cec5SDimitry Andric   }
53480b57cec5SDimitry Andric 
53490b57cec5SDimitry Andric   // Build _objc_method_list for class's instance methods if needed
53500b57cec5SDimitry Andric   SmallVector<ObjCMethodDecl *, 32> InstanceMethods(IDecl->instance_methods());
53510b57cec5SDimitry Andric 
53520b57cec5SDimitry Andric   // If any of our property implementations have associated getters or
53530b57cec5SDimitry Andric   // setters, produce metadata for them as well.
53540b57cec5SDimitry Andric   for (const auto *Prop : IDecl->property_impls()) {
53550b57cec5SDimitry Andric     if (Prop->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic)
53560b57cec5SDimitry Andric       continue;
53570b57cec5SDimitry Andric     if (!Prop->getPropertyIvarDecl())
53580b57cec5SDimitry Andric       continue;
53590b57cec5SDimitry Andric     ObjCPropertyDecl *PD = Prop->getPropertyDecl();
53600b57cec5SDimitry Andric     if (!PD)
53610b57cec5SDimitry Andric       continue;
5362480093f4SDimitry Andric     if (ObjCMethodDecl *Getter = Prop->getGetterMethodDecl())
53630b57cec5SDimitry Andric       if (!Getter->isDefined())
53640b57cec5SDimitry Andric         InstanceMethods.push_back(Getter);
53650b57cec5SDimitry Andric     if (PD->isReadOnly())
53660b57cec5SDimitry Andric       continue;
5367480093f4SDimitry Andric     if (ObjCMethodDecl *Setter = Prop->getSetterMethodDecl())
53680b57cec5SDimitry Andric       if (!Setter->isDefined())
53690b57cec5SDimitry Andric         InstanceMethods.push_back(Setter);
53700b57cec5SDimitry Andric   }
53710b57cec5SDimitry Andric   RewriteObjCMethodsMetaData(InstanceMethods.begin(), InstanceMethods.end(),
53720b57cec5SDimitry Andric                              true, "", IDecl->getName(), Result);
53730b57cec5SDimitry Andric 
53740b57cec5SDimitry Andric   // Build _objc_method_list for class's class methods if needed
53750b57cec5SDimitry Andric   RewriteObjCMethodsMetaData(IDecl->classmeth_begin(), IDecl->classmeth_end(),
53760b57cec5SDimitry Andric                              false, "", IDecl->getName(), Result);
53770b57cec5SDimitry Andric 
53780b57cec5SDimitry Andric   // Protocols referenced in class declaration?
53790b57cec5SDimitry Andric   RewriteObjCProtocolListMetaData(CDecl->getReferencedProtocols(),
53800b57cec5SDimitry Andric                                   "CLASS", CDecl->getName(), Result);
53810b57cec5SDimitry Andric 
53820b57cec5SDimitry Andric   // Declaration of class/meta-class metadata
53830b57cec5SDimitry Andric   /* struct _objc_class {
53840b57cec5SDimitry Andric    struct _objc_class *isa; // or const char *root_class_name when metadata
53850b57cec5SDimitry Andric    const char *super_class_name;
53860b57cec5SDimitry Andric    char *name;
53870b57cec5SDimitry Andric    long version;
53880b57cec5SDimitry Andric    long info;
53890b57cec5SDimitry Andric    long instance_size;
53900b57cec5SDimitry Andric    struct _objc_ivar_list *ivars;
53910b57cec5SDimitry Andric    struct _objc_method_list *methods;
53920b57cec5SDimitry Andric    struct objc_cache *cache;
53930b57cec5SDimitry Andric    struct objc_protocol_list *protocols;
53940b57cec5SDimitry Andric    const char *ivar_layout;
53950b57cec5SDimitry Andric    struct _objc_class_ext  *ext;
53960b57cec5SDimitry Andric    };
53970b57cec5SDimitry Andric    */
53980b57cec5SDimitry Andric   static bool objc_class = false;
53990b57cec5SDimitry Andric   if (!objc_class) {
54000b57cec5SDimitry Andric     Result += "\nstruct _objc_class {\n";
54010b57cec5SDimitry Andric     Result += "\tstruct _objc_class *isa;\n";
54020b57cec5SDimitry Andric     Result += "\tconst char *super_class_name;\n";
54030b57cec5SDimitry Andric     Result += "\tchar *name;\n";
54040b57cec5SDimitry Andric     Result += "\tlong version;\n";
54050b57cec5SDimitry Andric     Result += "\tlong info;\n";
54060b57cec5SDimitry Andric     Result += "\tlong instance_size;\n";
54070b57cec5SDimitry Andric     Result += "\tstruct _objc_ivar_list *ivars;\n";
54080b57cec5SDimitry Andric     Result += "\tstruct _objc_method_list *methods;\n";
54090b57cec5SDimitry Andric     Result += "\tstruct objc_cache *cache;\n";
54100b57cec5SDimitry Andric     Result += "\tstruct _objc_protocol_list *protocols;\n";
54110b57cec5SDimitry Andric     Result += "\tconst char *ivar_layout;\n";
54120b57cec5SDimitry Andric     Result += "\tstruct _objc_class_ext  *ext;\n";
54130b57cec5SDimitry Andric     Result += "};\n";
54140b57cec5SDimitry Andric     objc_class = true;
54150b57cec5SDimitry Andric   }
54160b57cec5SDimitry Andric 
54170b57cec5SDimitry Andric   // Meta-class metadata generation.
54180b57cec5SDimitry Andric   ObjCInterfaceDecl *RootClass = nullptr;
54190b57cec5SDimitry Andric   ObjCInterfaceDecl *SuperClass = CDecl->getSuperClass();
54200b57cec5SDimitry Andric   while (SuperClass) {
54210b57cec5SDimitry Andric     RootClass = SuperClass;
54220b57cec5SDimitry Andric     SuperClass = SuperClass->getSuperClass();
54230b57cec5SDimitry Andric   }
54240b57cec5SDimitry Andric   SuperClass = CDecl->getSuperClass();
54250b57cec5SDimitry Andric 
54260b57cec5SDimitry Andric   Result += "\nstatic struct _objc_class _OBJC_METACLASS_";
54270b57cec5SDimitry Andric   Result += CDecl->getNameAsString();
54280b57cec5SDimitry Andric   Result += " __attribute__ ((used, section (\"__OBJC, __meta_class\")))= "
54290b57cec5SDimitry Andric   "{\n\t(struct _objc_class *)\"";
54300b57cec5SDimitry Andric   Result += (RootClass ? RootClass->getNameAsString() : CDecl->getNameAsString());
54310b57cec5SDimitry Andric   Result += "\"";
54320b57cec5SDimitry Andric 
54330b57cec5SDimitry Andric   if (SuperClass) {
54340b57cec5SDimitry Andric     Result += ", \"";
54350b57cec5SDimitry Andric     Result += SuperClass->getNameAsString();
54360b57cec5SDimitry Andric     Result += "\", \"";
54370b57cec5SDimitry Andric     Result += CDecl->getNameAsString();
54380b57cec5SDimitry Andric     Result += "\"";
54390b57cec5SDimitry Andric   }
54400b57cec5SDimitry Andric   else {
54410b57cec5SDimitry Andric     Result += ", 0, \"";
54420b57cec5SDimitry Andric     Result += CDecl->getNameAsString();
54430b57cec5SDimitry Andric     Result += "\"";
54440b57cec5SDimitry Andric   }
54450b57cec5SDimitry Andric   // Set 'ivars' field for root class to 0. ObjC1 runtime does not use it.
54460b57cec5SDimitry Andric   // 'info' field is initialized to CLS_META(2) for metaclass
54470b57cec5SDimitry Andric   Result += ", 0,2, sizeof(struct _objc_class), 0";
54480b57cec5SDimitry Andric   if (IDecl->classmeth_begin() != IDecl->classmeth_end()) {
54490b57cec5SDimitry Andric     Result += "\n\t, (struct _objc_method_list *)&_OBJC_CLASS_METHODS_";
54500b57cec5SDimitry Andric     Result += IDecl->getNameAsString();
54510b57cec5SDimitry Andric     Result += "\n";
54520b57cec5SDimitry Andric   }
54530b57cec5SDimitry Andric   else
54540b57cec5SDimitry Andric     Result += ", 0\n";
54550b57cec5SDimitry Andric   if (CDecl->protocol_begin() != CDecl->protocol_end()) {
54560b57cec5SDimitry Andric     Result += "\t,0, (struct _objc_protocol_list *)&_OBJC_CLASS_PROTOCOLS_";
54570b57cec5SDimitry Andric     Result += CDecl->getNameAsString();
54580b57cec5SDimitry Andric     Result += ",0,0\n";
54590b57cec5SDimitry Andric   }
54600b57cec5SDimitry Andric   else
54610b57cec5SDimitry Andric     Result += "\t,0,0,0,0\n";
54620b57cec5SDimitry Andric   Result += "};\n";
54630b57cec5SDimitry Andric 
54640b57cec5SDimitry Andric   // class metadata generation.
54650b57cec5SDimitry Andric   Result += "\nstatic struct _objc_class _OBJC_CLASS_";
54660b57cec5SDimitry Andric   Result += CDecl->getNameAsString();
54670b57cec5SDimitry Andric   Result += " __attribute__ ((used, section (\"__OBJC, __class\")))= "
54680b57cec5SDimitry Andric   "{\n\t&_OBJC_METACLASS_";
54690b57cec5SDimitry Andric   Result += CDecl->getNameAsString();
54700b57cec5SDimitry Andric   if (SuperClass) {
54710b57cec5SDimitry Andric     Result += ", \"";
54720b57cec5SDimitry Andric     Result += SuperClass->getNameAsString();
54730b57cec5SDimitry Andric     Result += "\", \"";
54740b57cec5SDimitry Andric     Result += CDecl->getNameAsString();
54750b57cec5SDimitry Andric     Result += "\"";
54760b57cec5SDimitry Andric   }
54770b57cec5SDimitry Andric   else {
54780b57cec5SDimitry Andric     Result += ", 0, \"";
54790b57cec5SDimitry Andric     Result += CDecl->getNameAsString();
54800b57cec5SDimitry Andric     Result += "\"";
54810b57cec5SDimitry Andric   }
54820b57cec5SDimitry Andric   // 'info' field is initialized to CLS_CLASS(1) for class
54830b57cec5SDimitry Andric   Result += ", 0,1";
54840b57cec5SDimitry Andric   if (!ObjCSynthesizedStructs.count(CDecl))
54850b57cec5SDimitry Andric     Result += ",0";
54860b57cec5SDimitry Andric   else {
54870b57cec5SDimitry Andric     // class has size. Must synthesize its size.
54880b57cec5SDimitry Andric     Result += ",sizeof(struct ";
54890b57cec5SDimitry Andric     Result += CDecl->getNameAsString();
54900b57cec5SDimitry Andric     if (LangOpts.MicrosoftExt)
54910b57cec5SDimitry Andric       Result += "_IMPL";
54920b57cec5SDimitry Andric     Result += ")";
54930b57cec5SDimitry Andric   }
54940b57cec5SDimitry Andric   if (NumIvars > 0) {
54950b57cec5SDimitry Andric     Result += ", (struct _objc_ivar_list *)&_OBJC_INSTANCE_VARIABLES_";
54960b57cec5SDimitry Andric     Result += CDecl->getNameAsString();
54970b57cec5SDimitry Andric     Result += "\n\t";
54980b57cec5SDimitry Andric   }
54990b57cec5SDimitry Andric   else
55000b57cec5SDimitry Andric     Result += ",0";
55010b57cec5SDimitry Andric   if (IDecl->instmeth_begin() != IDecl->instmeth_end()) {
55020b57cec5SDimitry Andric     Result += ", (struct _objc_method_list *)&_OBJC_INSTANCE_METHODS_";
55030b57cec5SDimitry Andric     Result += CDecl->getNameAsString();
55040b57cec5SDimitry Andric     Result += ", 0\n\t";
55050b57cec5SDimitry Andric   }
55060b57cec5SDimitry Andric   else
55070b57cec5SDimitry Andric     Result += ",0,0";
55080b57cec5SDimitry Andric   if (CDecl->protocol_begin() != CDecl->protocol_end()) {
55090b57cec5SDimitry Andric     Result += ", (struct _objc_protocol_list*)&_OBJC_CLASS_PROTOCOLS_";
55100b57cec5SDimitry Andric     Result += CDecl->getNameAsString();
55110b57cec5SDimitry Andric     Result += ", 0,0\n";
55120b57cec5SDimitry Andric   }
55130b57cec5SDimitry Andric   else
55140b57cec5SDimitry Andric     Result += ",0,0,0\n";
55150b57cec5SDimitry Andric   Result += "};\n";
55160b57cec5SDimitry Andric }
55170b57cec5SDimitry Andric 
55180b57cec5SDimitry Andric void RewriteObjCFragileABI::RewriteMetaDataIntoBuffer(std::string &Result) {
55190b57cec5SDimitry Andric   int ClsDefCount = ClassImplementation.size();
55200b57cec5SDimitry Andric   int CatDefCount = CategoryImplementation.size();
55210b57cec5SDimitry Andric 
55220b57cec5SDimitry Andric   // For each implemented class, write out all its meta data.
55230b57cec5SDimitry Andric   for (int i = 0; i < ClsDefCount; i++)
55240b57cec5SDimitry Andric     RewriteObjCClassMetaData(ClassImplementation[i], Result);
55250b57cec5SDimitry Andric 
55260b57cec5SDimitry Andric   // For each implemented category, write out all its meta data.
55270b57cec5SDimitry Andric   for (int i = 0; i < CatDefCount; i++)
55280b57cec5SDimitry Andric     RewriteObjCCategoryImplDecl(CategoryImplementation[i], Result);
55290b57cec5SDimitry Andric 
55300b57cec5SDimitry Andric   // Write objc_symtab metadata
55310b57cec5SDimitry Andric   /*
55320b57cec5SDimitry Andric    struct _objc_symtab
55330b57cec5SDimitry Andric    {
55340b57cec5SDimitry Andric    long sel_ref_cnt;
55350b57cec5SDimitry Andric    SEL *refs;
55360b57cec5SDimitry Andric    short cls_def_cnt;
55370b57cec5SDimitry Andric    short cat_def_cnt;
55380b57cec5SDimitry Andric    void *defs[cls_def_cnt + cat_def_cnt];
55390b57cec5SDimitry Andric    };
55400b57cec5SDimitry Andric    */
55410b57cec5SDimitry Andric 
55420b57cec5SDimitry Andric   Result += "\nstruct _objc_symtab {\n";
55430b57cec5SDimitry Andric   Result += "\tlong sel_ref_cnt;\n";
55440b57cec5SDimitry Andric   Result += "\tSEL *refs;\n";
55450b57cec5SDimitry Andric   Result += "\tshort cls_def_cnt;\n";
55460b57cec5SDimitry Andric   Result += "\tshort cat_def_cnt;\n";
55470b57cec5SDimitry Andric   Result += "\tvoid *defs[" + utostr(ClsDefCount + CatDefCount)+ "];\n";
55480b57cec5SDimitry Andric   Result += "};\n\n";
55490b57cec5SDimitry Andric 
55500b57cec5SDimitry Andric   Result += "static struct _objc_symtab "
55510b57cec5SDimitry Andric   "_OBJC_SYMBOLS __attribute__((used, section (\"__OBJC, __symbols\")))= {\n";
55520b57cec5SDimitry Andric   Result += "\t0, 0, " + utostr(ClsDefCount)
55530b57cec5SDimitry Andric   + ", " + utostr(CatDefCount) + "\n";
55540b57cec5SDimitry Andric   for (int i = 0; i < ClsDefCount; i++) {
55550b57cec5SDimitry Andric     Result += "\t,&_OBJC_CLASS_";
55560b57cec5SDimitry Andric     Result += ClassImplementation[i]->getNameAsString();
55570b57cec5SDimitry Andric     Result += "\n";
55580b57cec5SDimitry Andric   }
55590b57cec5SDimitry Andric 
55600b57cec5SDimitry Andric   for (int i = 0; i < CatDefCount; i++) {
55610b57cec5SDimitry Andric     Result += "\t,&_OBJC_CATEGORY_";
55620b57cec5SDimitry Andric     Result += CategoryImplementation[i]->getClassInterface()->getNameAsString();
55630b57cec5SDimitry Andric     Result += "_";
55640b57cec5SDimitry Andric     Result += CategoryImplementation[i]->getNameAsString();
55650b57cec5SDimitry Andric     Result += "\n";
55660b57cec5SDimitry Andric   }
55670b57cec5SDimitry Andric 
55680b57cec5SDimitry Andric   Result += "};\n\n";
55690b57cec5SDimitry Andric 
55700b57cec5SDimitry Andric   // Write objc_module metadata
55710b57cec5SDimitry Andric 
55720b57cec5SDimitry Andric   /*
55730b57cec5SDimitry Andric    struct _objc_module {
55740b57cec5SDimitry Andric    long version;
55750b57cec5SDimitry Andric    long size;
55760b57cec5SDimitry Andric    const char *name;
55770b57cec5SDimitry Andric    struct _objc_symtab *symtab;
55780b57cec5SDimitry Andric    }
55790b57cec5SDimitry Andric    */
55800b57cec5SDimitry Andric 
55810b57cec5SDimitry Andric   Result += "\nstruct _objc_module {\n";
55820b57cec5SDimitry Andric   Result += "\tlong version;\n";
55830b57cec5SDimitry Andric   Result += "\tlong size;\n";
55840b57cec5SDimitry Andric   Result += "\tconst char *name;\n";
55850b57cec5SDimitry Andric   Result += "\tstruct _objc_symtab *symtab;\n";
55860b57cec5SDimitry Andric   Result += "};\n\n";
55870b57cec5SDimitry Andric   Result += "static struct _objc_module "
55880b57cec5SDimitry Andric   "_OBJC_MODULES __attribute__ ((used, section (\"__OBJC, __module_info\")))= {\n";
55890b57cec5SDimitry Andric   Result += "\t" + utostr(OBJC_ABI_VERSION) +
55900b57cec5SDimitry Andric   ", sizeof(struct _objc_module), \"\", &_OBJC_SYMBOLS\n";
55910b57cec5SDimitry Andric   Result += "};\n\n";
55920b57cec5SDimitry Andric 
55930b57cec5SDimitry Andric   if (LangOpts.MicrosoftExt) {
55940b57cec5SDimitry Andric     if (ProtocolExprDecls.size()) {
55950b57cec5SDimitry Andric       Result += "#pragma section(\".objc_protocol$B\",long,read,write)\n";
55960b57cec5SDimitry Andric       Result += "#pragma data_seg(push, \".objc_protocol$B\")\n";
55970b57cec5SDimitry Andric       for (ObjCProtocolDecl *ProtDecl : ProtocolExprDecls) {
55980b57cec5SDimitry Andric         Result += "static struct _objc_protocol *_POINTER_OBJC_PROTOCOL_";
55990b57cec5SDimitry Andric         Result += ProtDecl->getNameAsString();
56000b57cec5SDimitry Andric         Result += " = &_OBJC_PROTOCOL_";
56010b57cec5SDimitry Andric         Result += ProtDecl->getNameAsString();
56020b57cec5SDimitry Andric         Result += ";\n";
56030b57cec5SDimitry Andric       }
56040b57cec5SDimitry Andric       Result += "#pragma data_seg(pop)\n\n";
56050b57cec5SDimitry Andric     }
56060b57cec5SDimitry Andric     Result += "#pragma section(\".objc_module_info$B\",long,read,write)\n";
56070b57cec5SDimitry Andric     Result += "#pragma data_seg(push, \".objc_module_info$B\")\n";
56080b57cec5SDimitry Andric     Result += "static struct _objc_module *_POINTER_OBJC_MODULES = ";
56090b57cec5SDimitry Andric     Result += "&_OBJC_MODULES;\n";
56100b57cec5SDimitry Andric     Result += "#pragma data_seg(pop)\n\n";
56110b57cec5SDimitry Andric   }
56120b57cec5SDimitry Andric }
56130b57cec5SDimitry Andric 
56140b57cec5SDimitry Andric /// RewriteObjCCategoryImplDecl - Rewrite metadata for each category
56150b57cec5SDimitry Andric /// implementation.
56160b57cec5SDimitry Andric void RewriteObjCFragileABI::RewriteObjCCategoryImplDecl(ObjCCategoryImplDecl *IDecl,
56170b57cec5SDimitry Andric                                               std::string &Result) {
56180b57cec5SDimitry Andric   ObjCInterfaceDecl *ClassDecl = IDecl->getClassInterface();
56190b57cec5SDimitry Andric   // Find category declaration for this implementation.
56200b57cec5SDimitry Andric   ObjCCategoryDecl *CDecl
56210b57cec5SDimitry Andric     = ClassDecl->FindCategoryDeclaration(IDecl->getIdentifier());
56220b57cec5SDimitry Andric 
56230b57cec5SDimitry Andric   std::string FullCategoryName = ClassDecl->getNameAsString();
56240b57cec5SDimitry Andric   FullCategoryName += '_';
56250b57cec5SDimitry Andric   FullCategoryName += IDecl->getNameAsString();
56260b57cec5SDimitry Andric 
56270b57cec5SDimitry Andric   // Build _objc_method_list for class's instance methods if needed
56280b57cec5SDimitry Andric   SmallVector<ObjCMethodDecl *, 32> InstanceMethods(IDecl->instance_methods());
56290b57cec5SDimitry Andric 
56300b57cec5SDimitry Andric   // If any of our property implementations have associated getters or
56310b57cec5SDimitry Andric   // setters, produce metadata for them as well.
56320b57cec5SDimitry Andric   for (const auto *Prop : IDecl->property_impls()) {
56330b57cec5SDimitry Andric     if (Prop->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic)
56340b57cec5SDimitry Andric       continue;
56350b57cec5SDimitry Andric     if (!Prop->getPropertyIvarDecl())
56360b57cec5SDimitry Andric       continue;
56370b57cec5SDimitry Andric     ObjCPropertyDecl *PD = Prop->getPropertyDecl();
56380b57cec5SDimitry Andric     if (!PD)
56390b57cec5SDimitry Andric       continue;
5640480093f4SDimitry Andric     if (ObjCMethodDecl *Getter = Prop->getGetterMethodDecl())
56410b57cec5SDimitry Andric       InstanceMethods.push_back(Getter);
56420b57cec5SDimitry Andric     if (PD->isReadOnly())
56430b57cec5SDimitry Andric       continue;
5644480093f4SDimitry Andric     if (ObjCMethodDecl *Setter = Prop->getSetterMethodDecl())
56450b57cec5SDimitry Andric       InstanceMethods.push_back(Setter);
56460b57cec5SDimitry Andric   }
56470b57cec5SDimitry Andric   RewriteObjCMethodsMetaData(InstanceMethods.begin(), InstanceMethods.end(),
56480b57cec5SDimitry Andric                              true, "CATEGORY_", FullCategoryName, Result);
56490b57cec5SDimitry Andric 
56500b57cec5SDimitry Andric   // Build _objc_method_list for class's class methods if needed
56510b57cec5SDimitry Andric   RewriteObjCMethodsMetaData(IDecl->classmeth_begin(), IDecl->classmeth_end(),
56520b57cec5SDimitry Andric                              false, "CATEGORY_", FullCategoryName, Result);
56530b57cec5SDimitry Andric 
56540b57cec5SDimitry Andric   // Protocols referenced in class declaration?
56550b57cec5SDimitry Andric   // Null CDecl is case of a category implementation with no category interface
56560b57cec5SDimitry Andric   if (CDecl)
56570b57cec5SDimitry Andric     RewriteObjCProtocolListMetaData(CDecl->getReferencedProtocols(), "CATEGORY",
56580b57cec5SDimitry Andric                                     FullCategoryName, Result);
56590b57cec5SDimitry Andric   /* struct _objc_category {
56600b57cec5SDimitry Andric    char *category_name;
56610b57cec5SDimitry Andric    char *class_name;
56620b57cec5SDimitry Andric    struct _objc_method_list *instance_methods;
56630b57cec5SDimitry Andric    struct _objc_method_list *class_methods;
56640b57cec5SDimitry Andric    struct _objc_protocol_list *protocols;
56650b57cec5SDimitry Andric    // Objective-C 1.0 extensions
56660b57cec5SDimitry Andric    uint32_t size;     // sizeof (struct _objc_category)
56670b57cec5SDimitry Andric    struct _objc_property_list *instance_properties;  // category's own
56680b57cec5SDimitry Andric    // @property decl.
56690b57cec5SDimitry Andric    };
56700b57cec5SDimitry Andric    */
56710b57cec5SDimitry Andric 
56720b57cec5SDimitry Andric   static bool objc_category = false;
56730b57cec5SDimitry Andric   if (!objc_category) {
56740b57cec5SDimitry Andric     Result += "\nstruct _objc_category {\n";
56750b57cec5SDimitry Andric     Result += "\tchar *category_name;\n";
56760b57cec5SDimitry Andric     Result += "\tchar *class_name;\n";
56770b57cec5SDimitry Andric     Result += "\tstruct _objc_method_list *instance_methods;\n";
56780b57cec5SDimitry Andric     Result += "\tstruct _objc_method_list *class_methods;\n";
56790b57cec5SDimitry Andric     Result += "\tstruct _objc_protocol_list *protocols;\n";
56800b57cec5SDimitry Andric     Result += "\tunsigned int size;\n";
56810b57cec5SDimitry Andric     Result += "\tstruct _objc_property_list *instance_properties;\n";
56820b57cec5SDimitry Andric     Result += "};\n";
56830b57cec5SDimitry Andric     objc_category = true;
56840b57cec5SDimitry Andric   }
56850b57cec5SDimitry Andric   Result += "\nstatic struct _objc_category _OBJC_CATEGORY_";
56860b57cec5SDimitry Andric   Result += FullCategoryName;
56870b57cec5SDimitry Andric   Result += " __attribute__ ((used, section (\"__OBJC, __category\")))= {\n\t\"";
56880b57cec5SDimitry Andric   Result += IDecl->getNameAsString();
56890b57cec5SDimitry Andric   Result += "\"\n\t, \"";
56900b57cec5SDimitry Andric   Result += ClassDecl->getNameAsString();
56910b57cec5SDimitry Andric   Result += "\"\n";
56920b57cec5SDimitry Andric 
56930b57cec5SDimitry Andric   if (IDecl->instmeth_begin() != IDecl->instmeth_end()) {
56940b57cec5SDimitry Andric     Result += "\t, (struct _objc_method_list *)"
56950b57cec5SDimitry Andric     "&_OBJC_CATEGORY_INSTANCE_METHODS_";
56960b57cec5SDimitry Andric     Result += FullCategoryName;
56970b57cec5SDimitry Andric     Result += "\n";
56980b57cec5SDimitry Andric   }
56990b57cec5SDimitry Andric   else
57000b57cec5SDimitry Andric     Result += "\t, 0\n";
57010b57cec5SDimitry Andric   if (IDecl->classmeth_begin() != IDecl->classmeth_end()) {
57020b57cec5SDimitry Andric     Result += "\t, (struct _objc_method_list *)"
57030b57cec5SDimitry Andric     "&_OBJC_CATEGORY_CLASS_METHODS_";
57040b57cec5SDimitry Andric     Result += FullCategoryName;
57050b57cec5SDimitry Andric     Result += "\n";
57060b57cec5SDimitry Andric   }
57070b57cec5SDimitry Andric   else
57080b57cec5SDimitry Andric     Result += "\t, 0\n";
57090b57cec5SDimitry Andric 
57100b57cec5SDimitry Andric   if (CDecl && CDecl->protocol_begin() != CDecl->protocol_end()) {
57110b57cec5SDimitry Andric     Result += "\t, (struct _objc_protocol_list *)&_OBJC_CATEGORY_PROTOCOLS_";
57120b57cec5SDimitry Andric     Result += FullCategoryName;
57130b57cec5SDimitry Andric     Result += "\n";
57140b57cec5SDimitry Andric   }
57150b57cec5SDimitry Andric   else
57160b57cec5SDimitry Andric     Result += "\t, 0\n";
57170b57cec5SDimitry Andric   Result += "\t, sizeof(struct _objc_category), 0\n};\n";
57180b57cec5SDimitry Andric }
57190b57cec5SDimitry Andric 
57200b57cec5SDimitry Andric // RewriteObjCMethodsMetaData - Rewrite methods metadata for instance or
57210b57cec5SDimitry Andric /// class methods.
57220b57cec5SDimitry Andric template<typename MethodIterator>
57230b57cec5SDimitry Andric void RewriteObjCFragileABI::RewriteObjCMethodsMetaData(MethodIterator MethodBegin,
57240b57cec5SDimitry Andric                                              MethodIterator MethodEnd,
57250b57cec5SDimitry Andric                                              bool IsInstanceMethod,
57260b57cec5SDimitry Andric                                              StringRef prefix,
57270b57cec5SDimitry Andric                                              StringRef ClassName,
57280b57cec5SDimitry Andric                                              std::string &Result) {
57290b57cec5SDimitry Andric   if (MethodBegin == MethodEnd) return;
57300b57cec5SDimitry Andric 
57310b57cec5SDimitry Andric   if (!objc_impl_method) {
57320b57cec5SDimitry Andric     /* struct _objc_method {
57330b57cec5SDimitry Andric      SEL _cmd;
57340b57cec5SDimitry Andric      char *method_types;
57350b57cec5SDimitry Andric      void *_imp;
57360b57cec5SDimitry Andric      }
57370b57cec5SDimitry Andric      */
57380b57cec5SDimitry Andric     Result += "\nstruct _objc_method {\n";
57390b57cec5SDimitry Andric     Result += "\tSEL _cmd;\n";
57400b57cec5SDimitry Andric     Result += "\tchar *method_types;\n";
57410b57cec5SDimitry Andric     Result += "\tvoid *_imp;\n";
57420b57cec5SDimitry Andric     Result += "};\n";
57430b57cec5SDimitry Andric 
57440b57cec5SDimitry Andric     objc_impl_method = true;
57450b57cec5SDimitry Andric   }
57460b57cec5SDimitry Andric 
57470b57cec5SDimitry Andric   // Build _objc_method_list for class's methods if needed
57480b57cec5SDimitry Andric 
57490b57cec5SDimitry Andric   /* struct  {
57500b57cec5SDimitry Andric    struct _objc_method_list *next_method;
57510b57cec5SDimitry Andric    int method_count;
57520b57cec5SDimitry Andric    struct _objc_method method_list[];
57530b57cec5SDimitry Andric    }
57540b57cec5SDimitry Andric    */
57550b57cec5SDimitry Andric   unsigned NumMethods = std::distance(MethodBegin, MethodEnd);
57560b57cec5SDimitry Andric   Result += "\nstatic struct {\n";
57570b57cec5SDimitry Andric   Result += "\tstruct _objc_method_list *next_method;\n";
57580b57cec5SDimitry Andric   Result += "\tint method_count;\n";
57590b57cec5SDimitry Andric   Result += "\tstruct _objc_method method_list[";
57600b57cec5SDimitry Andric   Result += utostr(NumMethods);
57610b57cec5SDimitry Andric   Result += "];\n} _OBJC_";
57620b57cec5SDimitry Andric   Result += prefix;
57630b57cec5SDimitry Andric   Result += IsInstanceMethod ? "INSTANCE" : "CLASS";
57640b57cec5SDimitry Andric   Result += "_METHODS_";
57650b57cec5SDimitry Andric   Result += ClassName;
57660b57cec5SDimitry Andric   Result += " __attribute__ ((used, section (\"__OBJC, __";
57670b57cec5SDimitry Andric   Result += IsInstanceMethod ? "inst" : "cls";
57680b57cec5SDimitry Andric   Result += "_meth\")))= ";
57690b57cec5SDimitry Andric   Result += "{\n\t0, " + utostr(NumMethods) + "\n";
57700b57cec5SDimitry Andric 
57710b57cec5SDimitry Andric   Result += "\t,{{(SEL)\"";
57720b57cec5SDimitry Andric   Result += (*MethodBegin)->getSelector().getAsString();
57730b57cec5SDimitry Andric   std::string MethodTypeString =
57740b57cec5SDimitry Andric     Context->getObjCEncodingForMethodDecl(*MethodBegin);
57750b57cec5SDimitry Andric   Result += "\", \"";
57760b57cec5SDimitry Andric   Result += MethodTypeString;
57770b57cec5SDimitry Andric   Result += "\", (void *)";
57780b57cec5SDimitry Andric   Result += MethodInternalNames[*MethodBegin];
57790b57cec5SDimitry Andric   Result += "}\n";
57800b57cec5SDimitry Andric   for (++MethodBegin; MethodBegin != MethodEnd; ++MethodBegin) {
57810b57cec5SDimitry Andric     Result += "\t  ,{(SEL)\"";
57820b57cec5SDimitry Andric     Result += (*MethodBegin)->getSelector().getAsString();
57830b57cec5SDimitry Andric     std::string MethodTypeString =
57840b57cec5SDimitry Andric       Context->getObjCEncodingForMethodDecl(*MethodBegin);
57850b57cec5SDimitry Andric     Result += "\", \"";
57860b57cec5SDimitry Andric     Result += MethodTypeString;
57870b57cec5SDimitry Andric     Result += "\", (void *)";
57880b57cec5SDimitry Andric     Result += MethodInternalNames[*MethodBegin];
57890b57cec5SDimitry Andric     Result += "}\n";
57900b57cec5SDimitry Andric   }
57910b57cec5SDimitry Andric   Result += "\t }\n};\n";
57920b57cec5SDimitry Andric }
57930b57cec5SDimitry Andric 
57940b57cec5SDimitry Andric Stmt *RewriteObjCFragileABI::RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV) {
57950b57cec5SDimitry Andric   SourceRange OldRange = IV->getSourceRange();
57960b57cec5SDimitry Andric   Expr *BaseExpr = IV->getBase();
57970b57cec5SDimitry Andric 
57980b57cec5SDimitry Andric   // Rewrite the base, but without actually doing replaces.
57990b57cec5SDimitry Andric   {
58000b57cec5SDimitry Andric     DisableReplaceStmtScope S(*this);
58010b57cec5SDimitry Andric     BaseExpr = cast<Expr>(RewriteFunctionBodyOrGlobalInitializer(BaseExpr));
58020b57cec5SDimitry Andric     IV->setBase(BaseExpr);
58030b57cec5SDimitry Andric   }
58040b57cec5SDimitry Andric 
58050b57cec5SDimitry Andric   ObjCIvarDecl *D = IV->getDecl();
58060b57cec5SDimitry Andric 
58070b57cec5SDimitry Andric   Expr *Replacement = IV;
58080b57cec5SDimitry Andric   if (CurMethodDef) {
58090b57cec5SDimitry Andric     if (BaseExpr->getType()->isObjCObjectPointerType()) {
58100b57cec5SDimitry Andric       const ObjCInterfaceType *iFaceDecl =
58110b57cec5SDimitry Andric       dyn_cast<ObjCInterfaceType>(BaseExpr->getType()->getPointeeType());
58120b57cec5SDimitry Andric       assert(iFaceDecl && "RewriteObjCIvarRefExpr - iFaceDecl is null");
58130b57cec5SDimitry Andric       // lookup which class implements the instance variable.
58140b57cec5SDimitry Andric       ObjCInterfaceDecl *clsDeclared = nullptr;
58150b57cec5SDimitry Andric       iFaceDecl->getDecl()->lookupInstanceVariable(D->getIdentifier(),
58160b57cec5SDimitry Andric                                                    clsDeclared);
58170b57cec5SDimitry Andric       assert(clsDeclared && "RewriteObjCIvarRefExpr(): Can't find class");
58180b57cec5SDimitry Andric 
58190b57cec5SDimitry Andric       // Synthesize an explicit cast to gain access to the ivar.
58205ffd83dbSDimitry Andric       std::string RecName =
58215ffd83dbSDimitry Andric           std::string(clsDeclared->getIdentifier()->getName());
58220b57cec5SDimitry Andric       RecName += "_IMPL";
58230b57cec5SDimitry Andric       IdentifierInfo *II = &Context->Idents.get(RecName);
5824*5f757f3fSDimitry Andric       RecordDecl *RD =
5825*5f757f3fSDimitry Andric           RecordDecl::Create(*Context, TagTypeKind::Struct, TUDecl,
5826*5f757f3fSDimitry Andric                              SourceLocation(), SourceLocation(), II);
58270b57cec5SDimitry Andric       assert(RD && "RewriteObjCIvarRefExpr(): Can't find RecordDecl");
58280b57cec5SDimitry Andric       QualType castT = Context->getPointerType(Context->getTagDeclType(RD));
58290b57cec5SDimitry Andric       CastExpr *castExpr = NoTypeInfoCStyleCastExpr(Context, castT,
58300b57cec5SDimitry Andric                                                     CK_BitCast,
58310b57cec5SDimitry Andric                                                     IV->getBase());
58320b57cec5SDimitry Andric       // Don't forget the parens to enforce the proper binding.
58330b57cec5SDimitry Andric       ParenExpr *PE = new (Context) ParenExpr(OldRange.getBegin(),
58340b57cec5SDimitry Andric                                               OldRange.getEnd(),
58350b57cec5SDimitry Andric                                               castExpr);
58360b57cec5SDimitry Andric       if (IV->isFreeIvar() &&
58370b57cec5SDimitry Andric           declaresSameEntity(CurMethodDef->getClassInterface(),
58380b57cec5SDimitry Andric                              iFaceDecl->getDecl())) {
58390b57cec5SDimitry Andric         MemberExpr *ME = MemberExpr::CreateImplicit(
58400b57cec5SDimitry Andric             *Context, PE, true, D, D->getType(), VK_LValue, OK_Ordinary);
58410b57cec5SDimitry Andric         Replacement = ME;
58420b57cec5SDimitry Andric       } else {
58430b57cec5SDimitry Andric         IV->setBase(PE);
58440b57cec5SDimitry Andric       }
58450b57cec5SDimitry Andric     }
58460b57cec5SDimitry Andric   } else { // we are outside a method.
58470b57cec5SDimitry Andric     assert(!IV->isFreeIvar() && "Cannot have a free standing ivar outside a method");
58480b57cec5SDimitry Andric 
58490b57cec5SDimitry Andric     // Explicit ivar refs need to have a cast inserted.
58500b57cec5SDimitry Andric     // FIXME: consider sharing some of this code with the code above.
58510b57cec5SDimitry Andric     if (BaseExpr->getType()->isObjCObjectPointerType()) {
58520b57cec5SDimitry Andric       const ObjCInterfaceType *iFaceDecl =
58530b57cec5SDimitry Andric       dyn_cast<ObjCInterfaceType>(BaseExpr->getType()->getPointeeType());
58540b57cec5SDimitry Andric       // lookup which class implements the instance variable.
58550b57cec5SDimitry Andric       ObjCInterfaceDecl *clsDeclared = nullptr;
58560b57cec5SDimitry Andric       iFaceDecl->getDecl()->lookupInstanceVariable(D->getIdentifier(),
58570b57cec5SDimitry Andric                                                    clsDeclared);
58580b57cec5SDimitry Andric       assert(clsDeclared && "RewriteObjCIvarRefExpr(): Can't find class");
58590b57cec5SDimitry Andric 
58600b57cec5SDimitry Andric       // Synthesize an explicit cast to gain access to the ivar.
58615ffd83dbSDimitry Andric       std::string RecName =
58625ffd83dbSDimitry Andric           std::string(clsDeclared->getIdentifier()->getName());
58630b57cec5SDimitry Andric       RecName += "_IMPL";
58640b57cec5SDimitry Andric       IdentifierInfo *II = &Context->Idents.get(RecName);
5865*5f757f3fSDimitry Andric       RecordDecl *RD =
5866*5f757f3fSDimitry Andric           RecordDecl::Create(*Context, TagTypeKind::Struct, TUDecl,
5867*5f757f3fSDimitry Andric                              SourceLocation(), SourceLocation(), II);
58680b57cec5SDimitry Andric       assert(RD && "RewriteObjCIvarRefExpr(): Can't find RecordDecl");
58690b57cec5SDimitry Andric       QualType castT = Context->getPointerType(Context->getTagDeclType(RD));
58700b57cec5SDimitry Andric       CastExpr *castExpr = NoTypeInfoCStyleCastExpr(Context, castT,
58710b57cec5SDimitry Andric                                                     CK_BitCast,
58720b57cec5SDimitry Andric                                                     IV->getBase());
58730b57cec5SDimitry Andric       // Don't forget the parens to enforce the proper binding.
58740b57cec5SDimitry Andric       ParenExpr *PE = new (Context) ParenExpr(
58750b57cec5SDimitry Andric           IV->getBase()->getBeginLoc(), IV->getBase()->getEndLoc(), castExpr);
58760b57cec5SDimitry Andric       // Cannot delete IV->getBase(), since PE points to it.
58770b57cec5SDimitry Andric       // Replace the old base with the cast. This is important when doing
58780b57cec5SDimitry Andric       // embedded rewrites. For example, [newInv->_container addObject:0].
58790b57cec5SDimitry Andric       IV->setBase(PE);
58800b57cec5SDimitry Andric     }
58810b57cec5SDimitry Andric   }
58820b57cec5SDimitry Andric 
58830b57cec5SDimitry Andric   ReplaceStmtWithRange(IV, Replacement, OldRange);
58840b57cec5SDimitry Andric   return Replacement;
58850b57cec5SDimitry Andric }
58860b57cec5SDimitry Andric 
58870b57cec5SDimitry Andric #endif // CLANG_ENABLE_OBJC_REWRITER
5888