10b57cec5SDimitry Andric //===-- RewriteModernObjC.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/Basic/TargetInfo.h"
230b57cec5SDimitry Andric #include "clang/Config/config.h"
240b57cec5SDimitry Andric #include "clang/Lex/Lexer.h"
250b57cec5SDimitry Andric #include "clang/Rewrite/Core/Rewriter.h"
260b57cec5SDimitry Andric #include "llvm/ADT/DenseSet.h"
2781ad6265SDimitry Andric #include "llvm/ADT/SetVector.h"
280b57cec5SDimitry Andric #include "llvm/ADT/SmallPtrSet.h"
290b57cec5SDimitry Andric #include "llvm/ADT/StringExtras.h"
300b57cec5SDimitry Andric #include "llvm/Support/MemoryBuffer.h"
310b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
320b57cec5SDimitry Andric #include <memory>
330b57cec5SDimitry Andric 
340b57cec5SDimitry Andric #if CLANG_ENABLE_OBJC_REWRITER
350b57cec5SDimitry Andric 
360b57cec5SDimitry Andric using namespace clang;
370b57cec5SDimitry Andric using llvm::utostr;
380b57cec5SDimitry Andric 
390b57cec5SDimitry Andric namespace {
400b57cec5SDimitry Andric   class RewriteModernObjC : public ASTConsumer {
410b57cec5SDimitry Andric   protected:
420b57cec5SDimitry Andric 
430b57cec5SDimitry Andric     enum {
440b57cec5SDimitry Andric       BLOCK_FIELD_IS_OBJECT   =  3,  /* id, NSObject, __attribute__((NSObject)),
450b57cec5SDimitry Andric                                         block, ... */
460b57cec5SDimitry Andric       BLOCK_FIELD_IS_BLOCK    =  7,  /* a block variable */
470b57cec5SDimitry Andric       BLOCK_FIELD_IS_BYREF    =  8,  /* the on stack structure holding the
480b57cec5SDimitry Andric                                         __block variable */
490b57cec5SDimitry Andric       BLOCK_FIELD_IS_WEAK     = 16,  /* declared __weak, only used in byref copy
500b57cec5SDimitry Andric                                         helpers */
510b57cec5SDimitry Andric       BLOCK_BYREF_CALLER      = 128, /* called from __block (byref) copy/dispose
520b57cec5SDimitry Andric                                         support routines */
530b57cec5SDimitry Andric       BLOCK_BYREF_CURRENT_MAX = 256
540b57cec5SDimitry Andric     };
550b57cec5SDimitry Andric 
560b57cec5SDimitry Andric     enum {
570b57cec5SDimitry Andric       BLOCK_NEEDS_FREE =        (1 << 24),
580b57cec5SDimitry Andric       BLOCK_HAS_COPY_DISPOSE =  (1 << 25),
590b57cec5SDimitry Andric       BLOCK_HAS_CXX_OBJ =       (1 << 26),
600b57cec5SDimitry Andric       BLOCK_IS_GC =             (1 << 27),
610b57cec5SDimitry Andric       BLOCK_IS_GLOBAL =         (1 << 28),
620b57cec5SDimitry Andric       BLOCK_HAS_DESCRIPTOR =    (1 << 29)
630b57cec5SDimitry Andric     };
640b57cec5SDimitry Andric 
650b57cec5SDimitry Andric     Rewriter Rewrite;
660b57cec5SDimitry Andric     DiagnosticsEngine &Diags;
670b57cec5SDimitry Andric     const LangOptions &LangOpts;
680b57cec5SDimitry Andric     ASTContext *Context;
690b57cec5SDimitry Andric     SourceManager *SM;
700b57cec5SDimitry Andric     TranslationUnitDecl *TUDecl;
710b57cec5SDimitry Andric     FileID MainFileID;
720b57cec5SDimitry Andric     const char *MainFileStart, *MainFileEnd;
730b57cec5SDimitry Andric     Stmt *CurrentBody;
740b57cec5SDimitry Andric     ParentMap *PropParentMap; // created lazily.
750b57cec5SDimitry Andric     std::string InFileName;
760b57cec5SDimitry Andric     std::unique_ptr<raw_ostream> OutFile;
770b57cec5SDimitry Andric     std::string Preamble;
780b57cec5SDimitry Andric 
790b57cec5SDimitry Andric     TypeDecl *ProtocolTypeDecl;
800b57cec5SDimitry Andric     VarDecl *GlobalVarDecl;
810b57cec5SDimitry Andric     Expr *GlobalConstructionExp;
820b57cec5SDimitry Andric     unsigned RewriteFailedDiag;
830b57cec5SDimitry Andric     unsigned GlobalBlockRewriteFailedDiag;
840b57cec5SDimitry Andric     // ObjC string constant support.
850b57cec5SDimitry Andric     unsigned NumObjCStringLiterals;
860b57cec5SDimitry Andric     VarDecl *ConstantStringClassReference;
870b57cec5SDimitry Andric     RecordDecl *NSStringRecord;
880b57cec5SDimitry Andric 
890b57cec5SDimitry Andric     // ObjC foreach break/continue generation support.
900b57cec5SDimitry Andric     int BcLabelCount;
910b57cec5SDimitry Andric 
920b57cec5SDimitry Andric     unsigned TryFinallyContainsReturnDiag;
930b57cec5SDimitry Andric     // Needed for super.
940b57cec5SDimitry Andric     ObjCMethodDecl *CurMethodDef;
950b57cec5SDimitry Andric     RecordDecl *SuperStructDecl;
960b57cec5SDimitry Andric     RecordDecl *ConstantStringDecl;
970b57cec5SDimitry Andric 
980b57cec5SDimitry Andric     FunctionDecl *MsgSendFunctionDecl;
990b57cec5SDimitry Andric     FunctionDecl *MsgSendSuperFunctionDecl;
1000b57cec5SDimitry Andric     FunctionDecl *MsgSendStretFunctionDecl;
1010b57cec5SDimitry Andric     FunctionDecl *MsgSendSuperStretFunctionDecl;
1020b57cec5SDimitry Andric     FunctionDecl *MsgSendFpretFunctionDecl;
1030b57cec5SDimitry Andric     FunctionDecl *GetClassFunctionDecl;
1040b57cec5SDimitry Andric     FunctionDecl *GetMetaClassFunctionDecl;
1050b57cec5SDimitry Andric     FunctionDecl *GetSuperClassFunctionDecl;
1060b57cec5SDimitry Andric     FunctionDecl *SelGetUidFunctionDecl;
1070b57cec5SDimitry Andric     FunctionDecl *CFStringFunctionDecl;
1080b57cec5SDimitry Andric     FunctionDecl *SuperConstructorFunctionDecl;
1090b57cec5SDimitry Andric     FunctionDecl *CurFunctionDef;
1100b57cec5SDimitry Andric 
1110b57cec5SDimitry Andric     /* Misc. containers needed for meta-data rewrite. */
1120b57cec5SDimitry Andric     SmallVector<ObjCImplementationDecl *, 8> ClassImplementation;
1130b57cec5SDimitry Andric     SmallVector<ObjCCategoryImplDecl *, 8> CategoryImplementation;
1140b57cec5SDimitry Andric     llvm::SmallPtrSet<ObjCInterfaceDecl*, 8> ObjCSynthesizedStructs;
1150b57cec5SDimitry Andric     llvm::SmallPtrSet<ObjCProtocolDecl*, 8> ObjCSynthesizedProtocols;
1160b57cec5SDimitry Andric     llvm::SmallPtrSet<ObjCInterfaceDecl*, 8> ObjCWrittenInterfaces;
1170b57cec5SDimitry Andric     llvm::SmallPtrSet<TagDecl*, 32> GlobalDefinedTags;
1180b57cec5SDimitry Andric     SmallVector<ObjCInterfaceDecl*, 32> ObjCInterfacesSeen;
1190b57cec5SDimitry Andric     /// DefinedNonLazyClasses - List of defined "non-lazy" classes.
1200b57cec5SDimitry Andric     SmallVector<ObjCInterfaceDecl*, 8> DefinedNonLazyClasses;
1210b57cec5SDimitry Andric 
1220b57cec5SDimitry Andric     /// DefinedNonLazyCategories - List of defined "non-lazy" categories.
1230b57cec5SDimitry Andric     SmallVector<ObjCCategoryDecl *, 8> DefinedNonLazyCategories;
1240b57cec5SDimitry Andric 
1250b57cec5SDimitry Andric     SmallVector<Stmt *, 32> Stmts;
1260b57cec5SDimitry Andric     SmallVector<int, 8> ObjCBcLabelNo;
1270b57cec5SDimitry Andric     // Remember all the @protocol(<expr>) expressions.
1280b57cec5SDimitry Andric     llvm::SmallPtrSet<ObjCProtocolDecl *, 32> ProtocolExprDecls;
1290b57cec5SDimitry Andric 
1300b57cec5SDimitry Andric     llvm::DenseSet<uint64_t> CopyDestroyCache;
1310b57cec5SDimitry Andric 
1320b57cec5SDimitry Andric     // Block expressions.
1330b57cec5SDimitry Andric     SmallVector<BlockExpr *, 32> Blocks;
1340b57cec5SDimitry Andric     SmallVector<int, 32> InnerDeclRefsCount;
1350b57cec5SDimitry Andric     SmallVector<DeclRefExpr *, 32> InnerDeclRefs;
1360b57cec5SDimitry Andric 
1370b57cec5SDimitry Andric     SmallVector<DeclRefExpr *, 32> BlockDeclRefs;
1380b57cec5SDimitry Andric 
1390b57cec5SDimitry Andric     // Block related declarations.
1400b57cec5SDimitry Andric     SmallVector<ValueDecl *, 8> BlockByCopyDecls;
1410b57cec5SDimitry Andric     llvm::SmallPtrSet<ValueDecl *, 8> BlockByCopyDeclsPtrSet;
1420b57cec5SDimitry Andric     SmallVector<ValueDecl *, 8> BlockByRefDecls;
1430b57cec5SDimitry Andric     llvm::SmallPtrSet<ValueDecl *, 8> BlockByRefDeclsPtrSet;
1440b57cec5SDimitry Andric     llvm::DenseMap<ValueDecl *, unsigned> BlockByRefDeclNo;
1450b57cec5SDimitry Andric     llvm::SmallPtrSet<ValueDecl *, 8> ImportedBlockDecls;
1460b57cec5SDimitry Andric     llvm::SmallPtrSet<VarDecl *, 8> ImportedLocalExternalDecls;
1470b57cec5SDimitry Andric 
1480b57cec5SDimitry Andric     llvm::DenseMap<BlockExpr *, std::string> RewrittenBlockExprs;
1490b57cec5SDimitry Andric     llvm::DenseMap<ObjCInterfaceDecl *,
1500b57cec5SDimitry Andric                     llvm::SmallSetVector<ObjCIvarDecl *, 8> > ReferencedIvars;
1510b57cec5SDimitry Andric 
1520b57cec5SDimitry Andric     // ivar bitfield grouping containers
1530b57cec5SDimitry Andric     llvm::DenseSet<const ObjCInterfaceDecl *> ObjCInterefaceHasBitfieldGroups;
1540b57cec5SDimitry Andric     llvm::DenseMap<const ObjCIvarDecl* , unsigned> IvarGroupNumber;
1550b57cec5SDimitry Andric     // This container maps an <class, group number for ivar> tuple to the type
1560b57cec5SDimitry Andric     // of the struct where the bitfield belongs.
1570b57cec5SDimitry Andric     llvm::DenseMap<std::pair<const ObjCInterfaceDecl*, unsigned>, QualType> GroupRecordType;
1580b57cec5SDimitry Andric     SmallVector<FunctionDecl*, 32> FunctionDefinitionsSeen;
1590b57cec5SDimitry Andric 
1600b57cec5SDimitry Andric     // This maps an original source AST to it's rewritten form. This allows
1610b57cec5SDimitry Andric     // us to avoid rewriting the same node twice (which is very uncommon).
1620b57cec5SDimitry Andric     // This is needed to support some of the exotic property rewriting.
1630b57cec5SDimitry Andric     llvm::DenseMap<Stmt *, Stmt *> ReplacedNodes;
1640b57cec5SDimitry Andric 
1650b57cec5SDimitry Andric     // Needed for header files being rewritten
1660b57cec5SDimitry Andric     bool IsHeader;
1670b57cec5SDimitry Andric     bool SilenceRewriteMacroWarning;
1680b57cec5SDimitry Andric     bool GenerateLineInfo;
1690b57cec5SDimitry Andric     bool objc_impl_method;
1700b57cec5SDimitry Andric 
1710b57cec5SDimitry Andric     bool DisableReplaceStmt;
1720b57cec5SDimitry Andric     class DisableReplaceStmtScope {
1730b57cec5SDimitry Andric       RewriteModernObjC &R;
1740b57cec5SDimitry Andric       bool SavedValue;
1750b57cec5SDimitry Andric 
1760b57cec5SDimitry Andric     public:
DisableReplaceStmtScope(RewriteModernObjC & R)1770b57cec5SDimitry Andric       DisableReplaceStmtScope(RewriteModernObjC &R)
1780b57cec5SDimitry Andric         : R(R), SavedValue(R.DisableReplaceStmt) {
1790b57cec5SDimitry Andric         R.DisableReplaceStmt = true;
1800b57cec5SDimitry Andric       }
~DisableReplaceStmtScope()1810b57cec5SDimitry Andric       ~DisableReplaceStmtScope() {
1820b57cec5SDimitry Andric         R.DisableReplaceStmt = SavedValue;
1830b57cec5SDimitry Andric       }
1840b57cec5SDimitry Andric     };
1850b57cec5SDimitry Andric     void InitializeCommon(ASTContext &context);
1860b57cec5SDimitry Andric 
1870b57cec5SDimitry Andric   public:
1880b57cec5SDimitry Andric     llvm::DenseMap<ObjCMethodDecl*, std::string> MethodInternalNames;
1890b57cec5SDimitry Andric 
1900b57cec5SDimitry Andric     // Top Level Driver code.
HandleTopLevelDecl(DeclGroupRef D)1910b57cec5SDimitry Andric     bool HandleTopLevelDecl(DeclGroupRef D) override {
1920b57cec5SDimitry Andric       for (DeclGroupRef::iterator I = D.begin(), E = D.end(); I != E; ++I) {
1930b57cec5SDimitry Andric         if (ObjCInterfaceDecl *Class = dyn_cast<ObjCInterfaceDecl>(*I)) {
1940b57cec5SDimitry Andric           if (!Class->isThisDeclarationADefinition()) {
1950b57cec5SDimitry Andric             RewriteForwardClassDecl(D);
1960b57cec5SDimitry Andric             break;
1970b57cec5SDimitry Andric           } else {
1980b57cec5SDimitry Andric             // Keep track of all interface declarations seen.
1990b57cec5SDimitry Andric             ObjCInterfacesSeen.push_back(Class);
2000b57cec5SDimitry Andric             break;
2010b57cec5SDimitry Andric           }
2020b57cec5SDimitry Andric         }
2030b57cec5SDimitry Andric 
2040b57cec5SDimitry Andric         if (ObjCProtocolDecl *Proto = dyn_cast<ObjCProtocolDecl>(*I)) {
2050b57cec5SDimitry Andric           if (!Proto->isThisDeclarationADefinition()) {
2060b57cec5SDimitry Andric             RewriteForwardProtocolDecl(D);
2070b57cec5SDimitry Andric             break;
2080b57cec5SDimitry Andric           }
2090b57cec5SDimitry Andric         }
2100b57cec5SDimitry Andric 
2110b57cec5SDimitry Andric         if (FunctionDecl *FDecl = dyn_cast<FunctionDecl>(*I)) {
2120b57cec5SDimitry Andric           // Under modern abi, we cannot translate body of the function
2130b57cec5SDimitry Andric           // yet until all class extensions and its implementation is seen.
2140b57cec5SDimitry Andric           // This is because they may introduce new bitfields which must go
2150b57cec5SDimitry Andric           // into their grouping struct.
2160b57cec5SDimitry Andric           if (FDecl->isThisDeclarationADefinition() &&
2170b57cec5SDimitry Andric               // Not c functions defined inside an objc container.
2180b57cec5SDimitry Andric               !FDecl->isTopLevelDeclInObjCContainer()) {
2190b57cec5SDimitry Andric             FunctionDefinitionsSeen.push_back(FDecl);
2200b57cec5SDimitry Andric             break;
2210b57cec5SDimitry Andric           }
2220b57cec5SDimitry Andric         }
2230b57cec5SDimitry Andric         HandleTopLevelSingleDecl(*I);
2240b57cec5SDimitry Andric       }
2250b57cec5SDimitry Andric       return true;
2260b57cec5SDimitry Andric     }
2270b57cec5SDimitry Andric 
HandleTopLevelDeclInObjCContainer(DeclGroupRef D)2280b57cec5SDimitry Andric     void HandleTopLevelDeclInObjCContainer(DeclGroupRef D) override {
2290b57cec5SDimitry Andric       for (DeclGroupRef::iterator I = D.begin(), E = D.end(); I != E; ++I) {
2300b57cec5SDimitry Andric         if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(*I)) {
2310b57cec5SDimitry Andric           if (isTopLevelBlockPointerType(TD->getUnderlyingType()))
2320b57cec5SDimitry Andric             RewriteBlockPointerDecl(TD);
2330b57cec5SDimitry Andric           else if (TD->getUnderlyingType()->isFunctionPointerType())
2340b57cec5SDimitry Andric             CheckFunctionPointerDecl(TD->getUnderlyingType(), TD);
2350b57cec5SDimitry Andric           else
2360b57cec5SDimitry Andric             RewriteObjCQualifiedInterfaceTypes(TD);
2370b57cec5SDimitry Andric         }
2380b57cec5SDimitry Andric       }
2390b57cec5SDimitry Andric     }
2400b57cec5SDimitry Andric 
2410b57cec5SDimitry Andric     void HandleTopLevelSingleDecl(Decl *D);
2420b57cec5SDimitry Andric     void HandleDeclInMainFile(Decl *D);
2430b57cec5SDimitry Andric     RewriteModernObjC(std::string inFile, std::unique_ptr<raw_ostream> OS,
2440b57cec5SDimitry Andric                       DiagnosticsEngine &D, const LangOptions &LOpts,
2450b57cec5SDimitry Andric                       bool silenceMacroWarn, bool LineInfo);
2460b57cec5SDimitry Andric 
~RewriteModernObjC()2470b57cec5SDimitry Andric     ~RewriteModernObjC() override {}
2480b57cec5SDimitry Andric 
2490b57cec5SDimitry Andric     void HandleTranslationUnit(ASTContext &C) override;
2500b57cec5SDimitry Andric 
ReplaceStmt(Stmt * Old,Stmt * New)2510b57cec5SDimitry Andric     void ReplaceStmt(Stmt *Old, Stmt *New) {
2520b57cec5SDimitry Andric       ReplaceStmtWithRange(Old, New, Old->getSourceRange());
2530b57cec5SDimitry Andric     }
2540b57cec5SDimitry Andric 
ReplaceStmtWithRange(Stmt * Old,Stmt * New,SourceRange SrcRange)2550b57cec5SDimitry Andric     void ReplaceStmtWithRange(Stmt *Old, Stmt *New, SourceRange SrcRange) {
2560b57cec5SDimitry Andric       assert(Old != nullptr && New != nullptr && "Expected non-null Stmt's");
2570b57cec5SDimitry Andric 
2580b57cec5SDimitry Andric       Stmt *ReplacingStmt = ReplacedNodes[Old];
2590b57cec5SDimitry Andric       if (ReplacingStmt)
2600b57cec5SDimitry Andric         return; // We can't rewrite the same node twice.
2610b57cec5SDimitry Andric 
2620b57cec5SDimitry Andric       if (DisableReplaceStmt)
2630b57cec5SDimitry Andric         return;
2640b57cec5SDimitry Andric 
2650b57cec5SDimitry Andric       // Measure the old text.
2660b57cec5SDimitry Andric       int Size = Rewrite.getRangeSize(SrcRange);
2670b57cec5SDimitry Andric       if (Size == -1) {
2680b57cec5SDimitry Andric         Diags.Report(Context->getFullLoc(Old->getBeginLoc()), RewriteFailedDiag)
2690b57cec5SDimitry Andric             << Old->getSourceRange();
2700b57cec5SDimitry Andric         return;
2710b57cec5SDimitry Andric       }
2720b57cec5SDimitry Andric       // Get the new text.
2730b57cec5SDimitry Andric       std::string SStr;
2740b57cec5SDimitry Andric       llvm::raw_string_ostream S(SStr);
2750b57cec5SDimitry Andric       New->printPretty(S, nullptr, PrintingPolicy(LangOpts));
2760b57cec5SDimitry Andric       const std::string &Str = S.str();
2770b57cec5SDimitry Andric 
2780b57cec5SDimitry Andric       // If replacement succeeded or warning disabled return with no warning.
2790b57cec5SDimitry Andric       if (!Rewrite.ReplaceText(SrcRange.getBegin(), Size, Str)) {
2800b57cec5SDimitry Andric         ReplacedNodes[Old] = New;
2810b57cec5SDimitry Andric         return;
2820b57cec5SDimitry Andric       }
2830b57cec5SDimitry Andric       if (SilenceRewriteMacroWarning)
2840b57cec5SDimitry Andric         return;
2850b57cec5SDimitry Andric       Diags.Report(Context->getFullLoc(Old->getBeginLoc()), RewriteFailedDiag)
2860b57cec5SDimitry Andric           << Old->getSourceRange();
2870b57cec5SDimitry Andric     }
2880b57cec5SDimitry Andric 
InsertText(SourceLocation Loc,StringRef Str,bool InsertAfter=true)2890b57cec5SDimitry Andric     void InsertText(SourceLocation Loc, StringRef Str,
2900b57cec5SDimitry Andric                     bool InsertAfter = true) {
2910b57cec5SDimitry Andric       // If insertion succeeded or warning disabled return with no warning.
2920b57cec5SDimitry Andric       if (!Rewrite.InsertText(Loc, Str, InsertAfter) ||
2930b57cec5SDimitry Andric           SilenceRewriteMacroWarning)
2940b57cec5SDimitry Andric         return;
2950b57cec5SDimitry Andric 
2960b57cec5SDimitry Andric       Diags.Report(Context->getFullLoc(Loc), RewriteFailedDiag);
2970b57cec5SDimitry Andric     }
2980b57cec5SDimitry Andric 
ReplaceText(SourceLocation Start,unsigned OrigLength,StringRef Str)2990b57cec5SDimitry Andric     void ReplaceText(SourceLocation Start, unsigned OrigLength,
3000b57cec5SDimitry Andric                      StringRef Str) {
3010b57cec5SDimitry Andric       // If removal succeeded or warning disabled return with no warning.
3020b57cec5SDimitry Andric       if (!Rewrite.ReplaceText(Start, OrigLength, Str) ||
3030b57cec5SDimitry Andric           SilenceRewriteMacroWarning)
3040b57cec5SDimitry Andric         return;
3050b57cec5SDimitry Andric 
3060b57cec5SDimitry Andric       Diags.Report(Context->getFullLoc(Start), RewriteFailedDiag);
3070b57cec5SDimitry Andric     }
3080b57cec5SDimitry Andric 
3090b57cec5SDimitry Andric     // Syntactic Rewriting.
3100b57cec5SDimitry Andric     void RewriteRecordBody(RecordDecl *RD);
3110b57cec5SDimitry Andric     void RewriteInclude();
3120b57cec5SDimitry Andric     void RewriteLineDirective(const Decl *D);
3130b57cec5SDimitry Andric     void ConvertSourceLocationToLineDirective(SourceLocation Loc,
3140b57cec5SDimitry Andric                                               std::string &LineString);
3150b57cec5SDimitry Andric     void RewriteForwardClassDecl(DeclGroupRef D);
3160b57cec5SDimitry Andric     void RewriteForwardClassDecl(const SmallVectorImpl<Decl *> &DG);
3170b57cec5SDimitry Andric     void RewriteForwardClassEpilogue(ObjCInterfaceDecl *ClassDecl,
3180b57cec5SDimitry Andric                                      const std::string &typedefString);
3190b57cec5SDimitry Andric     void RewriteImplementations();
3200b57cec5SDimitry Andric     void RewritePropertyImplDecl(ObjCPropertyImplDecl *PID,
3210b57cec5SDimitry Andric                                  ObjCImplementationDecl *IMD,
3220b57cec5SDimitry Andric                                  ObjCCategoryImplDecl *CID);
3230b57cec5SDimitry Andric     void RewriteInterfaceDecl(ObjCInterfaceDecl *Dcl);
3240b57cec5SDimitry Andric     void RewriteImplementationDecl(Decl *Dcl);
3250b57cec5SDimitry Andric     void RewriteObjCMethodDecl(const ObjCInterfaceDecl *IDecl,
3260b57cec5SDimitry Andric                                ObjCMethodDecl *MDecl, std::string &ResultStr);
3270b57cec5SDimitry Andric     void RewriteTypeIntoString(QualType T, std::string &ResultStr,
3280b57cec5SDimitry Andric                                const FunctionType *&FPRetType);
3290b57cec5SDimitry Andric     void RewriteByRefString(std::string &ResultStr, const std::string &Name,
3300b57cec5SDimitry Andric                             ValueDecl *VD, bool def=false);
3310b57cec5SDimitry Andric     void RewriteCategoryDecl(ObjCCategoryDecl *Dcl);
3320b57cec5SDimitry Andric     void RewriteProtocolDecl(ObjCProtocolDecl *Dcl);
3330b57cec5SDimitry Andric     void RewriteForwardProtocolDecl(DeclGroupRef D);
3340b57cec5SDimitry Andric     void RewriteForwardProtocolDecl(const SmallVectorImpl<Decl *> &DG);
3350b57cec5SDimitry Andric     void RewriteMethodDeclaration(ObjCMethodDecl *Method);
3360b57cec5SDimitry Andric     void RewriteProperty(ObjCPropertyDecl *prop);
3370b57cec5SDimitry Andric     void RewriteFunctionDecl(FunctionDecl *FD);
3380b57cec5SDimitry Andric     void RewriteBlockPointerType(std::string& Str, QualType Type);
3390b57cec5SDimitry Andric     void RewriteBlockPointerTypeVariable(std::string& Str, ValueDecl *VD);
3400b57cec5SDimitry Andric     void RewriteBlockLiteralFunctionDecl(FunctionDecl *FD);
3410b57cec5SDimitry Andric     void RewriteObjCQualifiedInterfaceTypes(Decl *Dcl);
3420b57cec5SDimitry Andric     void RewriteTypeOfDecl(VarDecl *VD);
3430b57cec5SDimitry Andric     void RewriteObjCQualifiedInterfaceTypes(Expr *E);
3440b57cec5SDimitry Andric 
3450b57cec5SDimitry Andric     std::string getIvarAccessString(ObjCIvarDecl *D);
3460b57cec5SDimitry Andric 
3470b57cec5SDimitry Andric     // Expression Rewriting.
3480b57cec5SDimitry Andric     Stmt *RewriteFunctionBodyOrGlobalInitializer(Stmt *S);
3490b57cec5SDimitry Andric     Stmt *RewriteAtEncode(ObjCEncodeExpr *Exp);
3500b57cec5SDimitry Andric     Stmt *RewritePropertyOrImplicitGetter(PseudoObjectExpr *Pseudo);
3510b57cec5SDimitry Andric     Stmt *RewritePropertyOrImplicitSetter(PseudoObjectExpr *Pseudo);
3520b57cec5SDimitry Andric     Stmt *RewriteAtSelector(ObjCSelectorExpr *Exp);
3530b57cec5SDimitry Andric     Stmt *RewriteMessageExpr(ObjCMessageExpr *Exp);
3540b57cec5SDimitry Andric     Stmt *RewriteObjCStringLiteral(ObjCStringLiteral *Exp);
3550b57cec5SDimitry Andric     Stmt *RewriteObjCBoolLiteralExpr(ObjCBoolLiteralExpr *Exp);
3560b57cec5SDimitry Andric     Stmt *RewriteObjCBoxedExpr(ObjCBoxedExpr *Exp);
3570b57cec5SDimitry Andric     Stmt *RewriteObjCArrayLiteralExpr(ObjCArrayLiteral *Exp);
3580b57cec5SDimitry Andric     Stmt *RewriteObjCDictionaryLiteralExpr(ObjCDictionaryLiteral *Exp);
3590b57cec5SDimitry Andric     Stmt *RewriteObjCProtocolExpr(ObjCProtocolExpr *Exp);
3600b57cec5SDimitry Andric     Stmt *RewriteObjCTryStmt(ObjCAtTryStmt *S);
3610b57cec5SDimitry Andric     Stmt *RewriteObjCAutoreleasePoolStmt(ObjCAutoreleasePoolStmt  *S);
3620b57cec5SDimitry Andric     Stmt *RewriteObjCSynchronizedStmt(ObjCAtSynchronizedStmt *S);
3630b57cec5SDimitry Andric     Stmt *RewriteObjCThrowStmt(ObjCAtThrowStmt *S);
3640b57cec5SDimitry Andric     Stmt *RewriteObjCForCollectionStmt(ObjCForCollectionStmt *S,
3650b57cec5SDimitry Andric                                        SourceLocation OrigEnd);
3660b57cec5SDimitry Andric     Stmt *RewriteBreakStmt(BreakStmt *S);
3670b57cec5SDimitry Andric     Stmt *RewriteContinueStmt(ContinueStmt *S);
3680b57cec5SDimitry Andric     void RewriteCastExpr(CStyleCastExpr *CE);
3690b57cec5SDimitry Andric     void RewriteImplicitCastObjCExpr(CastExpr *IE);
3700b57cec5SDimitry Andric 
3710b57cec5SDimitry Andric     // Computes ivar bitfield group no.
3720b57cec5SDimitry Andric     unsigned ObjCIvarBitfieldGroupNo(ObjCIvarDecl *IV);
3730b57cec5SDimitry Andric     // Names field decl. for ivar bitfield group.
3740b57cec5SDimitry Andric     void ObjCIvarBitfieldGroupDecl(ObjCIvarDecl *IV, std::string &Result);
3750b57cec5SDimitry Andric     // Names struct type for ivar bitfield group.
3760b57cec5SDimitry Andric     void ObjCIvarBitfieldGroupType(ObjCIvarDecl *IV, std::string &Result);
3770b57cec5SDimitry Andric     // Names symbol for ivar bitfield group field offset.
3780b57cec5SDimitry Andric     void ObjCIvarBitfieldGroupOffset(ObjCIvarDecl *IV, std::string &Result);
3790b57cec5SDimitry Andric     // Given an ivar bitfield, it builds (or finds) its group record type.
3800b57cec5SDimitry Andric     QualType GetGroupRecordTypeForObjCIvarBitfield(ObjCIvarDecl *IV);
3810b57cec5SDimitry Andric     QualType SynthesizeBitfieldGroupStructType(
3820b57cec5SDimitry Andric                                     ObjCIvarDecl *IV,
3830b57cec5SDimitry Andric                                     SmallVectorImpl<ObjCIvarDecl *> &IVars);
3840b57cec5SDimitry Andric 
3850b57cec5SDimitry Andric     // Block rewriting.
3860b57cec5SDimitry Andric     void RewriteBlocksInFunctionProtoType(QualType funcType, NamedDecl *D);
3870b57cec5SDimitry Andric 
3880b57cec5SDimitry Andric     // Block specific rewrite rules.
3890b57cec5SDimitry Andric     void RewriteBlockPointerDecl(NamedDecl *VD);
3900b57cec5SDimitry Andric     void RewriteByRefVar(VarDecl *VD, bool firstDecl, bool lastDecl);
3910b57cec5SDimitry Andric     Stmt *RewriteBlockDeclRefExpr(DeclRefExpr *VD);
3920b57cec5SDimitry Andric     Stmt *RewriteLocalVariableExternalStorage(DeclRefExpr *DRE);
3930b57cec5SDimitry Andric     void RewriteBlockPointerFunctionArgs(FunctionDecl *FD);
3940b57cec5SDimitry Andric 
3950b57cec5SDimitry Andric     void RewriteObjCInternalStruct(ObjCInterfaceDecl *CDecl,
3960b57cec5SDimitry Andric                                       std::string &Result);
3970b57cec5SDimitry Andric 
3980b57cec5SDimitry Andric     void RewriteObjCFieldDecl(FieldDecl *fieldDecl, std::string &Result);
3990b57cec5SDimitry Andric     bool IsTagDefinedInsideClass(ObjCContainerDecl *IDecl, TagDecl *Tag,
4000b57cec5SDimitry Andric                                  bool &IsNamedDefinition);
4010b57cec5SDimitry Andric     void RewriteLocallyDefinedNamedAggregates(FieldDecl *fieldDecl,
4020b57cec5SDimitry Andric                                               std::string &Result);
4030b57cec5SDimitry Andric 
4040b57cec5SDimitry Andric     bool RewriteObjCFieldDeclType(QualType &Type, std::string &Result);
4050b57cec5SDimitry Andric 
4060b57cec5SDimitry Andric     void RewriteIvarOffsetSymbols(ObjCInterfaceDecl *CDecl,
4070b57cec5SDimitry Andric                                   std::string &Result);
4080b57cec5SDimitry Andric 
4090b57cec5SDimitry Andric     void Initialize(ASTContext &context) override;
4100b57cec5SDimitry Andric 
4110b57cec5SDimitry Andric     // Misc. AST transformation routines. Sometimes they end up calling
4120b57cec5SDimitry Andric     // rewriting routines on the new ASTs.
4130b57cec5SDimitry Andric     CallExpr *SynthesizeCallToFunctionDecl(FunctionDecl *FD,
4140b57cec5SDimitry Andric                                            ArrayRef<Expr *> Args,
4150b57cec5SDimitry Andric                                            SourceLocation StartLoc=SourceLocation(),
4160b57cec5SDimitry Andric                                            SourceLocation EndLoc=SourceLocation());
4170b57cec5SDimitry Andric 
4180b57cec5SDimitry Andric     Expr *SynthMsgSendStretCallExpr(FunctionDecl *MsgSendStretFlavor,
4190b57cec5SDimitry Andric                                         QualType returnType,
4200b57cec5SDimitry Andric                                         SmallVectorImpl<QualType> &ArgTypes,
4210b57cec5SDimitry Andric                                         SmallVectorImpl<Expr*> &MsgExprs,
4220b57cec5SDimitry Andric                                         ObjCMethodDecl *Method);
4230b57cec5SDimitry Andric 
4240b57cec5SDimitry Andric     Stmt *SynthMessageExpr(ObjCMessageExpr *Exp,
4250b57cec5SDimitry Andric                            SourceLocation StartLoc=SourceLocation(),
4260b57cec5SDimitry Andric                            SourceLocation EndLoc=SourceLocation());
4270b57cec5SDimitry Andric 
4280b57cec5SDimitry Andric     void SynthCountByEnumWithState(std::string &buf);
4290b57cec5SDimitry Andric     void SynthMsgSendFunctionDecl();
4300b57cec5SDimitry Andric     void SynthMsgSendSuperFunctionDecl();
4310b57cec5SDimitry Andric     void SynthMsgSendStretFunctionDecl();
4320b57cec5SDimitry Andric     void SynthMsgSendFpretFunctionDecl();
4330b57cec5SDimitry Andric     void SynthMsgSendSuperStretFunctionDecl();
4340b57cec5SDimitry Andric     void SynthGetClassFunctionDecl();
4350b57cec5SDimitry Andric     void SynthGetMetaClassFunctionDecl();
4360b57cec5SDimitry Andric     void SynthGetSuperClassFunctionDecl();
4370b57cec5SDimitry Andric     void SynthSelGetUidFunctionDecl();
4380b57cec5SDimitry Andric     void SynthSuperConstructorFunctionDecl();
4390b57cec5SDimitry Andric 
4400b57cec5SDimitry Andric     // Rewriting metadata
4410b57cec5SDimitry Andric     template<typename MethodIterator>
4420b57cec5SDimitry Andric     void RewriteObjCMethodsMetaData(MethodIterator MethodBegin,
4430b57cec5SDimitry Andric                                     MethodIterator MethodEnd,
4440b57cec5SDimitry Andric                                     bool IsInstanceMethod,
4450b57cec5SDimitry Andric                                     StringRef prefix,
4460b57cec5SDimitry Andric                                     StringRef ClassName,
4470b57cec5SDimitry Andric                                     std::string &Result);
4480b57cec5SDimitry Andric     void RewriteObjCProtocolMetaData(ObjCProtocolDecl *Protocol,
4490b57cec5SDimitry Andric                                      std::string &Result);
4500b57cec5SDimitry Andric     void RewriteObjCClassMetaData(ObjCImplementationDecl *IDecl,
4510b57cec5SDimitry Andric                                           std::string &Result);
4520b57cec5SDimitry Andric     void RewriteClassSetupInitHook(std::string &Result);
4530b57cec5SDimitry Andric 
4540b57cec5SDimitry Andric     void RewriteMetaDataIntoBuffer(std::string &Result);
4550b57cec5SDimitry Andric     void WriteImageInfo(std::string &Result);
4560b57cec5SDimitry Andric     void RewriteObjCCategoryImplDecl(ObjCCategoryImplDecl *CDecl,
4570b57cec5SDimitry Andric                                              std::string &Result);
4580b57cec5SDimitry Andric     void RewriteCategorySetupInitHook(std::string &Result);
4590b57cec5SDimitry Andric 
4600b57cec5SDimitry Andric     // Rewriting ivar
4610b57cec5SDimitry Andric     void RewriteIvarOffsetComputation(ObjCIvarDecl *ivar,
4620b57cec5SDimitry Andric                                               std::string &Result);
4630b57cec5SDimitry Andric     Stmt *RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV);
4640b57cec5SDimitry Andric 
4650b57cec5SDimitry Andric 
4660b57cec5SDimitry Andric     std::string SynthesizeByrefCopyDestroyHelper(VarDecl *VD, int flag);
4670b57cec5SDimitry Andric     std::string SynthesizeBlockHelperFuncs(BlockExpr *CE, int i,
4680b57cec5SDimitry Andric                                       StringRef funcName, std::string Tag);
4690b57cec5SDimitry Andric     std::string SynthesizeBlockFunc(BlockExpr *CE, int i,
4700b57cec5SDimitry Andric                                       StringRef funcName, std::string Tag);
4710b57cec5SDimitry Andric     std::string SynthesizeBlockImpl(BlockExpr *CE,
4720b57cec5SDimitry Andric                                     std::string Tag, std::string Desc);
4730b57cec5SDimitry Andric     std::string SynthesizeBlockDescriptor(std::string DescTag,
4740b57cec5SDimitry Andric                                           std::string ImplTag,
4750b57cec5SDimitry Andric                                           int i, StringRef funcName,
4760b57cec5SDimitry Andric                                           unsigned hasCopy);
4770b57cec5SDimitry Andric     Stmt *SynthesizeBlockCall(CallExpr *Exp, const Expr* BlockExp);
4780b57cec5SDimitry Andric     void SynthesizeBlockLiterals(SourceLocation FunLocStart,
4790b57cec5SDimitry Andric                                  StringRef FunName);
4800b57cec5SDimitry Andric     FunctionDecl *SynthBlockInitFunctionDecl(StringRef name);
4810b57cec5SDimitry Andric     Stmt *SynthBlockInitExpr(BlockExpr *Exp,
4820b57cec5SDimitry Andric                       const SmallVectorImpl<DeclRefExpr *> &InnerBlockDeclRefs);
4830b57cec5SDimitry Andric 
4840b57cec5SDimitry Andric     // Misc. helper routines.
4850b57cec5SDimitry Andric     QualType getProtocolType();
4860b57cec5SDimitry Andric     void WarnAboutReturnGotoStmts(Stmt *S);
4870b57cec5SDimitry Andric     void CheckFunctionPointerDecl(QualType dType, NamedDecl *ND);
4880b57cec5SDimitry Andric     void InsertBlockLiteralsWithinFunction(FunctionDecl *FD);
4890b57cec5SDimitry Andric     void InsertBlockLiteralsWithinMethod(ObjCMethodDecl *MD);
4900b57cec5SDimitry Andric 
4910b57cec5SDimitry Andric     bool IsDeclStmtInForeachHeader(DeclStmt *DS);
4920b57cec5SDimitry Andric     void CollectBlockDeclRefInfo(BlockExpr *Exp);
4930b57cec5SDimitry Andric     void GetBlockDeclRefExprs(Stmt *S);
4940b57cec5SDimitry Andric     void GetInnerBlockDeclRefExprs(Stmt *S,
4950b57cec5SDimitry Andric                 SmallVectorImpl<DeclRefExpr *> &InnerBlockDeclRefs,
4960b57cec5SDimitry Andric                 llvm::SmallPtrSetImpl<const DeclContext *> &InnerContexts);
4970b57cec5SDimitry Andric 
4980b57cec5SDimitry Andric     // We avoid calling Type::isBlockPointerType(), since it operates on the
4990b57cec5SDimitry Andric     // canonical type. We only care if the top-level type is a closure pointer.
isTopLevelBlockPointerType(QualType T)5000b57cec5SDimitry Andric     bool isTopLevelBlockPointerType(QualType T) {
5010b57cec5SDimitry Andric       return isa<BlockPointerType>(T);
5020b57cec5SDimitry Andric     }
5030b57cec5SDimitry Andric 
5040b57cec5SDimitry Andric     /// convertBlockPointerToFunctionPointer - Converts a block-pointer type
5050b57cec5SDimitry Andric     /// to a function pointer type and upon success, returns true; false
5060b57cec5SDimitry Andric     /// otherwise.
convertBlockPointerToFunctionPointer(QualType & T)5070b57cec5SDimitry Andric     bool convertBlockPointerToFunctionPointer(QualType &T) {
5080b57cec5SDimitry Andric       if (isTopLevelBlockPointerType(T)) {
509a7dea167SDimitry Andric         const auto *BPT = T->castAs<BlockPointerType>();
5100b57cec5SDimitry Andric         T = Context->getPointerType(BPT->getPointeeType());
5110b57cec5SDimitry Andric         return true;
5120b57cec5SDimitry Andric       }
5130b57cec5SDimitry Andric       return false;
5140b57cec5SDimitry Andric     }
5150b57cec5SDimitry Andric 
5160b57cec5SDimitry Andric     bool convertObjCTypeToCStyleType(QualType &T);
5170b57cec5SDimitry Andric 
5180b57cec5SDimitry Andric     bool needToScanForQualifiers(QualType T);
5190b57cec5SDimitry Andric     QualType getSuperStructType();
5200b57cec5SDimitry Andric     QualType getConstantStringStructType();
5210b57cec5SDimitry Andric     QualType convertFunctionTypeOfBlocks(const FunctionType *FT);
5220b57cec5SDimitry Andric 
convertToUnqualifiedObjCType(QualType & T)5230b57cec5SDimitry Andric     void convertToUnqualifiedObjCType(QualType &T) {
5240b57cec5SDimitry Andric       if (T->isObjCQualifiedIdType()) {
5250b57cec5SDimitry Andric         bool isConst = T.isConstQualified();
5260b57cec5SDimitry Andric         T = isConst ? Context->getObjCIdType().withConst()
5270b57cec5SDimitry Andric                     : Context->getObjCIdType();
5280b57cec5SDimitry Andric       }
5290b57cec5SDimitry Andric       else if (T->isObjCQualifiedClassType())
5300b57cec5SDimitry Andric         T = Context->getObjCClassType();
5310b57cec5SDimitry Andric       else if (T->isObjCObjectPointerType() &&
5320b57cec5SDimitry Andric                T->getPointeeType()->isObjCQualifiedInterfaceType()) {
5330b57cec5SDimitry Andric         if (const ObjCObjectPointerType * OBJPT =
5340b57cec5SDimitry Andric               T->getAsObjCInterfacePointerType()) {
5350b57cec5SDimitry Andric           const ObjCInterfaceType *IFaceT = OBJPT->getInterfaceType();
5360b57cec5SDimitry Andric           T = QualType(IFaceT, 0);
5370b57cec5SDimitry Andric           T = Context->getPointerType(T);
5380b57cec5SDimitry Andric         }
5390b57cec5SDimitry Andric      }
5400b57cec5SDimitry Andric     }
5410b57cec5SDimitry Andric 
5420b57cec5SDimitry Andric     // FIXME: This predicate seems like it would be useful to add to ASTContext.
isObjCType(QualType T)5430b57cec5SDimitry Andric     bool isObjCType(QualType T) {
5440b57cec5SDimitry Andric       if (!LangOpts.ObjC)
5450b57cec5SDimitry Andric         return false;
5460b57cec5SDimitry Andric 
5470b57cec5SDimitry Andric       QualType OCT = Context->getCanonicalType(T).getUnqualifiedType();
5480b57cec5SDimitry Andric 
5490b57cec5SDimitry Andric       if (OCT == Context->getCanonicalType(Context->getObjCIdType()) ||
5500b57cec5SDimitry Andric           OCT == Context->getCanonicalType(Context->getObjCClassType()))
5510b57cec5SDimitry Andric         return true;
5520b57cec5SDimitry Andric 
5530b57cec5SDimitry Andric       if (const PointerType *PT = OCT->getAs<PointerType>()) {
5540b57cec5SDimitry Andric         if (isa<ObjCInterfaceType>(PT->getPointeeType()) ||
5550b57cec5SDimitry Andric             PT->getPointeeType()->isObjCQualifiedIdType())
5560b57cec5SDimitry Andric           return true;
5570b57cec5SDimitry Andric       }
5580b57cec5SDimitry Andric       return false;
5590b57cec5SDimitry Andric     }
5600b57cec5SDimitry Andric 
5610b57cec5SDimitry Andric     bool PointerTypeTakesAnyBlockArguments(QualType QT);
5620b57cec5SDimitry Andric     bool PointerTypeTakesAnyObjCQualifiedType(QualType QT);
5630b57cec5SDimitry Andric     void GetExtentOfArgList(const char *Name, const char *&LParen,
5640b57cec5SDimitry Andric                             const char *&RParen);
5650b57cec5SDimitry Andric 
QuoteDoublequotes(std::string & From,std::string & To)5660b57cec5SDimitry Andric     void QuoteDoublequotes(std::string &From, std::string &To) {
5670b57cec5SDimitry Andric       for (unsigned i = 0; i < From.length(); i++) {
5680b57cec5SDimitry Andric         if (From[i] == '"')
5690b57cec5SDimitry Andric           To += "\\\"";
5700b57cec5SDimitry Andric         else
5710b57cec5SDimitry Andric           To += From[i];
5720b57cec5SDimitry Andric       }
5730b57cec5SDimitry Andric     }
5740b57cec5SDimitry Andric 
getSimpleFunctionType(QualType result,ArrayRef<QualType> args,bool variadic=false)5750b57cec5SDimitry Andric     QualType getSimpleFunctionType(QualType result,
5760b57cec5SDimitry Andric                                    ArrayRef<QualType> args,
5770b57cec5SDimitry Andric                                    bool variadic = false) {
5780b57cec5SDimitry Andric       if (result == Context->getObjCInstanceType())
5790b57cec5SDimitry Andric         result =  Context->getObjCIdType();
5800b57cec5SDimitry Andric       FunctionProtoType::ExtProtoInfo fpi;
5810b57cec5SDimitry Andric       fpi.Variadic = variadic;
5820b57cec5SDimitry Andric       return Context->getFunctionType(result, args, fpi);
5830b57cec5SDimitry Andric     }
5840b57cec5SDimitry Andric 
5850b57cec5SDimitry Andric     // Helper function: create a CStyleCastExpr with trivial type source info.
NoTypeInfoCStyleCastExpr(ASTContext * Ctx,QualType Ty,CastKind Kind,Expr * E)5860b57cec5SDimitry Andric     CStyleCastExpr* NoTypeInfoCStyleCastExpr(ASTContext *Ctx, QualType Ty,
5870b57cec5SDimitry Andric                                              CastKind Kind, Expr *E) {
5880b57cec5SDimitry Andric       TypeSourceInfo *TInfo = Ctx->getTrivialTypeSourceInfo(Ty, SourceLocation());
589fe6060f1SDimitry Andric       return CStyleCastExpr::Create(*Ctx, Ty, VK_PRValue, Kind, E, nullptr,
590e8d8bef9SDimitry Andric                                     FPOptionsOverride(), TInfo,
591e8d8bef9SDimitry Andric                                     SourceLocation(), SourceLocation());
5920b57cec5SDimitry Andric     }
5930b57cec5SDimitry Andric 
ImplementationIsNonLazy(const ObjCImplDecl * OD) const5940b57cec5SDimitry Andric     bool ImplementationIsNonLazy(const ObjCImplDecl *OD) const {
5950b57cec5SDimitry Andric       IdentifierInfo* II = &Context->Idents.get("load");
5960b57cec5SDimitry Andric       Selector LoadSel = Context->Selectors.getSelector(0, &II);
5970b57cec5SDimitry Andric       return OD->getClassMethod(LoadSel) != nullptr;
5980b57cec5SDimitry Andric     }
5990b57cec5SDimitry Andric 
getStringLiteral(StringRef Str)6000b57cec5SDimitry Andric     StringLiteral *getStringLiteral(StringRef Str) {
6010b57cec5SDimitry Andric       QualType StrType = Context->getConstantArrayType(
602a7dea167SDimitry Andric           Context->CharTy, llvm::APInt(32, Str.size() + 1), nullptr,
6035f757f3fSDimitry Andric           ArraySizeModifier::Normal, 0);
6045f757f3fSDimitry Andric       return StringLiteral::Create(*Context, Str, StringLiteralKind::Ordinary,
6050b57cec5SDimitry Andric                                    /*Pascal=*/false, StrType, SourceLocation());
6060b57cec5SDimitry Andric     }
6070b57cec5SDimitry Andric   };
6080b57cec5SDimitry Andric } // end anonymous namespace
6090b57cec5SDimitry Andric 
RewriteBlocksInFunctionProtoType(QualType funcType,NamedDecl * D)6100b57cec5SDimitry Andric void RewriteModernObjC::RewriteBlocksInFunctionProtoType(QualType funcType,
6110b57cec5SDimitry Andric                                                    NamedDecl *D) {
6120b57cec5SDimitry Andric   if (const FunctionProtoType *fproto
6130b57cec5SDimitry Andric       = dyn_cast<FunctionProtoType>(funcType.IgnoreParens())) {
6140b57cec5SDimitry Andric     for (const auto &I : fproto->param_types())
6150b57cec5SDimitry Andric       if (isTopLevelBlockPointerType(I)) {
6160b57cec5SDimitry Andric         // All the args are checked/rewritten. Don't call twice!
6170b57cec5SDimitry Andric         RewriteBlockPointerDecl(D);
6180b57cec5SDimitry Andric         break;
6190b57cec5SDimitry Andric       }
6200b57cec5SDimitry Andric   }
6210b57cec5SDimitry Andric }
6220b57cec5SDimitry Andric 
CheckFunctionPointerDecl(QualType funcType,NamedDecl * ND)6230b57cec5SDimitry Andric void RewriteModernObjC::CheckFunctionPointerDecl(QualType funcType, NamedDecl *ND) {
6240b57cec5SDimitry Andric   const PointerType *PT = funcType->getAs<PointerType>();
6250b57cec5SDimitry Andric   if (PT && PointerTypeTakesAnyBlockArguments(funcType))
6260b57cec5SDimitry Andric     RewriteBlocksInFunctionProtoType(PT->getPointeeType(), ND);
6270b57cec5SDimitry Andric }
6280b57cec5SDimitry Andric 
IsHeaderFile(const std::string & Filename)6290b57cec5SDimitry Andric static bool IsHeaderFile(const std::string &Filename) {
6300b57cec5SDimitry Andric   std::string::size_type DotPos = Filename.rfind('.');
6310b57cec5SDimitry Andric 
6320b57cec5SDimitry Andric   if (DotPos == std::string::npos) {
6330b57cec5SDimitry Andric     // no file extension
6340b57cec5SDimitry Andric     return false;
6350b57cec5SDimitry Andric   }
6360b57cec5SDimitry Andric 
6374824e7fdSDimitry Andric   std::string Ext = Filename.substr(DotPos + 1);
6380b57cec5SDimitry Andric   // C header: .h
6390b57cec5SDimitry Andric   // C++ header: .hh or .H;
6400b57cec5SDimitry Andric   return Ext == "h" || Ext == "hh" || Ext == "H";
6410b57cec5SDimitry Andric }
6420b57cec5SDimitry Andric 
RewriteModernObjC(std::string inFile,std::unique_ptr<raw_ostream> OS,DiagnosticsEngine & D,const LangOptions & LOpts,bool silenceMacroWarn,bool LineInfo)6430b57cec5SDimitry Andric RewriteModernObjC::RewriteModernObjC(std::string inFile,
6440b57cec5SDimitry Andric                                      std::unique_ptr<raw_ostream> OS,
6450b57cec5SDimitry Andric                                      DiagnosticsEngine &D,
6460b57cec5SDimitry Andric                                      const LangOptions &LOpts,
6470b57cec5SDimitry Andric                                      bool silenceMacroWarn, bool LineInfo)
6480b57cec5SDimitry Andric     : Diags(D), LangOpts(LOpts), InFileName(inFile), OutFile(std::move(OS)),
6490b57cec5SDimitry Andric       SilenceRewriteMacroWarning(silenceMacroWarn), GenerateLineInfo(LineInfo) {
6500b57cec5SDimitry Andric   IsHeader = IsHeaderFile(inFile);
6510b57cec5SDimitry Andric   RewriteFailedDiag = Diags.getCustomDiagID(DiagnosticsEngine::Warning,
6520b57cec5SDimitry Andric                "rewriting sub-expression within a macro (may not be correct)");
6530b57cec5SDimitry Andric   // FIXME. This should be an error. But if block is not called, it is OK. And it
6540b57cec5SDimitry Andric   // may break including some headers.
6550b57cec5SDimitry Andric   GlobalBlockRewriteFailedDiag = Diags.getCustomDiagID(DiagnosticsEngine::Warning,
6560b57cec5SDimitry Andric     "rewriting block literal declared in global scope is not implemented");
6570b57cec5SDimitry Andric 
6580b57cec5SDimitry Andric   TryFinallyContainsReturnDiag = Diags.getCustomDiagID(
6590b57cec5SDimitry Andric                DiagnosticsEngine::Warning,
6600b57cec5SDimitry Andric                "rewriter doesn't support user-specified control flow semantics "
6610b57cec5SDimitry Andric                "for @try/@finally (code may not execute properly)");
6620b57cec5SDimitry Andric }
6630b57cec5SDimitry Andric 
CreateModernObjCRewriter(const std::string & InFile,std::unique_ptr<raw_ostream> OS,DiagnosticsEngine & Diags,const LangOptions & LOpts,bool SilenceRewriteMacroWarning,bool LineInfo)6640b57cec5SDimitry Andric std::unique_ptr<ASTConsumer> clang::CreateModernObjCRewriter(
6650b57cec5SDimitry Andric     const std::string &InFile, std::unique_ptr<raw_ostream> OS,
6660b57cec5SDimitry Andric     DiagnosticsEngine &Diags, const LangOptions &LOpts,
6670b57cec5SDimitry Andric     bool SilenceRewriteMacroWarning, bool LineInfo) {
668a7dea167SDimitry Andric   return std::make_unique<RewriteModernObjC>(InFile, std::move(OS), Diags,
6690b57cec5SDimitry Andric                                               LOpts, SilenceRewriteMacroWarning,
6700b57cec5SDimitry Andric                                               LineInfo);
6710b57cec5SDimitry Andric }
6720b57cec5SDimitry Andric 
InitializeCommon(ASTContext & context)6730b57cec5SDimitry Andric void RewriteModernObjC::InitializeCommon(ASTContext &context) {
6740b57cec5SDimitry Andric   Context = &context;
6750b57cec5SDimitry Andric   SM = &Context->getSourceManager();
6760b57cec5SDimitry Andric   TUDecl = Context->getTranslationUnitDecl();
6770b57cec5SDimitry Andric   MsgSendFunctionDecl = nullptr;
6780b57cec5SDimitry Andric   MsgSendSuperFunctionDecl = nullptr;
6790b57cec5SDimitry Andric   MsgSendStretFunctionDecl = nullptr;
6800b57cec5SDimitry Andric   MsgSendSuperStretFunctionDecl = nullptr;
6810b57cec5SDimitry Andric   MsgSendFpretFunctionDecl = nullptr;
6820b57cec5SDimitry Andric   GetClassFunctionDecl = nullptr;
6830b57cec5SDimitry Andric   GetMetaClassFunctionDecl = nullptr;
6840b57cec5SDimitry Andric   GetSuperClassFunctionDecl = nullptr;
6850b57cec5SDimitry Andric   SelGetUidFunctionDecl = nullptr;
6860b57cec5SDimitry Andric   CFStringFunctionDecl = nullptr;
6870b57cec5SDimitry Andric   ConstantStringClassReference = nullptr;
6880b57cec5SDimitry Andric   NSStringRecord = nullptr;
6890b57cec5SDimitry Andric   CurMethodDef = nullptr;
6900b57cec5SDimitry Andric   CurFunctionDef = nullptr;
6910b57cec5SDimitry Andric   GlobalVarDecl = nullptr;
6920b57cec5SDimitry Andric   GlobalConstructionExp = nullptr;
6930b57cec5SDimitry Andric   SuperStructDecl = nullptr;
6940b57cec5SDimitry Andric   ProtocolTypeDecl = nullptr;
6950b57cec5SDimitry Andric   ConstantStringDecl = nullptr;
6960b57cec5SDimitry Andric   BcLabelCount = 0;
6970b57cec5SDimitry Andric   SuperConstructorFunctionDecl = nullptr;
6980b57cec5SDimitry Andric   NumObjCStringLiterals = 0;
6990b57cec5SDimitry Andric   PropParentMap = nullptr;
7000b57cec5SDimitry Andric   CurrentBody = nullptr;
7010b57cec5SDimitry Andric   DisableReplaceStmt = false;
7020b57cec5SDimitry Andric   objc_impl_method = false;
7030b57cec5SDimitry Andric 
7040b57cec5SDimitry Andric   // Get the ID and start/end of the main file.
7050b57cec5SDimitry Andric   MainFileID = SM->getMainFileID();
706e8d8bef9SDimitry Andric   llvm::MemoryBufferRef MainBuf = SM->getBufferOrFake(MainFileID);
707e8d8bef9SDimitry Andric   MainFileStart = MainBuf.getBufferStart();
708e8d8bef9SDimitry Andric   MainFileEnd = MainBuf.getBufferEnd();
7090b57cec5SDimitry Andric 
7100b57cec5SDimitry Andric   Rewrite.setSourceMgr(Context->getSourceManager(), Context->getLangOpts());
7110b57cec5SDimitry Andric }
7120b57cec5SDimitry Andric 
7130b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
7140b57cec5SDimitry Andric // Top Level Driver Code
7150b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
7160b57cec5SDimitry Andric 
HandleTopLevelSingleDecl(Decl * D)7170b57cec5SDimitry Andric void RewriteModernObjC::HandleTopLevelSingleDecl(Decl *D) {
7180b57cec5SDimitry Andric   if (Diags.hasErrorOccurred())
7190b57cec5SDimitry Andric     return;
7200b57cec5SDimitry Andric 
7210b57cec5SDimitry Andric   // Two cases: either the decl could be in the main file, or it could be in a
7220b57cec5SDimitry Andric   // #included file.  If the former, rewrite it now.  If the later, check to see
7230b57cec5SDimitry Andric   // if we rewrote the #include/#import.
7240b57cec5SDimitry Andric   SourceLocation Loc = D->getLocation();
7250b57cec5SDimitry Andric   Loc = SM->getExpansionLoc(Loc);
7260b57cec5SDimitry Andric 
7270b57cec5SDimitry Andric   // If this is for a builtin, ignore it.
7280b57cec5SDimitry Andric   if (Loc.isInvalid()) return;
7290b57cec5SDimitry Andric 
7300b57cec5SDimitry Andric   // Look for built-in declarations that we need to refer during the rewrite.
7310b57cec5SDimitry Andric   if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
7320b57cec5SDimitry Andric     RewriteFunctionDecl(FD);
7330b57cec5SDimitry Andric   } else if (VarDecl *FVD = dyn_cast<VarDecl>(D)) {
7340b57cec5SDimitry Andric     // declared in <Foundation/NSString.h>
7350b57cec5SDimitry Andric     if (FVD->getName() == "_NSConstantStringClassReference") {
7360b57cec5SDimitry Andric       ConstantStringClassReference = FVD;
7370b57cec5SDimitry Andric       return;
7380b57cec5SDimitry Andric     }
7390b57cec5SDimitry Andric   } else if (ObjCCategoryDecl *CD = dyn_cast<ObjCCategoryDecl>(D)) {
7400b57cec5SDimitry Andric     RewriteCategoryDecl(CD);
7410b57cec5SDimitry Andric   } else if (ObjCProtocolDecl *PD = dyn_cast<ObjCProtocolDecl>(D)) {
7420b57cec5SDimitry Andric     if (PD->isThisDeclarationADefinition())
7430b57cec5SDimitry Andric       RewriteProtocolDecl(PD);
7440b57cec5SDimitry Andric   } else if (LinkageSpecDecl *LSD = dyn_cast<LinkageSpecDecl>(D)) {
7450b57cec5SDimitry Andric     // Recurse into linkage specifications
7460b57cec5SDimitry Andric     for (DeclContext::decl_iterator DI = LSD->decls_begin(),
7470b57cec5SDimitry Andric                                  DIEnd = LSD->decls_end();
7480b57cec5SDimitry Andric          DI != DIEnd; ) {
7490b57cec5SDimitry Andric       if (ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>((*DI))) {
7500b57cec5SDimitry Andric         if (!IFace->isThisDeclarationADefinition()) {
7510b57cec5SDimitry Andric           SmallVector<Decl *, 8> DG;
7520b57cec5SDimitry Andric           SourceLocation StartLoc = IFace->getBeginLoc();
7530b57cec5SDimitry Andric           do {
7540b57cec5SDimitry Andric             if (isa<ObjCInterfaceDecl>(*DI) &&
7550b57cec5SDimitry Andric                 !cast<ObjCInterfaceDecl>(*DI)->isThisDeclarationADefinition() &&
7560b57cec5SDimitry Andric                 StartLoc == (*DI)->getBeginLoc())
7570b57cec5SDimitry Andric               DG.push_back(*DI);
7580b57cec5SDimitry Andric             else
7590b57cec5SDimitry Andric               break;
7600b57cec5SDimitry Andric 
7610b57cec5SDimitry Andric             ++DI;
7620b57cec5SDimitry Andric           } while (DI != DIEnd);
7630b57cec5SDimitry Andric           RewriteForwardClassDecl(DG);
7640b57cec5SDimitry Andric           continue;
7650b57cec5SDimitry Andric         }
7660b57cec5SDimitry Andric         else {
7670b57cec5SDimitry Andric           // Keep track of all interface declarations seen.
7680b57cec5SDimitry Andric           ObjCInterfacesSeen.push_back(IFace);
7690b57cec5SDimitry Andric           ++DI;
7700b57cec5SDimitry Andric           continue;
7710b57cec5SDimitry Andric         }
7720b57cec5SDimitry Andric       }
7730b57cec5SDimitry Andric 
7740b57cec5SDimitry Andric       if (ObjCProtocolDecl *Proto = dyn_cast<ObjCProtocolDecl>((*DI))) {
7750b57cec5SDimitry Andric         if (!Proto->isThisDeclarationADefinition()) {
7760b57cec5SDimitry Andric           SmallVector<Decl *, 8> DG;
7770b57cec5SDimitry Andric           SourceLocation StartLoc = Proto->getBeginLoc();
7780b57cec5SDimitry Andric           do {
7790b57cec5SDimitry Andric             if (isa<ObjCProtocolDecl>(*DI) &&
7800b57cec5SDimitry Andric                 !cast<ObjCProtocolDecl>(*DI)->isThisDeclarationADefinition() &&
7810b57cec5SDimitry Andric                 StartLoc == (*DI)->getBeginLoc())
7820b57cec5SDimitry Andric               DG.push_back(*DI);
7830b57cec5SDimitry Andric             else
7840b57cec5SDimitry Andric               break;
7850b57cec5SDimitry Andric 
7860b57cec5SDimitry Andric             ++DI;
7870b57cec5SDimitry Andric           } while (DI != DIEnd);
7880b57cec5SDimitry Andric           RewriteForwardProtocolDecl(DG);
7890b57cec5SDimitry Andric           continue;
7900b57cec5SDimitry Andric         }
7910b57cec5SDimitry Andric       }
7920b57cec5SDimitry Andric 
7930b57cec5SDimitry Andric       HandleTopLevelSingleDecl(*DI);
7940b57cec5SDimitry Andric       ++DI;
7950b57cec5SDimitry Andric     }
7960b57cec5SDimitry Andric   }
7970b57cec5SDimitry Andric   // If we have a decl in the main file, see if we should rewrite it.
7980b57cec5SDimitry Andric   if (SM->isWrittenInMainFile(Loc))
7990b57cec5SDimitry Andric     return HandleDeclInMainFile(D);
8000b57cec5SDimitry Andric }
8010b57cec5SDimitry Andric 
8020b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
8030b57cec5SDimitry Andric // Syntactic (non-AST) Rewriting Code
8040b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
8050b57cec5SDimitry Andric 
RewriteInclude()8060b57cec5SDimitry Andric void RewriteModernObjC::RewriteInclude() {
8070b57cec5SDimitry Andric   SourceLocation LocStart = SM->getLocForStartOfFile(MainFileID);
8080b57cec5SDimitry Andric   StringRef MainBuf = SM->getBufferData(MainFileID);
8090b57cec5SDimitry Andric   const char *MainBufStart = MainBuf.begin();
8100b57cec5SDimitry Andric   const char *MainBufEnd = MainBuf.end();
8110b57cec5SDimitry Andric   size_t ImportLen = strlen("import");
8120b57cec5SDimitry Andric 
8130b57cec5SDimitry Andric   // Loop over the whole file, looking for includes.
8140b57cec5SDimitry Andric   for (const char *BufPtr = MainBufStart; BufPtr < MainBufEnd; ++BufPtr) {
8150b57cec5SDimitry Andric     if (*BufPtr == '#') {
8160b57cec5SDimitry Andric       if (++BufPtr == MainBufEnd)
8170b57cec5SDimitry Andric         return;
8180b57cec5SDimitry Andric       while (*BufPtr == ' ' || *BufPtr == '\t')
8190b57cec5SDimitry Andric         if (++BufPtr == MainBufEnd)
8200b57cec5SDimitry Andric           return;
8210b57cec5SDimitry Andric       if (!strncmp(BufPtr, "import", ImportLen)) {
8220b57cec5SDimitry Andric         // replace import with include
8230b57cec5SDimitry Andric         SourceLocation ImportLoc =
8240b57cec5SDimitry Andric           LocStart.getLocWithOffset(BufPtr-MainBufStart);
8250b57cec5SDimitry Andric         ReplaceText(ImportLoc, ImportLen, "include");
8260b57cec5SDimitry Andric         BufPtr += ImportLen;
8270b57cec5SDimitry Andric       }
8280b57cec5SDimitry Andric     }
8290b57cec5SDimitry Andric   }
8300b57cec5SDimitry Andric }
8310b57cec5SDimitry Andric 
WriteInternalIvarName(const ObjCInterfaceDecl * IDecl,ObjCIvarDecl * IvarDecl,std::string & Result)8320b57cec5SDimitry Andric static void WriteInternalIvarName(const ObjCInterfaceDecl *IDecl,
8330b57cec5SDimitry Andric                                   ObjCIvarDecl *IvarDecl, std::string &Result) {
8340b57cec5SDimitry Andric   Result += "OBJC_IVAR_$_";
8350b57cec5SDimitry Andric   Result += IDecl->getName();
8360b57cec5SDimitry Andric   Result += "$";
8370b57cec5SDimitry Andric   Result += IvarDecl->getName();
8380b57cec5SDimitry Andric }
8390b57cec5SDimitry Andric 
8400b57cec5SDimitry Andric std::string
getIvarAccessString(ObjCIvarDecl * D)8410b57cec5SDimitry Andric RewriteModernObjC::getIvarAccessString(ObjCIvarDecl *D) {
8420b57cec5SDimitry Andric   const ObjCInterfaceDecl *ClassDecl = D->getContainingInterface();
8430b57cec5SDimitry Andric 
8440b57cec5SDimitry Andric   // Build name of symbol holding ivar offset.
8450b57cec5SDimitry Andric   std::string IvarOffsetName;
8460b57cec5SDimitry Andric   if (D->isBitField())
8470b57cec5SDimitry Andric     ObjCIvarBitfieldGroupOffset(D, IvarOffsetName);
8480b57cec5SDimitry Andric   else
8490b57cec5SDimitry Andric     WriteInternalIvarName(ClassDecl, D, IvarOffsetName);
8500b57cec5SDimitry Andric 
8510b57cec5SDimitry Andric   std::string S = "(*(";
8520b57cec5SDimitry Andric   QualType IvarT = D->getType();
8530b57cec5SDimitry Andric   if (D->isBitField())
8540b57cec5SDimitry Andric     IvarT = GetGroupRecordTypeForObjCIvarBitfield(D);
8550b57cec5SDimitry Andric 
856bdd1243dSDimitry Andric   if (!IvarT->getAs<TypedefType>() && IvarT->isRecordType()) {
857a7dea167SDimitry Andric     RecordDecl *RD = IvarT->castAs<RecordType>()->getDecl();
8580b57cec5SDimitry Andric     RD = RD->getDefinition();
8590b57cec5SDimitry Andric     if (RD && !RD->getDeclName().getAsIdentifierInfo()) {
8600b57cec5SDimitry Andric       // decltype(((Foo_IMPL*)0)->bar) *
861a7dea167SDimitry Andric       auto *CDecl = cast<ObjCContainerDecl>(D->getDeclContext());
8620b57cec5SDimitry Andric       // ivar in class extensions requires special treatment.
8630b57cec5SDimitry Andric       if (ObjCCategoryDecl *CatDecl = dyn_cast<ObjCCategoryDecl>(CDecl))
8640b57cec5SDimitry Andric         CDecl = CatDecl->getClassInterface();
8655ffd83dbSDimitry Andric       std::string RecName = std::string(CDecl->getName());
8660b57cec5SDimitry Andric       RecName += "_IMPL";
8675f757f3fSDimitry Andric       RecordDecl *RD = RecordDecl::Create(*Context, TagTypeKind::Struct, TUDecl,
8685f757f3fSDimitry Andric                                           SourceLocation(), SourceLocation(),
8695f757f3fSDimitry Andric                                           &Context->Idents.get(RecName));
8700b57cec5SDimitry Andric       QualType PtrStructIMPL = Context->getPointerType(Context->getTagDeclType(RD));
8710b57cec5SDimitry Andric       unsigned UnsignedIntSize =
8720b57cec5SDimitry Andric       static_cast<unsigned>(Context->getTypeSize(Context->UnsignedIntTy));
8730b57cec5SDimitry Andric       Expr *Zero = IntegerLiteral::Create(*Context,
8740b57cec5SDimitry Andric                                           llvm::APInt(UnsignedIntSize, 0),
8750b57cec5SDimitry Andric                                           Context->UnsignedIntTy, SourceLocation());
8760b57cec5SDimitry Andric       Zero = NoTypeInfoCStyleCastExpr(Context, PtrStructIMPL, CK_BitCast, Zero);
8770b57cec5SDimitry Andric       ParenExpr *PE = new (Context) ParenExpr(SourceLocation(), SourceLocation(),
8780b57cec5SDimitry Andric                                               Zero);
8790b57cec5SDimitry Andric       FieldDecl *FD = FieldDecl::Create(*Context, nullptr, SourceLocation(),
8800b57cec5SDimitry Andric                                         SourceLocation(),
8810b57cec5SDimitry Andric                                         &Context->Idents.get(D->getNameAsString()),
8820b57cec5SDimitry Andric                                         IvarT, nullptr,
8830b57cec5SDimitry Andric                                         /*BitWidth=*/nullptr, /*Mutable=*/true,
8840b57cec5SDimitry Andric                                         ICIS_NoInit);
8850b57cec5SDimitry Andric       MemberExpr *ME = MemberExpr::CreateImplicit(
8860b57cec5SDimitry Andric           *Context, PE, true, FD, FD->getType(), VK_LValue, OK_Ordinary);
8870b57cec5SDimitry Andric       IvarT = Context->getDecltypeType(ME, ME->getType());
8880b57cec5SDimitry Andric     }
8890b57cec5SDimitry Andric   }
8900b57cec5SDimitry Andric   convertObjCTypeToCStyleType(IvarT);
8910b57cec5SDimitry Andric   QualType castT = Context->getPointerType(IvarT);
8920b57cec5SDimitry Andric   std::string TypeString(castT.getAsString(Context->getPrintingPolicy()));
8930b57cec5SDimitry Andric   S += TypeString;
8940b57cec5SDimitry Andric   S += ")";
8950b57cec5SDimitry Andric 
8960b57cec5SDimitry Andric   // ((char *)self + IVAR_OFFSET_SYMBOL_NAME)
8970b57cec5SDimitry Andric   S += "((char *)self + ";
8980b57cec5SDimitry Andric   S += IvarOffsetName;
8990b57cec5SDimitry Andric   S += "))";
9000b57cec5SDimitry Andric   if (D->isBitField()) {
9010b57cec5SDimitry Andric     S += ".";
9020b57cec5SDimitry Andric     S += D->getNameAsString();
9030b57cec5SDimitry Andric   }
9040b57cec5SDimitry Andric   ReferencedIvars[const_cast<ObjCInterfaceDecl *>(ClassDecl)].insert(D);
9050b57cec5SDimitry Andric   return S;
9060b57cec5SDimitry Andric }
9070b57cec5SDimitry Andric 
9080b57cec5SDimitry Andric /// mustSynthesizeSetterGetterMethod - returns true if setter or getter has not
9090b57cec5SDimitry Andric /// been found in the class implementation. In this case, it must be synthesized.
mustSynthesizeSetterGetterMethod(ObjCImplementationDecl * IMP,ObjCPropertyDecl * PD,bool getter)9100b57cec5SDimitry Andric static bool mustSynthesizeSetterGetterMethod(ObjCImplementationDecl *IMP,
9110b57cec5SDimitry Andric                                              ObjCPropertyDecl *PD,
9120b57cec5SDimitry Andric                                              bool getter) {
913480093f4SDimitry Andric   auto *OMD = IMP->getInstanceMethod(getter ? PD->getGetterName()
914480093f4SDimitry Andric                                             : PD->getSetterName());
915480093f4SDimitry Andric   return !OMD || OMD->isSynthesizedAccessorStub();
9160b57cec5SDimitry Andric }
9170b57cec5SDimitry Andric 
RewritePropertyImplDecl(ObjCPropertyImplDecl * PID,ObjCImplementationDecl * IMD,ObjCCategoryImplDecl * CID)9180b57cec5SDimitry Andric void RewriteModernObjC::RewritePropertyImplDecl(ObjCPropertyImplDecl *PID,
9190b57cec5SDimitry Andric                                           ObjCImplementationDecl *IMD,
9200b57cec5SDimitry Andric                                           ObjCCategoryImplDecl *CID) {
9210b57cec5SDimitry Andric   static bool objcGetPropertyDefined = false;
9220b57cec5SDimitry Andric   static bool objcSetPropertyDefined = false;
9230b57cec5SDimitry Andric   SourceLocation startGetterSetterLoc;
9240b57cec5SDimitry Andric 
9250b57cec5SDimitry Andric   if (PID->getBeginLoc().isValid()) {
9260b57cec5SDimitry Andric     SourceLocation startLoc = PID->getBeginLoc();
9270b57cec5SDimitry Andric     InsertText(startLoc, "// ");
9280b57cec5SDimitry Andric     const char *startBuf = SM->getCharacterData(startLoc);
9290b57cec5SDimitry Andric     assert((*startBuf == '@') && "bogus @synthesize location");
9300b57cec5SDimitry Andric     const char *semiBuf = strchr(startBuf, ';');
9310b57cec5SDimitry Andric     assert((*semiBuf == ';') && "@synthesize: can't find ';'");
9320b57cec5SDimitry Andric     startGetterSetterLoc = startLoc.getLocWithOffset(semiBuf-startBuf+1);
9330b57cec5SDimitry Andric   } else
9340b57cec5SDimitry Andric     startGetterSetterLoc = IMD ? IMD->getEndLoc() : CID->getEndLoc();
9350b57cec5SDimitry Andric 
9360b57cec5SDimitry Andric   if (PID->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic)
9370b57cec5SDimitry Andric     return; // FIXME: is this correct?
9380b57cec5SDimitry Andric 
9390b57cec5SDimitry Andric   // Generate the 'getter' function.
9400b57cec5SDimitry Andric   ObjCPropertyDecl *PD = PID->getPropertyDecl();
9410b57cec5SDimitry Andric   ObjCIvarDecl *OID = PID->getPropertyIvarDecl();
9420b57cec5SDimitry Andric   assert(IMD && OID && "Synthesized ivars must be attached to @implementation");
9430b57cec5SDimitry Andric 
9440b57cec5SDimitry Andric   unsigned Attributes = PD->getPropertyAttributes();
9450b57cec5SDimitry Andric   if (mustSynthesizeSetterGetterMethod(IMD, PD, true /*getter*/)) {
9465ffd83dbSDimitry Andric     bool GenGetProperty =
9475ffd83dbSDimitry Andric         !(Attributes & ObjCPropertyAttribute::kind_nonatomic) &&
9485ffd83dbSDimitry Andric         (Attributes & (ObjCPropertyAttribute::kind_retain |
9495ffd83dbSDimitry Andric                        ObjCPropertyAttribute::kind_copy));
9500b57cec5SDimitry Andric     std::string Getr;
9510b57cec5SDimitry Andric     if (GenGetProperty && !objcGetPropertyDefined) {
9520b57cec5SDimitry Andric       objcGetPropertyDefined = true;
9530b57cec5SDimitry Andric       // FIXME. Is this attribute correct in all cases?
9540b57cec5SDimitry Andric       Getr = "\nextern \"C\" __declspec(dllimport) "
9550b57cec5SDimitry Andric             "id objc_getProperty(id, SEL, long, bool);\n";
9560b57cec5SDimitry Andric     }
9570b57cec5SDimitry Andric     RewriteObjCMethodDecl(OID->getContainingInterface(),
958480093f4SDimitry Andric                           PID->getGetterMethodDecl(), Getr);
9590b57cec5SDimitry Andric     Getr += "{ ";
9600b57cec5SDimitry Andric     // Synthesize an explicit cast to gain access to the ivar.
9610b57cec5SDimitry Andric     // See objc-act.c:objc_synthesize_new_getter() for details.
9620b57cec5SDimitry Andric     if (GenGetProperty) {
9630b57cec5SDimitry Andric       // return objc_getProperty(self, _cmd, offsetof(ClassDecl, OID), 1)
9640b57cec5SDimitry Andric       Getr += "typedef ";
9650b57cec5SDimitry Andric       const FunctionType *FPRetType = nullptr;
966480093f4SDimitry Andric       RewriteTypeIntoString(PID->getGetterMethodDecl()->getReturnType(), Getr,
9670b57cec5SDimitry Andric                             FPRetType);
9680b57cec5SDimitry Andric       Getr += " _TYPE";
9690b57cec5SDimitry Andric       if (FPRetType) {
9700b57cec5SDimitry Andric         Getr += ")"; // close the precedence "scope" for "*".
9710b57cec5SDimitry Andric 
9720b57cec5SDimitry Andric         // Now, emit the argument types (if any).
9730b57cec5SDimitry Andric         if (const FunctionProtoType *FT = dyn_cast<FunctionProtoType>(FPRetType)){
9740b57cec5SDimitry Andric           Getr += "(";
9750b57cec5SDimitry Andric           for (unsigned i = 0, e = FT->getNumParams(); i != e; ++i) {
9760b57cec5SDimitry Andric             if (i) Getr += ", ";
9770b57cec5SDimitry Andric             std::string ParamStr =
9780b57cec5SDimitry Andric                 FT->getParamType(i).getAsString(Context->getPrintingPolicy());
9790b57cec5SDimitry Andric             Getr += ParamStr;
9800b57cec5SDimitry Andric           }
9810b57cec5SDimitry Andric           if (FT->isVariadic()) {
9820b57cec5SDimitry Andric             if (FT->getNumParams())
9830b57cec5SDimitry Andric               Getr += ", ";
9840b57cec5SDimitry Andric             Getr += "...";
9850b57cec5SDimitry Andric           }
9860b57cec5SDimitry Andric           Getr += ")";
9870b57cec5SDimitry Andric         } else
9880b57cec5SDimitry Andric           Getr += "()";
9890b57cec5SDimitry Andric       }
9900b57cec5SDimitry Andric       Getr += ";\n";
9910b57cec5SDimitry Andric       Getr += "return (_TYPE)";
9920b57cec5SDimitry Andric       Getr += "objc_getProperty(self, _cmd, ";
9930b57cec5SDimitry Andric       RewriteIvarOffsetComputation(OID, Getr);
9940b57cec5SDimitry Andric       Getr += ", 1)";
9950b57cec5SDimitry Andric     }
9960b57cec5SDimitry Andric     else
9970b57cec5SDimitry Andric       Getr += "return " + getIvarAccessString(OID);
9980b57cec5SDimitry Andric     Getr += "; }";
9990b57cec5SDimitry Andric     InsertText(startGetterSetterLoc, Getr);
10000b57cec5SDimitry Andric   }
10010b57cec5SDimitry Andric 
10020b57cec5SDimitry Andric   if (PD->isReadOnly() ||
10030b57cec5SDimitry Andric       !mustSynthesizeSetterGetterMethod(IMD, PD, false /*setter*/))
10040b57cec5SDimitry Andric     return;
10050b57cec5SDimitry Andric 
10060b57cec5SDimitry Andric   // Generate the 'setter' function.
10070b57cec5SDimitry Andric   std::string Setr;
10085ffd83dbSDimitry Andric   bool GenSetProperty = Attributes & (ObjCPropertyAttribute::kind_retain |
10095ffd83dbSDimitry Andric                                       ObjCPropertyAttribute::kind_copy);
10100b57cec5SDimitry Andric   if (GenSetProperty && !objcSetPropertyDefined) {
10110b57cec5SDimitry Andric     objcSetPropertyDefined = true;
10120b57cec5SDimitry Andric     // FIXME. Is this attribute correct in all cases?
10130b57cec5SDimitry Andric     Setr = "\nextern \"C\" __declspec(dllimport) "
10140b57cec5SDimitry Andric     "void objc_setProperty (id, SEL, long, id, bool, bool);\n";
10150b57cec5SDimitry Andric   }
10160b57cec5SDimitry Andric 
10170b57cec5SDimitry Andric   RewriteObjCMethodDecl(OID->getContainingInterface(),
1018480093f4SDimitry Andric                         PID->getSetterMethodDecl(), Setr);
10190b57cec5SDimitry Andric   Setr += "{ ";
10200b57cec5SDimitry Andric   // Synthesize an explicit cast to initialize the ivar.
10210b57cec5SDimitry Andric   // See objc-act.c:objc_synthesize_new_setter() for details.
10220b57cec5SDimitry Andric   if (GenSetProperty) {
10230b57cec5SDimitry Andric     Setr += "objc_setProperty (self, _cmd, ";
10240b57cec5SDimitry Andric     RewriteIvarOffsetComputation(OID, Setr);
10250b57cec5SDimitry Andric     Setr += ", (id)";
10260b57cec5SDimitry Andric     Setr += PD->getName();
10270b57cec5SDimitry Andric     Setr += ", ";
10285ffd83dbSDimitry Andric     if (Attributes & ObjCPropertyAttribute::kind_nonatomic)
10290b57cec5SDimitry Andric       Setr += "0, ";
10300b57cec5SDimitry Andric     else
10310b57cec5SDimitry Andric       Setr += "1, ";
10325ffd83dbSDimitry Andric     if (Attributes & ObjCPropertyAttribute::kind_copy)
10330b57cec5SDimitry Andric       Setr += "1)";
10340b57cec5SDimitry Andric     else
10350b57cec5SDimitry Andric       Setr += "0)";
10360b57cec5SDimitry Andric   }
10370b57cec5SDimitry Andric   else {
10380b57cec5SDimitry Andric     Setr += getIvarAccessString(OID) + " = ";
10390b57cec5SDimitry Andric     Setr += PD->getName();
10400b57cec5SDimitry Andric   }
10410b57cec5SDimitry Andric   Setr += "; }\n";
10420b57cec5SDimitry Andric   InsertText(startGetterSetterLoc, Setr);
10430b57cec5SDimitry Andric }
10440b57cec5SDimitry Andric 
RewriteOneForwardClassDecl(ObjCInterfaceDecl * ForwardDecl,std::string & typedefString)10450b57cec5SDimitry Andric static void RewriteOneForwardClassDecl(ObjCInterfaceDecl *ForwardDecl,
10460b57cec5SDimitry Andric                                        std::string &typedefString) {
10470b57cec5SDimitry Andric   typedefString += "\n#ifndef _REWRITER_typedef_";
10480b57cec5SDimitry Andric   typedefString += ForwardDecl->getNameAsString();
10490b57cec5SDimitry Andric   typedefString += "\n";
10500b57cec5SDimitry Andric   typedefString += "#define _REWRITER_typedef_";
10510b57cec5SDimitry Andric   typedefString += ForwardDecl->getNameAsString();
10520b57cec5SDimitry Andric   typedefString += "\n";
10530b57cec5SDimitry Andric   typedefString += "typedef struct objc_object ";
10540b57cec5SDimitry Andric   typedefString += ForwardDecl->getNameAsString();
10550b57cec5SDimitry Andric   // typedef struct { } _objc_exc_Classname;
10560b57cec5SDimitry Andric   typedefString += ";\ntypedef struct {} _objc_exc_";
10570b57cec5SDimitry Andric   typedefString += ForwardDecl->getNameAsString();
10580b57cec5SDimitry Andric   typedefString += ";\n#endif\n";
10590b57cec5SDimitry Andric }
10600b57cec5SDimitry Andric 
RewriteForwardClassEpilogue(ObjCInterfaceDecl * ClassDecl,const std::string & typedefString)10610b57cec5SDimitry Andric void RewriteModernObjC::RewriteForwardClassEpilogue(ObjCInterfaceDecl *ClassDecl,
10620b57cec5SDimitry Andric                                               const std::string &typedefString) {
10630b57cec5SDimitry Andric   SourceLocation startLoc = ClassDecl->getBeginLoc();
10640b57cec5SDimitry Andric   const char *startBuf = SM->getCharacterData(startLoc);
10650b57cec5SDimitry Andric   const char *semiPtr = strchr(startBuf, ';');
10660b57cec5SDimitry Andric   // Replace the @class with typedefs corresponding to the classes.
10670b57cec5SDimitry Andric   ReplaceText(startLoc, semiPtr-startBuf+1, typedefString);
10680b57cec5SDimitry Andric }
10690b57cec5SDimitry Andric 
RewriteForwardClassDecl(DeclGroupRef D)10700b57cec5SDimitry Andric void RewriteModernObjC::RewriteForwardClassDecl(DeclGroupRef D) {
10710b57cec5SDimitry Andric   std::string typedefString;
10720b57cec5SDimitry Andric   for (DeclGroupRef::iterator I = D.begin(), E = D.end(); I != E; ++I) {
10730b57cec5SDimitry Andric     if (ObjCInterfaceDecl *ForwardDecl = dyn_cast<ObjCInterfaceDecl>(*I)) {
10740b57cec5SDimitry Andric       if (I == D.begin()) {
10750b57cec5SDimitry Andric         // Translate to typedef's that forward reference structs with the same name
10760b57cec5SDimitry Andric         // as the class. As a convenience, we include the original declaration
10770b57cec5SDimitry Andric         // as a comment.
10780b57cec5SDimitry Andric         typedefString += "// @class ";
10790b57cec5SDimitry Andric         typedefString += ForwardDecl->getNameAsString();
10800b57cec5SDimitry Andric         typedefString += ";";
10810b57cec5SDimitry Andric       }
10820b57cec5SDimitry Andric       RewriteOneForwardClassDecl(ForwardDecl, typedefString);
10830b57cec5SDimitry Andric     }
10840b57cec5SDimitry Andric     else
10850b57cec5SDimitry Andric       HandleTopLevelSingleDecl(*I);
10860b57cec5SDimitry Andric   }
10870b57cec5SDimitry Andric   DeclGroupRef::iterator I = D.begin();
10880b57cec5SDimitry Andric   RewriteForwardClassEpilogue(cast<ObjCInterfaceDecl>(*I), typedefString);
10890b57cec5SDimitry Andric }
10900b57cec5SDimitry Andric 
RewriteForwardClassDecl(const SmallVectorImpl<Decl * > & D)10910b57cec5SDimitry Andric void RewriteModernObjC::RewriteForwardClassDecl(
10920b57cec5SDimitry Andric                                 const SmallVectorImpl<Decl *> &D) {
10930b57cec5SDimitry Andric   std::string typedefString;
10940b57cec5SDimitry Andric   for (unsigned i = 0; i < D.size(); i++) {
10950b57cec5SDimitry Andric     ObjCInterfaceDecl *ForwardDecl = cast<ObjCInterfaceDecl>(D[i]);
10960b57cec5SDimitry Andric     if (i == 0) {
10970b57cec5SDimitry Andric       typedefString += "// @class ";
10980b57cec5SDimitry Andric       typedefString += ForwardDecl->getNameAsString();
10990b57cec5SDimitry Andric       typedefString += ";";
11000b57cec5SDimitry Andric     }
11010b57cec5SDimitry Andric     RewriteOneForwardClassDecl(ForwardDecl, typedefString);
11020b57cec5SDimitry Andric   }
11030b57cec5SDimitry Andric   RewriteForwardClassEpilogue(cast<ObjCInterfaceDecl>(D[0]), typedefString);
11040b57cec5SDimitry Andric }
11050b57cec5SDimitry Andric 
RewriteMethodDeclaration(ObjCMethodDecl * Method)11060b57cec5SDimitry Andric void RewriteModernObjC::RewriteMethodDeclaration(ObjCMethodDecl *Method) {
11070b57cec5SDimitry Andric   // When method is a synthesized one, such as a getter/setter there is
11080b57cec5SDimitry Andric   // nothing to rewrite.
11090b57cec5SDimitry Andric   if (Method->isImplicit())
11100b57cec5SDimitry Andric     return;
11110b57cec5SDimitry Andric   SourceLocation LocStart = Method->getBeginLoc();
11120b57cec5SDimitry Andric   SourceLocation LocEnd = Method->getEndLoc();
11130b57cec5SDimitry Andric 
11140b57cec5SDimitry Andric   if (SM->getExpansionLineNumber(LocEnd) >
11150b57cec5SDimitry Andric       SM->getExpansionLineNumber(LocStart)) {
11160b57cec5SDimitry Andric     InsertText(LocStart, "#if 0\n");
11170b57cec5SDimitry Andric     ReplaceText(LocEnd, 1, ";\n#endif\n");
11180b57cec5SDimitry Andric   } else {
11190b57cec5SDimitry Andric     InsertText(LocStart, "// ");
11200b57cec5SDimitry Andric   }
11210b57cec5SDimitry Andric }
11220b57cec5SDimitry Andric 
RewriteProperty(ObjCPropertyDecl * prop)11230b57cec5SDimitry Andric void RewriteModernObjC::RewriteProperty(ObjCPropertyDecl *prop) {
11240b57cec5SDimitry Andric   SourceLocation Loc = prop->getAtLoc();
11250b57cec5SDimitry Andric 
11260b57cec5SDimitry Andric   ReplaceText(Loc, 0, "// ");
11270b57cec5SDimitry Andric   // FIXME: handle properties that are declared across multiple lines.
11280b57cec5SDimitry Andric }
11290b57cec5SDimitry Andric 
RewriteCategoryDecl(ObjCCategoryDecl * CatDecl)11300b57cec5SDimitry Andric void RewriteModernObjC::RewriteCategoryDecl(ObjCCategoryDecl *CatDecl) {
11310b57cec5SDimitry Andric   SourceLocation LocStart = CatDecl->getBeginLoc();
11320b57cec5SDimitry Andric 
11330b57cec5SDimitry Andric   // FIXME: handle category headers that are declared across multiple lines.
11340b57cec5SDimitry Andric   if (CatDecl->getIvarRBraceLoc().isValid()) {
11350b57cec5SDimitry Andric     ReplaceText(LocStart, 1, "/** ");
11360b57cec5SDimitry Andric     ReplaceText(CatDecl->getIvarRBraceLoc(), 1, "**/ ");
11370b57cec5SDimitry Andric   }
11380b57cec5SDimitry Andric   else {
11390b57cec5SDimitry Andric     ReplaceText(LocStart, 0, "// ");
11400b57cec5SDimitry Andric   }
11410b57cec5SDimitry Andric 
11420b57cec5SDimitry Andric   for (auto *I : CatDecl->instance_properties())
11430b57cec5SDimitry Andric     RewriteProperty(I);
11440b57cec5SDimitry Andric 
11450b57cec5SDimitry Andric   for (auto *I : CatDecl->instance_methods())
11460b57cec5SDimitry Andric     RewriteMethodDeclaration(I);
11470b57cec5SDimitry Andric   for (auto *I : CatDecl->class_methods())
11480b57cec5SDimitry Andric     RewriteMethodDeclaration(I);
11490b57cec5SDimitry Andric 
11500b57cec5SDimitry Andric   // Lastly, comment out the @end.
11510b57cec5SDimitry Andric   ReplaceText(CatDecl->getAtEndRange().getBegin(),
11520b57cec5SDimitry Andric               strlen("@end"), "/* @end */\n");
11530b57cec5SDimitry Andric }
11540b57cec5SDimitry Andric 
RewriteProtocolDecl(ObjCProtocolDecl * PDecl)11550b57cec5SDimitry Andric void RewriteModernObjC::RewriteProtocolDecl(ObjCProtocolDecl *PDecl) {
11560b57cec5SDimitry Andric   SourceLocation LocStart = PDecl->getBeginLoc();
11570b57cec5SDimitry Andric   assert(PDecl->isThisDeclarationADefinition());
11580b57cec5SDimitry Andric 
11590b57cec5SDimitry Andric   // FIXME: handle protocol headers that are declared across multiple lines.
11600b57cec5SDimitry Andric   ReplaceText(LocStart, 0, "// ");
11610b57cec5SDimitry Andric 
11620b57cec5SDimitry Andric   for (auto *I : PDecl->instance_methods())
11630b57cec5SDimitry Andric     RewriteMethodDeclaration(I);
11640b57cec5SDimitry Andric   for (auto *I : PDecl->class_methods())
11650b57cec5SDimitry Andric     RewriteMethodDeclaration(I);
11660b57cec5SDimitry Andric   for (auto *I : PDecl->instance_properties())
11670b57cec5SDimitry Andric     RewriteProperty(I);
11680b57cec5SDimitry Andric 
11690b57cec5SDimitry Andric   // Lastly, comment out the @end.
11700b57cec5SDimitry Andric   SourceLocation LocEnd = PDecl->getAtEndRange().getBegin();
11710b57cec5SDimitry Andric   ReplaceText(LocEnd, strlen("@end"), "/* @end */\n");
11720b57cec5SDimitry Andric 
11730b57cec5SDimitry Andric   // Must comment out @optional/@required
11740b57cec5SDimitry Andric   const char *startBuf = SM->getCharacterData(LocStart);
11750b57cec5SDimitry Andric   const char *endBuf = SM->getCharacterData(LocEnd);
11760b57cec5SDimitry Andric   for (const char *p = startBuf; p < endBuf; p++) {
11770b57cec5SDimitry Andric     if (*p == '@' && !strncmp(p+1, "optional", strlen("optional"))) {
11780b57cec5SDimitry Andric       SourceLocation OptionalLoc = LocStart.getLocWithOffset(p-startBuf);
11790b57cec5SDimitry Andric       ReplaceText(OptionalLoc, strlen("@optional"), "/* @optional */");
11800b57cec5SDimitry Andric 
11810b57cec5SDimitry Andric     }
11820b57cec5SDimitry Andric     else if (*p == '@' && !strncmp(p+1, "required", strlen("required"))) {
11830b57cec5SDimitry Andric       SourceLocation OptionalLoc = LocStart.getLocWithOffset(p-startBuf);
11840b57cec5SDimitry Andric       ReplaceText(OptionalLoc, strlen("@required"), "/* @required */");
11850b57cec5SDimitry Andric 
11860b57cec5SDimitry Andric     }
11870b57cec5SDimitry Andric   }
11880b57cec5SDimitry Andric }
11890b57cec5SDimitry Andric 
RewriteForwardProtocolDecl(DeclGroupRef D)11900b57cec5SDimitry Andric void RewriteModernObjC::RewriteForwardProtocolDecl(DeclGroupRef D) {
11910b57cec5SDimitry Andric   SourceLocation LocStart = (*D.begin())->getBeginLoc();
11920b57cec5SDimitry Andric   if (LocStart.isInvalid())
11930b57cec5SDimitry Andric     llvm_unreachable("Invalid SourceLocation");
11940b57cec5SDimitry Andric   // FIXME: handle forward protocol that are declared across multiple lines.
11950b57cec5SDimitry Andric   ReplaceText(LocStart, 0, "// ");
11960b57cec5SDimitry Andric }
11970b57cec5SDimitry Andric 
11980b57cec5SDimitry Andric void
RewriteForwardProtocolDecl(const SmallVectorImpl<Decl * > & DG)11990b57cec5SDimitry Andric RewriteModernObjC::RewriteForwardProtocolDecl(const SmallVectorImpl<Decl *> &DG) {
12000b57cec5SDimitry Andric   SourceLocation LocStart = DG[0]->getBeginLoc();
12010b57cec5SDimitry Andric   if (LocStart.isInvalid())
12020b57cec5SDimitry Andric     llvm_unreachable("Invalid SourceLocation");
12030b57cec5SDimitry Andric   // FIXME: handle forward protocol that are declared across multiple lines.
12040b57cec5SDimitry Andric   ReplaceText(LocStart, 0, "// ");
12050b57cec5SDimitry Andric }
12060b57cec5SDimitry Andric 
RewriteTypeIntoString(QualType T,std::string & ResultStr,const FunctionType * & FPRetType)12070b57cec5SDimitry Andric void RewriteModernObjC::RewriteTypeIntoString(QualType T, std::string &ResultStr,
12080b57cec5SDimitry Andric                                         const FunctionType *&FPRetType) {
12090b57cec5SDimitry Andric   if (T->isObjCQualifiedIdType())
12100b57cec5SDimitry Andric     ResultStr += "id";
12110b57cec5SDimitry Andric   else if (T->isFunctionPointerType() ||
12120b57cec5SDimitry Andric            T->isBlockPointerType()) {
12130b57cec5SDimitry Andric     // needs special handling, since pointer-to-functions have special
12140b57cec5SDimitry Andric     // syntax (where a decaration models use).
12150b57cec5SDimitry Andric     QualType retType = T;
12160b57cec5SDimitry Andric     QualType PointeeTy;
12170b57cec5SDimitry Andric     if (const PointerType* PT = retType->getAs<PointerType>())
12180b57cec5SDimitry Andric       PointeeTy = PT->getPointeeType();
12190b57cec5SDimitry Andric     else if (const BlockPointerType *BPT = retType->getAs<BlockPointerType>())
12200b57cec5SDimitry Andric       PointeeTy = BPT->getPointeeType();
12210b57cec5SDimitry Andric     if ((FPRetType = PointeeTy->getAs<FunctionType>())) {
12220b57cec5SDimitry Andric       ResultStr +=
12230b57cec5SDimitry Andric           FPRetType->getReturnType().getAsString(Context->getPrintingPolicy());
12240b57cec5SDimitry Andric       ResultStr += "(*";
12250b57cec5SDimitry Andric     }
12260b57cec5SDimitry Andric   } else
12270b57cec5SDimitry Andric     ResultStr += T.getAsString(Context->getPrintingPolicy());
12280b57cec5SDimitry Andric }
12290b57cec5SDimitry Andric 
RewriteObjCMethodDecl(const ObjCInterfaceDecl * IDecl,ObjCMethodDecl * OMD,std::string & ResultStr)12300b57cec5SDimitry Andric void RewriteModernObjC::RewriteObjCMethodDecl(const ObjCInterfaceDecl *IDecl,
12310b57cec5SDimitry Andric                                         ObjCMethodDecl *OMD,
12320b57cec5SDimitry Andric                                         std::string &ResultStr) {
12330b57cec5SDimitry Andric   //fprintf(stderr,"In RewriteObjCMethodDecl\n");
12340b57cec5SDimitry Andric   const FunctionType *FPRetType = nullptr;
12350b57cec5SDimitry Andric   ResultStr += "\nstatic ";
12360b57cec5SDimitry Andric   RewriteTypeIntoString(OMD->getReturnType(), ResultStr, FPRetType);
12370b57cec5SDimitry Andric   ResultStr += " ";
12380b57cec5SDimitry Andric 
12390b57cec5SDimitry Andric   // Unique method name
12400b57cec5SDimitry Andric   std::string NameStr;
12410b57cec5SDimitry Andric 
12420b57cec5SDimitry Andric   if (OMD->isInstanceMethod())
12430b57cec5SDimitry Andric     NameStr += "_I_";
12440b57cec5SDimitry Andric   else
12450b57cec5SDimitry Andric     NameStr += "_C_";
12460b57cec5SDimitry Andric 
12470b57cec5SDimitry Andric   NameStr += IDecl->getNameAsString();
12480b57cec5SDimitry Andric   NameStr += "_";
12490b57cec5SDimitry Andric 
12500b57cec5SDimitry Andric   if (ObjCCategoryImplDecl *CID =
12510b57cec5SDimitry Andric       dyn_cast<ObjCCategoryImplDecl>(OMD->getDeclContext())) {
12520b57cec5SDimitry Andric     NameStr += CID->getNameAsString();
12530b57cec5SDimitry Andric     NameStr += "_";
12540b57cec5SDimitry Andric   }
12550b57cec5SDimitry Andric   // Append selector names, replacing ':' with '_'
12560b57cec5SDimitry Andric   {
12570b57cec5SDimitry Andric     std::string selString = OMD->getSelector().getAsString();
12580b57cec5SDimitry Andric     int len = selString.size();
12590b57cec5SDimitry Andric     for (int i = 0; i < len; i++)
12600b57cec5SDimitry Andric       if (selString[i] == ':')
12610b57cec5SDimitry Andric         selString[i] = '_';
12620b57cec5SDimitry Andric     NameStr += selString;
12630b57cec5SDimitry Andric   }
12640b57cec5SDimitry Andric   // Remember this name for metadata emission
12650b57cec5SDimitry Andric   MethodInternalNames[OMD] = NameStr;
12660b57cec5SDimitry Andric   ResultStr += NameStr;
12670b57cec5SDimitry Andric 
12680b57cec5SDimitry Andric   // Rewrite arguments
12690b57cec5SDimitry Andric   ResultStr += "(";
12700b57cec5SDimitry Andric 
12710b57cec5SDimitry Andric   // invisible arguments
12720b57cec5SDimitry Andric   if (OMD->isInstanceMethod()) {
12730b57cec5SDimitry Andric     QualType selfTy = Context->getObjCInterfaceType(IDecl);
12740b57cec5SDimitry Andric     selfTy = Context->getPointerType(selfTy);
12750b57cec5SDimitry Andric     if (!LangOpts.MicrosoftExt) {
12760b57cec5SDimitry Andric       if (ObjCSynthesizedStructs.count(const_cast<ObjCInterfaceDecl*>(IDecl)))
12770b57cec5SDimitry Andric         ResultStr += "struct ";
12780b57cec5SDimitry Andric     }
12790b57cec5SDimitry Andric     // When rewriting for Microsoft, explicitly omit the structure name.
12800b57cec5SDimitry Andric     ResultStr += IDecl->getNameAsString();
12810b57cec5SDimitry Andric     ResultStr += " *";
12820b57cec5SDimitry Andric   }
12830b57cec5SDimitry Andric   else
12840b57cec5SDimitry Andric     ResultStr += Context->getObjCClassType().getAsString(
12850b57cec5SDimitry Andric       Context->getPrintingPolicy());
12860b57cec5SDimitry Andric 
12870b57cec5SDimitry Andric   ResultStr += " self, ";
12880b57cec5SDimitry Andric   ResultStr += Context->getObjCSelType().getAsString(Context->getPrintingPolicy());
12890b57cec5SDimitry Andric   ResultStr += " _cmd";
12900b57cec5SDimitry Andric 
12910b57cec5SDimitry Andric   // Method arguments.
12920b57cec5SDimitry Andric   for (const auto *PDecl : OMD->parameters()) {
12930b57cec5SDimitry Andric     ResultStr += ", ";
12940b57cec5SDimitry Andric     if (PDecl->getType()->isObjCQualifiedIdType()) {
12950b57cec5SDimitry Andric       ResultStr += "id ";
12960b57cec5SDimitry Andric       ResultStr += PDecl->getNameAsString();
12970b57cec5SDimitry Andric     } else {
12980b57cec5SDimitry Andric       std::string Name = PDecl->getNameAsString();
12990b57cec5SDimitry Andric       QualType QT = PDecl->getType();
13000b57cec5SDimitry Andric       // Make sure we convert "t (^)(...)" to "t (*)(...)".
13010b57cec5SDimitry Andric       (void)convertBlockPointerToFunctionPointer(QT);
13020b57cec5SDimitry Andric       QT.getAsStringInternal(Name, Context->getPrintingPolicy());
13030b57cec5SDimitry Andric       ResultStr += Name;
13040b57cec5SDimitry Andric     }
13050b57cec5SDimitry Andric   }
13060b57cec5SDimitry Andric   if (OMD->isVariadic())
13070b57cec5SDimitry Andric     ResultStr += ", ...";
13080b57cec5SDimitry Andric   ResultStr += ") ";
13090b57cec5SDimitry Andric 
13100b57cec5SDimitry Andric   if (FPRetType) {
13110b57cec5SDimitry Andric     ResultStr += ")"; // close the precedence "scope" for "*".
13120b57cec5SDimitry Andric 
13130b57cec5SDimitry Andric     // Now, emit the argument types (if any).
13140b57cec5SDimitry Andric     if (const FunctionProtoType *FT = dyn_cast<FunctionProtoType>(FPRetType)) {
13150b57cec5SDimitry Andric       ResultStr += "(";
13160b57cec5SDimitry Andric       for (unsigned i = 0, e = FT->getNumParams(); i != e; ++i) {
13170b57cec5SDimitry Andric         if (i) ResultStr += ", ";
13180b57cec5SDimitry Andric         std::string ParamStr =
13190b57cec5SDimitry Andric             FT->getParamType(i).getAsString(Context->getPrintingPolicy());
13200b57cec5SDimitry Andric         ResultStr += ParamStr;
13210b57cec5SDimitry Andric       }
13220b57cec5SDimitry Andric       if (FT->isVariadic()) {
13230b57cec5SDimitry Andric         if (FT->getNumParams())
13240b57cec5SDimitry Andric           ResultStr += ", ";
13250b57cec5SDimitry Andric         ResultStr += "...";
13260b57cec5SDimitry Andric       }
13270b57cec5SDimitry Andric       ResultStr += ")";
13280b57cec5SDimitry Andric     } else {
13290b57cec5SDimitry Andric       ResultStr += "()";
13300b57cec5SDimitry Andric     }
13310b57cec5SDimitry Andric   }
13320b57cec5SDimitry Andric }
13330b57cec5SDimitry Andric 
RewriteImplementationDecl(Decl * OID)13340b57cec5SDimitry Andric void RewriteModernObjC::RewriteImplementationDecl(Decl *OID) {
13350b57cec5SDimitry Andric   ObjCImplementationDecl *IMD = dyn_cast<ObjCImplementationDecl>(OID);
13360b57cec5SDimitry Andric   ObjCCategoryImplDecl *CID = dyn_cast<ObjCCategoryImplDecl>(OID);
1337a7dea167SDimitry Andric   assert((IMD || CID) && "Unknown implementation type");
13380b57cec5SDimitry Andric 
13390b57cec5SDimitry Andric   if (IMD) {
13400b57cec5SDimitry Andric     if (IMD->getIvarRBraceLoc().isValid()) {
13410b57cec5SDimitry Andric       ReplaceText(IMD->getBeginLoc(), 1, "/** ");
13420b57cec5SDimitry Andric       ReplaceText(IMD->getIvarRBraceLoc(), 1, "**/ ");
13430b57cec5SDimitry Andric     }
13440b57cec5SDimitry Andric     else {
13450b57cec5SDimitry Andric       InsertText(IMD->getBeginLoc(), "// ");
13460b57cec5SDimitry Andric     }
13470b57cec5SDimitry Andric   }
13480b57cec5SDimitry Andric   else
13490b57cec5SDimitry Andric     InsertText(CID->getBeginLoc(), "// ");
13500b57cec5SDimitry Andric 
13510b57cec5SDimitry Andric   for (auto *OMD : IMD ? IMD->instance_methods() : CID->instance_methods()) {
1352480093f4SDimitry Andric     if (!OMD->getBody())
1353480093f4SDimitry Andric       continue;
13540b57cec5SDimitry Andric     std::string ResultStr;
13550b57cec5SDimitry Andric     RewriteObjCMethodDecl(OMD->getClassInterface(), OMD, ResultStr);
13560b57cec5SDimitry Andric     SourceLocation LocStart = OMD->getBeginLoc();
13570b57cec5SDimitry Andric     SourceLocation LocEnd = OMD->getCompoundBody()->getBeginLoc();
13580b57cec5SDimitry Andric 
13590b57cec5SDimitry Andric     const char *startBuf = SM->getCharacterData(LocStart);
13600b57cec5SDimitry Andric     const char *endBuf = SM->getCharacterData(LocEnd);
13610b57cec5SDimitry Andric     ReplaceText(LocStart, endBuf-startBuf, ResultStr);
13620b57cec5SDimitry Andric   }
13630b57cec5SDimitry Andric 
13640b57cec5SDimitry Andric   for (auto *OMD : IMD ? IMD->class_methods() : CID->class_methods()) {
1365480093f4SDimitry Andric     if (!OMD->getBody())
1366480093f4SDimitry Andric       continue;
13670b57cec5SDimitry Andric     std::string ResultStr;
13680b57cec5SDimitry Andric     RewriteObjCMethodDecl(OMD->getClassInterface(), OMD, ResultStr);
13690b57cec5SDimitry Andric     SourceLocation LocStart = OMD->getBeginLoc();
13700b57cec5SDimitry Andric     SourceLocation LocEnd = OMD->getCompoundBody()->getBeginLoc();
13710b57cec5SDimitry Andric 
13720b57cec5SDimitry Andric     const char *startBuf = SM->getCharacterData(LocStart);
13730b57cec5SDimitry Andric     const char *endBuf = SM->getCharacterData(LocEnd);
13740b57cec5SDimitry Andric     ReplaceText(LocStart, endBuf-startBuf, ResultStr);
13750b57cec5SDimitry Andric   }
13760b57cec5SDimitry Andric   for (auto *I : IMD ? IMD->property_impls() : CID->property_impls())
13770b57cec5SDimitry Andric     RewritePropertyImplDecl(I, IMD, CID);
13780b57cec5SDimitry Andric 
13790b57cec5SDimitry Andric   InsertText(IMD ? IMD->getEndLoc() : CID->getEndLoc(), "// ");
13800b57cec5SDimitry Andric }
13810b57cec5SDimitry Andric 
RewriteInterfaceDecl(ObjCInterfaceDecl * ClassDecl)13820b57cec5SDimitry Andric void RewriteModernObjC::RewriteInterfaceDecl(ObjCInterfaceDecl *ClassDecl) {
13830b57cec5SDimitry Andric   // Do not synthesize more than once.
13840b57cec5SDimitry Andric   if (ObjCSynthesizedStructs.count(ClassDecl))
13850b57cec5SDimitry Andric     return;
13860b57cec5SDimitry Andric   // Make sure super class's are written before current class is written.
13870b57cec5SDimitry Andric   ObjCInterfaceDecl *SuperClass = ClassDecl->getSuperClass();
13880b57cec5SDimitry Andric   while (SuperClass) {
13890b57cec5SDimitry Andric     RewriteInterfaceDecl(SuperClass);
13900b57cec5SDimitry Andric     SuperClass = SuperClass->getSuperClass();
13910b57cec5SDimitry Andric   }
13920b57cec5SDimitry Andric   std::string ResultStr;
13930b57cec5SDimitry Andric   if (!ObjCWrittenInterfaces.count(ClassDecl->getCanonicalDecl())) {
13940b57cec5SDimitry Andric     // we haven't seen a forward decl - generate a typedef.
13950b57cec5SDimitry Andric     RewriteOneForwardClassDecl(ClassDecl, ResultStr);
13960b57cec5SDimitry Andric     RewriteIvarOffsetSymbols(ClassDecl, ResultStr);
13970b57cec5SDimitry Andric 
13980b57cec5SDimitry Andric     RewriteObjCInternalStruct(ClassDecl, ResultStr);
13990b57cec5SDimitry Andric     // Mark this typedef as having been written into its c++ equivalent.
14000b57cec5SDimitry Andric     ObjCWrittenInterfaces.insert(ClassDecl->getCanonicalDecl());
14010b57cec5SDimitry Andric 
14020b57cec5SDimitry Andric     for (auto *I : ClassDecl->instance_properties())
14030b57cec5SDimitry Andric       RewriteProperty(I);
14040b57cec5SDimitry Andric     for (auto *I : ClassDecl->instance_methods())
14050b57cec5SDimitry Andric       RewriteMethodDeclaration(I);
14060b57cec5SDimitry Andric     for (auto *I : ClassDecl->class_methods())
14070b57cec5SDimitry Andric       RewriteMethodDeclaration(I);
14080b57cec5SDimitry Andric 
14090b57cec5SDimitry Andric     // Lastly, comment out the @end.
14100b57cec5SDimitry Andric     ReplaceText(ClassDecl->getAtEndRange().getBegin(), strlen("@end"),
14110b57cec5SDimitry Andric                 "/* @end */\n");
14120b57cec5SDimitry Andric   }
14130b57cec5SDimitry Andric }
14140b57cec5SDimitry Andric 
RewritePropertyOrImplicitSetter(PseudoObjectExpr * PseudoOp)14150b57cec5SDimitry Andric Stmt *RewriteModernObjC::RewritePropertyOrImplicitSetter(PseudoObjectExpr *PseudoOp) {
14160b57cec5SDimitry Andric   SourceRange OldRange = PseudoOp->getSourceRange();
14170b57cec5SDimitry Andric 
14180b57cec5SDimitry Andric   // We just magically know some things about the structure of this
14190b57cec5SDimitry Andric   // expression.
14200b57cec5SDimitry Andric   ObjCMessageExpr *OldMsg =
14210b57cec5SDimitry Andric     cast<ObjCMessageExpr>(PseudoOp->getSemanticExpr(
14220b57cec5SDimitry Andric                             PseudoOp->getNumSemanticExprs() - 1));
14230b57cec5SDimitry Andric 
14240b57cec5SDimitry Andric   // Because the rewriter doesn't allow us to rewrite rewritten code,
14250b57cec5SDimitry Andric   // we need to suppress rewriting the sub-statements.
14260b57cec5SDimitry Andric   Expr *Base;
14270b57cec5SDimitry Andric   SmallVector<Expr*, 2> Args;
14280b57cec5SDimitry Andric   {
14290b57cec5SDimitry Andric     DisableReplaceStmtScope S(*this);
14300b57cec5SDimitry Andric 
14310b57cec5SDimitry Andric     // Rebuild the base expression if we have one.
14320b57cec5SDimitry Andric     Base = nullptr;
14330b57cec5SDimitry Andric     if (OldMsg->getReceiverKind() == ObjCMessageExpr::Instance) {
14340b57cec5SDimitry Andric       Base = OldMsg->getInstanceReceiver();
14350b57cec5SDimitry Andric       Base = cast<OpaqueValueExpr>(Base)->getSourceExpr();
14360b57cec5SDimitry Andric       Base = cast<Expr>(RewriteFunctionBodyOrGlobalInitializer(Base));
14370b57cec5SDimitry Andric     }
14380b57cec5SDimitry Andric 
14390b57cec5SDimitry Andric     unsigned numArgs = OldMsg->getNumArgs();
14400b57cec5SDimitry Andric     for (unsigned i = 0; i < numArgs; i++) {
14410b57cec5SDimitry Andric       Expr *Arg = OldMsg->getArg(i);
14420b57cec5SDimitry Andric       if (isa<OpaqueValueExpr>(Arg))
14430b57cec5SDimitry Andric         Arg = cast<OpaqueValueExpr>(Arg)->getSourceExpr();
14440b57cec5SDimitry Andric       Arg = cast<Expr>(RewriteFunctionBodyOrGlobalInitializer(Arg));
14450b57cec5SDimitry Andric       Args.push_back(Arg);
14460b57cec5SDimitry Andric     }
14470b57cec5SDimitry Andric   }
14480b57cec5SDimitry Andric 
14490b57cec5SDimitry Andric   // TODO: avoid this copy.
14500b57cec5SDimitry Andric   SmallVector<SourceLocation, 1> SelLocs;
14510b57cec5SDimitry Andric   OldMsg->getSelectorLocs(SelLocs);
14520b57cec5SDimitry Andric 
14530b57cec5SDimitry Andric   ObjCMessageExpr *NewMsg = nullptr;
14540b57cec5SDimitry Andric   switch (OldMsg->getReceiverKind()) {
14550b57cec5SDimitry Andric   case ObjCMessageExpr::Class:
14560b57cec5SDimitry Andric     NewMsg = ObjCMessageExpr::Create(*Context, OldMsg->getType(),
14570b57cec5SDimitry Andric                                      OldMsg->getValueKind(),
14580b57cec5SDimitry Andric                                      OldMsg->getLeftLoc(),
14590b57cec5SDimitry Andric                                      OldMsg->getClassReceiverTypeInfo(),
14600b57cec5SDimitry Andric                                      OldMsg->getSelector(),
14610b57cec5SDimitry Andric                                      SelLocs,
14620b57cec5SDimitry Andric                                      OldMsg->getMethodDecl(),
14630b57cec5SDimitry Andric                                      Args,
14640b57cec5SDimitry Andric                                      OldMsg->getRightLoc(),
14650b57cec5SDimitry Andric                                      OldMsg->isImplicit());
14660b57cec5SDimitry Andric     break;
14670b57cec5SDimitry Andric 
14680b57cec5SDimitry Andric   case ObjCMessageExpr::Instance:
14690b57cec5SDimitry Andric     NewMsg = ObjCMessageExpr::Create(*Context, OldMsg->getType(),
14700b57cec5SDimitry Andric                                      OldMsg->getValueKind(),
14710b57cec5SDimitry Andric                                      OldMsg->getLeftLoc(),
14720b57cec5SDimitry Andric                                      Base,
14730b57cec5SDimitry Andric                                      OldMsg->getSelector(),
14740b57cec5SDimitry Andric                                      SelLocs,
14750b57cec5SDimitry Andric                                      OldMsg->getMethodDecl(),
14760b57cec5SDimitry Andric                                      Args,
14770b57cec5SDimitry Andric                                      OldMsg->getRightLoc(),
14780b57cec5SDimitry Andric                                      OldMsg->isImplicit());
14790b57cec5SDimitry Andric     break;
14800b57cec5SDimitry Andric 
14810b57cec5SDimitry Andric   case ObjCMessageExpr::SuperClass:
14820b57cec5SDimitry Andric   case ObjCMessageExpr::SuperInstance:
14830b57cec5SDimitry Andric     NewMsg = ObjCMessageExpr::Create(*Context, OldMsg->getType(),
14840b57cec5SDimitry Andric                                      OldMsg->getValueKind(),
14850b57cec5SDimitry Andric                                      OldMsg->getLeftLoc(),
14860b57cec5SDimitry Andric                                      OldMsg->getSuperLoc(),
14870b57cec5SDimitry Andric                  OldMsg->getReceiverKind() == ObjCMessageExpr::SuperInstance,
14880b57cec5SDimitry Andric                                      OldMsg->getSuperType(),
14890b57cec5SDimitry Andric                                      OldMsg->getSelector(),
14900b57cec5SDimitry Andric                                      SelLocs,
14910b57cec5SDimitry Andric                                      OldMsg->getMethodDecl(),
14920b57cec5SDimitry Andric                                      Args,
14930b57cec5SDimitry Andric                                      OldMsg->getRightLoc(),
14940b57cec5SDimitry Andric                                      OldMsg->isImplicit());
14950b57cec5SDimitry Andric     break;
14960b57cec5SDimitry Andric   }
14970b57cec5SDimitry Andric 
14980b57cec5SDimitry Andric   Stmt *Replacement = SynthMessageExpr(NewMsg);
14990b57cec5SDimitry Andric   ReplaceStmtWithRange(PseudoOp, Replacement, OldRange);
15000b57cec5SDimitry Andric   return Replacement;
15010b57cec5SDimitry Andric }
15020b57cec5SDimitry Andric 
RewritePropertyOrImplicitGetter(PseudoObjectExpr * PseudoOp)15030b57cec5SDimitry Andric Stmt *RewriteModernObjC::RewritePropertyOrImplicitGetter(PseudoObjectExpr *PseudoOp) {
15040b57cec5SDimitry Andric   SourceRange OldRange = PseudoOp->getSourceRange();
15050b57cec5SDimitry Andric 
15060b57cec5SDimitry Andric   // We just magically know some things about the structure of this
15070b57cec5SDimitry Andric   // expression.
15080b57cec5SDimitry Andric   ObjCMessageExpr *OldMsg =
15090b57cec5SDimitry Andric     cast<ObjCMessageExpr>(PseudoOp->getResultExpr()->IgnoreImplicit());
15100b57cec5SDimitry Andric 
15110b57cec5SDimitry Andric   // Because the rewriter doesn't allow us to rewrite rewritten code,
15120b57cec5SDimitry Andric   // we need to suppress rewriting the sub-statements.
15130b57cec5SDimitry Andric   Expr *Base = nullptr;
15140b57cec5SDimitry Andric   SmallVector<Expr*, 1> Args;
15150b57cec5SDimitry Andric   {
15160b57cec5SDimitry Andric     DisableReplaceStmtScope S(*this);
15170b57cec5SDimitry Andric     // Rebuild the base expression if we have one.
15180b57cec5SDimitry Andric     if (OldMsg->getReceiverKind() == ObjCMessageExpr::Instance) {
15190b57cec5SDimitry Andric       Base = OldMsg->getInstanceReceiver();
15200b57cec5SDimitry Andric       Base = cast<OpaqueValueExpr>(Base)->getSourceExpr();
15210b57cec5SDimitry Andric       Base = cast<Expr>(RewriteFunctionBodyOrGlobalInitializer(Base));
15220b57cec5SDimitry Andric     }
15230b57cec5SDimitry Andric     unsigned numArgs = OldMsg->getNumArgs();
15240b57cec5SDimitry Andric     for (unsigned i = 0; i < numArgs; i++) {
15250b57cec5SDimitry Andric       Expr *Arg = OldMsg->getArg(i);
15260b57cec5SDimitry Andric       if (isa<OpaqueValueExpr>(Arg))
15270b57cec5SDimitry Andric         Arg = cast<OpaqueValueExpr>(Arg)->getSourceExpr();
15280b57cec5SDimitry Andric       Arg = cast<Expr>(RewriteFunctionBodyOrGlobalInitializer(Arg));
15290b57cec5SDimitry Andric       Args.push_back(Arg);
15300b57cec5SDimitry Andric     }
15310b57cec5SDimitry Andric   }
15320b57cec5SDimitry Andric 
15330b57cec5SDimitry Andric   // Intentionally empty.
15340b57cec5SDimitry Andric   SmallVector<SourceLocation, 1> SelLocs;
15350b57cec5SDimitry Andric 
15360b57cec5SDimitry Andric   ObjCMessageExpr *NewMsg = nullptr;
15370b57cec5SDimitry Andric   switch (OldMsg->getReceiverKind()) {
15380b57cec5SDimitry Andric   case ObjCMessageExpr::Class:
15390b57cec5SDimitry Andric     NewMsg = ObjCMessageExpr::Create(*Context, OldMsg->getType(),
15400b57cec5SDimitry Andric                                      OldMsg->getValueKind(),
15410b57cec5SDimitry Andric                                      OldMsg->getLeftLoc(),
15420b57cec5SDimitry Andric                                      OldMsg->getClassReceiverTypeInfo(),
15430b57cec5SDimitry Andric                                      OldMsg->getSelector(),
15440b57cec5SDimitry Andric                                      SelLocs,
15450b57cec5SDimitry Andric                                      OldMsg->getMethodDecl(),
15460b57cec5SDimitry Andric                                      Args,
15470b57cec5SDimitry Andric                                      OldMsg->getRightLoc(),
15480b57cec5SDimitry Andric                                      OldMsg->isImplicit());
15490b57cec5SDimitry Andric     break;
15500b57cec5SDimitry Andric 
15510b57cec5SDimitry Andric   case ObjCMessageExpr::Instance:
15520b57cec5SDimitry Andric     NewMsg = ObjCMessageExpr::Create(*Context, OldMsg->getType(),
15530b57cec5SDimitry Andric                                      OldMsg->getValueKind(),
15540b57cec5SDimitry Andric                                      OldMsg->getLeftLoc(),
15550b57cec5SDimitry Andric                                      Base,
15560b57cec5SDimitry Andric                                      OldMsg->getSelector(),
15570b57cec5SDimitry Andric                                      SelLocs,
15580b57cec5SDimitry Andric                                      OldMsg->getMethodDecl(),
15590b57cec5SDimitry Andric                                      Args,
15600b57cec5SDimitry Andric                                      OldMsg->getRightLoc(),
15610b57cec5SDimitry Andric                                      OldMsg->isImplicit());
15620b57cec5SDimitry Andric     break;
15630b57cec5SDimitry Andric 
15640b57cec5SDimitry Andric   case ObjCMessageExpr::SuperClass:
15650b57cec5SDimitry Andric   case ObjCMessageExpr::SuperInstance:
15660b57cec5SDimitry Andric     NewMsg = ObjCMessageExpr::Create(*Context, OldMsg->getType(),
15670b57cec5SDimitry Andric                                      OldMsg->getValueKind(),
15680b57cec5SDimitry Andric                                      OldMsg->getLeftLoc(),
15690b57cec5SDimitry Andric                                      OldMsg->getSuperLoc(),
15700b57cec5SDimitry Andric                  OldMsg->getReceiverKind() == ObjCMessageExpr::SuperInstance,
15710b57cec5SDimitry Andric                                      OldMsg->getSuperType(),
15720b57cec5SDimitry Andric                                      OldMsg->getSelector(),
15730b57cec5SDimitry Andric                                      SelLocs,
15740b57cec5SDimitry Andric                                      OldMsg->getMethodDecl(),
15750b57cec5SDimitry Andric                                      Args,
15760b57cec5SDimitry Andric                                      OldMsg->getRightLoc(),
15770b57cec5SDimitry Andric                                      OldMsg->isImplicit());
15780b57cec5SDimitry Andric     break;
15790b57cec5SDimitry Andric   }
15800b57cec5SDimitry Andric 
15810b57cec5SDimitry Andric   Stmt *Replacement = SynthMessageExpr(NewMsg);
15820b57cec5SDimitry Andric   ReplaceStmtWithRange(PseudoOp, Replacement, OldRange);
15830b57cec5SDimitry Andric   return Replacement;
15840b57cec5SDimitry Andric }
15850b57cec5SDimitry Andric 
15860b57cec5SDimitry Andric /// SynthCountByEnumWithState - To print:
15870b57cec5SDimitry Andric /// ((NSUInteger (*)
15880b57cec5SDimitry Andric ///  (id, SEL, struct __objcFastEnumerationState *, id *, NSUInteger))
15890b57cec5SDimitry Andric ///  (void *)objc_msgSend)((id)l_collection,
15900b57cec5SDimitry Andric ///                        sel_registerName(
15910b57cec5SDimitry Andric ///                          "countByEnumeratingWithState:objects:count:"),
15920b57cec5SDimitry Andric ///                        &enumState,
15930b57cec5SDimitry Andric ///                        (id *)__rw_items, (NSUInteger)16)
15940b57cec5SDimitry Andric ///
SynthCountByEnumWithState(std::string & buf)15950b57cec5SDimitry Andric void RewriteModernObjC::SynthCountByEnumWithState(std::string &buf) {
15960b57cec5SDimitry Andric   buf += "((_WIN_NSUInteger (*) (id, SEL, struct __objcFastEnumerationState *, "
15970b57cec5SDimitry Andric   "id *, _WIN_NSUInteger))(void *)objc_msgSend)";
15980b57cec5SDimitry Andric   buf += "\n\t\t";
15990b57cec5SDimitry Andric   buf += "((id)l_collection,\n\t\t";
16000b57cec5SDimitry Andric   buf += "sel_registerName(\"countByEnumeratingWithState:objects:count:\"),";
16010b57cec5SDimitry Andric   buf += "\n\t\t";
16020b57cec5SDimitry Andric   buf += "&enumState, "
16030b57cec5SDimitry Andric          "(id *)__rw_items, (_WIN_NSUInteger)16)";
16040b57cec5SDimitry Andric }
16050b57cec5SDimitry Andric 
16060b57cec5SDimitry Andric /// RewriteBreakStmt - Rewrite for a break-stmt inside an ObjC2's foreach
16070b57cec5SDimitry Andric /// statement to exit to its outer synthesized loop.
16080b57cec5SDimitry Andric ///
RewriteBreakStmt(BreakStmt * S)16090b57cec5SDimitry Andric Stmt *RewriteModernObjC::RewriteBreakStmt(BreakStmt *S) {
16100b57cec5SDimitry Andric   if (Stmts.empty() || !isa<ObjCForCollectionStmt>(Stmts.back()))
16110b57cec5SDimitry Andric     return S;
16120b57cec5SDimitry Andric   // replace break with goto __break_label
16130b57cec5SDimitry Andric   std::string buf;
16140b57cec5SDimitry Andric 
16150b57cec5SDimitry Andric   SourceLocation startLoc = S->getBeginLoc();
16160b57cec5SDimitry Andric   buf = "goto __break_label_";
16170b57cec5SDimitry Andric   buf += utostr(ObjCBcLabelNo.back());
16180b57cec5SDimitry Andric   ReplaceText(startLoc, strlen("break"), buf);
16190b57cec5SDimitry Andric 
16200b57cec5SDimitry Andric   return nullptr;
16210b57cec5SDimitry Andric }
16220b57cec5SDimitry Andric 
ConvertSourceLocationToLineDirective(SourceLocation Loc,std::string & LineString)16230b57cec5SDimitry Andric void RewriteModernObjC::ConvertSourceLocationToLineDirective(
16240b57cec5SDimitry Andric                                           SourceLocation Loc,
16250b57cec5SDimitry Andric                                           std::string &LineString) {
16260b57cec5SDimitry Andric   if (Loc.isFileID() && GenerateLineInfo) {
16270b57cec5SDimitry Andric     LineString += "\n#line ";
16280b57cec5SDimitry Andric     PresumedLoc PLoc = SM->getPresumedLoc(Loc);
16290b57cec5SDimitry Andric     LineString += utostr(PLoc.getLine());
16300b57cec5SDimitry Andric     LineString += " \"";
16310b57cec5SDimitry Andric     LineString += Lexer::Stringify(PLoc.getFilename());
16320b57cec5SDimitry Andric     LineString += "\"\n";
16330b57cec5SDimitry Andric   }
16340b57cec5SDimitry Andric }
16350b57cec5SDimitry Andric 
16360b57cec5SDimitry Andric /// RewriteContinueStmt - Rewrite for a continue-stmt inside an ObjC2's foreach
16370b57cec5SDimitry Andric /// statement to continue with its inner synthesized loop.
16380b57cec5SDimitry Andric ///
RewriteContinueStmt(ContinueStmt * S)16390b57cec5SDimitry Andric Stmt *RewriteModernObjC::RewriteContinueStmt(ContinueStmt *S) {
16400b57cec5SDimitry Andric   if (Stmts.empty() || !isa<ObjCForCollectionStmt>(Stmts.back()))
16410b57cec5SDimitry Andric     return S;
16420b57cec5SDimitry Andric   // replace continue with goto __continue_label
16430b57cec5SDimitry Andric   std::string buf;
16440b57cec5SDimitry Andric 
16450b57cec5SDimitry Andric   SourceLocation startLoc = S->getBeginLoc();
16460b57cec5SDimitry Andric   buf = "goto __continue_label_";
16470b57cec5SDimitry Andric   buf += utostr(ObjCBcLabelNo.back());
16480b57cec5SDimitry Andric   ReplaceText(startLoc, strlen("continue"), buf);
16490b57cec5SDimitry Andric 
16500b57cec5SDimitry Andric   return nullptr;
16510b57cec5SDimitry Andric }
16520b57cec5SDimitry Andric 
16530b57cec5SDimitry Andric /// RewriteObjCForCollectionStmt - Rewriter for ObjC2's foreach statement.
16540b57cec5SDimitry Andric ///  It rewrites:
16550b57cec5SDimitry Andric /// for ( type elem in collection) { stmts; }
16560b57cec5SDimitry Andric 
16570b57cec5SDimitry Andric /// Into:
16580b57cec5SDimitry Andric /// {
16590b57cec5SDimitry Andric ///   type elem;
16600b57cec5SDimitry Andric ///   struct __objcFastEnumerationState enumState = { 0 };
16610b57cec5SDimitry Andric ///   id __rw_items[16];
16620b57cec5SDimitry Andric ///   id l_collection = (id)collection;
16630b57cec5SDimitry Andric ///   NSUInteger limit = [l_collection countByEnumeratingWithState:&enumState
16640b57cec5SDimitry Andric ///                                       objects:__rw_items count:16];
16650b57cec5SDimitry Andric /// if (limit) {
16660b57cec5SDimitry Andric ///   unsigned long startMutations = *enumState.mutationsPtr;
16670b57cec5SDimitry Andric ///   do {
16680b57cec5SDimitry Andric ///        unsigned long counter = 0;
16690b57cec5SDimitry Andric ///        do {
16700b57cec5SDimitry Andric ///             if (startMutations != *enumState.mutationsPtr)
16710b57cec5SDimitry Andric ///               objc_enumerationMutation(l_collection);
16720b57cec5SDimitry Andric ///             elem = (type)enumState.itemsPtr[counter++];
16730b57cec5SDimitry Andric ///             stmts;
16740b57cec5SDimitry Andric ///             __continue_label: ;
16750b57cec5SDimitry Andric ///        } while (counter < limit);
16760b57cec5SDimitry Andric ///   } while ((limit = [l_collection countByEnumeratingWithState:&enumState
16770b57cec5SDimitry Andric ///                                  objects:__rw_items count:16]));
16780b57cec5SDimitry Andric ///   elem = nil;
16790b57cec5SDimitry Andric ///   __break_label: ;
16800b57cec5SDimitry Andric ///  }
16810b57cec5SDimitry Andric ///  else
16820b57cec5SDimitry Andric ///       elem = nil;
16830b57cec5SDimitry Andric ///  }
16840b57cec5SDimitry Andric ///
RewriteObjCForCollectionStmt(ObjCForCollectionStmt * S,SourceLocation OrigEnd)16850b57cec5SDimitry Andric Stmt *RewriteModernObjC::RewriteObjCForCollectionStmt(ObjCForCollectionStmt *S,
16860b57cec5SDimitry Andric                                                 SourceLocation OrigEnd) {
16870b57cec5SDimitry Andric   assert(!Stmts.empty() && "ObjCForCollectionStmt - Statement stack empty");
16880b57cec5SDimitry Andric   assert(isa<ObjCForCollectionStmt>(Stmts.back()) &&
16890b57cec5SDimitry Andric          "ObjCForCollectionStmt Statement stack mismatch");
16900b57cec5SDimitry Andric   assert(!ObjCBcLabelNo.empty() &&
16910b57cec5SDimitry Andric          "ObjCForCollectionStmt - Label No stack empty");
16920b57cec5SDimitry Andric 
16930b57cec5SDimitry Andric   SourceLocation startLoc = S->getBeginLoc();
16940b57cec5SDimitry Andric   const char *startBuf = SM->getCharacterData(startLoc);
16950b57cec5SDimitry Andric   StringRef elementName;
16960b57cec5SDimitry Andric   std::string elementTypeAsString;
16970b57cec5SDimitry Andric   std::string buf;
16980b57cec5SDimitry Andric   // line directive first.
16990b57cec5SDimitry Andric   SourceLocation ForEachLoc = S->getForLoc();
17000b57cec5SDimitry Andric   ConvertSourceLocationToLineDirective(ForEachLoc, buf);
17010b57cec5SDimitry Andric   buf += "{\n\t";
17020b57cec5SDimitry Andric   if (DeclStmt *DS = dyn_cast<DeclStmt>(S->getElement())) {
17030b57cec5SDimitry Andric     // type elem;
17040b57cec5SDimitry Andric     NamedDecl* D = cast<NamedDecl>(DS->getSingleDecl());
17050b57cec5SDimitry Andric     QualType ElementType = cast<ValueDecl>(D)->getType();
17060b57cec5SDimitry Andric     if (ElementType->isObjCQualifiedIdType() ||
17070b57cec5SDimitry Andric         ElementType->isObjCQualifiedInterfaceType())
17080b57cec5SDimitry Andric       // Simply use 'id' for all qualified types.
17090b57cec5SDimitry Andric       elementTypeAsString = "id";
17100b57cec5SDimitry Andric     else
17110b57cec5SDimitry Andric       elementTypeAsString = ElementType.getAsString(Context->getPrintingPolicy());
17120b57cec5SDimitry Andric     buf += elementTypeAsString;
17130b57cec5SDimitry Andric     buf += " ";
17140b57cec5SDimitry Andric     elementName = D->getName();
17150b57cec5SDimitry Andric     buf += elementName;
17160b57cec5SDimitry Andric     buf += ";\n\t";
17170b57cec5SDimitry Andric   }
17180b57cec5SDimitry Andric   else {
17190b57cec5SDimitry Andric     DeclRefExpr *DR = cast<DeclRefExpr>(S->getElement());
17200b57cec5SDimitry Andric     elementName = DR->getDecl()->getName();
17210b57cec5SDimitry Andric     ValueDecl *VD = DR->getDecl();
17220b57cec5SDimitry Andric     if (VD->getType()->isObjCQualifiedIdType() ||
17230b57cec5SDimitry Andric         VD->getType()->isObjCQualifiedInterfaceType())
17240b57cec5SDimitry Andric       // Simply use 'id' for all qualified types.
17250b57cec5SDimitry Andric       elementTypeAsString = "id";
17260b57cec5SDimitry Andric     else
17270b57cec5SDimitry Andric       elementTypeAsString = VD->getType().getAsString(Context->getPrintingPolicy());
17280b57cec5SDimitry Andric   }
17290b57cec5SDimitry Andric 
17300b57cec5SDimitry Andric   // struct __objcFastEnumerationState enumState = { 0 };
17310b57cec5SDimitry Andric   buf += "struct __objcFastEnumerationState enumState = { 0 };\n\t";
17320b57cec5SDimitry Andric   // id __rw_items[16];
17330b57cec5SDimitry Andric   buf += "id __rw_items[16];\n\t";
17340b57cec5SDimitry Andric   // id l_collection = (id)
17350b57cec5SDimitry Andric   buf += "id l_collection = (id)";
17360b57cec5SDimitry Andric   // Find start location of 'collection' the hard way!
17370b57cec5SDimitry Andric   const char *startCollectionBuf = startBuf;
17380b57cec5SDimitry Andric   startCollectionBuf += 3;  // skip 'for'
17390b57cec5SDimitry Andric   startCollectionBuf = strchr(startCollectionBuf, '(');
17400b57cec5SDimitry Andric   startCollectionBuf++; // skip '('
17410b57cec5SDimitry Andric   // find 'in' and skip it.
17420b57cec5SDimitry Andric   while (*startCollectionBuf != ' ' ||
17430b57cec5SDimitry Andric          *(startCollectionBuf+1) != 'i' || *(startCollectionBuf+2) != 'n' ||
17440b57cec5SDimitry Andric          (*(startCollectionBuf+3) != ' ' &&
17450b57cec5SDimitry Andric           *(startCollectionBuf+3) != '[' && *(startCollectionBuf+3) != '('))
17460b57cec5SDimitry Andric     startCollectionBuf++;
17470b57cec5SDimitry Andric   startCollectionBuf += 3;
17480b57cec5SDimitry Andric 
17490b57cec5SDimitry Andric   // Replace: "for (type element in" with string constructed thus far.
17500b57cec5SDimitry Andric   ReplaceText(startLoc, startCollectionBuf - startBuf, buf);
17510b57cec5SDimitry Andric   // Replace ')' in for '(' type elem in collection ')' with ';'
17520b57cec5SDimitry Andric   SourceLocation rightParenLoc = S->getRParenLoc();
17530b57cec5SDimitry Andric   const char *rparenBuf = SM->getCharacterData(rightParenLoc);
17540b57cec5SDimitry Andric   SourceLocation lparenLoc = startLoc.getLocWithOffset(rparenBuf-startBuf);
17550b57cec5SDimitry Andric   buf = ";\n\t";
17560b57cec5SDimitry Andric 
17570b57cec5SDimitry Andric   // unsigned long limit = [l_collection countByEnumeratingWithState:&enumState
17580b57cec5SDimitry Andric   //                                   objects:__rw_items count:16];
17590b57cec5SDimitry Andric   // which is synthesized into:
17600b57cec5SDimitry Andric   // NSUInteger limit =
17610b57cec5SDimitry Andric   // ((NSUInteger (*)
17620b57cec5SDimitry Andric   //  (id, SEL, struct __objcFastEnumerationState *, id *, NSUInteger))
17630b57cec5SDimitry Andric   //  (void *)objc_msgSend)((id)l_collection,
17640b57cec5SDimitry Andric   //                        sel_registerName(
17650b57cec5SDimitry Andric   //                          "countByEnumeratingWithState:objects:count:"),
17660b57cec5SDimitry Andric   //                        (struct __objcFastEnumerationState *)&state,
17670b57cec5SDimitry Andric   //                        (id *)__rw_items, (NSUInteger)16);
17680b57cec5SDimitry Andric   buf += "_WIN_NSUInteger limit =\n\t\t";
17690b57cec5SDimitry Andric   SynthCountByEnumWithState(buf);
17700b57cec5SDimitry Andric   buf += ";\n\t";
17710b57cec5SDimitry Andric   /// if (limit) {
17720b57cec5SDimitry Andric   ///   unsigned long startMutations = *enumState.mutationsPtr;
17730b57cec5SDimitry Andric   ///   do {
17740b57cec5SDimitry Andric   ///        unsigned long counter = 0;
17750b57cec5SDimitry Andric   ///        do {
17760b57cec5SDimitry Andric   ///             if (startMutations != *enumState.mutationsPtr)
17770b57cec5SDimitry Andric   ///               objc_enumerationMutation(l_collection);
17780b57cec5SDimitry Andric   ///             elem = (type)enumState.itemsPtr[counter++];
17790b57cec5SDimitry Andric   buf += "if (limit) {\n\t";
17800b57cec5SDimitry Andric   buf += "unsigned long startMutations = *enumState.mutationsPtr;\n\t";
17810b57cec5SDimitry Andric   buf += "do {\n\t\t";
17820b57cec5SDimitry Andric   buf += "unsigned long counter = 0;\n\t\t";
17830b57cec5SDimitry Andric   buf += "do {\n\t\t\t";
17840b57cec5SDimitry Andric   buf += "if (startMutations != *enumState.mutationsPtr)\n\t\t\t\t";
17850b57cec5SDimitry Andric   buf += "objc_enumerationMutation(l_collection);\n\t\t\t";
17860b57cec5SDimitry Andric   buf += elementName;
17870b57cec5SDimitry Andric   buf += " = (";
17880b57cec5SDimitry Andric   buf += elementTypeAsString;
17890b57cec5SDimitry Andric   buf += ")enumState.itemsPtr[counter++];";
17900b57cec5SDimitry Andric   // Replace ')' in for '(' type elem in collection ')' with all of these.
17910b57cec5SDimitry Andric   ReplaceText(lparenLoc, 1, buf);
17920b57cec5SDimitry Andric 
17930b57cec5SDimitry Andric   ///            __continue_label: ;
17940b57cec5SDimitry Andric   ///        } while (counter < limit);
17950b57cec5SDimitry Andric   ///   } while ((limit = [l_collection countByEnumeratingWithState:&enumState
17960b57cec5SDimitry Andric   ///                                  objects:__rw_items count:16]));
17970b57cec5SDimitry Andric   ///   elem = nil;
17980b57cec5SDimitry Andric   ///   __break_label: ;
17990b57cec5SDimitry Andric   ///  }
18000b57cec5SDimitry Andric   ///  else
18010b57cec5SDimitry Andric   ///       elem = nil;
18020b57cec5SDimitry Andric   ///  }
18030b57cec5SDimitry Andric   ///
18040b57cec5SDimitry Andric   buf = ";\n\t";
18050b57cec5SDimitry Andric   buf += "__continue_label_";
18060b57cec5SDimitry Andric   buf += utostr(ObjCBcLabelNo.back());
18070b57cec5SDimitry Andric   buf += ": ;";
18080b57cec5SDimitry Andric   buf += "\n\t\t";
18090b57cec5SDimitry Andric   buf += "} while (counter < limit);\n\t";
18100b57cec5SDimitry Andric   buf += "} while ((limit = ";
18110b57cec5SDimitry Andric   SynthCountByEnumWithState(buf);
18120b57cec5SDimitry Andric   buf += "));\n\t";
18130b57cec5SDimitry Andric   buf += elementName;
18140b57cec5SDimitry Andric   buf += " = ((";
18150b57cec5SDimitry Andric   buf += elementTypeAsString;
18160b57cec5SDimitry Andric   buf += ")0);\n\t";
18170b57cec5SDimitry Andric   buf += "__break_label_";
18180b57cec5SDimitry Andric   buf += utostr(ObjCBcLabelNo.back());
18190b57cec5SDimitry Andric   buf += ": ;\n\t";
18200b57cec5SDimitry Andric   buf += "}\n\t";
18210b57cec5SDimitry Andric   buf += "else\n\t\t";
18220b57cec5SDimitry Andric   buf += elementName;
18230b57cec5SDimitry Andric   buf += " = ((";
18240b57cec5SDimitry Andric   buf += elementTypeAsString;
18250b57cec5SDimitry Andric   buf += ")0);\n\t";
18260b57cec5SDimitry Andric   buf += "}\n";
18270b57cec5SDimitry Andric 
18280b57cec5SDimitry Andric   // Insert all these *after* the statement body.
18290b57cec5SDimitry Andric   // FIXME: If this should support Obj-C++, support CXXTryStmt
18300b57cec5SDimitry Andric   if (isa<CompoundStmt>(S->getBody())) {
18310b57cec5SDimitry Andric     SourceLocation endBodyLoc = OrigEnd.getLocWithOffset(1);
18320b57cec5SDimitry Andric     InsertText(endBodyLoc, buf);
18330b57cec5SDimitry Andric   } else {
18340b57cec5SDimitry Andric     /* Need to treat single statements specially. For example:
18350b57cec5SDimitry Andric      *
18360b57cec5SDimitry Andric      *     for (A *a in b) if (stuff()) break;
18370b57cec5SDimitry Andric      *     for (A *a in b) xxxyy;
18380b57cec5SDimitry Andric      *
18390b57cec5SDimitry Andric      * The following code simply scans ahead to the semi to find the actual end.
18400b57cec5SDimitry Andric      */
18410b57cec5SDimitry Andric     const char *stmtBuf = SM->getCharacterData(OrigEnd);
18420b57cec5SDimitry Andric     const char *semiBuf = strchr(stmtBuf, ';');
18430b57cec5SDimitry Andric     assert(semiBuf && "Can't find ';'");
18440b57cec5SDimitry Andric     SourceLocation endBodyLoc = OrigEnd.getLocWithOffset(semiBuf-stmtBuf+1);
18450b57cec5SDimitry Andric     InsertText(endBodyLoc, buf);
18460b57cec5SDimitry Andric   }
18470b57cec5SDimitry Andric   Stmts.pop_back();
18480b57cec5SDimitry Andric   ObjCBcLabelNo.pop_back();
18490b57cec5SDimitry Andric   return nullptr;
18500b57cec5SDimitry Andric }
18510b57cec5SDimitry Andric 
Write_RethrowObject(std::string & buf)18520b57cec5SDimitry Andric static void Write_RethrowObject(std::string &buf) {
18530b57cec5SDimitry Andric   buf += "{ struct _FIN { _FIN(id reth) : rethrow(reth) {}\n";
18540b57cec5SDimitry Andric   buf += "\t~_FIN() { if (rethrow) objc_exception_throw(rethrow); }\n";
18550b57cec5SDimitry Andric   buf += "\tid rethrow;\n";
18560b57cec5SDimitry Andric   buf += "\t} _fin_force_rethow(_rethrow);";
18570b57cec5SDimitry Andric }
18580b57cec5SDimitry Andric 
18590b57cec5SDimitry Andric /// RewriteObjCSynchronizedStmt -
18600b57cec5SDimitry Andric /// This routine rewrites @synchronized(expr) stmt;
18610b57cec5SDimitry Andric /// into:
18620b57cec5SDimitry Andric /// objc_sync_enter(expr);
18630b57cec5SDimitry Andric /// @try stmt @finally { objc_sync_exit(expr); }
18640b57cec5SDimitry Andric ///
RewriteObjCSynchronizedStmt(ObjCAtSynchronizedStmt * S)18650b57cec5SDimitry Andric Stmt *RewriteModernObjC::RewriteObjCSynchronizedStmt(ObjCAtSynchronizedStmt *S) {
18660b57cec5SDimitry Andric   // Get the start location and compute the semi location.
18670b57cec5SDimitry Andric   SourceLocation startLoc = S->getBeginLoc();
18680b57cec5SDimitry Andric   const char *startBuf = SM->getCharacterData(startLoc);
18690b57cec5SDimitry Andric 
18700b57cec5SDimitry Andric   assert((*startBuf == '@') && "bogus @synchronized location");
18710b57cec5SDimitry Andric 
18720b57cec5SDimitry Andric   std::string buf;
18730b57cec5SDimitry Andric   SourceLocation SynchLoc = S->getAtSynchronizedLoc();
18740b57cec5SDimitry Andric   ConvertSourceLocationToLineDirective(SynchLoc, buf);
18750b57cec5SDimitry Andric   buf += "{ id _rethrow = 0; id _sync_obj = (id)";
18760b57cec5SDimitry Andric 
18770b57cec5SDimitry Andric   const char *lparenBuf = startBuf;
18780b57cec5SDimitry Andric   while (*lparenBuf != '(') lparenBuf++;
18790b57cec5SDimitry Andric   ReplaceText(startLoc, lparenBuf-startBuf+1, buf);
18800b57cec5SDimitry Andric 
18810b57cec5SDimitry Andric   buf = "; objc_sync_enter(_sync_obj);\n";
18820b57cec5SDimitry Andric   buf += "try {\n\tstruct _SYNC_EXIT { _SYNC_EXIT(id arg) : sync_exit(arg) {}";
18830b57cec5SDimitry Andric   buf += "\n\t~_SYNC_EXIT() {objc_sync_exit(sync_exit);}";
18840b57cec5SDimitry Andric   buf += "\n\tid sync_exit;";
18850b57cec5SDimitry Andric   buf += "\n\t} _sync_exit(_sync_obj);\n";
18860b57cec5SDimitry Andric 
18870b57cec5SDimitry Andric   // We can't use S->getSynchExpr()->getEndLoc() to find the end location, since
18880b57cec5SDimitry Andric   // the sync expression is typically a message expression that's already
18890b57cec5SDimitry Andric   // been rewritten! (which implies the SourceLocation's are invalid).
18900b57cec5SDimitry Andric   SourceLocation RParenExprLoc = S->getSynchBody()->getBeginLoc();
18910b57cec5SDimitry Andric   const char *RParenExprLocBuf = SM->getCharacterData(RParenExprLoc);
18920b57cec5SDimitry Andric   while (*RParenExprLocBuf != ')') RParenExprLocBuf--;
18930b57cec5SDimitry Andric   RParenExprLoc = startLoc.getLocWithOffset(RParenExprLocBuf-startBuf);
18940b57cec5SDimitry Andric 
18950b57cec5SDimitry Andric   SourceLocation LBranceLoc = S->getSynchBody()->getBeginLoc();
18960b57cec5SDimitry Andric   const char *LBraceLocBuf = SM->getCharacterData(LBranceLoc);
18970b57cec5SDimitry Andric   assert (*LBraceLocBuf == '{');
18980b57cec5SDimitry Andric   ReplaceText(RParenExprLoc, (LBraceLocBuf - SM->getCharacterData(RParenExprLoc) + 1), buf);
18990b57cec5SDimitry Andric 
19000b57cec5SDimitry Andric   SourceLocation startRBraceLoc = S->getSynchBody()->getEndLoc();
19010b57cec5SDimitry Andric   assert((*SM->getCharacterData(startRBraceLoc) == '}') &&
19020b57cec5SDimitry Andric          "bogus @synchronized block");
19030b57cec5SDimitry Andric 
19040b57cec5SDimitry Andric   buf = "} catch (id e) {_rethrow = e;}\n";
19050b57cec5SDimitry Andric   Write_RethrowObject(buf);
19060b57cec5SDimitry Andric   buf += "}\n";
19070b57cec5SDimitry Andric   buf += "}\n";
19080b57cec5SDimitry Andric 
19090b57cec5SDimitry Andric   ReplaceText(startRBraceLoc, 1, buf);
19100b57cec5SDimitry Andric 
19110b57cec5SDimitry Andric   return nullptr;
19120b57cec5SDimitry Andric }
19130b57cec5SDimitry Andric 
WarnAboutReturnGotoStmts(Stmt * S)19140b57cec5SDimitry Andric void RewriteModernObjC::WarnAboutReturnGotoStmts(Stmt *S)
19150b57cec5SDimitry Andric {
19160b57cec5SDimitry Andric   // Perform a bottom up traversal of all children.
19170b57cec5SDimitry Andric   for (Stmt *SubStmt : S->children())
19180b57cec5SDimitry Andric     if (SubStmt)
19190b57cec5SDimitry Andric       WarnAboutReturnGotoStmts(SubStmt);
19200b57cec5SDimitry Andric 
19210b57cec5SDimitry Andric   if (isa<ReturnStmt>(S) || isa<GotoStmt>(S)) {
19220b57cec5SDimitry Andric     Diags.Report(Context->getFullLoc(S->getBeginLoc()),
19230b57cec5SDimitry Andric                  TryFinallyContainsReturnDiag);
19240b57cec5SDimitry Andric   }
19250b57cec5SDimitry Andric }
19260b57cec5SDimitry Andric 
RewriteObjCAutoreleasePoolStmt(ObjCAutoreleasePoolStmt * S)19270b57cec5SDimitry Andric Stmt *RewriteModernObjC::RewriteObjCAutoreleasePoolStmt(ObjCAutoreleasePoolStmt  *S) {
19280b57cec5SDimitry Andric   SourceLocation startLoc = S->getAtLoc();
19290b57cec5SDimitry Andric   ReplaceText(startLoc, strlen("@autoreleasepool"), "/* @autoreleasepool */");
19300b57cec5SDimitry Andric   ReplaceText(S->getSubStmt()->getBeginLoc(), 1,
19310b57cec5SDimitry Andric               "{ __AtAutoreleasePool __autoreleasepool; ");
19320b57cec5SDimitry Andric 
19330b57cec5SDimitry Andric   return nullptr;
19340b57cec5SDimitry Andric }
19350b57cec5SDimitry Andric 
RewriteObjCTryStmt(ObjCAtTryStmt * S)19360b57cec5SDimitry Andric Stmt *RewriteModernObjC::RewriteObjCTryStmt(ObjCAtTryStmt *S) {
19370b57cec5SDimitry Andric   ObjCAtFinallyStmt *finalStmt = S->getFinallyStmt();
19380b57cec5SDimitry Andric   bool noCatch = S->getNumCatchStmts() == 0;
19390b57cec5SDimitry Andric   std::string buf;
19400b57cec5SDimitry Andric   SourceLocation TryLocation = S->getAtTryLoc();
19410b57cec5SDimitry Andric   ConvertSourceLocationToLineDirective(TryLocation, buf);
19420b57cec5SDimitry Andric 
19430b57cec5SDimitry Andric   if (finalStmt) {
19440b57cec5SDimitry Andric     if (noCatch)
19450b57cec5SDimitry Andric       buf += "{ id volatile _rethrow = 0;\n";
19460b57cec5SDimitry Andric     else {
19470b57cec5SDimitry Andric       buf += "{ id volatile _rethrow = 0;\ntry {\n";
19480b57cec5SDimitry Andric     }
19490b57cec5SDimitry Andric   }
19500b57cec5SDimitry Andric   // Get the start location and compute the semi location.
19510b57cec5SDimitry Andric   SourceLocation startLoc = S->getBeginLoc();
19520b57cec5SDimitry Andric   const char *startBuf = SM->getCharacterData(startLoc);
19530b57cec5SDimitry Andric 
19540b57cec5SDimitry Andric   assert((*startBuf == '@') && "bogus @try location");
19550b57cec5SDimitry Andric   if (finalStmt)
19560b57cec5SDimitry Andric     ReplaceText(startLoc, 1, buf);
19570b57cec5SDimitry Andric   else
19580b57cec5SDimitry Andric     // @try -> try
19590b57cec5SDimitry Andric     ReplaceText(startLoc, 1, "");
19600b57cec5SDimitry Andric 
1961349cc55cSDimitry Andric   for (ObjCAtCatchStmt *Catch : S->catch_stmts()) {
19620b57cec5SDimitry Andric     VarDecl *catchDecl = Catch->getCatchParamDecl();
19630b57cec5SDimitry Andric 
19640b57cec5SDimitry Andric     startLoc = Catch->getBeginLoc();
19650b57cec5SDimitry Andric     bool AtRemoved = false;
19660b57cec5SDimitry Andric     if (catchDecl) {
19670b57cec5SDimitry Andric       QualType t = catchDecl->getType();
1968349cc55cSDimitry Andric       if (const ObjCObjectPointerType *Ptr =
1969349cc55cSDimitry Andric               t->getAs<ObjCObjectPointerType>()) {
19700b57cec5SDimitry Andric         // Should be a pointer to a class.
19710b57cec5SDimitry Andric         ObjCInterfaceDecl *IDecl = Ptr->getObjectType()->getInterface();
19720b57cec5SDimitry Andric         if (IDecl) {
19730b57cec5SDimitry Andric           std::string Result;
19740b57cec5SDimitry Andric           ConvertSourceLocationToLineDirective(Catch->getBeginLoc(), Result);
19750b57cec5SDimitry Andric 
19760b57cec5SDimitry Andric           startBuf = SM->getCharacterData(startLoc);
19770b57cec5SDimitry Andric           assert((*startBuf == '@') && "bogus @catch location");
19780b57cec5SDimitry Andric           SourceLocation rParenLoc = Catch->getRParenLoc();
19790b57cec5SDimitry Andric           const char *rParenBuf = SM->getCharacterData(rParenLoc);
19800b57cec5SDimitry Andric 
19810b57cec5SDimitry Andric           // _objc_exc_Foo *_e as argument to catch.
19820b57cec5SDimitry Andric           Result += "catch (_objc_exc_"; Result += IDecl->getNameAsString();
19830b57cec5SDimitry Andric           Result += " *_"; Result += catchDecl->getNameAsString();
19840b57cec5SDimitry Andric           Result += ")";
19850b57cec5SDimitry Andric           ReplaceText(startLoc, rParenBuf-startBuf+1, Result);
19860b57cec5SDimitry Andric           // Foo *e = (Foo *)_e;
19870b57cec5SDimitry Andric           Result.clear();
19880b57cec5SDimitry Andric           Result = "{ ";
19890b57cec5SDimitry Andric           Result += IDecl->getNameAsString();
19900b57cec5SDimitry Andric           Result += " *"; Result += catchDecl->getNameAsString();
19910b57cec5SDimitry Andric           Result += " = ("; Result += IDecl->getNameAsString(); Result += "*)";
19920b57cec5SDimitry Andric           Result += "_"; Result += catchDecl->getNameAsString();
19930b57cec5SDimitry Andric 
19940b57cec5SDimitry Andric           Result += "; ";
19950b57cec5SDimitry Andric           SourceLocation lBraceLoc = Catch->getCatchBody()->getBeginLoc();
19960b57cec5SDimitry Andric           ReplaceText(lBraceLoc, 1, Result);
19970b57cec5SDimitry Andric           AtRemoved = true;
19980b57cec5SDimitry Andric         }
19990b57cec5SDimitry Andric       }
20000b57cec5SDimitry Andric     }
20010b57cec5SDimitry Andric     if (!AtRemoved)
20020b57cec5SDimitry Andric       // @catch -> catch
20030b57cec5SDimitry Andric       ReplaceText(startLoc, 1, "");
20040b57cec5SDimitry Andric 
20050b57cec5SDimitry Andric   }
20060b57cec5SDimitry Andric   if (finalStmt) {
20070b57cec5SDimitry Andric     buf.clear();
20080b57cec5SDimitry Andric     SourceLocation FinallyLoc = finalStmt->getBeginLoc();
20090b57cec5SDimitry Andric 
20100b57cec5SDimitry Andric     if (noCatch) {
20110b57cec5SDimitry Andric       ConvertSourceLocationToLineDirective(FinallyLoc, buf);
20120b57cec5SDimitry Andric       buf += "catch (id e) {_rethrow = e;}\n";
20130b57cec5SDimitry Andric     }
20140b57cec5SDimitry Andric     else {
20150b57cec5SDimitry Andric       buf += "}\n";
20160b57cec5SDimitry Andric       ConvertSourceLocationToLineDirective(FinallyLoc, buf);
20170b57cec5SDimitry Andric       buf += "catch (id e) {_rethrow = e;}\n";
20180b57cec5SDimitry Andric     }
20190b57cec5SDimitry Andric 
20200b57cec5SDimitry Andric     SourceLocation startFinalLoc = finalStmt->getBeginLoc();
20210b57cec5SDimitry Andric     ReplaceText(startFinalLoc, 8, buf);
20220b57cec5SDimitry Andric     Stmt *body = finalStmt->getFinallyBody();
20230b57cec5SDimitry Andric     SourceLocation startFinalBodyLoc = body->getBeginLoc();
20240b57cec5SDimitry Andric     buf.clear();
20250b57cec5SDimitry Andric     Write_RethrowObject(buf);
20260b57cec5SDimitry Andric     ReplaceText(startFinalBodyLoc, 1, buf);
20270b57cec5SDimitry Andric 
20280b57cec5SDimitry Andric     SourceLocation endFinalBodyLoc = body->getEndLoc();
20290b57cec5SDimitry Andric     ReplaceText(endFinalBodyLoc, 1, "}\n}");
20300b57cec5SDimitry Andric     // Now check for any return/continue/go statements within the @try.
20310b57cec5SDimitry Andric     WarnAboutReturnGotoStmts(S->getTryBody());
20320b57cec5SDimitry Andric   }
20330b57cec5SDimitry Andric 
20340b57cec5SDimitry Andric   return nullptr;
20350b57cec5SDimitry Andric }
20360b57cec5SDimitry Andric 
20370b57cec5SDimitry Andric // This can't be done with ReplaceStmt(S, ThrowExpr), since
20380b57cec5SDimitry Andric // the throw expression is typically a message expression that's already
20390b57cec5SDimitry Andric // been rewritten! (which implies the SourceLocation's are invalid).
RewriteObjCThrowStmt(ObjCAtThrowStmt * S)20400b57cec5SDimitry Andric Stmt *RewriteModernObjC::RewriteObjCThrowStmt(ObjCAtThrowStmt *S) {
20410b57cec5SDimitry Andric   // Get the start location and compute the semi location.
20420b57cec5SDimitry Andric   SourceLocation startLoc = S->getBeginLoc();
20430b57cec5SDimitry Andric   const char *startBuf = SM->getCharacterData(startLoc);
20440b57cec5SDimitry Andric 
20450b57cec5SDimitry Andric   assert((*startBuf == '@') && "bogus @throw location");
20460b57cec5SDimitry Andric 
20470b57cec5SDimitry Andric   std::string buf;
20480b57cec5SDimitry Andric   /* void objc_exception_throw(id) __attribute__((noreturn)); */
20490b57cec5SDimitry Andric   if (S->getThrowExpr())
20500b57cec5SDimitry Andric     buf = "objc_exception_throw(";
20510b57cec5SDimitry Andric   else
20520b57cec5SDimitry Andric     buf = "throw";
20530b57cec5SDimitry Andric 
20540b57cec5SDimitry Andric   // handle "@  throw" correctly.
20550b57cec5SDimitry Andric   const char *wBuf = strchr(startBuf, 'w');
20560b57cec5SDimitry Andric   assert((*wBuf == 'w') && "@throw: can't find 'w'");
20570b57cec5SDimitry Andric   ReplaceText(startLoc, wBuf-startBuf+1, buf);
20580b57cec5SDimitry Andric 
20590b57cec5SDimitry Andric   SourceLocation endLoc = S->getEndLoc();
20600b57cec5SDimitry Andric   const char *endBuf = SM->getCharacterData(endLoc);
20610b57cec5SDimitry Andric   const char *semiBuf = strchr(endBuf, ';');
20620b57cec5SDimitry Andric   assert((*semiBuf == ';') && "@throw: can't find ';'");
20630b57cec5SDimitry Andric   SourceLocation semiLoc = startLoc.getLocWithOffset(semiBuf-startBuf);
20640b57cec5SDimitry Andric   if (S->getThrowExpr())
20650b57cec5SDimitry Andric     ReplaceText(semiLoc, 1, ");");
20660b57cec5SDimitry Andric   return nullptr;
20670b57cec5SDimitry Andric }
20680b57cec5SDimitry Andric 
RewriteAtEncode(ObjCEncodeExpr * Exp)20690b57cec5SDimitry Andric Stmt *RewriteModernObjC::RewriteAtEncode(ObjCEncodeExpr *Exp) {
20700b57cec5SDimitry Andric   // Create a new string expression.
20710b57cec5SDimitry Andric   std::string StrEncoding;
20720b57cec5SDimitry Andric   Context->getObjCEncodingForType(Exp->getEncodedType(), StrEncoding);
20730b57cec5SDimitry Andric   Expr *Replacement = getStringLiteral(StrEncoding);
20740b57cec5SDimitry Andric   ReplaceStmt(Exp, Replacement);
20750b57cec5SDimitry Andric 
20760b57cec5SDimitry Andric   // Replace this subexpr in the parent.
20770b57cec5SDimitry Andric   // delete Exp; leak for now, see RewritePropertyOrImplicitSetter() usage for more info.
20780b57cec5SDimitry Andric   return Replacement;
20790b57cec5SDimitry Andric }
20800b57cec5SDimitry Andric 
RewriteAtSelector(ObjCSelectorExpr * Exp)20810b57cec5SDimitry Andric Stmt *RewriteModernObjC::RewriteAtSelector(ObjCSelectorExpr *Exp) {
20820b57cec5SDimitry Andric   if (!SelGetUidFunctionDecl)
20830b57cec5SDimitry Andric     SynthSelGetUidFunctionDecl();
20840b57cec5SDimitry Andric   assert(SelGetUidFunctionDecl && "Can't find sel_registerName() decl");
20850b57cec5SDimitry Andric   // Create a call to sel_registerName("selName").
20860b57cec5SDimitry Andric   SmallVector<Expr*, 8> SelExprs;
20870b57cec5SDimitry Andric   SelExprs.push_back(getStringLiteral(Exp->getSelector().getAsString()));
20880b57cec5SDimitry Andric   CallExpr *SelExp = SynthesizeCallToFunctionDecl(SelGetUidFunctionDecl,
20890b57cec5SDimitry Andric                                                   SelExprs);
20900b57cec5SDimitry Andric   ReplaceStmt(Exp, SelExp);
20910b57cec5SDimitry Andric   // delete Exp; leak for now, see RewritePropertyOrImplicitSetter() usage for more info.
20920b57cec5SDimitry Andric   return SelExp;
20930b57cec5SDimitry Andric }
20940b57cec5SDimitry Andric 
20950b57cec5SDimitry Andric CallExpr *
SynthesizeCallToFunctionDecl(FunctionDecl * FD,ArrayRef<Expr * > Args,SourceLocation StartLoc,SourceLocation EndLoc)20960b57cec5SDimitry Andric RewriteModernObjC::SynthesizeCallToFunctionDecl(FunctionDecl *FD,
20970b57cec5SDimitry Andric                                                 ArrayRef<Expr *> Args,
20980b57cec5SDimitry Andric                                                 SourceLocation StartLoc,
20990b57cec5SDimitry Andric                                                 SourceLocation EndLoc) {
21000b57cec5SDimitry Andric   // Get the type, we will need to reference it in a couple spots.
21010b57cec5SDimitry Andric   QualType msgSendType = FD->getType();
21020b57cec5SDimitry Andric 
21030b57cec5SDimitry Andric   // Create a reference to the objc_msgSend() declaration.
21040b57cec5SDimitry Andric   DeclRefExpr *DRE = new (Context) DeclRefExpr(*Context, FD, false, msgSendType,
21050b57cec5SDimitry Andric                                                VK_LValue, SourceLocation());
21060b57cec5SDimitry Andric 
21070b57cec5SDimitry Andric   // Now, we cast the reference to a pointer to the objc_msgSend type.
21080b57cec5SDimitry Andric   QualType pToFunc = Context->getPointerType(msgSendType);
21090b57cec5SDimitry Andric   ImplicitCastExpr *ICE =
21100b57cec5SDimitry Andric       ImplicitCastExpr::Create(*Context, pToFunc, CK_FunctionToPointerDecay,
2111fe6060f1SDimitry Andric                                DRE, nullptr, VK_PRValue, FPOptionsOverride());
21120b57cec5SDimitry Andric 
2113a7dea167SDimitry Andric   const auto *FT = msgSendType->castAs<FunctionType>();
2114e8d8bef9SDimitry Andric   CallExpr *Exp =
2115e8d8bef9SDimitry Andric       CallExpr::Create(*Context, ICE, Args, FT->getCallResultType(*Context),
2116fe6060f1SDimitry Andric                        VK_PRValue, EndLoc, FPOptionsOverride());
21170b57cec5SDimitry Andric   return Exp;
21180b57cec5SDimitry Andric }
21190b57cec5SDimitry Andric 
scanForProtocolRefs(const char * startBuf,const char * endBuf,const char * & startRef,const char * & endRef)21200b57cec5SDimitry Andric static bool scanForProtocolRefs(const char *startBuf, const char *endBuf,
21210b57cec5SDimitry Andric                                 const char *&startRef, const char *&endRef) {
21220b57cec5SDimitry Andric   while (startBuf < endBuf) {
21230b57cec5SDimitry Andric     if (*startBuf == '<')
21240b57cec5SDimitry Andric       startRef = startBuf; // mark the start.
21250b57cec5SDimitry Andric     if (*startBuf == '>') {
21260b57cec5SDimitry Andric       if (startRef && *startRef == '<') {
21270b57cec5SDimitry Andric         endRef = startBuf; // mark the end.
21280b57cec5SDimitry Andric         return true;
21290b57cec5SDimitry Andric       }
21300b57cec5SDimitry Andric       return false;
21310b57cec5SDimitry Andric     }
21320b57cec5SDimitry Andric     startBuf++;
21330b57cec5SDimitry Andric   }
21340b57cec5SDimitry Andric   return false;
21350b57cec5SDimitry Andric }
21360b57cec5SDimitry Andric 
scanToNextArgument(const char * & argRef)21370b57cec5SDimitry Andric static void scanToNextArgument(const char *&argRef) {
21380b57cec5SDimitry Andric   int angle = 0;
21390b57cec5SDimitry Andric   while (*argRef != ')' && (*argRef != ',' || angle > 0)) {
21400b57cec5SDimitry Andric     if (*argRef == '<')
21410b57cec5SDimitry Andric       angle++;
21420b57cec5SDimitry Andric     else if (*argRef == '>')
21430b57cec5SDimitry Andric       angle--;
21440b57cec5SDimitry Andric     argRef++;
21450b57cec5SDimitry Andric   }
21460b57cec5SDimitry Andric   assert(angle == 0 && "scanToNextArgument - bad protocol type syntax");
21470b57cec5SDimitry Andric }
21480b57cec5SDimitry Andric 
needToScanForQualifiers(QualType T)21490b57cec5SDimitry Andric bool RewriteModernObjC::needToScanForQualifiers(QualType T) {
21500b57cec5SDimitry Andric   if (T->isObjCQualifiedIdType())
21510b57cec5SDimitry Andric     return true;
21520b57cec5SDimitry Andric   if (const PointerType *PT = T->getAs<PointerType>()) {
21530b57cec5SDimitry Andric     if (PT->getPointeeType()->isObjCQualifiedIdType())
21540b57cec5SDimitry Andric       return true;
21550b57cec5SDimitry Andric   }
21560b57cec5SDimitry Andric   if (T->isObjCObjectPointerType()) {
21570b57cec5SDimitry Andric     T = T->getPointeeType();
21580b57cec5SDimitry Andric     return T->isObjCQualifiedInterfaceType();
21590b57cec5SDimitry Andric   }
21600b57cec5SDimitry Andric   if (T->isArrayType()) {
21610b57cec5SDimitry Andric     QualType ElemTy = Context->getBaseElementType(T);
21620b57cec5SDimitry Andric     return needToScanForQualifiers(ElemTy);
21630b57cec5SDimitry Andric   }
21640b57cec5SDimitry Andric   return false;
21650b57cec5SDimitry Andric }
21660b57cec5SDimitry Andric 
RewriteObjCQualifiedInterfaceTypes(Expr * E)21670b57cec5SDimitry Andric void RewriteModernObjC::RewriteObjCQualifiedInterfaceTypes(Expr *E) {
21680b57cec5SDimitry Andric   QualType Type = E->getType();
21690b57cec5SDimitry Andric   if (needToScanForQualifiers(Type)) {
21700b57cec5SDimitry Andric     SourceLocation Loc, EndLoc;
21710b57cec5SDimitry Andric 
21720b57cec5SDimitry Andric     if (const CStyleCastExpr *ECE = dyn_cast<CStyleCastExpr>(E)) {
21730b57cec5SDimitry Andric       Loc = ECE->getLParenLoc();
21740b57cec5SDimitry Andric       EndLoc = ECE->getRParenLoc();
21750b57cec5SDimitry Andric     } else {
21760b57cec5SDimitry Andric       Loc = E->getBeginLoc();
21770b57cec5SDimitry Andric       EndLoc = E->getEndLoc();
21780b57cec5SDimitry Andric     }
21790b57cec5SDimitry Andric     // This will defend against trying to rewrite synthesized expressions.
21800b57cec5SDimitry Andric     if (Loc.isInvalid() || EndLoc.isInvalid())
21810b57cec5SDimitry Andric       return;
21820b57cec5SDimitry Andric 
21830b57cec5SDimitry Andric     const char *startBuf = SM->getCharacterData(Loc);
21840b57cec5SDimitry Andric     const char *endBuf = SM->getCharacterData(EndLoc);
21850b57cec5SDimitry Andric     const char *startRef = nullptr, *endRef = nullptr;
21860b57cec5SDimitry Andric     if (scanForProtocolRefs(startBuf, endBuf, startRef, endRef)) {
21870b57cec5SDimitry Andric       // Get the locations of the startRef, endRef.
21880b57cec5SDimitry Andric       SourceLocation LessLoc = Loc.getLocWithOffset(startRef-startBuf);
21890b57cec5SDimitry Andric       SourceLocation GreaterLoc = Loc.getLocWithOffset(endRef-startBuf+1);
21900b57cec5SDimitry Andric       // Comment out the protocol references.
21910b57cec5SDimitry Andric       InsertText(LessLoc, "/*");
21920b57cec5SDimitry Andric       InsertText(GreaterLoc, "*/");
21930b57cec5SDimitry Andric     }
21940b57cec5SDimitry Andric   }
21950b57cec5SDimitry Andric }
21960b57cec5SDimitry Andric 
RewriteObjCQualifiedInterfaceTypes(Decl * Dcl)21970b57cec5SDimitry Andric void RewriteModernObjC::RewriteObjCQualifiedInterfaceTypes(Decl *Dcl) {
21980b57cec5SDimitry Andric   SourceLocation Loc;
21990b57cec5SDimitry Andric   QualType Type;
22000b57cec5SDimitry Andric   const FunctionProtoType *proto = nullptr;
22010b57cec5SDimitry Andric   if (VarDecl *VD = dyn_cast<VarDecl>(Dcl)) {
22020b57cec5SDimitry Andric     Loc = VD->getLocation();
22030b57cec5SDimitry Andric     Type = VD->getType();
22040b57cec5SDimitry Andric   }
22050b57cec5SDimitry Andric   else if (FunctionDecl *FD = dyn_cast<FunctionDecl>(Dcl)) {
22060b57cec5SDimitry Andric     Loc = FD->getLocation();
22070b57cec5SDimitry Andric     // Check for ObjC 'id' and class types that have been adorned with protocol
22080b57cec5SDimitry Andric     // information (id<p>, C<p>*). The protocol references need to be rewritten!
22090b57cec5SDimitry Andric     const FunctionType *funcType = FD->getType()->getAs<FunctionType>();
22100b57cec5SDimitry Andric     assert(funcType && "missing function type");
22110b57cec5SDimitry Andric     proto = dyn_cast<FunctionProtoType>(funcType);
22120b57cec5SDimitry Andric     if (!proto)
22130b57cec5SDimitry Andric       return;
22140b57cec5SDimitry Andric     Type = proto->getReturnType();
22150b57cec5SDimitry Andric   }
22160b57cec5SDimitry Andric   else if (FieldDecl *FD = dyn_cast<FieldDecl>(Dcl)) {
22170b57cec5SDimitry Andric     Loc = FD->getLocation();
22180b57cec5SDimitry Andric     Type = FD->getType();
22190b57cec5SDimitry Andric   }
22200b57cec5SDimitry Andric   else if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(Dcl)) {
22210b57cec5SDimitry Andric     Loc = TD->getLocation();
22220b57cec5SDimitry Andric     Type = TD->getUnderlyingType();
22230b57cec5SDimitry Andric   }
22240b57cec5SDimitry Andric   else
22250b57cec5SDimitry Andric     return;
22260b57cec5SDimitry Andric 
22270b57cec5SDimitry Andric   if (needToScanForQualifiers(Type)) {
22280b57cec5SDimitry Andric     // Since types are unique, we need to scan the buffer.
22290b57cec5SDimitry Andric 
22300b57cec5SDimitry Andric     const char *endBuf = SM->getCharacterData(Loc);
22310b57cec5SDimitry Andric     const char *startBuf = endBuf;
22320b57cec5SDimitry Andric     while (*startBuf != ';' && *startBuf != '<' && startBuf != MainFileStart)
22330b57cec5SDimitry Andric       startBuf--; // scan backward (from the decl location) for return type.
22340b57cec5SDimitry Andric     const char *startRef = nullptr, *endRef = nullptr;
22350b57cec5SDimitry Andric     if (scanForProtocolRefs(startBuf, endBuf, startRef, endRef)) {
22360b57cec5SDimitry Andric       // Get the locations of the startRef, endRef.
22370b57cec5SDimitry Andric       SourceLocation LessLoc = Loc.getLocWithOffset(startRef-endBuf);
22380b57cec5SDimitry Andric       SourceLocation GreaterLoc = Loc.getLocWithOffset(endRef-endBuf+1);
22390b57cec5SDimitry Andric       // Comment out the protocol references.
22400b57cec5SDimitry Andric       InsertText(LessLoc, "/*");
22410b57cec5SDimitry Andric       InsertText(GreaterLoc, "*/");
22420b57cec5SDimitry Andric     }
22430b57cec5SDimitry Andric   }
22440b57cec5SDimitry Andric   if (!proto)
22450b57cec5SDimitry Andric       return; // most likely, was a variable
22460b57cec5SDimitry Andric   // Now check arguments.
22470b57cec5SDimitry Andric   const char *startBuf = SM->getCharacterData(Loc);
22480b57cec5SDimitry Andric   const char *startFuncBuf = startBuf;
22490b57cec5SDimitry Andric   for (unsigned i = 0; i < proto->getNumParams(); i++) {
22500b57cec5SDimitry Andric     if (needToScanForQualifiers(proto->getParamType(i))) {
22510b57cec5SDimitry Andric       // Since types are unique, we need to scan the buffer.
22520b57cec5SDimitry Andric 
22530b57cec5SDimitry Andric       const char *endBuf = startBuf;
22540b57cec5SDimitry Andric       // scan forward (from the decl location) for argument types.
22550b57cec5SDimitry Andric       scanToNextArgument(endBuf);
22560b57cec5SDimitry Andric       const char *startRef = nullptr, *endRef = nullptr;
22570b57cec5SDimitry Andric       if (scanForProtocolRefs(startBuf, endBuf, startRef, endRef)) {
22580b57cec5SDimitry Andric         // Get the locations of the startRef, endRef.
22590b57cec5SDimitry Andric         SourceLocation LessLoc =
22600b57cec5SDimitry Andric           Loc.getLocWithOffset(startRef-startFuncBuf);
22610b57cec5SDimitry Andric         SourceLocation GreaterLoc =
22620b57cec5SDimitry Andric           Loc.getLocWithOffset(endRef-startFuncBuf+1);
22630b57cec5SDimitry Andric         // Comment out the protocol references.
22640b57cec5SDimitry Andric         InsertText(LessLoc, "/*");
22650b57cec5SDimitry Andric         InsertText(GreaterLoc, "*/");
22660b57cec5SDimitry Andric       }
22670b57cec5SDimitry Andric       startBuf = ++endBuf;
22680b57cec5SDimitry Andric     }
22690b57cec5SDimitry Andric     else {
22700b57cec5SDimitry Andric       // If the function name is derived from a macro expansion, then the
22710b57cec5SDimitry Andric       // argument buffer will not follow the name. Need to speak with Chris.
22720b57cec5SDimitry Andric       while (*startBuf && *startBuf != ')' && *startBuf != ',')
22730b57cec5SDimitry Andric         startBuf++; // scan forward (from the decl location) for argument types.
22740b57cec5SDimitry Andric       startBuf++;
22750b57cec5SDimitry Andric     }
22760b57cec5SDimitry Andric   }
22770b57cec5SDimitry Andric }
22780b57cec5SDimitry Andric 
RewriteTypeOfDecl(VarDecl * ND)22790b57cec5SDimitry Andric void RewriteModernObjC::RewriteTypeOfDecl(VarDecl *ND) {
22800b57cec5SDimitry Andric   QualType QT = ND->getType();
22810b57cec5SDimitry Andric   const Type* TypePtr = QT->getAs<Type>();
22820b57cec5SDimitry Andric   if (!isa<TypeOfExprType>(TypePtr))
22830b57cec5SDimitry Andric     return;
22840b57cec5SDimitry Andric   while (isa<TypeOfExprType>(TypePtr)) {
22850b57cec5SDimitry Andric     const TypeOfExprType *TypeOfExprTypePtr = cast<TypeOfExprType>(TypePtr);
22860b57cec5SDimitry Andric     QT = TypeOfExprTypePtr->getUnderlyingExpr()->getType();
22870b57cec5SDimitry Andric     TypePtr = QT->getAs<Type>();
22880b57cec5SDimitry Andric   }
22890b57cec5SDimitry Andric   // FIXME. This will not work for multiple declarators; as in:
22900b57cec5SDimitry Andric   // __typeof__(a) b,c,d;
22910b57cec5SDimitry Andric   std::string TypeAsString(QT.getAsString(Context->getPrintingPolicy()));
22920b57cec5SDimitry Andric   SourceLocation DeclLoc = ND->getTypeSpecStartLoc();
22930b57cec5SDimitry Andric   const char *startBuf = SM->getCharacterData(DeclLoc);
22940b57cec5SDimitry Andric   if (ND->getInit()) {
22950b57cec5SDimitry Andric     std::string Name(ND->getNameAsString());
22960b57cec5SDimitry Andric     TypeAsString += " " + Name + " = ";
22970b57cec5SDimitry Andric     Expr *E = ND->getInit();
22980b57cec5SDimitry Andric     SourceLocation startLoc;
22990b57cec5SDimitry Andric     if (const CStyleCastExpr *ECE = dyn_cast<CStyleCastExpr>(E))
23000b57cec5SDimitry Andric       startLoc = ECE->getLParenLoc();
23010b57cec5SDimitry Andric     else
23020b57cec5SDimitry Andric       startLoc = E->getBeginLoc();
23030b57cec5SDimitry Andric     startLoc = SM->getExpansionLoc(startLoc);
23040b57cec5SDimitry Andric     const char *endBuf = SM->getCharacterData(startLoc);
23050b57cec5SDimitry Andric     ReplaceText(DeclLoc, endBuf-startBuf-1, TypeAsString);
23060b57cec5SDimitry Andric   }
23070b57cec5SDimitry Andric   else {
23080b57cec5SDimitry Andric     SourceLocation X = ND->getEndLoc();
23090b57cec5SDimitry Andric     X = SM->getExpansionLoc(X);
23100b57cec5SDimitry Andric     const char *endBuf = SM->getCharacterData(X);
23110b57cec5SDimitry Andric     ReplaceText(DeclLoc, endBuf-startBuf-1, TypeAsString);
23120b57cec5SDimitry Andric   }
23130b57cec5SDimitry Andric }
23140b57cec5SDimitry Andric 
23150b57cec5SDimitry Andric // SynthSelGetUidFunctionDecl - SEL sel_registerName(const char *str);
SynthSelGetUidFunctionDecl()23160b57cec5SDimitry Andric void RewriteModernObjC::SynthSelGetUidFunctionDecl() {
23170b57cec5SDimitry Andric   IdentifierInfo *SelGetUidIdent = &Context->Idents.get("sel_registerName");
23180b57cec5SDimitry Andric   SmallVector<QualType, 16> ArgTys;
23190b57cec5SDimitry Andric   ArgTys.push_back(Context->getPointerType(Context->CharTy.withConst()));
23200b57cec5SDimitry Andric   QualType getFuncType =
23210b57cec5SDimitry Andric     getSimpleFunctionType(Context->getObjCSelType(), ArgTys);
23220b57cec5SDimitry Andric   SelGetUidFunctionDecl = FunctionDecl::Create(*Context, TUDecl,
23230b57cec5SDimitry Andric                                                SourceLocation(),
23240b57cec5SDimitry Andric                                                SourceLocation(),
23250b57cec5SDimitry Andric                                                SelGetUidIdent, getFuncType,
23260b57cec5SDimitry Andric                                                nullptr, SC_Extern);
23270b57cec5SDimitry Andric }
23280b57cec5SDimitry Andric 
RewriteFunctionDecl(FunctionDecl * FD)23290b57cec5SDimitry Andric void RewriteModernObjC::RewriteFunctionDecl(FunctionDecl *FD) {
23300b57cec5SDimitry Andric   // declared in <objc/objc.h>
23310b57cec5SDimitry Andric   if (FD->getIdentifier() &&
23320b57cec5SDimitry Andric       FD->getName() == "sel_registerName") {
23330b57cec5SDimitry Andric     SelGetUidFunctionDecl = FD;
23340b57cec5SDimitry Andric     return;
23350b57cec5SDimitry Andric   }
23360b57cec5SDimitry Andric   RewriteObjCQualifiedInterfaceTypes(FD);
23370b57cec5SDimitry Andric }
23380b57cec5SDimitry Andric 
RewriteBlockPointerType(std::string & Str,QualType Type)23390b57cec5SDimitry Andric void RewriteModernObjC::RewriteBlockPointerType(std::string& Str, QualType Type) {
23400b57cec5SDimitry Andric   std::string TypeString(Type.getAsString(Context->getPrintingPolicy()));
23410b57cec5SDimitry Andric   const char *argPtr = TypeString.c_str();
23420b57cec5SDimitry Andric   if (!strchr(argPtr, '^')) {
23430b57cec5SDimitry Andric     Str += TypeString;
23440b57cec5SDimitry Andric     return;
23450b57cec5SDimitry Andric   }
23460b57cec5SDimitry Andric   while (*argPtr) {
23470b57cec5SDimitry Andric     Str += (*argPtr == '^' ? '*' : *argPtr);
23480b57cec5SDimitry Andric     argPtr++;
23490b57cec5SDimitry Andric   }
23500b57cec5SDimitry Andric }
23510b57cec5SDimitry Andric 
23520b57cec5SDimitry Andric // FIXME. Consolidate this routine with RewriteBlockPointerType.
RewriteBlockPointerTypeVariable(std::string & Str,ValueDecl * VD)23530b57cec5SDimitry Andric void RewriteModernObjC::RewriteBlockPointerTypeVariable(std::string& Str,
23540b57cec5SDimitry Andric                                                   ValueDecl *VD) {
23550b57cec5SDimitry Andric   QualType Type = VD->getType();
23560b57cec5SDimitry Andric   std::string TypeString(Type.getAsString(Context->getPrintingPolicy()));
23570b57cec5SDimitry Andric   const char *argPtr = TypeString.c_str();
23580b57cec5SDimitry Andric   int paren = 0;
23590b57cec5SDimitry Andric   while (*argPtr) {
23600b57cec5SDimitry Andric     switch (*argPtr) {
23610b57cec5SDimitry Andric       case '(':
23620b57cec5SDimitry Andric         Str += *argPtr;
23630b57cec5SDimitry Andric         paren++;
23640b57cec5SDimitry Andric         break;
23650b57cec5SDimitry Andric       case ')':
23660b57cec5SDimitry Andric         Str += *argPtr;
23670b57cec5SDimitry Andric         paren--;
23680b57cec5SDimitry Andric         break;
23690b57cec5SDimitry Andric       case '^':
23700b57cec5SDimitry Andric         Str += '*';
23710b57cec5SDimitry Andric         if (paren == 1)
23720b57cec5SDimitry Andric           Str += VD->getNameAsString();
23730b57cec5SDimitry Andric         break;
23740b57cec5SDimitry Andric       default:
23750b57cec5SDimitry Andric         Str += *argPtr;
23760b57cec5SDimitry Andric         break;
23770b57cec5SDimitry Andric     }
23780b57cec5SDimitry Andric     argPtr++;
23790b57cec5SDimitry Andric   }
23800b57cec5SDimitry Andric }
23810b57cec5SDimitry Andric 
RewriteBlockLiteralFunctionDecl(FunctionDecl * FD)23820b57cec5SDimitry Andric void RewriteModernObjC::RewriteBlockLiteralFunctionDecl(FunctionDecl *FD) {
23830b57cec5SDimitry Andric   SourceLocation FunLocStart = FD->getTypeSpecStartLoc();
23840b57cec5SDimitry Andric   const FunctionType *funcType = FD->getType()->getAs<FunctionType>();
23850b57cec5SDimitry Andric   const FunctionProtoType *proto = dyn_cast<FunctionProtoType>(funcType);
23860b57cec5SDimitry Andric   if (!proto)
23870b57cec5SDimitry Andric     return;
23880b57cec5SDimitry Andric   QualType Type = proto->getReturnType();
23890b57cec5SDimitry Andric   std::string FdStr = Type.getAsString(Context->getPrintingPolicy());
23900b57cec5SDimitry Andric   FdStr += " ";
23910b57cec5SDimitry Andric   FdStr += FD->getName();
23920b57cec5SDimitry Andric   FdStr +=  "(";
23930b57cec5SDimitry Andric   unsigned numArgs = proto->getNumParams();
23940b57cec5SDimitry Andric   for (unsigned i = 0; i < numArgs; i++) {
23950b57cec5SDimitry Andric     QualType ArgType = proto->getParamType(i);
23960b57cec5SDimitry Andric   RewriteBlockPointerType(FdStr, ArgType);
23970b57cec5SDimitry Andric   if (i+1 < numArgs)
23980b57cec5SDimitry Andric     FdStr += ", ";
23990b57cec5SDimitry Andric   }
24000b57cec5SDimitry Andric   if (FD->isVariadic()) {
24010b57cec5SDimitry Andric     FdStr +=  (numArgs > 0) ? ", ...);\n" : "...);\n";
24020b57cec5SDimitry Andric   }
24030b57cec5SDimitry Andric   else
24040b57cec5SDimitry Andric     FdStr +=  ");\n";
24050b57cec5SDimitry Andric   InsertText(FunLocStart, FdStr);
24060b57cec5SDimitry Andric }
24070b57cec5SDimitry Andric 
24080b57cec5SDimitry Andric // SynthSuperConstructorFunctionDecl - id __rw_objc_super(id obj, id super);
SynthSuperConstructorFunctionDecl()24090b57cec5SDimitry Andric void RewriteModernObjC::SynthSuperConstructorFunctionDecl() {
24100b57cec5SDimitry Andric   if (SuperConstructorFunctionDecl)
24110b57cec5SDimitry Andric     return;
24120b57cec5SDimitry Andric   IdentifierInfo *msgSendIdent = &Context->Idents.get("__rw_objc_super");
24130b57cec5SDimitry Andric   SmallVector<QualType, 16> ArgTys;
24140b57cec5SDimitry Andric   QualType argT = Context->getObjCIdType();
24150b57cec5SDimitry Andric   assert(!argT.isNull() && "Can't find 'id' type");
24160b57cec5SDimitry Andric   ArgTys.push_back(argT);
24170b57cec5SDimitry Andric   ArgTys.push_back(argT);
24180b57cec5SDimitry Andric   QualType msgSendType = getSimpleFunctionType(Context->getObjCIdType(),
24190b57cec5SDimitry Andric                                                ArgTys);
24200b57cec5SDimitry Andric   SuperConstructorFunctionDecl = FunctionDecl::Create(*Context, TUDecl,
24210b57cec5SDimitry Andric                                                      SourceLocation(),
24220b57cec5SDimitry Andric                                                      SourceLocation(),
24230b57cec5SDimitry Andric                                                      msgSendIdent, msgSendType,
24240b57cec5SDimitry Andric                                                      nullptr, SC_Extern);
24250b57cec5SDimitry Andric }
24260b57cec5SDimitry Andric 
24270b57cec5SDimitry Andric // SynthMsgSendFunctionDecl - id objc_msgSend(id self, SEL op, ...);
SynthMsgSendFunctionDecl()24280b57cec5SDimitry Andric void RewriteModernObjC::SynthMsgSendFunctionDecl() {
24290b57cec5SDimitry Andric   IdentifierInfo *msgSendIdent = &Context->Idents.get("objc_msgSend");
24300b57cec5SDimitry Andric   SmallVector<QualType, 16> ArgTys;
24310b57cec5SDimitry Andric   QualType argT = Context->getObjCIdType();
24320b57cec5SDimitry Andric   assert(!argT.isNull() && "Can't find 'id' type");
24330b57cec5SDimitry Andric   ArgTys.push_back(argT);
24340b57cec5SDimitry Andric   argT = Context->getObjCSelType();
24350b57cec5SDimitry Andric   assert(!argT.isNull() && "Can't find 'SEL' type");
24360b57cec5SDimitry Andric   ArgTys.push_back(argT);
24370b57cec5SDimitry Andric   QualType msgSendType = getSimpleFunctionType(Context->getObjCIdType(),
24380b57cec5SDimitry Andric                                                ArgTys, /*variadic=*/true);
24390b57cec5SDimitry Andric   MsgSendFunctionDecl = FunctionDecl::Create(*Context, TUDecl,
24400b57cec5SDimitry Andric                                              SourceLocation(),
24410b57cec5SDimitry Andric                                              SourceLocation(),
24420b57cec5SDimitry Andric                                              msgSendIdent, msgSendType, nullptr,
24430b57cec5SDimitry Andric                                              SC_Extern);
24440b57cec5SDimitry Andric }
24450b57cec5SDimitry Andric 
24460b57cec5SDimitry Andric // SynthMsgSendSuperFunctionDecl - id objc_msgSendSuper(void);
SynthMsgSendSuperFunctionDecl()24470b57cec5SDimitry Andric void RewriteModernObjC::SynthMsgSendSuperFunctionDecl() {
24480b57cec5SDimitry Andric   IdentifierInfo *msgSendIdent = &Context->Idents.get("objc_msgSendSuper");
24490b57cec5SDimitry Andric   SmallVector<QualType, 2> ArgTys;
24500b57cec5SDimitry Andric   ArgTys.push_back(Context->VoidTy);
24510b57cec5SDimitry Andric   QualType msgSendType = getSimpleFunctionType(Context->getObjCIdType(),
24520b57cec5SDimitry Andric                                                ArgTys, /*variadic=*/true);
24530b57cec5SDimitry Andric   MsgSendSuperFunctionDecl = FunctionDecl::Create(*Context, TUDecl,
24540b57cec5SDimitry Andric                                                   SourceLocation(),
24550b57cec5SDimitry Andric                                                   SourceLocation(),
24560b57cec5SDimitry Andric                                                   msgSendIdent, msgSendType,
24570b57cec5SDimitry Andric                                                   nullptr, SC_Extern);
24580b57cec5SDimitry Andric }
24590b57cec5SDimitry Andric 
24600b57cec5SDimitry Andric // SynthMsgSendStretFunctionDecl - id objc_msgSend_stret(id self, SEL op, ...);
SynthMsgSendStretFunctionDecl()24610b57cec5SDimitry Andric void RewriteModernObjC::SynthMsgSendStretFunctionDecl() {
24620b57cec5SDimitry Andric   IdentifierInfo *msgSendIdent = &Context->Idents.get("objc_msgSend_stret");
24630b57cec5SDimitry Andric   SmallVector<QualType, 16> ArgTys;
24640b57cec5SDimitry Andric   QualType argT = Context->getObjCIdType();
24650b57cec5SDimitry Andric   assert(!argT.isNull() && "Can't find 'id' type");
24660b57cec5SDimitry Andric   ArgTys.push_back(argT);
24670b57cec5SDimitry Andric   argT = Context->getObjCSelType();
24680b57cec5SDimitry Andric   assert(!argT.isNull() && "Can't find 'SEL' type");
24690b57cec5SDimitry Andric   ArgTys.push_back(argT);
24700b57cec5SDimitry Andric   QualType msgSendType = getSimpleFunctionType(Context->getObjCIdType(),
24710b57cec5SDimitry Andric                                                ArgTys, /*variadic=*/true);
24720b57cec5SDimitry Andric   MsgSendStretFunctionDecl = FunctionDecl::Create(*Context, TUDecl,
24730b57cec5SDimitry Andric                                                   SourceLocation(),
24740b57cec5SDimitry Andric                                                   SourceLocation(),
24750b57cec5SDimitry Andric                                                   msgSendIdent, msgSendType,
24760b57cec5SDimitry Andric                                                   nullptr, SC_Extern);
24770b57cec5SDimitry Andric }
24780b57cec5SDimitry Andric 
24790b57cec5SDimitry Andric // SynthMsgSendSuperStretFunctionDecl -
24800b57cec5SDimitry Andric // id objc_msgSendSuper_stret(void);
SynthMsgSendSuperStretFunctionDecl()24810b57cec5SDimitry Andric void RewriteModernObjC::SynthMsgSendSuperStretFunctionDecl() {
24820b57cec5SDimitry Andric   IdentifierInfo *msgSendIdent =
24830b57cec5SDimitry Andric     &Context->Idents.get("objc_msgSendSuper_stret");
24840b57cec5SDimitry Andric   SmallVector<QualType, 2> ArgTys;
24850b57cec5SDimitry Andric   ArgTys.push_back(Context->VoidTy);
24860b57cec5SDimitry Andric   QualType msgSendType = getSimpleFunctionType(Context->getObjCIdType(),
24870b57cec5SDimitry Andric                                                ArgTys, /*variadic=*/true);
24880b57cec5SDimitry Andric   MsgSendSuperStretFunctionDecl = FunctionDecl::Create(*Context, TUDecl,
24890b57cec5SDimitry Andric                                                        SourceLocation(),
24900b57cec5SDimitry Andric                                                        SourceLocation(),
24910b57cec5SDimitry Andric                                                        msgSendIdent,
24920b57cec5SDimitry Andric                                                        msgSendType, nullptr,
24930b57cec5SDimitry Andric                                                        SC_Extern);
24940b57cec5SDimitry Andric }
24950b57cec5SDimitry Andric 
24960b57cec5SDimitry Andric // SynthMsgSendFpretFunctionDecl - double objc_msgSend_fpret(id self, SEL op, ...);
SynthMsgSendFpretFunctionDecl()24970b57cec5SDimitry Andric void RewriteModernObjC::SynthMsgSendFpretFunctionDecl() {
24980b57cec5SDimitry Andric   IdentifierInfo *msgSendIdent = &Context->Idents.get("objc_msgSend_fpret");
24990b57cec5SDimitry Andric   SmallVector<QualType, 16> ArgTys;
25000b57cec5SDimitry Andric   QualType argT = Context->getObjCIdType();
25010b57cec5SDimitry Andric   assert(!argT.isNull() && "Can't find 'id' type");
25020b57cec5SDimitry Andric   ArgTys.push_back(argT);
25030b57cec5SDimitry Andric   argT = Context->getObjCSelType();
25040b57cec5SDimitry Andric   assert(!argT.isNull() && "Can't find 'SEL' type");
25050b57cec5SDimitry Andric   ArgTys.push_back(argT);
25060b57cec5SDimitry Andric   QualType msgSendType = getSimpleFunctionType(Context->DoubleTy,
25070b57cec5SDimitry Andric                                                ArgTys, /*variadic=*/true);
25080b57cec5SDimitry Andric   MsgSendFpretFunctionDecl = FunctionDecl::Create(*Context, TUDecl,
25090b57cec5SDimitry Andric                                                   SourceLocation(),
25100b57cec5SDimitry Andric                                                   SourceLocation(),
25110b57cec5SDimitry Andric                                                   msgSendIdent, msgSendType,
25120b57cec5SDimitry Andric                                                   nullptr, SC_Extern);
25130b57cec5SDimitry Andric }
25140b57cec5SDimitry Andric 
25150b57cec5SDimitry Andric // SynthGetClassFunctionDecl - Class objc_getClass(const char *name);
SynthGetClassFunctionDecl()25160b57cec5SDimitry Andric void RewriteModernObjC::SynthGetClassFunctionDecl() {
25170b57cec5SDimitry Andric   IdentifierInfo *getClassIdent = &Context->Idents.get("objc_getClass");
25180b57cec5SDimitry Andric   SmallVector<QualType, 16> ArgTys;
25190b57cec5SDimitry Andric   ArgTys.push_back(Context->getPointerType(Context->CharTy.withConst()));
25200b57cec5SDimitry Andric   QualType getClassType = getSimpleFunctionType(Context->getObjCClassType(),
25210b57cec5SDimitry Andric                                                 ArgTys);
25220b57cec5SDimitry Andric   GetClassFunctionDecl = FunctionDecl::Create(*Context, TUDecl,
25230b57cec5SDimitry Andric                                               SourceLocation(),
25240b57cec5SDimitry Andric                                               SourceLocation(),
25250b57cec5SDimitry Andric                                               getClassIdent, getClassType,
25260b57cec5SDimitry Andric                                               nullptr, SC_Extern);
25270b57cec5SDimitry Andric }
25280b57cec5SDimitry Andric 
25290b57cec5SDimitry Andric // SynthGetSuperClassFunctionDecl - Class class_getSuperclass(Class cls);
SynthGetSuperClassFunctionDecl()25300b57cec5SDimitry Andric void RewriteModernObjC::SynthGetSuperClassFunctionDecl() {
25310b57cec5SDimitry Andric   IdentifierInfo *getSuperClassIdent =
25320b57cec5SDimitry Andric     &Context->Idents.get("class_getSuperclass");
25330b57cec5SDimitry Andric   SmallVector<QualType, 16> ArgTys;
25340b57cec5SDimitry Andric   ArgTys.push_back(Context->getObjCClassType());
25350b57cec5SDimitry Andric   QualType getClassType = getSimpleFunctionType(Context->getObjCClassType(),
25360b57cec5SDimitry Andric                                                 ArgTys);
25370b57cec5SDimitry Andric   GetSuperClassFunctionDecl = FunctionDecl::Create(*Context, TUDecl,
25380b57cec5SDimitry Andric                                                    SourceLocation(),
25390b57cec5SDimitry Andric                                                    SourceLocation(),
25400b57cec5SDimitry Andric                                                    getSuperClassIdent,
25410b57cec5SDimitry Andric                                                    getClassType, nullptr,
25420b57cec5SDimitry Andric                                                    SC_Extern);
25430b57cec5SDimitry Andric }
25440b57cec5SDimitry Andric 
25450b57cec5SDimitry Andric // SynthGetMetaClassFunctionDecl - Class objc_getMetaClass(const char *name);
SynthGetMetaClassFunctionDecl()25460b57cec5SDimitry Andric void RewriteModernObjC::SynthGetMetaClassFunctionDecl() {
25470b57cec5SDimitry Andric   IdentifierInfo *getClassIdent = &Context->Idents.get("objc_getMetaClass");
25480b57cec5SDimitry Andric   SmallVector<QualType, 16> ArgTys;
25490b57cec5SDimitry Andric   ArgTys.push_back(Context->getPointerType(Context->CharTy.withConst()));
25500b57cec5SDimitry Andric   QualType getClassType = getSimpleFunctionType(Context->getObjCClassType(),
25510b57cec5SDimitry Andric                                                 ArgTys);
25520b57cec5SDimitry Andric   GetMetaClassFunctionDecl = FunctionDecl::Create(*Context, TUDecl,
25530b57cec5SDimitry Andric                                                   SourceLocation(),
25540b57cec5SDimitry Andric                                                   SourceLocation(),
25550b57cec5SDimitry Andric                                                   getClassIdent, getClassType,
25560b57cec5SDimitry Andric                                                   nullptr, SC_Extern);
25570b57cec5SDimitry Andric }
25580b57cec5SDimitry Andric 
RewriteObjCStringLiteral(ObjCStringLiteral * Exp)25590b57cec5SDimitry Andric Stmt *RewriteModernObjC::RewriteObjCStringLiteral(ObjCStringLiteral *Exp) {
25600b57cec5SDimitry Andric   assert (Exp != nullptr && "Expected non-null ObjCStringLiteral");
25610b57cec5SDimitry Andric   QualType strType = getConstantStringStructType();
25620b57cec5SDimitry Andric 
25630b57cec5SDimitry Andric   std::string S = "__NSConstantStringImpl_";
25640b57cec5SDimitry Andric 
25650b57cec5SDimitry Andric   std::string tmpName = InFileName;
25660b57cec5SDimitry Andric   unsigned i;
25670b57cec5SDimitry Andric   for (i=0; i < tmpName.length(); i++) {
25680b57cec5SDimitry Andric     char c = tmpName.at(i);
25690b57cec5SDimitry Andric     // replace any non-alphanumeric characters with '_'.
25700b57cec5SDimitry Andric     if (!isAlphanumeric(c))
25710b57cec5SDimitry Andric       tmpName[i] = '_';
25720b57cec5SDimitry Andric   }
25730b57cec5SDimitry Andric   S += tmpName;
25740b57cec5SDimitry Andric   S += "_";
25750b57cec5SDimitry Andric   S += utostr(NumObjCStringLiterals++);
25760b57cec5SDimitry Andric 
25770b57cec5SDimitry Andric   Preamble += "static __NSConstantStringImpl " + S;
25780b57cec5SDimitry Andric   Preamble += " __attribute__ ((section (\"__DATA, __cfstring\"))) = {__CFConstantStringClassReference,";
25790b57cec5SDimitry Andric   Preamble += "0x000007c8,"; // utf8_str
25800b57cec5SDimitry Andric   // The pretty printer for StringLiteral handles escape characters properly.
25810b57cec5SDimitry Andric   std::string prettyBufS;
25820b57cec5SDimitry Andric   llvm::raw_string_ostream prettyBuf(prettyBufS);
25830b57cec5SDimitry Andric   Exp->getString()->printPretty(prettyBuf, nullptr, PrintingPolicy(LangOpts));
25840b57cec5SDimitry Andric   Preamble += prettyBuf.str();
25850b57cec5SDimitry Andric   Preamble += ",";
25860b57cec5SDimitry Andric   Preamble += utostr(Exp->getString()->getByteLength()) + "};\n";
25870b57cec5SDimitry Andric 
25880b57cec5SDimitry Andric   VarDecl *NewVD = VarDecl::Create(*Context, TUDecl, SourceLocation(),
25890b57cec5SDimitry Andric                                    SourceLocation(), &Context->Idents.get(S),
25900b57cec5SDimitry Andric                                    strType, nullptr, SC_Static);
25910b57cec5SDimitry Andric   DeclRefExpr *DRE = new (Context)
25920b57cec5SDimitry Andric       DeclRefExpr(*Context, NewVD, false, strType, VK_LValue, SourceLocation());
25935ffd83dbSDimitry Andric   Expr *Unop = UnaryOperator::Create(
25945ffd83dbSDimitry Andric       const_cast<ASTContext &>(*Context), DRE, UO_AddrOf,
2595fe6060f1SDimitry Andric       Context->getPointerType(DRE->getType()), VK_PRValue, OK_Ordinary,
25965ffd83dbSDimitry Andric       SourceLocation(), false, FPOptionsOverride());
25970b57cec5SDimitry Andric   // cast to NSConstantString *
25980b57cec5SDimitry Andric   CastExpr *cast = NoTypeInfoCStyleCastExpr(Context, Exp->getType(),
25990b57cec5SDimitry Andric                                             CK_CPointerToObjCPointerCast, Unop);
26000b57cec5SDimitry Andric   ReplaceStmt(Exp, cast);
26010b57cec5SDimitry Andric   // delete Exp; leak for now, see RewritePropertyOrImplicitSetter() usage for more info.
26020b57cec5SDimitry Andric   return cast;
26030b57cec5SDimitry Andric }
26040b57cec5SDimitry Andric 
RewriteObjCBoolLiteralExpr(ObjCBoolLiteralExpr * Exp)26050b57cec5SDimitry Andric Stmt *RewriteModernObjC::RewriteObjCBoolLiteralExpr(ObjCBoolLiteralExpr *Exp) {
26060b57cec5SDimitry Andric   unsigned IntSize =
26070b57cec5SDimitry Andric     static_cast<unsigned>(Context->getTypeSize(Context->IntTy));
26080b57cec5SDimitry Andric 
26090b57cec5SDimitry Andric   Expr *FlagExp = IntegerLiteral::Create(*Context,
26100b57cec5SDimitry Andric                                          llvm::APInt(IntSize, Exp->getValue()),
26110b57cec5SDimitry Andric                                          Context->IntTy, Exp->getLocation());
26120b57cec5SDimitry Andric   CastExpr *cast = NoTypeInfoCStyleCastExpr(Context, Context->ObjCBuiltinBoolTy,
26130b57cec5SDimitry Andric                                             CK_BitCast, FlagExp);
26140b57cec5SDimitry Andric   ParenExpr *PE = new (Context) ParenExpr(Exp->getLocation(), Exp->getExprLoc(),
26150b57cec5SDimitry Andric                                           cast);
26160b57cec5SDimitry Andric   ReplaceStmt(Exp, PE);
26170b57cec5SDimitry Andric   return PE;
26180b57cec5SDimitry Andric }
26190b57cec5SDimitry Andric 
RewriteObjCBoxedExpr(ObjCBoxedExpr * Exp)26200b57cec5SDimitry Andric Stmt *RewriteModernObjC::RewriteObjCBoxedExpr(ObjCBoxedExpr *Exp) {
26210b57cec5SDimitry Andric   // synthesize declaration of helper functions needed in this routine.
26220b57cec5SDimitry Andric   if (!SelGetUidFunctionDecl)
26230b57cec5SDimitry Andric     SynthSelGetUidFunctionDecl();
26240b57cec5SDimitry Andric   // use objc_msgSend() for all.
26250b57cec5SDimitry Andric   if (!MsgSendFunctionDecl)
26260b57cec5SDimitry Andric     SynthMsgSendFunctionDecl();
26270b57cec5SDimitry Andric   if (!GetClassFunctionDecl)
26280b57cec5SDimitry Andric     SynthGetClassFunctionDecl();
26290b57cec5SDimitry Andric 
26300b57cec5SDimitry Andric   FunctionDecl *MsgSendFlavor = MsgSendFunctionDecl;
26310b57cec5SDimitry Andric   SourceLocation StartLoc = Exp->getBeginLoc();
26320b57cec5SDimitry Andric   SourceLocation EndLoc = Exp->getEndLoc();
26330b57cec5SDimitry Andric 
26340b57cec5SDimitry Andric   // Synthesize a call to objc_msgSend().
26350b57cec5SDimitry Andric   SmallVector<Expr*, 4> MsgExprs;
26360b57cec5SDimitry Andric   SmallVector<Expr*, 4> ClsExprs;
26370b57cec5SDimitry Andric 
26380b57cec5SDimitry Andric   // Create a call to objc_getClass("<BoxingClass>"). It will be the 1st argument.
26390b57cec5SDimitry Andric   ObjCMethodDecl *BoxingMethod = Exp->getBoxingMethod();
26400b57cec5SDimitry Andric   ObjCInterfaceDecl *BoxingClass = BoxingMethod->getClassInterface();
26410b57cec5SDimitry Andric 
26420b57cec5SDimitry Andric   IdentifierInfo *clsName = BoxingClass->getIdentifier();
26430b57cec5SDimitry Andric   ClsExprs.push_back(getStringLiteral(clsName->getName()));
26440b57cec5SDimitry Andric   CallExpr *Cls = SynthesizeCallToFunctionDecl(GetClassFunctionDecl, ClsExprs,
26450b57cec5SDimitry Andric                                                StartLoc, EndLoc);
26460b57cec5SDimitry Andric   MsgExprs.push_back(Cls);
26470b57cec5SDimitry Andric 
26480b57cec5SDimitry Andric   // Create a call to sel_registerName("<BoxingMethod>:"), etc.
26490b57cec5SDimitry Andric   // it will be the 2nd argument.
26500b57cec5SDimitry Andric   SmallVector<Expr*, 4> SelExprs;
26510b57cec5SDimitry Andric   SelExprs.push_back(
26520b57cec5SDimitry Andric       getStringLiteral(BoxingMethod->getSelector().getAsString()));
26530b57cec5SDimitry Andric   CallExpr *SelExp = SynthesizeCallToFunctionDecl(SelGetUidFunctionDecl,
26540b57cec5SDimitry Andric                                                   SelExprs, StartLoc, EndLoc);
26550b57cec5SDimitry Andric   MsgExprs.push_back(SelExp);
26560b57cec5SDimitry Andric 
26570b57cec5SDimitry Andric   // User provided sub-expression is the 3rd, and last, argument.
26580b57cec5SDimitry Andric   Expr *subExpr  = Exp->getSubExpr();
26590b57cec5SDimitry Andric   if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(subExpr)) {
26600b57cec5SDimitry Andric     QualType type = ICE->getType();
26610b57cec5SDimitry Andric     const Expr *SubExpr = ICE->IgnoreParenImpCasts();
26620b57cec5SDimitry Andric     CastKind CK = CK_BitCast;
26630b57cec5SDimitry Andric     if (SubExpr->getType()->isIntegralType(*Context) && type->isBooleanType())
26640b57cec5SDimitry Andric       CK = CK_IntegralToBoolean;
26650b57cec5SDimitry Andric     subExpr = NoTypeInfoCStyleCastExpr(Context, type, CK, subExpr);
26660b57cec5SDimitry Andric   }
26670b57cec5SDimitry Andric   MsgExprs.push_back(subExpr);
26680b57cec5SDimitry Andric 
26690b57cec5SDimitry Andric   SmallVector<QualType, 4> ArgTypes;
26700b57cec5SDimitry Andric   ArgTypes.push_back(Context->getObjCClassType());
26710b57cec5SDimitry Andric   ArgTypes.push_back(Context->getObjCSelType());
26720b57cec5SDimitry Andric   for (const auto PI : BoxingMethod->parameters())
26730b57cec5SDimitry Andric     ArgTypes.push_back(PI->getType());
26740b57cec5SDimitry Andric 
26750b57cec5SDimitry Andric   QualType returnType = Exp->getType();
26760b57cec5SDimitry Andric   // Get the type, we will need to reference it in a couple spots.
26770b57cec5SDimitry Andric   QualType msgSendType = MsgSendFlavor->getType();
26780b57cec5SDimitry Andric 
26790b57cec5SDimitry Andric   // Create a reference to the objc_msgSend() declaration.
26800b57cec5SDimitry Andric   DeclRefExpr *DRE = new (Context) DeclRefExpr(
26810b57cec5SDimitry Andric       *Context, MsgSendFlavor, false, msgSendType, VK_LValue, SourceLocation());
26820b57cec5SDimitry Andric 
26830b57cec5SDimitry Andric   CastExpr *cast = NoTypeInfoCStyleCastExpr(
26840b57cec5SDimitry Andric       Context, Context->getPointerType(Context->VoidTy), CK_BitCast, DRE);
26850b57cec5SDimitry Andric 
26860b57cec5SDimitry Andric   // Now do the "normal" pointer to function cast.
26870b57cec5SDimitry Andric   QualType castType =
26880b57cec5SDimitry Andric     getSimpleFunctionType(returnType, ArgTypes, BoxingMethod->isVariadic());
26890b57cec5SDimitry Andric   castType = Context->getPointerType(castType);
26900b57cec5SDimitry Andric   cast = NoTypeInfoCStyleCastExpr(Context, castType, CK_BitCast,
26910b57cec5SDimitry Andric                                   cast);
26920b57cec5SDimitry Andric 
26930b57cec5SDimitry Andric   // Don't forget the parens to enforce the proper binding.
26940b57cec5SDimitry Andric   ParenExpr *PE = new (Context) ParenExpr(StartLoc, EndLoc, cast);
26950b57cec5SDimitry Andric 
26965ffd83dbSDimitry Andric   auto *FT = msgSendType->castAs<FunctionType>();
26970b57cec5SDimitry Andric   CallExpr *CE = CallExpr::Create(*Context, PE, MsgExprs, FT->getReturnType(),
2698fe6060f1SDimitry Andric                                   VK_PRValue, EndLoc, FPOptionsOverride());
26990b57cec5SDimitry Andric   ReplaceStmt(Exp, CE);
27000b57cec5SDimitry Andric   return CE;
27010b57cec5SDimitry Andric }
27020b57cec5SDimitry Andric 
RewriteObjCArrayLiteralExpr(ObjCArrayLiteral * Exp)27030b57cec5SDimitry Andric Stmt *RewriteModernObjC::RewriteObjCArrayLiteralExpr(ObjCArrayLiteral *Exp) {
27040b57cec5SDimitry Andric   // synthesize declaration of helper functions needed in this routine.
27050b57cec5SDimitry Andric   if (!SelGetUidFunctionDecl)
27060b57cec5SDimitry Andric     SynthSelGetUidFunctionDecl();
27070b57cec5SDimitry Andric   // use objc_msgSend() for all.
27080b57cec5SDimitry Andric   if (!MsgSendFunctionDecl)
27090b57cec5SDimitry Andric     SynthMsgSendFunctionDecl();
27100b57cec5SDimitry Andric   if (!GetClassFunctionDecl)
27110b57cec5SDimitry Andric     SynthGetClassFunctionDecl();
27120b57cec5SDimitry Andric 
27130b57cec5SDimitry Andric   FunctionDecl *MsgSendFlavor = MsgSendFunctionDecl;
27140b57cec5SDimitry Andric   SourceLocation StartLoc = Exp->getBeginLoc();
27150b57cec5SDimitry Andric   SourceLocation EndLoc = Exp->getEndLoc();
27160b57cec5SDimitry Andric 
27170b57cec5SDimitry Andric   // Build the expression: __NSContainer_literal(int, ...).arr
27180b57cec5SDimitry Andric   QualType IntQT = Context->IntTy;
27190b57cec5SDimitry Andric   QualType NSArrayFType =
27200b57cec5SDimitry Andric     getSimpleFunctionType(Context->VoidTy, IntQT, true);
27210b57cec5SDimitry Andric   std::string NSArrayFName("__NSContainer_literal");
27220b57cec5SDimitry Andric   FunctionDecl *NSArrayFD = SynthBlockInitFunctionDecl(NSArrayFName);
27230b57cec5SDimitry Andric   DeclRefExpr *NSArrayDRE = new (Context) DeclRefExpr(
2724fe6060f1SDimitry Andric       *Context, NSArrayFD, false, NSArrayFType, VK_PRValue, SourceLocation());
27250b57cec5SDimitry Andric 
27260b57cec5SDimitry Andric   SmallVector<Expr*, 16> InitExprs;
27270b57cec5SDimitry Andric   unsigned NumElements = Exp->getNumElements();
27280b57cec5SDimitry Andric   unsigned UnsignedIntSize =
27290b57cec5SDimitry Andric     static_cast<unsigned>(Context->getTypeSize(Context->UnsignedIntTy));
27300b57cec5SDimitry Andric   Expr *count = IntegerLiteral::Create(*Context,
27310b57cec5SDimitry Andric                                        llvm::APInt(UnsignedIntSize, NumElements),
27320b57cec5SDimitry Andric                                        Context->UnsignedIntTy, SourceLocation());
27330b57cec5SDimitry Andric   InitExprs.push_back(count);
27340b57cec5SDimitry Andric   for (unsigned i = 0; i < NumElements; i++)
27350b57cec5SDimitry Andric     InitExprs.push_back(Exp->getElement(i));
27360b57cec5SDimitry Andric   Expr *NSArrayCallExpr =
27370b57cec5SDimitry Andric       CallExpr::Create(*Context, NSArrayDRE, InitExprs, NSArrayFType, VK_LValue,
2738e8d8bef9SDimitry Andric                        SourceLocation(), FPOptionsOverride());
27390b57cec5SDimitry Andric 
27400b57cec5SDimitry Andric   FieldDecl *ARRFD = FieldDecl::Create(*Context, nullptr, SourceLocation(),
27410b57cec5SDimitry Andric                                     SourceLocation(),
27420b57cec5SDimitry Andric                                     &Context->Idents.get("arr"),
27430b57cec5SDimitry Andric                                     Context->getPointerType(Context->VoidPtrTy),
27440b57cec5SDimitry Andric                                     nullptr, /*BitWidth=*/nullptr,
27450b57cec5SDimitry Andric                                     /*Mutable=*/true, ICIS_NoInit);
27460b57cec5SDimitry Andric   MemberExpr *ArrayLiteralME =
27470b57cec5SDimitry Andric       MemberExpr::CreateImplicit(*Context, NSArrayCallExpr, false, ARRFD,
27480b57cec5SDimitry Andric                                  ARRFD->getType(), VK_LValue, OK_Ordinary);
27490b57cec5SDimitry Andric   QualType ConstIdT = Context->getObjCIdType().withConst();
27500b57cec5SDimitry Andric   CStyleCastExpr * ArrayLiteralObjects =
27510b57cec5SDimitry Andric     NoTypeInfoCStyleCastExpr(Context,
27520b57cec5SDimitry Andric                              Context->getPointerType(ConstIdT),
27530b57cec5SDimitry Andric                              CK_BitCast,
27540b57cec5SDimitry Andric                              ArrayLiteralME);
27550b57cec5SDimitry Andric 
27560b57cec5SDimitry Andric   // Synthesize a call to objc_msgSend().
27570b57cec5SDimitry Andric   SmallVector<Expr*, 32> MsgExprs;
27580b57cec5SDimitry Andric   SmallVector<Expr*, 4> ClsExprs;
27590b57cec5SDimitry Andric   QualType expType = Exp->getType();
27600b57cec5SDimitry Andric 
27610b57cec5SDimitry Andric   // Create a call to objc_getClass("NSArray"). It will be th 1st argument.
27620b57cec5SDimitry Andric   ObjCInterfaceDecl *Class =
2763a7dea167SDimitry Andric     expType->getPointeeType()->castAs<ObjCObjectType>()->getInterface();
27640b57cec5SDimitry Andric 
27650b57cec5SDimitry Andric   IdentifierInfo *clsName = Class->getIdentifier();
27660b57cec5SDimitry Andric   ClsExprs.push_back(getStringLiteral(clsName->getName()));
27670b57cec5SDimitry Andric   CallExpr *Cls = SynthesizeCallToFunctionDecl(GetClassFunctionDecl, ClsExprs,
27680b57cec5SDimitry Andric                                                StartLoc, EndLoc);
27690b57cec5SDimitry Andric   MsgExprs.push_back(Cls);
27700b57cec5SDimitry Andric 
27710b57cec5SDimitry Andric   // Create a call to sel_registerName("arrayWithObjects:count:").
27720b57cec5SDimitry Andric   // it will be the 2nd argument.
27730b57cec5SDimitry Andric   SmallVector<Expr*, 4> SelExprs;
27740b57cec5SDimitry Andric   ObjCMethodDecl *ArrayMethod = Exp->getArrayWithObjectsMethod();
27750b57cec5SDimitry Andric   SelExprs.push_back(
27760b57cec5SDimitry Andric       getStringLiteral(ArrayMethod->getSelector().getAsString()));
27770b57cec5SDimitry Andric   CallExpr *SelExp = SynthesizeCallToFunctionDecl(SelGetUidFunctionDecl,
27780b57cec5SDimitry Andric                                                   SelExprs, StartLoc, EndLoc);
27790b57cec5SDimitry Andric   MsgExprs.push_back(SelExp);
27800b57cec5SDimitry Andric 
27810b57cec5SDimitry Andric   // (const id [])objects
27820b57cec5SDimitry Andric   MsgExprs.push_back(ArrayLiteralObjects);
27830b57cec5SDimitry Andric 
27840b57cec5SDimitry Andric   // (NSUInteger)cnt
27850b57cec5SDimitry Andric   Expr *cnt = IntegerLiteral::Create(*Context,
27860b57cec5SDimitry Andric                                      llvm::APInt(UnsignedIntSize, NumElements),
27870b57cec5SDimitry Andric                                      Context->UnsignedIntTy, SourceLocation());
27880b57cec5SDimitry Andric   MsgExprs.push_back(cnt);
27890b57cec5SDimitry Andric 
27900b57cec5SDimitry Andric   SmallVector<QualType, 4> ArgTypes;
27910b57cec5SDimitry Andric   ArgTypes.push_back(Context->getObjCClassType());
27920b57cec5SDimitry Andric   ArgTypes.push_back(Context->getObjCSelType());
27930b57cec5SDimitry Andric   for (const auto *PI : ArrayMethod->parameters())
27940b57cec5SDimitry Andric     ArgTypes.push_back(PI->getType());
27950b57cec5SDimitry Andric 
27960b57cec5SDimitry Andric   QualType returnType = Exp->getType();
27970b57cec5SDimitry Andric   // Get the type, we will need to reference it in a couple spots.
27980b57cec5SDimitry Andric   QualType msgSendType = MsgSendFlavor->getType();
27990b57cec5SDimitry Andric 
28000b57cec5SDimitry Andric   // Create a reference to the objc_msgSend() declaration.
28010b57cec5SDimitry Andric   DeclRefExpr *DRE = new (Context) DeclRefExpr(
28020b57cec5SDimitry Andric       *Context, MsgSendFlavor, false, msgSendType, VK_LValue, SourceLocation());
28030b57cec5SDimitry Andric 
28040b57cec5SDimitry Andric   CastExpr *cast = NoTypeInfoCStyleCastExpr(
28050b57cec5SDimitry Andric       Context, Context->getPointerType(Context->VoidTy), CK_BitCast, DRE);
28060b57cec5SDimitry Andric 
28070b57cec5SDimitry Andric   // Now do the "normal" pointer to function cast.
28080b57cec5SDimitry Andric   QualType castType =
28090b57cec5SDimitry Andric   getSimpleFunctionType(returnType, ArgTypes, ArrayMethod->isVariadic());
28100b57cec5SDimitry Andric   castType = Context->getPointerType(castType);
28110b57cec5SDimitry Andric   cast = NoTypeInfoCStyleCastExpr(Context, castType, CK_BitCast,
28120b57cec5SDimitry Andric                                   cast);
28130b57cec5SDimitry Andric 
28140b57cec5SDimitry Andric   // Don't forget the parens to enforce the proper binding.
28150b57cec5SDimitry Andric   ParenExpr *PE = new (Context) ParenExpr(StartLoc, EndLoc, cast);
28160b57cec5SDimitry Andric 
2817a7dea167SDimitry Andric   const FunctionType *FT = msgSendType->castAs<FunctionType>();
28180b57cec5SDimitry Andric   CallExpr *CE = CallExpr::Create(*Context, PE, MsgExprs, FT->getReturnType(),
2819fe6060f1SDimitry Andric                                   VK_PRValue, EndLoc, FPOptionsOverride());
28200b57cec5SDimitry Andric   ReplaceStmt(Exp, CE);
28210b57cec5SDimitry Andric   return CE;
28220b57cec5SDimitry Andric }
28230b57cec5SDimitry Andric 
RewriteObjCDictionaryLiteralExpr(ObjCDictionaryLiteral * Exp)28240b57cec5SDimitry Andric Stmt *RewriteModernObjC::RewriteObjCDictionaryLiteralExpr(ObjCDictionaryLiteral *Exp) {
28250b57cec5SDimitry Andric   // synthesize declaration of helper functions needed in this routine.
28260b57cec5SDimitry Andric   if (!SelGetUidFunctionDecl)
28270b57cec5SDimitry Andric     SynthSelGetUidFunctionDecl();
28280b57cec5SDimitry Andric   // use objc_msgSend() for all.
28290b57cec5SDimitry Andric   if (!MsgSendFunctionDecl)
28300b57cec5SDimitry Andric     SynthMsgSendFunctionDecl();
28310b57cec5SDimitry Andric   if (!GetClassFunctionDecl)
28320b57cec5SDimitry Andric     SynthGetClassFunctionDecl();
28330b57cec5SDimitry Andric 
28340b57cec5SDimitry Andric   FunctionDecl *MsgSendFlavor = MsgSendFunctionDecl;
28350b57cec5SDimitry Andric   SourceLocation StartLoc = Exp->getBeginLoc();
28360b57cec5SDimitry Andric   SourceLocation EndLoc = Exp->getEndLoc();
28370b57cec5SDimitry Andric 
28380b57cec5SDimitry Andric   // Build the expression: __NSContainer_literal(int, ...).arr
28390b57cec5SDimitry Andric   QualType IntQT = Context->IntTy;
28400b57cec5SDimitry Andric   QualType NSDictFType =
28410b57cec5SDimitry Andric     getSimpleFunctionType(Context->VoidTy, IntQT, true);
28420b57cec5SDimitry Andric   std::string NSDictFName("__NSContainer_literal");
28430b57cec5SDimitry Andric   FunctionDecl *NSDictFD = SynthBlockInitFunctionDecl(NSDictFName);
28440b57cec5SDimitry Andric   DeclRefExpr *NSDictDRE = new (Context) DeclRefExpr(
2845fe6060f1SDimitry Andric       *Context, NSDictFD, false, NSDictFType, VK_PRValue, SourceLocation());
28460b57cec5SDimitry Andric 
28470b57cec5SDimitry Andric   SmallVector<Expr*, 16> KeyExprs;
28480b57cec5SDimitry Andric   SmallVector<Expr*, 16> ValueExprs;
28490b57cec5SDimitry Andric 
28500b57cec5SDimitry Andric   unsigned NumElements = Exp->getNumElements();
28510b57cec5SDimitry Andric   unsigned UnsignedIntSize =
28520b57cec5SDimitry Andric     static_cast<unsigned>(Context->getTypeSize(Context->UnsignedIntTy));
28530b57cec5SDimitry Andric   Expr *count = IntegerLiteral::Create(*Context,
28540b57cec5SDimitry Andric                                        llvm::APInt(UnsignedIntSize, NumElements),
28550b57cec5SDimitry Andric                                        Context->UnsignedIntTy, SourceLocation());
28560b57cec5SDimitry Andric   KeyExprs.push_back(count);
28570b57cec5SDimitry Andric   ValueExprs.push_back(count);
28580b57cec5SDimitry Andric   for (unsigned i = 0; i < NumElements; i++) {
28590b57cec5SDimitry Andric     ObjCDictionaryElement Element = Exp->getKeyValueElement(i);
28600b57cec5SDimitry Andric     KeyExprs.push_back(Element.Key);
28610b57cec5SDimitry Andric     ValueExprs.push_back(Element.Value);
28620b57cec5SDimitry Andric   }
28630b57cec5SDimitry Andric 
28640b57cec5SDimitry Andric   // (const id [])objects
28650b57cec5SDimitry Andric   Expr *NSValueCallExpr =
28660b57cec5SDimitry Andric       CallExpr::Create(*Context, NSDictDRE, ValueExprs, NSDictFType, VK_LValue,
2867e8d8bef9SDimitry Andric                        SourceLocation(), FPOptionsOverride());
28680b57cec5SDimitry Andric 
28690b57cec5SDimitry Andric   FieldDecl *ARRFD = FieldDecl::Create(*Context, nullptr, SourceLocation(),
28700b57cec5SDimitry Andric                                        SourceLocation(),
28710b57cec5SDimitry Andric                                        &Context->Idents.get("arr"),
28720b57cec5SDimitry Andric                                        Context->getPointerType(Context->VoidPtrTy),
28730b57cec5SDimitry Andric                                        nullptr, /*BitWidth=*/nullptr,
28740b57cec5SDimitry Andric                                        /*Mutable=*/true, ICIS_NoInit);
28750b57cec5SDimitry Andric   MemberExpr *DictLiteralValueME =
28760b57cec5SDimitry Andric       MemberExpr::CreateImplicit(*Context, NSValueCallExpr, false, ARRFD,
28770b57cec5SDimitry Andric                                  ARRFD->getType(), VK_LValue, OK_Ordinary);
28780b57cec5SDimitry Andric   QualType ConstIdT = Context->getObjCIdType().withConst();
28790b57cec5SDimitry Andric   CStyleCastExpr * DictValueObjects =
28800b57cec5SDimitry Andric     NoTypeInfoCStyleCastExpr(Context,
28810b57cec5SDimitry Andric                              Context->getPointerType(ConstIdT),
28820b57cec5SDimitry Andric                              CK_BitCast,
28830b57cec5SDimitry Andric                              DictLiteralValueME);
28840b57cec5SDimitry Andric   // (const id <NSCopying> [])keys
2885e8d8bef9SDimitry Andric   Expr *NSKeyCallExpr =
2886e8d8bef9SDimitry Andric       CallExpr::Create(*Context, NSDictDRE, KeyExprs, NSDictFType, VK_LValue,
2887e8d8bef9SDimitry Andric                        SourceLocation(), FPOptionsOverride());
28880b57cec5SDimitry Andric 
28890b57cec5SDimitry Andric   MemberExpr *DictLiteralKeyME =
28900b57cec5SDimitry Andric       MemberExpr::CreateImplicit(*Context, NSKeyCallExpr, false, ARRFD,
28910b57cec5SDimitry Andric                                  ARRFD->getType(), VK_LValue, OK_Ordinary);
28920b57cec5SDimitry Andric 
28930b57cec5SDimitry Andric   CStyleCastExpr * DictKeyObjects =
28940b57cec5SDimitry Andric     NoTypeInfoCStyleCastExpr(Context,
28950b57cec5SDimitry Andric                              Context->getPointerType(ConstIdT),
28960b57cec5SDimitry Andric                              CK_BitCast,
28970b57cec5SDimitry Andric                              DictLiteralKeyME);
28980b57cec5SDimitry Andric 
28990b57cec5SDimitry Andric   // Synthesize a call to objc_msgSend().
29000b57cec5SDimitry Andric   SmallVector<Expr*, 32> MsgExprs;
29010b57cec5SDimitry Andric   SmallVector<Expr*, 4> ClsExprs;
29020b57cec5SDimitry Andric   QualType expType = Exp->getType();
29030b57cec5SDimitry Andric 
29040b57cec5SDimitry Andric   // Create a call to objc_getClass("NSArray"). It will be th 1st argument.
29050b57cec5SDimitry Andric   ObjCInterfaceDecl *Class =
2906a7dea167SDimitry Andric   expType->getPointeeType()->castAs<ObjCObjectType>()->getInterface();
29070b57cec5SDimitry Andric 
29080b57cec5SDimitry Andric   IdentifierInfo *clsName = Class->getIdentifier();
29090b57cec5SDimitry Andric   ClsExprs.push_back(getStringLiteral(clsName->getName()));
29100b57cec5SDimitry Andric   CallExpr *Cls = SynthesizeCallToFunctionDecl(GetClassFunctionDecl, ClsExprs,
29110b57cec5SDimitry Andric                                                StartLoc, EndLoc);
29120b57cec5SDimitry Andric   MsgExprs.push_back(Cls);
29130b57cec5SDimitry Andric 
29140b57cec5SDimitry Andric   // Create a call to sel_registerName("arrayWithObjects:count:").
29150b57cec5SDimitry Andric   // it will be the 2nd argument.
29160b57cec5SDimitry Andric   SmallVector<Expr*, 4> SelExprs;
29170b57cec5SDimitry Andric   ObjCMethodDecl *DictMethod = Exp->getDictWithObjectsMethod();
29180b57cec5SDimitry Andric   SelExprs.push_back(getStringLiteral(DictMethod->getSelector().getAsString()));
29190b57cec5SDimitry Andric   CallExpr *SelExp = SynthesizeCallToFunctionDecl(SelGetUidFunctionDecl,
29200b57cec5SDimitry Andric                                                   SelExprs, StartLoc, EndLoc);
29210b57cec5SDimitry Andric   MsgExprs.push_back(SelExp);
29220b57cec5SDimitry Andric 
29230b57cec5SDimitry Andric   // (const id [])objects
29240b57cec5SDimitry Andric   MsgExprs.push_back(DictValueObjects);
29250b57cec5SDimitry Andric 
29260b57cec5SDimitry Andric   // (const id <NSCopying> [])keys
29270b57cec5SDimitry Andric   MsgExprs.push_back(DictKeyObjects);
29280b57cec5SDimitry Andric 
29290b57cec5SDimitry Andric   // (NSUInteger)cnt
29300b57cec5SDimitry Andric   Expr *cnt = IntegerLiteral::Create(*Context,
29310b57cec5SDimitry Andric                                      llvm::APInt(UnsignedIntSize, NumElements),
29320b57cec5SDimitry Andric                                      Context->UnsignedIntTy, SourceLocation());
29330b57cec5SDimitry Andric   MsgExprs.push_back(cnt);
29340b57cec5SDimitry Andric 
29350b57cec5SDimitry Andric   SmallVector<QualType, 8> ArgTypes;
29360b57cec5SDimitry Andric   ArgTypes.push_back(Context->getObjCClassType());
29370b57cec5SDimitry Andric   ArgTypes.push_back(Context->getObjCSelType());
29380b57cec5SDimitry Andric   for (const auto *PI : DictMethod->parameters()) {
29390b57cec5SDimitry Andric     QualType T = PI->getType();
29400b57cec5SDimitry Andric     if (const PointerType* PT = T->getAs<PointerType>()) {
29410b57cec5SDimitry Andric       QualType PointeeTy = PT->getPointeeType();
29420b57cec5SDimitry Andric       convertToUnqualifiedObjCType(PointeeTy);
29430b57cec5SDimitry Andric       T = Context->getPointerType(PointeeTy);
29440b57cec5SDimitry Andric     }
29450b57cec5SDimitry Andric     ArgTypes.push_back(T);
29460b57cec5SDimitry Andric   }
29470b57cec5SDimitry Andric 
29480b57cec5SDimitry Andric   QualType returnType = Exp->getType();
29490b57cec5SDimitry Andric   // Get the type, we will need to reference it in a couple spots.
29500b57cec5SDimitry Andric   QualType msgSendType = MsgSendFlavor->getType();
29510b57cec5SDimitry Andric 
29520b57cec5SDimitry Andric   // Create a reference to the objc_msgSend() declaration.
29530b57cec5SDimitry Andric   DeclRefExpr *DRE = new (Context) DeclRefExpr(
29540b57cec5SDimitry Andric       *Context, MsgSendFlavor, false, msgSendType, VK_LValue, SourceLocation());
29550b57cec5SDimitry Andric 
29560b57cec5SDimitry Andric   CastExpr *cast = NoTypeInfoCStyleCastExpr(
29570b57cec5SDimitry Andric       Context, Context->getPointerType(Context->VoidTy), CK_BitCast, DRE);
29580b57cec5SDimitry Andric 
29590b57cec5SDimitry Andric   // Now do the "normal" pointer to function cast.
29600b57cec5SDimitry Andric   QualType castType =
29610b57cec5SDimitry Andric   getSimpleFunctionType(returnType, ArgTypes, DictMethod->isVariadic());
29620b57cec5SDimitry Andric   castType = Context->getPointerType(castType);
29630b57cec5SDimitry Andric   cast = NoTypeInfoCStyleCastExpr(Context, castType, CK_BitCast,
29640b57cec5SDimitry Andric                                   cast);
29650b57cec5SDimitry Andric 
29660b57cec5SDimitry Andric   // Don't forget the parens to enforce the proper binding.
29670b57cec5SDimitry Andric   ParenExpr *PE = new (Context) ParenExpr(StartLoc, EndLoc, cast);
29680b57cec5SDimitry Andric 
2969a7dea167SDimitry Andric   const FunctionType *FT = msgSendType->castAs<FunctionType>();
29700b57cec5SDimitry Andric   CallExpr *CE = CallExpr::Create(*Context, PE, MsgExprs, FT->getReturnType(),
2971fe6060f1SDimitry Andric                                   VK_PRValue, EndLoc, FPOptionsOverride());
29720b57cec5SDimitry Andric   ReplaceStmt(Exp, CE);
29730b57cec5SDimitry Andric   return CE;
29740b57cec5SDimitry Andric }
29750b57cec5SDimitry Andric 
29760b57cec5SDimitry Andric // struct __rw_objc_super {
29770b57cec5SDimitry Andric //   struct objc_object *object; struct objc_object *superClass;
29780b57cec5SDimitry Andric // };
getSuperStructType()29790b57cec5SDimitry Andric QualType RewriteModernObjC::getSuperStructType() {
29800b57cec5SDimitry Andric   if (!SuperStructDecl) {
29815f757f3fSDimitry Andric     SuperStructDecl = RecordDecl::Create(
29825f757f3fSDimitry Andric         *Context, TagTypeKind::Struct, TUDecl, SourceLocation(),
29835f757f3fSDimitry Andric         SourceLocation(), &Context->Idents.get("__rw_objc_super"));
29840b57cec5SDimitry Andric     QualType FieldTypes[2];
29850b57cec5SDimitry Andric 
29860b57cec5SDimitry Andric     // struct objc_object *object;
29870b57cec5SDimitry Andric     FieldTypes[0] = Context->getObjCIdType();
29880b57cec5SDimitry Andric     // struct objc_object *superClass;
29890b57cec5SDimitry Andric     FieldTypes[1] = Context->getObjCIdType();
29900b57cec5SDimitry Andric 
29910b57cec5SDimitry Andric     // Create fields
29920b57cec5SDimitry Andric     for (unsigned i = 0; i < 2; ++i) {
29930b57cec5SDimitry Andric       SuperStructDecl->addDecl(FieldDecl::Create(*Context, SuperStructDecl,
29940b57cec5SDimitry Andric                                                  SourceLocation(),
29950b57cec5SDimitry Andric                                                  SourceLocation(), nullptr,
29960b57cec5SDimitry Andric                                                  FieldTypes[i], nullptr,
29970b57cec5SDimitry Andric                                                  /*BitWidth=*/nullptr,
29980b57cec5SDimitry Andric                                                  /*Mutable=*/false,
29990b57cec5SDimitry Andric                                                  ICIS_NoInit));
30000b57cec5SDimitry Andric     }
30010b57cec5SDimitry Andric 
30020b57cec5SDimitry Andric     SuperStructDecl->completeDefinition();
30030b57cec5SDimitry Andric   }
30040b57cec5SDimitry Andric   return Context->getTagDeclType(SuperStructDecl);
30050b57cec5SDimitry Andric }
30060b57cec5SDimitry Andric 
getConstantStringStructType()30070b57cec5SDimitry Andric QualType RewriteModernObjC::getConstantStringStructType() {
30080b57cec5SDimitry Andric   if (!ConstantStringDecl) {
30095f757f3fSDimitry Andric     ConstantStringDecl = RecordDecl::Create(
30105f757f3fSDimitry Andric         *Context, TagTypeKind::Struct, TUDecl, SourceLocation(),
30115f757f3fSDimitry Andric         SourceLocation(), &Context->Idents.get("__NSConstantStringImpl"));
30120b57cec5SDimitry Andric     QualType FieldTypes[4];
30130b57cec5SDimitry Andric 
30140b57cec5SDimitry Andric     // struct objc_object *receiver;
30150b57cec5SDimitry Andric     FieldTypes[0] = Context->getObjCIdType();
30160b57cec5SDimitry Andric     // int flags;
30170b57cec5SDimitry Andric     FieldTypes[1] = Context->IntTy;
30180b57cec5SDimitry Andric     // char *str;
30190b57cec5SDimitry Andric     FieldTypes[2] = Context->getPointerType(Context->CharTy);
30200b57cec5SDimitry Andric     // long length;
30210b57cec5SDimitry Andric     FieldTypes[3] = Context->LongTy;
30220b57cec5SDimitry Andric 
30230b57cec5SDimitry Andric     // Create fields
30240b57cec5SDimitry Andric     for (unsigned i = 0; i < 4; ++i) {
30250b57cec5SDimitry Andric       ConstantStringDecl->addDecl(FieldDecl::Create(*Context,
30260b57cec5SDimitry Andric                                                     ConstantStringDecl,
30270b57cec5SDimitry Andric                                                     SourceLocation(),
30280b57cec5SDimitry Andric                                                     SourceLocation(), nullptr,
30290b57cec5SDimitry Andric                                                     FieldTypes[i], nullptr,
30300b57cec5SDimitry Andric                                                     /*BitWidth=*/nullptr,
30310b57cec5SDimitry Andric                                                     /*Mutable=*/true,
30320b57cec5SDimitry Andric                                                     ICIS_NoInit));
30330b57cec5SDimitry Andric     }
30340b57cec5SDimitry Andric 
30350b57cec5SDimitry Andric     ConstantStringDecl->completeDefinition();
30360b57cec5SDimitry Andric   }
30370b57cec5SDimitry Andric   return Context->getTagDeclType(ConstantStringDecl);
30380b57cec5SDimitry Andric }
30390b57cec5SDimitry Andric 
30400b57cec5SDimitry Andric /// getFunctionSourceLocation - returns start location of a function
30410b57cec5SDimitry Andric /// definition. Complication arises when function has declared as
30420b57cec5SDimitry Andric /// extern "C" or extern "C" {...}
getFunctionSourceLocation(RewriteModernObjC & R,FunctionDecl * FD)30430b57cec5SDimitry Andric static SourceLocation getFunctionSourceLocation (RewriteModernObjC &R,
30440b57cec5SDimitry Andric                                                  FunctionDecl *FD) {
30450b57cec5SDimitry Andric   if (FD->isExternC()  && !FD->isMain()) {
30460b57cec5SDimitry Andric     const DeclContext *DC = FD->getDeclContext();
30470b57cec5SDimitry Andric     if (const LinkageSpecDecl *LSD = dyn_cast<LinkageSpecDecl>(DC))
30480b57cec5SDimitry Andric       // if it is extern "C" {...}, return function decl's own location.
30490b57cec5SDimitry Andric       if (!LSD->getRBraceLoc().isValid())
30500b57cec5SDimitry Andric         return LSD->getExternLoc();
30510b57cec5SDimitry Andric   }
30520b57cec5SDimitry Andric   if (FD->getStorageClass() != SC_None)
30530b57cec5SDimitry Andric     R.RewriteBlockLiteralFunctionDecl(FD);
30540b57cec5SDimitry Andric   return FD->getTypeSpecStartLoc();
30550b57cec5SDimitry Andric }
30560b57cec5SDimitry Andric 
RewriteLineDirective(const Decl * D)30570b57cec5SDimitry Andric void RewriteModernObjC::RewriteLineDirective(const Decl *D) {
30580b57cec5SDimitry Andric 
30590b57cec5SDimitry Andric   SourceLocation Location = D->getLocation();
30600b57cec5SDimitry Andric 
30610b57cec5SDimitry Andric   if (Location.isFileID() && GenerateLineInfo) {
30620b57cec5SDimitry Andric     std::string LineString("\n#line ");
30630b57cec5SDimitry Andric     PresumedLoc PLoc = SM->getPresumedLoc(Location);
30640b57cec5SDimitry Andric     LineString += utostr(PLoc.getLine());
30650b57cec5SDimitry Andric     LineString += " \"";
30660b57cec5SDimitry Andric     LineString += Lexer::Stringify(PLoc.getFilename());
30670b57cec5SDimitry Andric     if (isa<ObjCMethodDecl>(D))
30680b57cec5SDimitry Andric       LineString += "\"";
30690b57cec5SDimitry Andric     else LineString += "\"\n";
30700b57cec5SDimitry Andric 
30710b57cec5SDimitry Andric     Location = D->getBeginLoc();
30720b57cec5SDimitry Andric     if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
30730b57cec5SDimitry Andric       if (FD->isExternC()  && !FD->isMain()) {
30740b57cec5SDimitry Andric         const DeclContext *DC = FD->getDeclContext();
30750b57cec5SDimitry Andric         if (const LinkageSpecDecl *LSD = dyn_cast<LinkageSpecDecl>(DC))
30760b57cec5SDimitry Andric           // if it is extern "C" {...}, return function decl's own location.
30770b57cec5SDimitry Andric           if (!LSD->getRBraceLoc().isValid())
30780b57cec5SDimitry Andric             Location = LSD->getExternLoc();
30790b57cec5SDimitry Andric       }
30800b57cec5SDimitry Andric     }
30810b57cec5SDimitry Andric     InsertText(Location, LineString);
30820b57cec5SDimitry Andric   }
30830b57cec5SDimitry Andric }
30840b57cec5SDimitry Andric 
30850b57cec5SDimitry Andric /// SynthMsgSendStretCallExpr - This routine translates message expression
30860b57cec5SDimitry Andric /// into a call to objc_msgSend_stret() entry point. Tricky part is that
30870b57cec5SDimitry Andric /// nil check on receiver must be performed before calling objc_msgSend_stret.
30880b57cec5SDimitry Andric /// MsgSendStretFlavor - function declaration objc_msgSend_stret(...)
30890b57cec5SDimitry Andric /// msgSendType - function type of objc_msgSend_stret(...)
30900b57cec5SDimitry Andric /// returnType - Result type of the method being synthesized.
30910b57cec5SDimitry Andric /// ArgTypes - type of the arguments passed to objc_msgSend_stret, starting with receiver type.
30920b57cec5SDimitry Andric /// MsgExprs - list of argument expressions being passed to objc_msgSend_stret,
30930b57cec5SDimitry Andric /// starting with receiver.
30940b57cec5SDimitry Andric /// Method - Method being rewritten.
SynthMsgSendStretCallExpr(FunctionDecl * MsgSendStretFlavor,QualType returnType,SmallVectorImpl<QualType> & ArgTypes,SmallVectorImpl<Expr * > & MsgExprs,ObjCMethodDecl * Method)30950b57cec5SDimitry Andric Expr *RewriteModernObjC::SynthMsgSendStretCallExpr(FunctionDecl *MsgSendStretFlavor,
30960b57cec5SDimitry Andric                                                  QualType returnType,
30970b57cec5SDimitry Andric                                                  SmallVectorImpl<QualType> &ArgTypes,
30980b57cec5SDimitry Andric                                                  SmallVectorImpl<Expr*> &MsgExprs,
30990b57cec5SDimitry Andric                                                  ObjCMethodDecl *Method) {
31000b57cec5SDimitry Andric   // Now do the "normal" pointer to function cast.
31010b57cec5SDimitry Andric   QualType FuncType = getSimpleFunctionType(
31020b57cec5SDimitry Andric       returnType, ArgTypes, Method ? Method->isVariadic() : false);
31030b57cec5SDimitry Andric   QualType castType = Context->getPointerType(FuncType);
31040b57cec5SDimitry Andric 
31050b57cec5SDimitry Andric   // build type for containing the objc_msgSend_stret object.
31060b57cec5SDimitry Andric   static unsigned stretCount=0;
31070b57cec5SDimitry Andric   std::string name = "__Stret"; name += utostr(stretCount);
31080b57cec5SDimitry Andric   std::string str =
31090b57cec5SDimitry Andric     "extern \"C\" void * __cdecl memset(void *_Dst, int _Val, size_t _Size);\n";
31100b57cec5SDimitry Andric   str += "namespace {\n";
31110b57cec5SDimitry Andric   str += "struct "; str += name;
31120b57cec5SDimitry Andric   str += " {\n\t";
31130b57cec5SDimitry Andric   str += name;
31140b57cec5SDimitry Andric   str += "(id receiver, SEL sel";
31150b57cec5SDimitry Andric   for (unsigned i = 2; i < ArgTypes.size(); i++) {
31160b57cec5SDimitry Andric     std::string ArgName = "arg"; ArgName += utostr(i);
31170b57cec5SDimitry Andric     ArgTypes[i].getAsStringInternal(ArgName, Context->getPrintingPolicy());
31180b57cec5SDimitry Andric     str += ", "; str += ArgName;
31190b57cec5SDimitry Andric   }
31200b57cec5SDimitry Andric   // could be vararg.
31210b57cec5SDimitry Andric   for (unsigned i = ArgTypes.size(); i < MsgExprs.size(); i++) {
31220b57cec5SDimitry Andric     std::string ArgName = "arg"; ArgName += utostr(i);
31230b57cec5SDimitry Andric     MsgExprs[i]->getType().getAsStringInternal(ArgName,
31240b57cec5SDimitry Andric                                                Context->getPrintingPolicy());
31250b57cec5SDimitry Andric     str += ", "; str += ArgName;
31260b57cec5SDimitry Andric   }
31270b57cec5SDimitry Andric 
31280b57cec5SDimitry Andric   str += ") {\n";
31290b57cec5SDimitry Andric   str += "\t  unsigned size = sizeof(";
31300b57cec5SDimitry Andric   str += returnType.getAsString(Context->getPrintingPolicy()); str += ");\n";
31310b57cec5SDimitry Andric 
31320b57cec5SDimitry Andric   str += "\t  if (size == 1 || size == 2 || size == 4 || size == 8)\n";
31330b57cec5SDimitry Andric 
31340b57cec5SDimitry Andric   str += "\t    s = (("; str += castType.getAsString(Context->getPrintingPolicy());
31350b57cec5SDimitry Andric   str += ")(void *)objc_msgSend)(receiver, sel";
31360b57cec5SDimitry Andric   for (unsigned i = 2; i < ArgTypes.size(); i++) {
31370b57cec5SDimitry Andric     str += ", arg"; str += utostr(i);
31380b57cec5SDimitry Andric   }
31390b57cec5SDimitry Andric   // could be vararg.
31400b57cec5SDimitry Andric   for (unsigned i = ArgTypes.size(); i < MsgExprs.size(); i++) {
31410b57cec5SDimitry Andric     str += ", arg"; str += utostr(i);
31420b57cec5SDimitry Andric   }
31430b57cec5SDimitry Andric   str+= ");\n";
31440b57cec5SDimitry Andric 
31450b57cec5SDimitry Andric   str += "\t  else if (receiver == 0)\n";
31460b57cec5SDimitry Andric   str += "\t    memset((void*)&s, 0, sizeof(s));\n";
31470b57cec5SDimitry Andric   str += "\t  else\n";
31480b57cec5SDimitry Andric 
31490b57cec5SDimitry Andric   str += "\t    s = (("; str += castType.getAsString(Context->getPrintingPolicy());
31500b57cec5SDimitry Andric   str += ")(void *)objc_msgSend_stret)(receiver, sel";
31510b57cec5SDimitry Andric   for (unsigned i = 2; i < ArgTypes.size(); i++) {
31520b57cec5SDimitry Andric     str += ", arg"; str += utostr(i);
31530b57cec5SDimitry Andric   }
31540b57cec5SDimitry Andric   // could be vararg.
31550b57cec5SDimitry Andric   for (unsigned i = ArgTypes.size(); i < MsgExprs.size(); i++) {
31560b57cec5SDimitry Andric     str += ", arg"; str += utostr(i);
31570b57cec5SDimitry Andric   }
31580b57cec5SDimitry Andric   str += ");\n";
31590b57cec5SDimitry Andric 
31600b57cec5SDimitry Andric   str += "\t}\n";
31610b57cec5SDimitry Andric   str += "\t"; str += returnType.getAsString(Context->getPrintingPolicy());
31620b57cec5SDimitry Andric   str += " s;\n";
31630b57cec5SDimitry Andric   str += "};\n};\n\n";
31640b57cec5SDimitry Andric   SourceLocation FunLocStart;
31650b57cec5SDimitry Andric   if (CurFunctionDef)
31660b57cec5SDimitry Andric     FunLocStart = getFunctionSourceLocation(*this, CurFunctionDef);
31670b57cec5SDimitry Andric   else {
31680b57cec5SDimitry Andric     assert(CurMethodDef && "SynthMsgSendStretCallExpr - CurMethodDef is null");
31690b57cec5SDimitry Andric     FunLocStart = CurMethodDef->getBeginLoc();
31700b57cec5SDimitry Andric   }
31710b57cec5SDimitry Andric 
31720b57cec5SDimitry Andric   InsertText(FunLocStart, str);
31730b57cec5SDimitry Andric   ++stretCount;
31740b57cec5SDimitry Andric 
31750b57cec5SDimitry Andric   // AST for __Stretn(receiver, args).s;
31760b57cec5SDimitry Andric   IdentifierInfo *ID = &Context->Idents.get(name);
31770b57cec5SDimitry Andric   FunctionDecl *FD =
31780b57cec5SDimitry Andric       FunctionDecl::Create(*Context, TUDecl, SourceLocation(), SourceLocation(),
31790b57cec5SDimitry Andric                            ID, FuncType, nullptr, SC_Extern, false, false);
31800b57cec5SDimitry Andric   DeclRefExpr *DRE = new (Context)
3181fe6060f1SDimitry Andric       DeclRefExpr(*Context, FD, false, castType, VK_PRValue, SourceLocation());
3182e8d8bef9SDimitry Andric   CallExpr *STCE =
3183e8d8bef9SDimitry Andric       CallExpr::Create(*Context, DRE, MsgExprs, castType, VK_LValue,
3184e8d8bef9SDimitry Andric                        SourceLocation(), FPOptionsOverride());
31850b57cec5SDimitry Andric 
31860b57cec5SDimitry Andric   FieldDecl *FieldD = FieldDecl::Create(*Context, nullptr, SourceLocation(),
31870b57cec5SDimitry Andric                                     SourceLocation(),
31880b57cec5SDimitry Andric                                     &Context->Idents.get("s"),
31890b57cec5SDimitry Andric                                     returnType, nullptr,
31900b57cec5SDimitry Andric                                     /*BitWidth=*/nullptr,
31910b57cec5SDimitry Andric                                     /*Mutable=*/true, ICIS_NoInit);
31920b57cec5SDimitry Andric   MemberExpr *ME = MemberExpr::CreateImplicit(
31930b57cec5SDimitry Andric       *Context, STCE, false, FieldD, FieldD->getType(), VK_LValue, OK_Ordinary);
31940b57cec5SDimitry Andric 
31950b57cec5SDimitry Andric   return ME;
31960b57cec5SDimitry Andric }
31970b57cec5SDimitry Andric 
SynthMessageExpr(ObjCMessageExpr * Exp,SourceLocation StartLoc,SourceLocation EndLoc)31980b57cec5SDimitry Andric Stmt *RewriteModernObjC::SynthMessageExpr(ObjCMessageExpr *Exp,
31990b57cec5SDimitry Andric                                     SourceLocation StartLoc,
32000b57cec5SDimitry Andric                                     SourceLocation EndLoc) {
32010b57cec5SDimitry Andric   if (!SelGetUidFunctionDecl)
32020b57cec5SDimitry Andric     SynthSelGetUidFunctionDecl();
32030b57cec5SDimitry Andric   if (!MsgSendFunctionDecl)
32040b57cec5SDimitry Andric     SynthMsgSendFunctionDecl();
32050b57cec5SDimitry Andric   if (!MsgSendSuperFunctionDecl)
32060b57cec5SDimitry Andric     SynthMsgSendSuperFunctionDecl();
32070b57cec5SDimitry Andric   if (!MsgSendStretFunctionDecl)
32080b57cec5SDimitry Andric     SynthMsgSendStretFunctionDecl();
32090b57cec5SDimitry Andric   if (!MsgSendSuperStretFunctionDecl)
32100b57cec5SDimitry Andric     SynthMsgSendSuperStretFunctionDecl();
32110b57cec5SDimitry Andric   if (!MsgSendFpretFunctionDecl)
32120b57cec5SDimitry Andric     SynthMsgSendFpretFunctionDecl();
32130b57cec5SDimitry Andric   if (!GetClassFunctionDecl)
32140b57cec5SDimitry Andric     SynthGetClassFunctionDecl();
32150b57cec5SDimitry Andric   if (!GetSuperClassFunctionDecl)
32160b57cec5SDimitry Andric     SynthGetSuperClassFunctionDecl();
32170b57cec5SDimitry Andric   if (!GetMetaClassFunctionDecl)
32180b57cec5SDimitry Andric     SynthGetMetaClassFunctionDecl();
32190b57cec5SDimitry Andric 
32200b57cec5SDimitry Andric   // default to objc_msgSend().
32210b57cec5SDimitry Andric   FunctionDecl *MsgSendFlavor = MsgSendFunctionDecl;
32220b57cec5SDimitry Andric   // May need to use objc_msgSend_stret() as well.
32230b57cec5SDimitry Andric   FunctionDecl *MsgSendStretFlavor = nullptr;
32240b57cec5SDimitry Andric   if (ObjCMethodDecl *mDecl = Exp->getMethodDecl()) {
32250b57cec5SDimitry Andric     QualType resultType = mDecl->getReturnType();
32260b57cec5SDimitry Andric     if (resultType->isRecordType())
32270b57cec5SDimitry Andric       MsgSendStretFlavor = MsgSendStretFunctionDecl;
32280b57cec5SDimitry Andric     else if (resultType->isRealFloatingType())
32290b57cec5SDimitry Andric       MsgSendFlavor = MsgSendFpretFunctionDecl;
32300b57cec5SDimitry Andric   }
32310b57cec5SDimitry Andric 
32320b57cec5SDimitry Andric   // Synthesize a call to objc_msgSend().
32330b57cec5SDimitry Andric   SmallVector<Expr*, 8> MsgExprs;
32340b57cec5SDimitry Andric   switch (Exp->getReceiverKind()) {
32350b57cec5SDimitry Andric   case ObjCMessageExpr::SuperClass: {
32360b57cec5SDimitry Andric     MsgSendFlavor = MsgSendSuperFunctionDecl;
32370b57cec5SDimitry Andric     if (MsgSendStretFlavor)
32380b57cec5SDimitry Andric       MsgSendStretFlavor = MsgSendSuperStretFunctionDecl;
32390b57cec5SDimitry Andric     assert(MsgSendFlavor && "MsgSendFlavor is NULL!");
32400b57cec5SDimitry Andric 
32410b57cec5SDimitry Andric     ObjCInterfaceDecl *ClassDecl = CurMethodDef->getClassInterface();
32420b57cec5SDimitry Andric 
32430b57cec5SDimitry Andric     SmallVector<Expr*, 4> InitExprs;
32440b57cec5SDimitry Andric 
32450b57cec5SDimitry Andric     // set the receiver to self, the first argument to all methods.
3246fe6060f1SDimitry Andric     InitExprs.push_back(NoTypeInfoCStyleCastExpr(
3247fe6060f1SDimitry Andric         Context, Context->getObjCIdType(), CK_BitCast,
3248fe6060f1SDimitry Andric         new (Context) DeclRefExpr(*Context, CurMethodDef->getSelfDecl(), false,
3249fe6060f1SDimitry Andric                                   Context->getObjCIdType(), VK_PRValue,
3250fe6060f1SDimitry Andric                                   SourceLocation()))); // set the 'receiver'.
32510b57cec5SDimitry Andric 
32520b57cec5SDimitry Andric     // (id)class_getSuperclass((Class)objc_getClass("CurrentClass"))
32530b57cec5SDimitry Andric     SmallVector<Expr*, 8> ClsExprs;
32540b57cec5SDimitry Andric     ClsExprs.push_back(getStringLiteral(ClassDecl->getIdentifier()->getName()));
32550b57cec5SDimitry Andric     // (Class)objc_getClass("CurrentClass")
32560b57cec5SDimitry Andric     CallExpr *Cls = SynthesizeCallToFunctionDecl(GetMetaClassFunctionDecl,
32570b57cec5SDimitry Andric                                                  ClsExprs, StartLoc, EndLoc);
32580b57cec5SDimitry Andric     ClsExprs.clear();
32590b57cec5SDimitry Andric     ClsExprs.push_back(Cls);
32600b57cec5SDimitry Andric     Cls = SynthesizeCallToFunctionDecl(GetSuperClassFunctionDecl, ClsExprs,
32610b57cec5SDimitry Andric                                        StartLoc, EndLoc);
32620b57cec5SDimitry Andric 
32630b57cec5SDimitry Andric     // (id)class_getSuperclass((Class)objc_getClass("CurrentClass"))
32640b57cec5SDimitry Andric     // To turn off a warning, type-cast to 'id'
32650b57cec5SDimitry Andric     InitExprs.push_back( // set 'super class', using class_getSuperclass().
32660b57cec5SDimitry Andric                         NoTypeInfoCStyleCastExpr(Context,
32670b57cec5SDimitry Andric                                                  Context->getObjCIdType(),
32680b57cec5SDimitry Andric                                                  CK_BitCast, Cls));
32690b57cec5SDimitry Andric     // struct __rw_objc_super
32700b57cec5SDimitry Andric     QualType superType = getSuperStructType();
32710b57cec5SDimitry Andric     Expr *SuperRep;
32720b57cec5SDimitry Andric 
32730b57cec5SDimitry Andric     if (LangOpts.MicrosoftExt) {
32740b57cec5SDimitry Andric       SynthSuperConstructorFunctionDecl();
32750b57cec5SDimitry Andric       // Simulate a constructor call...
32760b57cec5SDimitry Andric       DeclRefExpr *DRE = new (Context)
32770b57cec5SDimitry Andric           DeclRefExpr(*Context, SuperConstructorFunctionDecl, false, superType,
32780b57cec5SDimitry Andric                       VK_LValue, SourceLocation());
3279e8d8bef9SDimitry Andric       SuperRep =
3280e8d8bef9SDimitry Andric           CallExpr::Create(*Context, DRE, InitExprs, superType, VK_LValue,
3281e8d8bef9SDimitry Andric                            SourceLocation(), FPOptionsOverride());
32820b57cec5SDimitry Andric       // The code for super is a little tricky to prevent collision with
32830b57cec5SDimitry Andric       // the structure definition in the header. The rewriter has it's own
32840b57cec5SDimitry Andric       // internal definition (__rw_objc_super) that is uses. This is why
32850b57cec5SDimitry Andric       // we need the cast below. For example:
32860b57cec5SDimitry Andric       // (struct __rw_objc_super *)&__rw_objc_super((id)self, (id)objc_getClass("SUPER"))
32870b57cec5SDimitry Andric       //
32885ffd83dbSDimitry Andric       SuperRep = UnaryOperator::Create(
32895ffd83dbSDimitry Andric           const_cast<ASTContext &>(*Context), SuperRep, UO_AddrOf,
3290fe6060f1SDimitry Andric           Context->getPointerType(SuperRep->getType()), VK_PRValue, OK_Ordinary,
32915ffd83dbSDimitry Andric           SourceLocation(), false, FPOptionsOverride());
32920b57cec5SDimitry Andric       SuperRep = NoTypeInfoCStyleCastExpr(Context,
32930b57cec5SDimitry Andric                                           Context->getPointerType(superType),
32940b57cec5SDimitry Andric                                           CK_BitCast, SuperRep);
32950b57cec5SDimitry Andric     } else {
32960b57cec5SDimitry Andric       // (struct __rw_objc_super) { <exprs from above> }
32970b57cec5SDimitry Andric       InitListExpr *ILE =
32980b57cec5SDimitry Andric         new (Context) InitListExpr(*Context, SourceLocation(), InitExprs,
32990b57cec5SDimitry Andric                                    SourceLocation());
33000b57cec5SDimitry Andric       TypeSourceInfo *superTInfo
33010b57cec5SDimitry Andric         = Context->getTrivialTypeSourceInfo(superType);
33020b57cec5SDimitry Andric       SuperRep = new (Context) CompoundLiteralExpr(SourceLocation(), superTInfo,
33030b57cec5SDimitry Andric                                                    superType, VK_LValue,
33040b57cec5SDimitry Andric                                                    ILE, false);
33050b57cec5SDimitry Andric       // struct __rw_objc_super *
33065ffd83dbSDimitry Andric       SuperRep = UnaryOperator::Create(
33075ffd83dbSDimitry Andric           const_cast<ASTContext &>(*Context), SuperRep, UO_AddrOf,
3308fe6060f1SDimitry Andric           Context->getPointerType(SuperRep->getType()), VK_PRValue, OK_Ordinary,
33095ffd83dbSDimitry Andric           SourceLocation(), false, FPOptionsOverride());
33100b57cec5SDimitry Andric     }
33110b57cec5SDimitry Andric     MsgExprs.push_back(SuperRep);
33120b57cec5SDimitry Andric     break;
33130b57cec5SDimitry Andric   }
33140b57cec5SDimitry Andric 
33150b57cec5SDimitry Andric   case ObjCMessageExpr::Class: {
33160b57cec5SDimitry Andric     SmallVector<Expr*, 8> ClsExprs;
33170b57cec5SDimitry Andric     ObjCInterfaceDecl *Class
3318a7dea167SDimitry Andric       = Exp->getClassReceiver()->castAs<ObjCObjectType>()->getInterface();
33190b57cec5SDimitry Andric     IdentifierInfo *clsName = Class->getIdentifier();
33200b57cec5SDimitry Andric     ClsExprs.push_back(getStringLiteral(clsName->getName()));
33210b57cec5SDimitry Andric     CallExpr *Cls = SynthesizeCallToFunctionDecl(GetClassFunctionDecl, ClsExprs,
33220b57cec5SDimitry Andric                                                  StartLoc, EndLoc);
33230b57cec5SDimitry Andric     CastExpr *ArgExpr = NoTypeInfoCStyleCastExpr(Context,
33240b57cec5SDimitry Andric                                                  Context->getObjCIdType(),
33250b57cec5SDimitry Andric                                                  CK_BitCast, Cls);
33260b57cec5SDimitry Andric     MsgExprs.push_back(ArgExpr);
33270b57cec5SDimitry Andric     break;
33280b57cec5SDimitry Andric   }
33290b57cec5SDimitry Andric 
33300b57cec5SDimitry Andric   case ObjCMessageExpr::SuperInstance:{
33310b57cec5SDimitry Andric     MsgSendFlavor = MsgSendSuperFunctionDecl;
33320b57cec5SDimitry Andric     if (MsgSendStretFlavor)
33330b57cec5SDimitry Andric       MsgSendStretFlavor = MsgSendSuperStretFunctionDecl;
33340b57cec5SDimitry Andric     assert(MsgSendFlavor && "MsgSendFlavor is NULL!");
33350b57cec5SDimitry Andric     ObjCInterfaceDecl *ClassDecl = CurMethodDef->getClassInterface();
33360b57cec5SDimitry Andric     SmallVector<Expr*, 4> InitExprs;
33370b57cec5SDimitry Andric 
3338fe6060f1SDimitry Andric     InitExprs.push_back(NoTypeInfoCStyleCastExpr(
3339fe6060f1SDimitry Andric         Context, Context->getObjCIdType(), CK_BitCast,
3340fe6060f1SDimitry Andric         new (Context) DeclRefExpr(*Context, CurMethodDef->getSelfDecl(), false,
3341fe6060f1SDimitry Andric                                   Context->getObjCIdType(), VK_PRValue,
3342fe6060f1SDimitry Andric                                   SourceLocation()))); // set the 'receiver'.
33430b57cec5SDimitry Andric 
33440b57cec5SDimitry Andric     // (id)class_getSuperclass((Class)objc_getClass("CurrentClass"))
33450b57cec5SDimitry Andric     SmallVector<Expr*, 8> ClsExprs;
33460b57cec5SDimitry Andric     ClsExprs.push_back(getStringLiteral(ClassDecl->getIdentifier()->getName()));
33470b57cec5SDimitry Andric     // (Class)objc_getClass("CurrentClass")
33480b57cec5SDimitry Andric     CallExpr *Cls = SynthesizeCallToFunctionDecl(GetClassFunctionDecl, ClsExprs,
33490b57cec5SDimitry Andric                                                  StartLoc, EndLoc);
33500b57cec5SDimitry Andric     ClsExprs.clear();
33510b57cec5SDimitry Andric     ClsExprs.push_back(Cls);
33520b57cec5SDimitry Andric     Cls = SynthesizeCallToFunctionDecl(GetSuperClassFunctionDecl, ClsExprs,
33530b57cec5SDimitry Andric                                        StartLoc, EndLoc);
33540b57cec5SDimitry Andric 
33550b57cec5SDimitry Andric     // (id)class_getSuperclass((Class)objc_getClass("CurrentClass"))
33560b57cec5SDimitry Andric     // To turn off a warning, type-cast to 'id'
33570b57cec5SDimitry Andric     InitExprs.push_back(
33580b57cec5SDimitry Andric       // set 'super class', using class_getSuperclass().
33590b57cec5SDimitry Andric       NoTypeInfoCStyleCastExpr(Context, Context->getObjCIdType(),
33600b57cec5SDimitry Andric                                CK_BitCast, Cls));
33610b57cec5SDimitry Andric     // struct __rw_objc_super
33620b57cec5SDimitry Andric     QualType superType = getSuperStructType();
33630b57cec5SDimitry Andric     Expr *SuperRep;
33640b57cec5SDimitry Andric 
33650b57cec5SDimitry Andric     if (LangOpts.MicrosoftExt) {
33660b57cec5SDimitry Andric       SynthSuperConstructorFunctionDecl();
33670b57cec5SDimitry Andric       // Simulate a constructor call...
33680b57cec5SDimitry Andric       DeclRefExpr *DRE = new (Context)
33690b57cec5SDimitry Andric           DeclRefExpr(*Context, SuperConstructorFunctionDecl, false, superType,
33700b57cec5SDimitry Andric                       VK_LValue, SourceLocation());
3371e8d8bef9SDimitry Andric       SuperRep =
3372e8d8bef9SDimitry Andric           CallExpr::Create(*Context, DRE, InitExprs, superType, VK_LValue,
3373e8d8bef9SDimitry Andric                            SourceLocation(), FPOptionsOverride());
33740b57cec5SDimitry Andric       // The code for super is a little tricky to prevent collision with
33750b57cec5SDimitry Andric       // the structure definition in the header. The rewriter has it's own
33760b57cec5SDimitry Andric       // internal definition (__rw_objc_super) that is uses. This is why
33770b57cec5SDimitry Andric       // we need the cast below. For example:
33780b57cec5SDimitry Andric       // (struct __rw_objc_super *)&__rw_objc_super((id)self, (id)objc_getClass("SUPER"))
33790b57cec5SDimitry Andric       //
33805ffd83dbSDimitry Andric       SuperRep = UnaryOperator::Create(
33815ffd83dbSDimitry Andric           const_cast<ASTContext &>(*Context), SuperRep, UO_AddrOf,
3382fe6060f1SDimitry Andric           Context->getPointerType(SuperRep->getType()), VK_PRValue, OK_Ordinary,
33835ffd83dbSDimitry Andric           SourceLocation(), false, FPOptionsOverride());
33840b57cec5SDimitry Andric       SuperRep = NoTypeInfoCStyleCastExpr(Context,
33850b57cec5SDimitry Andric                                Context->getPointerType(superType),
33860b57cec5SDimitry Andric                                CK_BitCast, SuperRep);
33870b57cec5SDimitry Andric     } else {
33880b57cec5SDimitry Andric       // (struct __rw_objc_super) { <exprs from above> }
33890b57cec5SDimitry Andric       InitListExpr *ILE =
33900b57cec5SDimitry Andric         new (Context) InitListExpr(*Context, SourceLocation(), InitExprs,
33910b57cec5SDimitry Andric                                    SourceLocation());
33920b57cec5SDimitry Andric       TypeSourceInfo *superTInfo
33930b57cec5SDimitry Andric         = Context->getTrivialTypeSourceInfo(superType);
3394fe6060f1SDimitry Andric       SuperRep = new (Context) CompoundLiteralExpr(
3395fe6060f1SDimitry Andric           SourceLocation(), superTInfo, superType, VK_PRValue, ILE, false);
33960b57cec5SDimitry Andric     }
33970b57cec5SDimitry Andric     MsgExprs.push_back(SuperRep);
33980b57cec5SDimitry Andric     break;
33990b57cec5SDimitry Andric   }
34000b57cec5SDimitry Andric 
34010b57cec5SDimitry Andric   case ObjCMessageExpr::Instance: {
34020b57cec5SDimitry Andric     // Remove all type-casts because it may contain objc-style types; e.g.
34030b57cec5SDimitry Andric     // Foo<Proto> *.
34040b57cec5SDimitry Andric     Expr *recExpr = Exp->getInstanceReceiver();
34050b57cec5SDimitry Andric     while (CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(recExpr))
34060b57cec5SDimitry Andric       recExpr = CE->getSubExpr();
34070b57cec5SDimitry Andric     CastKind CK = recExpr->getType()->isObjCObjectPointerType()
34080b57cec5SDimitry Andric                     ? CK_BitCast : recExpr->getType()->isBlockPointerType()
34090b57cec5SDimitry Andric                                      ? CK_BlockPointerToObjCPointerCast
34100b57cec5SDimitry Andric                                      : CK_CPointerToObjCPointerCast;
34110b57cec5SDimitry Andric 
34120b57cec5SDimitry Andric     recExpr = NoTypeInfoCStyleCastExpr(Context, Context->getObjCIdType(),
34130b57cec5SDimitry Andric                                        CK, recExpr);
34140b57cec5SDimitry Andric     MsgExprs.push_back(recExpr);
34150b57cec5SDimitry Andric     break;
34160b57cec5SDimitry Andric   }
34170b57cec5SDimitry Andric   }
34180b57cec5SDimitry Andric 
34190b57cec5SDimitry Andric   // Create a call to sel_registerName("selName"), it will be the 2nd argument.
34200b57cec5SDimitry Andric   SmallVector<Expr*, 8> SelExprs;
34210b57cec5SDimitry Andric   SelExprs.push_back(getStringLiteral(Exp->getSelector().getAsString()));
34220b57cec5SDimitry Andric   CallExpr *SelExp = SynthesizeCallToFunctionDecl(SelGetUidFunctionDecl,
34230b57cec5SDimitry Andric                                                   SelExprs, StartLoc, EndLoc);
34240b57cec5SDimitry Andric   MsgExprs.push_back(SelExp);
34250b57cec5SDimitry Andric 
34260b57cec5SDimitry Andric   // Now push any user supplied arguments.
34270b57cec5SDimitry Andric   for (unsigned i = 0; i < Exp->getNumArgs(); i++) {
34280b57cec5SDimitry Andric     Expr *userExpr = Exp->getArg(i);
34290b57cec5SDimitry Andric     // Make all implicit casts explicit...ICE comes in handy:-)
34300b57cec5SDimitry Andric     if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(userExpr)) {
34310b57cec5SDimitry Andric       // Reuse the ICE type, it is exactly what the doctor ordered.
34320b57cec5SDimitry Andric       QualType type = ICE->getType();
34330b57cec5SDimitry Andric       if (needToScanForQualifiers(type))
34340b57cec5SDimitry Andric         type = Context->getObjCIdType();
34350b57cec5SDimitry Andric       // Make sure we convert "type (^)(...)" to "type (*)(...)".
34360b57cec5SDimitry Andric       (void)convertBlockPointerToFunctionPointer(type);
34370b57cec5SDimitry Andric       const Expr *SubExpr = ICE->IgnoreParenImpCasts();
34380b57cec5SDimitry Andric       CastKind CK;
34390b57cec5SDimitry Andric       if (SubExpr->getType()->isIntegralType(*Context) &&
34400b57cec5SDimitry Andric           type->isBooleanType()) {
34410b57cec5SDimitry Andric         CK = CK_IntegralToBoolean;
34420b57cec5SDimitry Andric       } else if (type->isObjCObjectPointerType()) {
34430b57cec5SDimitry Andric         if (SubExpr->getType()->isBlockPointerType()) {
34440b57cec5SDimitry Andric           CK = CK_BlockPointerToObjCPointerCast;
34450b57cec5SDimitry Andric         } else if (SubExpr->getType()->isPointerType()) {
34460b57cec5SDimitry Andric           CK = CK_CPointerToObjCPointerCast;
34470b57cec5SDimitry Andric         } else {
34480b57cec5SDimitry Andric           CK = CK_BitCast;
34490b57cec5SDimitry Andric         }
34500b57cec5SDimitry Andric       } else {
34510b57cec5SDimitry Andric         CK = CK_BitCast;
34520b57cec5SDimitry Andric       }
34530b57cec5SDimitry Andric 
34540b57cec5SDimitry Andric       userExpr = NoTypeInfoCStyleCastExpr(Context, type, CK, userExpr);
34550b57cec5SDimitry Andric     }
34560b57cec5SDimitry Andric     // Make id<P...> cast into an 'id' cast.
34570b57cec5SDimitry Andric     else if (CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(userExpr)) {
34580b57cec5SDimitry Andric       if (CE->getType()->isObjCQualifiedIdType()) {
34590b57cec5SDimitry Andric         while ((CE = dyn_cast<CStyleCastExpr>(userExpr)))
34600b57cec5SDimitry Andric           userExpr = CE->getSubExpr();
34610b57cec5SDimitry Andric         CastKind CK;
34620b57cec5SDimitry Andric         if (userExpr->getType()->isIntegralType(*Context)) {
34630b57cec5SDimitry Andric           CK = CK_IntegralToPointer;
34640b57cec5SDimitry Andric         } else if (userExpr->getType()->isBlockPointerType()) {
34650b57cec5SDimitry Andric           CK = CK_BlockPointerToObjCPointerCast;
34660b57cec5SDimitry Andric         } else if (userExpr->getType()->isPointerType()) {
34670b57cec5SDimitry Andric           CK = CK_CPointerToObjCPointerCast;
34680b57cec5SDimitry Andric         } else {
34690b57cec5SDimitry Andric           CK = CK_BitCast;
34700b57cec5SDimitry Andric         }
34710b57cec5SDimitry Andric         userExpr = NoTypeInfoCStyleCastExpr(Context, Context->getObjCIdType(),
34720b57cec5SDimitry Andric                                             CK, userExpr);
34730b57cec5SDimitry Andric       }
34740b57cec5SDimitry Andric     }
34750b57cec5SDimitry Andric     MsgExprs.push_back(userExpr);
34760b57cec5SDimitry Andric     // We've transferred the ownership to MsgExprs. For now, we *don't* null
34770b57cec5SDimitry Andric     // out the argument in the original expression (since we aren't deleting
34780b57cec5SDimitry Andric     // the ObjCMessageExpr). See RewritePropertyOrImplicitSetter() usage for more info.
34790b57cec5SDimitry Andric     //Exp->setArg(i, 0);
34800b57cec5SDimitry Andric   }
34810b57cec5SDimitry Andric   // Generate the funky cast.
34820b57cec5SDimitry Andric   CastExpr *cast;
34830b57cec5SDimitry Andric   SmallVector<QualType, 8> ArgTypes;
34840b57cec5SDimitry Andric   QualType returnType;
34850b57cec5SDimitry Andric 
34860b57cec5SDimitry Andric   // Push 'id' and 'SEL', the 2 implicit arguments.
34870b57cec5SDimitry Andric   if (MsgSendFlavor == MsgSendSuperFunctionDecl)
34880b57cec5SDimitry Andric     ArgTypes.push_back(Context->getPointerType(getSuperStructType()));
34890b57cec5SDimitry Andric   else
34900b57cec5SDimitry Andric     ArgTypes.push_back(Context->getObjCIdType());
34910b57cec5SDimitry Andric   ArgTypes.push_back(Context->getObjCSelType());
34920b57cec5SDimitry Andric   if (ObjCMethodDecl *OMD = Exp->getMethodDecl()) {
34930b57cec5SDimitry Andric     // Push any user argument types.
34940b57cec5SDimitry Andric     for (const auto *PI : OMD->parameters()) {
34950b57cec5SDimitry Andric       QualType t = PI->getType()->isObjCQualifiedIdType()
34960b57cec5SDimitry Andric                      ? Context->getObjCIdType()
34970b57cec5SDimitry Andric                      : PI->getType();
34980b57cec5SDimitry Andric       // Make sure we convert "t (^)(...)" to "t (*)(...)".
34990b57cec5SDimitry Andric       (void)convertBlockPointerToFunctionPointer(t);
35000b57cec5SDimitry Andric       ArgTypes.push_back(t);
35010b57cec5SDimitry Andric     }
35020b57cec5SDimitry Andric     returnType = Exp->getType();
35030b57cec5SDimitry Andric     convertToUnqualifiedObjCType(returnType);
35040b57cec5SDimitry Andric     (void)convertBlockPointerToFunctionPointer(returnType);
35050b57cec5SDimitry Andric   } else {
35060b57cec5SDimitry Andric     returnType = Context->getObjCIdType();
35070b57cec5SDimitry Andric   }
35080b57cec5SDimitry Andric   // Get the type, we will need to reference it in a couple spots.
35090b57cec5SDimitry Andric   QualType msgSendType = MsgSendFlavor->getType();
35100b57cec5SDimitry Andric 
35110b57cec5SDimitry Andric   // Create a reference to the objc_msgSend() declaration.
35120b57cec5SDimitry Andric   DeclRefExpr *DRE = new (Context) DeclRefExpr(
35130b57cec5SDimitry Andric       *Context, MsgSendFlavor, false, msgSendType, VK_LValue, SourceLocation());
35140b57cec5SDimitry Andric 
35150b57cec5SDimitry Andric   // Need to cast objc_msgSend to "void *" (to workaround a GCC bandaid).
35160b57cec5SDimitry Andric   // If we don't do this cast, we get the following bizarre warning/note:
35170b57cec5SDimitry Andric   // xx.m:13: warning: function called through a non-compatible type
35180b57cec5SDimitry Andric   // xx.m:13: note: if this code is reached, the program will abort
35190b57cec5SDimitry Andric   cast = NoTypeInfoCStyleCastExpr(Context,
35200b57cec5SDimitry Andric                                   Context->getPointerType(Context->VoidTy),
35210b57cec5SDimitry Andric                                   CK_BitCast, DRE);
35220b57cec5SDimitry Andric 
35230b57cec5SDimitry Andric   // Now do the "normal" pointer to function cast.
35240b57cec5SDimitry Andric   // If we don't have a method decl, force a variadic cast.
35250b57cec5SDimitry Andric   const ObjCMethodDecl *MD = Exp->getMethodDecl();
35260b57cec5SDimitry Andric   QualType castType =
35270b57cec5SDimitry Andric     getSimpleFunctionType(returnType, ArgTypes, MD ? MD->isVariadic() : true);
35280b57cec5SDimitry Andric   castType = Context->getPointerType(castType);
35290b57cec5SDimitry Andric   cast = NoTypeInfoCStyleCastExpr(Context, castType, CK_BitCast,
35300b57cec5SDimitry Andric                                   cast);
35310b57cec5SDimitry Andric 
35320b57cec5SDimitry Andric   // Don't forget the parens to enforce the proper binding.
35330b57cec5SDimitry Andric   ParenExpr *PE = new (Context) ParenExpr(StartLoc, EndLoc, cast);
35340b57cec5SDimitry Andric 
3535a7dea167SDimitry Andric   const FunctionType *FT = msgSendType->castAs<FunctionType>();
35360b57cec5SDimitry Andric   CallExpr *CE = CallExpr::Create(*Context, PE, MsgExprs, FT->getReturnType(),
3537fe6060f1SDimitry Andric                                   VK_PRValue, EndLoc, FPOptionsOverride());
35380b57cec5SDimitry Andric   Stmt *ReplacingStmt = CE;
35390b57cec5SDimitry Andric   if (MsgSendStretFlavor) {
35400b57cec5SDimitry Andric     // We have the method which returns a struct/union. Must also generate
35410b57cec5SDimitry Andric     // call to objc_msgSend_stret and hang both varieties on a conditional
35420b57cec5SDimitry Andric     // expression which dictate which one to envoke depending on size of
35430b57cec5SDimitry Andric     // method's return type.
35440b57cec5SDimitry Andric 
35450b57cec5SDimitry Andric     Expr *STCE = SynthMsgSendStretCallExpr(MsgSendStretFlavor,
35460b57cec5SDimitry Andric                                            returnType,
35470b57cec5SDimitry Andric                                            ArgTypes, MsgExprs,
35480b57cec5SDimitry Andric                                            Exp->getMethodDecl());
35490b57cec5SDimitry Andric     ReplacingStmt = STCE;
35500b57cec5SDimitry Andric   }
35510b57cec5SDimitry Andric   // delete Exp; leak for now, see RewritePropertyOrImplicitSetter() usage for more info.
35520b57cec5SDimitry Andric   return ReplacingStmt;
35530b57cec5SDimitry Andric }
35540b57cec5SDimitry Andric 
RewriteMessageExpr(ObjCMessageExpr * Exp)35550b57cec5SDimitry Andric Stmt *RewriteModernObjC::RewriteMessageExpr(ObjCMessageExpr *Exp) {
35560b57cec5SDimitry Andric   Stmt *ReplacingStmt =
35570b57cec5SDimitry Andric       SynthMessageExpr(Exp, Exp->getBeginLoc(), Exp->getEndLoc());
35580b57cec5SDimitry Andric 
35590b57cec5SDimitry Andric   // Now do the actual rewrite.
35600b57cec5SDimitry Andric   ReplaceStmt(Exp, ReplacingStmt);
35610b57cec5SDimitry Andric 
35620b57cec5SDimitry Andric   // delete Exp; leak for now, see RewritePropertyOrImplicitSetter() usage for more info.
35630b57cec5SDimitry Andric   return ReplacingStmt;
35640b57cec5SDimitry Andric }
35650b57cec5SDimitry Andric 
35660b57cec5SDimitry Andric // typedef struct objc_object Protocol;
getProtocolType()35670b57cec5SDimitry Andric QualType RewriteModernObjC::getProtocolType() {
35680b57cec5SDimitry Andric   if (!ProtocolTypeDecl) {
35690b57cec5SDimitry Andric     TypeSourceInfo *TInfo
35700b57cec5SDimitry Andric       = Context->getTrivialTypeSourceInfo(Context->getObjCIdType());
35710b57cec5SDimitry Andric     ProtocolTypeDecl = TypedefDecl::Create(*Context, TUDecl,
35720b57cec5SDimitry Andric                                            SourceLocation(), SourceLocation(),
35730b57cec5SDimitry Andric                                            &Context->Idents.get("Protocol"),
35740b57cec5SDimitry Andric                                            TInfo);
35750b57cec5SDimitry Andric   }
35760b57cec5SDimitry Andric   return Context->getTypeDeclType(ProtocolTypeDecl);
35770b57cec5SDimitry Andric }
35780b57cec5SDimitry Andric 
35790b57cec5SDimitry Andric /// RewriteObjCProtocolExpr - Rewrite a protocol expression into
35800b57cec5SDimitry Andric /// a synthesized/forward data reference (to the protocol's metadata).
35810b57cec5SDimitry Andric /// The forward references (and metadata) are generated in
35820b57cec5SDimitry Andric /// RewriteModernObjC::HandleTranslationUnit().
RewriteObjCProtocolExpr(ObjCProtocolExpr * Exp)35830b57cec5SDimitry Andric Stmt *RewriteModernObjC::RewriteObjCProtocolExpr(ObjCProtocolExpr *Exp) {
35840b57cec5SDimitry Andric   std::string Name = "_OBJC_PROTOCOL_REFERENCE_$_" +
35850b57cec5SDimitry Andric                       Exp->getProtocol()->getNameAsString();
35860b57cec5SDimitry Andric   IdentifierInfo *ID = &Context->Idents.get(Name);
35870b57cec5SDimitry Andric   VarDecl *VD = VarDecl::Create(*Context, TUDecl, SourceLocation(),
35880b57cec5SDimitry Andric                                 SourceLocation(), ID, getProtocolType(),
35890b57cec5SDimitry Andric                                 nullptr, SC_Extern);
35900b57cec5SDimitry Andric   DeclRefExpr *DRE = new (Context) DeclRefExpr(
35910b57cec5SDimitry Andric       *Context, VD, false, getProtocolType(), VK_LValue, SourceLocation());
35920b57cec5SDimitry Andric   CastExpr *castExpr = NoTypeInfoCStyleCastExpr(
35930b57cec5SDimitry Andric       Context, Context->getPointerType(DRE->getType()), CK_BitCast, DRE);
35940b57cec5SDimitry Andric   ReplaceStmt(Exp, castExpr);
35950b57cec5SDimitry Andric   ProtocolExprDecls.insert(Exp->getProtocol()->getCanonicalDecl());
35960b57cec5SDimitry Andric   // delete Exp; leak for now, see RewritePropertyOrImplicitSetter() usage for more info.
35970b57cec5SDimitry Andric   return castExpr;
35980b57cec5SDimitry Andric }
35990b57cec5SDimitry Andric 
36000b57cec5SDimitry Andric /// IsTagDefinedInsideClass - This routine checks that a named tagged type
36010b57cec5SDimitry Andric /// is defined inside an objective-c class. If so, it returns true.
IsTagDefinedInsideClass(ObjCContainerDecl * IDecl,TagDecl * Tag,bool & IsNamedDefinition)36020b57cec5SDimitry Andric bool RewriteModernObjC::IsTagDefinedInsideClass(ObjCContainerDecl *IDecl,
36030b57cec5SDimitry Andric                                                 TagDecl *Tag,
36040b57cec5SDimitry Andric                                                 bool &IsNamedDefinition) {
36050b57cec5SDimitry Andric   if (!IDecl)
36060b57cec5SDimitry Andric     return false;
36070b57cec5SDimitry Andric   SourceLocation TagLocation;
36080b57cec5SDimitry Andric   if (RecordDecl *RD = dyn_cast<RecordDecl>(Tag)) {
36090b57cec5SDimitry Andric     RD = RD->getDefinition();
36100b57cec5SDimitry Andric     if (!RD || !RD->getDeclName().getAsIdentifierInfo())
36110b57cec5SDimitry Andric       return false;
36120b57cec5SDimitry Andric     IsNamedDefinition = true;
36130b57cec5SDimitry Andric     TagLocation = RD->getLocation();
36140b57cec5SDimitry Andric     return Context->getSourceManager().isBeforeInTranslationUnit(
36150b57cec5SDimitry Andric                                           IDecl->getLocation(), TagLocation);
36160b57cec5SDimitry Andric   }
36170b57cec5SDimitry Andric   if (EnumDecl *ED = dyn_cast<EnumDecl>(Tag)) {
36180b57cec5SDimitry Andric     if (!ED || !ED->getDeclName().getAsIdentifierInfo())
36190b57cec5SDimitry Andric       return false;
36200b57cec5SDimitry Andric     IsNamedDefinition = true;
36210b57cec5SDimitry Andric     TagLocation = ED->getLocation();
36220b57cec5SDimitry Andric     return Context->getSourceManager().isBeforeInTranslationUnit(
36230b57cec5SDimitry Andric                                           IDecl->getLocation(), TagLocation);
36240b57cec5SDimitry Andric   }
36250b57cec5SDimitry Andric   return false;
36260b57cec5SDimitry Andric }
36270b57cec5SDimitry Andric 
36280b57cec5SDimitry Andric /// RewriteObjCFieldDeclType - This routine rewrites a type into the buffer.
36290b57cec5SDimitry Andric /// It handles elaborated types, as well as enum types in the process.
RewriteObjCFieldDeclType(QualType & Type,std::string & Result)36300b57cec5SDimitry Andric bool RewriteModernObjC::RewriteObjCFieldDeclType(QualType &Type,
36310b57cec5SDimitry Andric                                                  std::string &Result) {
3632bdd1243dSDimitry Andric   if (Type->getAs<TypedefType>()) {
36330b57cec5SDimitry Andric     Result += "\t";
36340b57cec5SDimitry Andric     return false;
36350b57cec5SDimitry Andric   }
36360b57cec5SDimitry Andric 
36370b57cec5SDimitry Andric   if (Type->isArrayType()) {
36380b57cec5SDimitry Andric     QualType ElemTy = Context->getBaseElementType(Type);
36390b57cec5SDimitry Andric     return RewriteObjCFieldDeclType(ElemTy, Result);
36400b57cec5SDimitry Andric   }
36410b57cec5SDimitry Andric   else if (Type->isRecordType()) {
3642a7dea167SDimitry Andric     RecordDecl *RD = Type->castAs<RecordType>()->getDecl();
36430b57cec5SDimitry Andric     if (RD->isCompleteDefinition()) {
36440b57cec5SDimitry Andric       if (RD->isStruct())
36450b57cec5SDimitry Andric         Result += "\n\tstruct ";
36460b57cec5SDimitry Andric       else if (RD->isUnion())
36470b57cec5SDimitry Andric         Result += "\n\tunion ";
36480b57cec5SDimitry Andric       else
36490b57cec5SDimitry Andric         assert(false && "class not allowed as an ivar type");
36500b57cec5SDimitry Andric 
36510b57cec5SDimitry Andric       Result += RD->getName();
36520b57cec5SDimitry Andric       if (GlobalDefinedTags.count(RD)) {
36530b57cec5SDimitry Andric         // struct/union is defined globally, use it.
36540b57cec5SDimitry Andric         Result += " ";
36550b57cec5SDimitry Andric         return true;
36560b57cec5SDimitry Andric       }
36570b57cec5SDimitry Andric       Result += " {\n";
36580b57cec5SDimitry Andric       for (auto *FD : RD->fields())
36590b57cec5SDimitry Andric         RewriteObjCFieldDecl(FD, Result);
36600b57cec5SDimitry Andric       Result += "\t} ";
36610b57cec5SDimitry Andric       return true;
36620b57cec5SDimitry Andric     }
36630b57cec5SDimitry Andric   }
36640b57cec5SDimitry Andric   else if (Type->isEnumeralType()) {
3665a7dea167SDimitry Andric     EnumDecl *ED = Type->castAs<EnumType>()->getDecl();
36660b57cec5SDimitry Andric     if (ED->isCompleteDefinition()) {
36670b57cec5SDimitry Andric       Result += "\n\tenum ";
36680b57cec5SDimitry Andric       Result += ED->getName();
36690b57cec5SDimitry Andric       if (GlobalDefinedTags.count(ED)) {
36700b57cec5SDimitry Andric         // Enum is globall defined, use it.
36710b57cec5SDimitry Andric         Result += " ";
36720b57cec5SDimitry Andric         return true;
36730b57cec5SDimitry Andric       }
36740b57cec5SDimitry Andric 
36750b57cec5SDimitry Andric       Result += " {\n";
36760b57cec5SDimitry Andric       for (const auto *EC : ED->enumerators()) {
36770b57cec5SDimitry Andric         Result += "\t"; Result += EC->getName(); Result += " = ";
3678fe6060f1SDimitry Andric         Result += toString(EC->getInitVal(), 10);
36790b57cec5SDimitry Andric         Result += ",\n";
36800b57cec5SDimitry Andric       }
36810b57cec5SDimitry Andric       Result += "\t} ";
36820b57cec5SDimitry Andric       return true;
36830b57cec5SDimitry Andric     }
36840b57cec5SDimitry Andric   }
36850b57cec5SDimitry Andric 
36860b57cec5SDimitry Andric   Result += "\t";
36870b57cec5SDimitry Andric   convertObjCTypeToCStyleType(Type);
36880b57cec5SDimitry Andric   return false;
36890b57cec5SDimitry Andric }
36900b57cec5SDimitry Andric 
36910b57cec5SDimitry Andric 
36920b57cec5SDimitry Andric /// RewriteObjCFieldDecl - This routine rewrites a field into the buffer.
36930b57cec5SDimitry Andric /// It handles elaborated types, as well as enum types in the process.
RewriteObjCFieldDecl(FieldDecl * fieldDecl,std::string & Result)36940b57cec5SDimitry Andric void RewriteModernObjC::RewriteObjCFieldDecl(FieldDecl *fieldDecl,
36950b57cec5SDimitry Andric                                              std::string &Result) {
36960b57cec5SDimitry Andric   QualType Type = fieldDecl->getType();
36970b57cec5SDimitry Andric   std::string Name = fieldDecl->getNameAsString();
36980b57cec5SDimitry Andric 
36990b57cec5SDimitry Andric   bool EleboratedType = RewriteObjCFieldDeclType(Type, Result);
37000b57cec5SDimitry Andric   if (!EleboratedType)
37010b57cec5SDimitry Andric     Type.getAsStringInternal(Name, Context->getPrintingPolicy());
37020b57cec5SDimitry Andric   Result += Name;
37030b57cec5SDimitry Andric   if (fieldDecl->isBitField()) {
37040b57cec5SDimitry Andric     Result += " : "; Result += utostr(fieldDecl->getBitWidthValue(*Context));
37050b57cec5SDimitry Andric   }
37060b57cec5SDimitry Andric   else if (EleboratedType && Type->isArrayType()) {
37070b57cec5SDimitry Andric     const ArrayType *AT = Context->getAsArrayType(Type);
37080b57cec5SDimitry Andric     do {
37090b57cec5SDimitry Andric       if (const ConstantArrayType *CAT = dyn_cast<ConstantArrayType>(AT)) {
37100b57cec5SDimitry Andric         Result += "[";
37110b57cec5SDimitry Andric         llvm::APInt Dim = CAT->getSize();
37120b57cec5SDimitry Andric         Result += utostr(Dim.getZExtValue());
37130b57cec5SDimitry Andric         Result += "]";
37140b57cec5SDimitry Andric       }
37150b57cec5SDimitry Andric       AT = Context->getAsArrayType(AT->getElementType());
37160b57cec5SDimitry Andric     } while (AT);
37170b57cec5SDimitry Andric   }
37180b57cec5SDimitry Andric 
37190b57cec5SDimitry Andric   Result += ";\n";
37200b57cec5SDimitry Andric }
37210b57cec5SDimitry Andric 
37220b57cec5SDimitry Andric /// RewriteLocallyDefinedNamedAggregates - This routine rewrites locally defined
37230b57cec5SDimitry Andric /// named aggregate types into the input buffer.
RewriteLocallyDefinedNamedAggregates(FieldDecl * fieldDecl,std::string & Result)37240b57cec5SDimitry Andric void RewriteModernObjC::RewriteLocallyDefinedNamedAggregates(FieldDecl *fieldDecl,
37250b57cec5SDimitry Andric                                              std::string &Result) {
37260b57cec5SDimitry Andric   QualType Type = fieldDecl->getType();
3727bdd1243dSDimitry Andric   if (Type->getAs<TypedefType>())
37280b57cec5SDimitry Andric     return;
37290b57cec5SDimitry Andric   if (Type->isArrayType())
37300b57cec5SDimitry Andric     Type = Context->getBaseElementType(Type);
3731a7dea167SDimitry Andric 
3732a7dea167SDimitry Andric   auto *IDecl = dyn_cast<ObjCContainerDecl>(fieldDecl->getDeclContext());
37330b57cec5SDimitry Andric 
37340b57cec5SDimitry Andric   TagDecl *TD = nullptr;
37350b57cec5SDimitry Andric   if (Type->isRecordType()) {
3736a7dea167SDimitry Andric     TD = Type->castAs<RecordType>()->getDecl();
37370b57cec5SDimitry Andric   }
37380b57cec5SDimitry Andric   else if (Type->isEnumeralType()) {
3739a7dea167SDimitry Andric     TD = Type->castAs<EnumType>()->getDecl();
37400b57cec5SDimitry Andric   }
37410b57cec5SDimitry Andric 
37420b57cec5SDimitry Andric   if (TD) {
37430b57cec5SDimitry Andric     if (GlobalDefinedTags.count(TD))
37440b57cec5SDimitry Andric       return;
37450b57cec5SDimitry Andric 
37460b57cec5SDimitry Andric     bool IsNamedDefinition = false;
37470b57cec5SDimitry Andric     if (IsTagDefinedInsideClass(IDecl, TD, IsNamedDefinition)) {
37480b57cec5SDimitry Andric       RewriteObjCFieldDeclType(Type, Result);
37490b57cec5SDimitry Andric       Result += ";";
37500b57cec5SDimitry Andric     }
37510b57cec5SDimitry Andric     if (IsNamedDefinition)
37520b57cec5SDimitry Andric       GlobalDefinedTags.insert(TD);
37530b57cec5SDimitry Andric   }
37540b57cec5SDimitry Andric }
37550b57cec5SDimitry Andric 
ObjCIvarBitfieldGroupNo(ObjCIvarDecl * IV)37560b57cec5SDimitry Andric unsigned RewriteModernObjC::ObjCIvarBitfieldGroupNo(ObjCIvarDecl *IV) {
37570b57cec5SDimitry Andric   const ObjCInterfaceDecl *CDecl = IV->getContainingInterface();
37580b57cec5SDimitry Andric   if (ObjCInterefaceHasBitfieldGroups.count(CDecl)) {
37590b57cec5SDimitry Andric     return IvarGroupNumber[IV];
37600b57cec5SDimitry Andric   }
37610b57cec5SDimitry Andric   unsigned GroupNo = 0;
37620b57cec5SDimitry Andric   SmallVector<const ObjCIvarDecl *, 8> IVars;
37630b57cec5SDimitry Andric   for (const ObjCIvarDecl *IVD = CDecl->all_declared_ivar_begin();
37640b57cec5SDimitry Andric        IVD; IVD = IVD->getNextIvar())
37650b57cec5SDimitry Andric     IVars.push_back(IVD);
37660b57cec5SDimitry Andric 
37670b57cec5SDimitry Andric   for (unsigned i = 0, e = IVars.size(); i < e; i++)
37680b57cec5SDimitry Andric     if (IVars[i]->isBitField()) {
37690b57cec5SDimitry Andric       IvarGroupNumber[IVars[i++]] = ++GroupNo;
37700b57cec5SDimitry Andric       while (i < e && IVars[i]->isBitField())
37710b57cec5SDimitry Andric         IvarGroupNumber[IVars[i++]] = GroupNo;
37720b57cec5SDimitry Andric       if (i < e)
37730b57cec5SDimitry Andric         --i;
37740b57cec5SDimitry Andric     }
37750b57cec5SDimitry Andric 
37760b57cec5SDimitry Andric   ObjCInterefaceHasBitfieldGroups.insert(CDecl);
37770b57cec5SDimitry Andric   return IvarGroupNumber[IV];
37780b57cec5SDimitry Andric }
37790b57cec5SDimitry Andric 
SynthesizeBitfieldGroupStructType(ObjCIvarDecl * IV,SmallVectorImpl<ObjCIvarDecl * > & IVars)37800b57cec5SDimitry Andric QualType RewriteModernObjC::SynthesizeBitfieldGroupStructType(
37810b57cec5SDimitry Andric                               ObjCIvarDecl *IV,
37820b57cec5SDimitry Andric                               SmallVectorImpl<ObjCIvarDecl *> &IVars) {
37830b57cec5SDimitry Andric   std::string StructTagName;
37840b57cec5SDimitry Andric   ObjCIvarBitfieldGroupType(IV, StructTagName);
37855f757f3fSDimitry Andric   RecordDecl *RD = RecordDecl::Create(
37865f757f3fSDimitry Andric       *Context, TagTypeKind::Struct, Context->getTranslationUnitDecl(),
37875f757f3fSDimitry Andric       SourceLocation(), SourceLocation(), &Context->Idents.get(StructTagName));
37880b57cec5SDimitry Andric   for (unsigned i=0, e = IVars.size(); i < e; i++) {
37890b57cec5SDimitry Andric     ObjCIvarDecl *Ivar = IVars[i];
37900b57cec5SDimitry Andric     RD->addDecl(FieldDecl::Create(*Context, RD, SourceLocation(), SourceLocation(),
37910b57cec5SDimitry Andric                                   &Context->Idents.get(Ivar->getName()),
37920b57cec5SDimitry Andric                                   Ivar->getType(),
37930b57cec5SDimitry Andric                                   nullptr, /*Expr *BW */Ivar->getBitWidth(),
37940b57cec5SDimitry Andric                                   false, ICIS_NoInit));
37950b57cec5SDimitry Andric   }
37960b57cec5SDimitry Andric   RD->completeDefinition();
37970b57cec5SDimitry Andric   return Context->getTagDeclType(RD);
37980b57cec5SDimitry Andric }
37990b57cec5SDimitry Andric 
GetGroupRecordTypeForObjCIvarBitfield(ObjCIvarDecl * IV)38000b57cec5SDimitry Andric QualType RewriteModernObjC::GetGroupRecordTypeForObjCIvarBitfield(ObjCIvarDecl *IV) {
38010b57cec5SDimitry Andric   const ObjCInterfaceDecl *CDecl = IV->getContainingInterface();
38020b57cec5SDimitry Andric   unsigned GroupNo = ObjCIvarBitfieldGroupNo(IV);
38030b57cec5SDimitry Andric   std::pair<const ObjCInterfaceDecl*, unsigned> tuple = std::make_pair(CDecl, GroupNo);
38040b57cec5SDimitry Andric   if (GroupRecordType.count(tuple))
38050b57cec5SDimitry Andric     return GroupRecordType[tuple];
38060b57cec5SDimitry Andric 
38070b57cec5SDimitry Andric   SmallVector<ObjCIvarDecl *, 8> IVars;
38080b57cec5SDimitry Andric   for (const ObjCIvarDecl *IVD = CDecl->all_declared_ivar_begin();
38090b57cec5SDimitry Andric        IVD; IVD = IVD->getNextIvar()) {
38100b57cec5SDimitry Andric     if (IVD->isBitField())
38110b57cec5SDimitry Andric       IVars.push_back(const_cast<ObjCIvarDecl *>(IVD));
38120b57cec5SDimitry Andric     else {
38130b57cec5SDimitry Andric       if (!IVars.empty()) {
38140b57cec5SDimitry Andric         unsigned GroupNo = ObjCIvarBitfieldGroupNo(IVars[0]);
38150b57cec5SDimitry Andric         // Generate the struct type for this group of bitfield ivars.
38160b57cec5SDimitry Andric         GroupRecordType[std::make_pair(CDecl, GroupNo)] =
38170b57cec5SDimitry Andric           SynthesizeBitfieldGroupStructType(IVars[0], IVars);
38180b57cec5SDimitry Andric         IVars.clear();
38190b57cec5SDimitry Andric       }
38200b57cec5SDimitry Andric     }
38210b57cec5SDimitry Andric   }
38220b57cec5SDimitry Andric   if (!IVars.empty()) {
38230b57cec5SDimitry Andric     // Do the last one.
38240b57cec5SDimitry Andric     unsigned GroupNo = ObjCIvarBitfieldGroupNo(IVars[0]);
38250b57cec5SDimitry Andric     GroupRecordType[std::make_pair(CDecl, GroupNo)] =
38260b57cec5SDimitry Andric       SynthesizeBitfieldGroupStructType(IVars[0], IVars);
38270b57cec5SDimitry Andric   }
38280b57cec5SDimitry Andric   QualType RetQT = GroupRecordType[tuple];
38290b57cec5SDimitry Andric   assert(!RetQT.isNull() && "GetGroupRecordTypeForObjCIvarBitfield struct type is NULL");
38300b57cec5SDimitry Andric 
38310b57cec5SDimitry Andric   return RetQT;
38320b57cec5SDimitry Andric }
38330b57cec5SDimitry Andric 
38340b57cec5SDimitry Andric /// ObjCIvarBitfieldGroupDecl - Names field decl. for ivar bitfield group.
38350b57cec5SDimitry Andric /// Name would be: classname__GRBF_n where n is the group number for this ivar.
ObjCIvarBitfieldGroupDecl(ObjCIvarDecl * IV,std::string & Result)38360b57cec5SDimitry Andric void RewriteModernObjC::ObjCIvarBitfieldGroupDecl(ObjCIvarDecl *IV,
38370b57cec5SDimitry Andric                                                   std::string &Result) {
38380b57cec5SDimitry Andric   const ObjCInterfaceDecl *CDecl = IV->getContainingInterface();
38390b57cec5SDimitry Andric   Result += CDecl->getName();
38400b57cec5SDimitry Andric   Result += "__GRBF_";
38410b57cec5SDimitry Andric   unsigned GroupNo = ObjCIvarBitfieldGroupNo(IV);
38420b57cec5SDimitry Andric   Result += utostr(GroupNo);
38430b57cec5SDimitry Andric }
38440b57cec5SDimitry Andric 
38450b57cec5SDimitry Andric /// ObjCIvarBitfieldGroupType - Names struct type for ivar bitfield group.
38460b57cec5SDimitry Andric /// Name of the struct would be: classname__T_n where n is the group number for
38470b57cec5SDimitry Andric /// this ivar.
ObjCIvarBitfieldGroupType(ObjCIvarDecl * IV,std::string & Result)38480b57cec5SDimitry Andric void RewriteModernObjC::ObjCIvarBitfieldGroupType(ObjCIvarDecl *IV,
38490b57cec5SDimitry Andric                                                   std::string &Result) {
38500b57cec5SDimitry Andric   const ObjCInterfaceDecl *CDecl = IV->getContainingInterface();
38510b57cec5SDimitry Andric   Result += CDecl->getName();
38520b57cec5SDimitry Andric   Result += "__T_";
38530b57cec5SDimitry Andric   unsigned GroupNo = ObjCIvarBitfieldGroupNo(IV);
38540b57cec5SDimitry Andric   Result += utostr(GroupNo);
38550b57cec5SDimitry Andric }
38560b57cec5SDimitry Andric 
38570b57cec5SDimitry Andric /// ObjCIvarBitfieldGroupOffset - Names symbol for ivar bitfield group field offset.
38580b57cec5SDimitry Andric /// Name would be: OBJC_IVAR_$_classname__GRBF_n where n is the group number for
38590b57cec5SDimitry Andric /// this ivar.
ObjCIvarBitfieldGroupOffset(ObjCIvarDecl * IV,std::string & Result)38600b57cec5SDimitry Andric void RewriteModernObjC::ObjCIvarBitfieldGroupOffset(ObjCIvarDecl *IV,
38610b57cec5SDimitry Andric                                                     std::string &Result) {
38620b57cec5SDimitry Andric   Result += "OBJC_IVAR_$_";
38630b57cec5SDimitry Andric   ObjCIvarBitfieldGroupDecl(IV, Result);
38640b57cec5SDimitry Andric }
38650b57cec5SDimitry Andric 
38660b57cec5SDimitry Andric #define SKIP_BITFIELDS(IX, ENDIX, VEC) { \
38670b57cec5SDimitry Andric       while ((IX < ENDIX) && VEC[IX]->isBitField()) \
38680b57cec5SDimitry Andric         ++IX; \
38690b57cec5SDimitry Andric       if (IX < ENDIX) \
38700b57cec5SDimitry Andric         --IX; \
38710b57cec5SDimitry Andric }
38720b57cec5SDimitry Andric 
38730b57cec5SDimitry Andric /// RewriteObjCInternalStruct - Rewrite one internal struct corresponding to
38740b57cec5SDimitry Andric /// an objective-c class with ivars.
RewriteObjCInternalStruct(ObjCInterfaceDecl * CDecl,std::string & Result)38750b57cec5SDimitry Andric void RewriteModernObjC::RewriteObjCInternalStruct(ObjCInterfaceDecl *CDecl,
38760b57cec5SDimitry Andric                                                std::string &Result) {
38770b57cec5SDimitry Andric   assert(CDecl && "Class missing in SynthesizeObjCInternalStruct");
38780b57cec5SDimitry Andric   assert(CDecl->getName() != "" &&
38790b57cec5SDimitry Andric          "Name missing in SynthesizeObjCInternalStruct");
38800b57cec5SDimitry Andric   ObjCInterfaceDecl *RCDecl = CDecl->getSuperClass();
38810b57cec5SDimitry Andric   SmallVector<ObjCIvarDecl *, 8> IVars;
38820b57cec5SDimitry Andric   for (ObjCIvarDecl *IVD = CDecl->all_declared_ivar_begin();
38830b57cec5SDimitry Andric        IVD; IVD = IVD->getNextIvar())
38840b57cec5SDimitry Andric     IVars.push_back(IVD);
38850b57cec5SDimitry Andric 
38860b57cec5SDimitry Andric   SourceLocation LocStart = CDecl->getBeginLoc();
38870b57cec5SDimitry Andric   SourceLocation LocEnd = CDecl->getEndOfDefinitionLoc();
38880b57cec5SDimitry Andric 
38890b57cec5SDimitry Andric   const char *startBuf = SM->getCharacterData(LocStart);
38900b57cec5SDimitry Andric   const char *endBuf = SM->getCharacterData(LocEnd);
38910b57cec5SDimitry Andric 
38920b57cec5SDimitry Andric   // If no ivars and no root or if its root, directly or indirectly,
38930b57cec5SDimitry Andric   // have no ivars (thus not synthesized) then no need to synthesize this class.
38940b57cec5SDimitry Andric   if ((!CDecl->isThisDeclarationADefinition() || IVars.size() == 0) &&
38950b57cec5SDimitry Andric       (!RCDecl || !ObjCSynthesizedStructs.count(RCDecl))) {
38960b57cec5SDimitry Andric     endBuf += Lexer::MeasureTokenLength(LocEnd, *SM, LangOpts);
38970b57cec5SDimitry Andric     ReplaceText(LocStart, endBuf-startBuf, Result);
38980b57cec5SDimitry Andric     return;
38990b57cec5SDimitry Andric   }
39000b57cec5SDimitry Andric 
39010b57cec5SDimitry Andric   // Insert named struct/union definitions inside class to
39020b57cec5SDimitry Andric   // outer scope. This follows semantics of locally defined
39030b57cec5SDimitry Andric   // struct/unions in objective-c classes.
39040b57cec5SDimitry Andric   for (unsigned i = 0, e = IVars.size(); i < e; i++)
39050b57cec5SDimitry Andric     RewriteLocallyDefinedNamedAggregates(IVars[i], Result);
39060b57cec5SDimitry Andric 
39070b57cec5SDimitry Andric   // Insert named structs which are syntheized to group ivar bitfields
39080b57cec5SDimitry Andric   // to outer scope as well.
39090b57cec5SDimitry Andric   for (unsigned i = 0, e = IVars.size(); i < e; i++)
39100b57cec5SDimitry Andric     if (IVars[i]->isBitField()) {
39110b57cec5SDimitry Andric       ObjCIvarDecl *IV = IVars[i];
39120b57cec5SDimitry Andric       QualType QT = GetGroupRecordTypeForObjCIvarBitfield(IV);
39130b57cec5SDimitry Andric       RewriteObjCFieldDeclType(QT, Result);
39140b57cec5SDimitry Andric       Result += ";";
39150b57cec5SDimitry Andric       // skip over ivar bitfields in this group.
39160b57cec5SDimitry Andric       SKIP_BITFIELDS(i , e, IVars);
39170b57cec5SDimitry Andric     }
39180b57cec5SDimitry Andric 
39190b57cec5SDimitry Andric   Result += "\nstruct ";
39200b57cec5SDimitry Andric   Result += CDecl->getNameAsString();
39210b57cec5SDimitry Andric   Result += "_IMPL {\n";
39220b57cec5SDimitry Andric 
39230b57cec5SDimitry Andric   if (RCDecl && ObjCSynthesizedStructs.count(RCDecl)) {
39240b57cec5SDimitry Andric     Result += "\tstruct "; Result += RCDecl->getNameAsString();
39250b57cec5SDimitry Andric     Result += "_IMPL "; Result += RCDecl->getNameAsString();
39260b57cec5SDimitry Andric     Result += "_IVARS;\n";
39270b57cec5SDimitry Andric   }
39280b57cec5SDimitry Andric 
39290b57cec5SDimitry Andric   for (unsigned i = 0, e = IVars.size(); i < e; i++) {
39300b57cec5SDimitry Andric     if (IVars[i]->isBitField()) {
39310b57cec5SDimitry Andric       ObjCIvarDecl *IV = IVars[i];
39320b57cec5SDimitry Andric       Result += "\tstruct ";
39330b57cec5SDimitry Andric       ObjCIvarBitfieldGroupType(IV, Result); Result += " ";
39340b57cec5SDimitry Andric       ObjCIvarBitfieldGroupDecl(IV, Result); Result += ";\n";
39350b57cec5SDimitry Andric       // skip over ivar bitfields in this group.
39360b57cec5SDimitry Andric       SKIP_BITFIELDS(i , e, IVars);
39370b57cec5SDimitry Andric     }
39380b57cec5SDimitry Andric     else
39390b57cec5SDimitry Andric       RewriteObjCFieldDecl(IVars[i], Result);
39400b57cec5SDimitry Andric   }
39410b57cec5SDimitry Andric 
39420b57cec5SDimitry Andric   Result += "};\n";
39430b57cec5SDimitry Andric   endBuf += Lexer::MeasureTokenLength(LocEnd, *SM, LangOpts);
39440b57cec5SDimitry Andric   ReplaceText(LocStart, endBuf-startBuf, Result);
39450b57cec5SDimitry Andric   // Mark this struct as having been generated.
39460b57cec5SDimitry Andric   if (!ObjCSynthesizedStructs.insert(CDecl).second)
39470b57cec5SDimitry Andric     llvm_unreachable("struct already synthesize- RewriteObjCInternalStruct");
39480b57cec5SDimitry Andric }
39490b57cec5SDimitry Andric 
39500b57cec5SDimitry Andric /// RewriteIvarOffsetSymbols - Rewrite ivar offset symbols of those ivars which
39510b57cec5SDimitry Andric /// have been referenced in an ivar access expression.
RewriteIvarOffsetSymbols(ObjCInterfaceDecl * CDecl,std::string & Result)39520b57cec5SDimitry Andric void RewriteModernObjC::RewriteIvarOffsetSymbols(ObjCInterfaceDecl *CDecl,
39530b57cec5SDimitry Andric                                                   std::string &Result) {
39540b57cec5SDimitry Andric   // write out ivar offset symbols which have been referenced in an ivar
39550b57cec5SDimitry Andric   // access expression.
39560b57cec5SDimitry Andric   llvm::SmallSetVector<ObjCIvarDecl *, 8> Ivars = ReferencedIvars[CDecl];
39570b57cec5SDimitry Andric 
39580b57cec5SDimitry Andric   if (Ivars.empty())
39590b57cec5SDimitry Andric     return;
39600b57cec5SDimitry Andric 
39610b57cec5SDimitry Andric   llvm::DenseSet<std::pair<const ObjCInterfaceDecl*, unsigned> > GroupSymbolOutput;
39620b57cec5SDimitry Andric   for (ObjCIvarDecl *IvarDecl : Ivars) {
39630b57cec5SDimitry Andric     const ObjCInterfaceDecl *IDecl = IvarDecl->getContainingInterface();
39640b57cec5SDimitry Andric     unsigned GroupNo = 0;
39650b57cec5SDimitry Andric     if (IvarDecl->isBitField()) {
39660b57cec5SDimitry Andric       GroupNo = ObjCIvarBitfieldGroupNo(IvarDecl);
39670b57cec5SDimitry Andric       if (GroupSymbolOutput.count(std::make_pair(IDecl, GroupNo)))
39680b57cec5SDimitry Andric         continue;
39690b57cec5SDimitry Andric     }
39700b57cec5SDimitry Andric     Result += "\n";
39710b57cec5SDimitry Andric     if (LangOpts.MicrosoftExt)
39720b57cec5SDimitry Andric       Result += "__declspec(allocate(\".objc_ivar$B\")) ";
39730b57cec5SDimitry Andric     Result += "extern \"C\" ";
39740b57cec5SDimitry Andric     if (LangOpts.MicrosoftExt &&
39750b57cec5SDimitry Andric         IvarDecl->getAccessControl() != ObjCIvarDecl::Private &&
39760b57cec5SDimitry Andric         IvarDecl->getAccessControl() != ObjCIvarDecl::Package)
39770b57cec5SDimitry Andric         Result += "__declspec(dllimport) ";
39780b57cec5SDimitry Andric 
39790b57cec5SDimitry Andric     Result += "unsigned long ";
39800b57cec5SDimitry Andric     if (IvarDecl->isBitField()) {
39810b57cec5SDimitry Andric       ObjCIvarBitfieldGroupOffset(IvarDecl, Result);
39820b57cec5SDimitry Andric       GroupSymbolOutput.insert(std::make_pair(IDecl, GroupNo));
39830b57cec5SDimitry Andric     }
39840b57cec5SDimitry Andric     else
39850b57cec5SDimitry Andric       WriteInternalIvarName(CDecl, IvarDecl, Result);
39860b57cec5SDimitry Andric     Result += ";";
39870b57cec5SDimitry Andric   }
39880b57cec5SDimitry Andric }
39890b57cec5SDimitry Andric 
39900b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
39910b57cec5SDimitry Andric // Meta Data Emission
39920b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
39930b57cec5SDimitry Andric 
39940b57cec5SDimitry Andric /// RewriteImplementations - This routine rewrites all method implementations
39950b57cec5SDimitry Andric /// and emits meta-data.
39960b57cec5SDimitry Andric 
RewriteImplementations()39970b57cec5SDimitry Andric void RewriteModernObjC::RewriteImplementations() {
39980b57cec5SDimitry Andric   int ClsDefCount = ClassImplementation.size();
39990b57cec5SDimitry Andric   int CatDefCount = CategoryImplementation.size();
40000b57cec5SDimitry Andric 
40010b57cec5SDimitry Andric   // Rewrite implemented methods
40020b57cec5SDimitry Andric   for (int i = 0; i < ClsDefCount; i++) {
40030b57cec5SDimitry Andric     ObjCImplementationDecl *OIMP = ClassImplementation[i];
40040b57cec5SDimitry Andric     ObjCInterfaceDecl *CDecl = OIMP->getClassInterface();
40050b57cec5SDimitry Andric     if (CDecl->isImplicitInterfaceDecl())
40060b57cec5SDimitry Andric       assert(false &&
40070b57cec5SDimitry Andric              "Legacy implicit interface rewriting not supported in moder abi");
40080b57cec5SDimitry Andric     RewriteImplementationDecl(OIMP);
40090b57cec5SDimitry Andric   }
40100b57cec5SDimitry Andric 
40110b57cec5SDimitry Andric   for (int i = 0; i < CatDefCount; i++) {
40120b57cec5SDimitry Andric     ObjCCategoryImplDecl *CIMP = CategoryImplementation[i];
40130b57cec5SDimitry Andric     ObjCInterfaceDecl *CDecl = CIMP->getClassInterface();
40140b57cec5SDimitry Andric     if (CDecl->isImplicitInterfaceDecl())
40150b57cec5SDimitry Andric       assert(false &&
40160b57cec5SDimitry Andric              "Legacy implicit interface rewriting not supported in moder abi");
40170b57cec5SDimitry Andric     RewriteImplementationDecl(CIMP);
40180b57cec5SDimitry Andric   }
40190b57cec5SDimitry Andric }
40200b57cec5SDimitry Andric 
RewriteByRefString(std::string & ResultStr,const std::string & Name,ValueDecl * VD,bool def)40210b57cec5SDimitry Andric void RewriteModernObjC::RewriteByRefString(std::string &ResultStr,
40220b57cec5SDimitry Andric                                      const std::string &Name,
40230b57cec5SDimitry Andric                                      ValueDecl *VD, bool def) {
40240b57cec5SDimitry Andric   assert(BlockByRefDeclNo.count(VD) &&
40250b57cec5SDimitry Andric          "RewriteByRefString: ByRef decl missing");
40260b57cec5SDimitry Andric   if (def)
40270b57cec5SDimitry Andric     ResultStr += "struct ";
40280b57cec5SDimitry Andric   ResultStr += "__Block_byref_" + Name +
40290b57cec5SDimitry Andric     "_" + utostr(BlockByRefDeclNo[VD]) ;
40300b57cec5SDimitry Andric }
40310b57cec5SDimitry Andric 
HasLocalVariableExternalStorage(ValueDecl * VD)40320b57cec5SDimitry Andric static bool HasLocalVariableExternalStorage(ValueDecl *VD) {
40330b57cec5SDimitry Andric   if (VarDecl *Var = dyn_cast<VarDecl>(VD))
40340b57cec5SDimitry Andric     return (Var->isFunctionOrMethodVarDecl() && !Var->hasLocalStorage());
40350b57cec5SDimitry Andric   return false;
40360b57cec5SDimitry Andric }
40370b57cec5SDimitry Andric 
SynthesizeBlockFunc(BlockExpr * CE,int i,StringRef funcName,std::string Tag)40380b57cec5SDimitry Andric std::string RewriteModernObjC::SynthesizeBlockFunc(BlockExpr *CE, int i,
40390b57cec5SDimitry Andric                                                    StringRef funcName,
40400b57cec5SDimitry Andric                                                    std::string Tag) {
40410b57cec5SDimitry Andric   const FunctionType *AFT = CE->getFunctionType();
40420b57cec5SDimitry Andric   QualType RT = AFT->getReturnType();
40430b57cec5SDimitry Andric   std::string StructRef = "struct " + Tag;
40440b57cec5SDimitry Andric   SourceLocation BlockLoc = CE->getExprLoc();
40450b57cec5SDimitry Andric   std::string S;
40460b57cec5SDimitry Andric   ConvertSourceLocationToLineDirective(BlockLoc, S);
40470b57cec5SDimitry Andric 
40480b57cec5SDimitry Andric   S += "static " + RT.getAsString(Context->getPrintingPolicy()) + " __" +
40490b57cec5SDimitry Andric          funcName.str() + "_block_func_" + utostr(i);
40500b57cec5SDimitry Andric 
40510b57cec5SDimitry Andric   BlockDecl *BD = CE->getBlockDecl();
40520b57cec5SDimitry Andric 
40530b57cec5SDimitry Andric   if (isa<FunctionNoProtoType>(AFT)) {
40540b57cec5SDimitry Andric     // No user-supplied arguments. Still need to pass in a pointer to the
40550b57cec5SDimitry Andric     // block (to reference imported block decl refs).
40560b57cec5SDimitry Andric     S += "(" + StructRef + " *__cself)";
40570b57cec5SDimitry Andric   } else if (BD->param_empty()) {
40580b57cec5SDimitry Andric     S += "(" + StructRef + " *__cself)";
40590b57cec5SDimitry Andric   } else {
40600b57cec5SDimitry Andric     const FunctionProtoType *FT = cast<FunctionProtoType>(AFT);
40610b57cec5SDimitry Andric     assert(FT && "SynthesizeBlockFunc: No function proto");
40620b57cec5SDimitry Andric     S += '(';
40630b57cec5SDimitry Andric     // first add the implicit argument.
40640b57cec5SDimitry Andric     S += StructRef + " *__cself, ";
40650b57cec5SDimitry Andric     std::string ParamStr;
40660b57cec5SDimitry Andric     for (BlockDecl::param_iterator AI = BD->param_begin(),
40670b57cec5SDimitry Andric          E = BD->param_end(); AI != E; ++AI) {
40680b57cec5SDimitry Andric       if (AI != BD->param_begin()) S += ", ";
40690b57cec5SDimitry Andric       ParamStr = (*AI)->getNameAsString();
40700b57cec5SDimitry Andric       QualType QT = (*AI)->getType();
40710b57cec5SDimitry Andric       (void)convertBlockPointerToFunctionPointer(QT);
40720b57cec5SDimitry Andric       QT.getAsStringInternal(ParamStr, Context->getPrintingPolicy());
40730b57cec5SDimitry Andric       S += ParamStr;
40740b57cec5SDimitry Andric     }
40750b57cec5SDimitry Andric     if (FT->isVariadic()) {
40760b57cec5SDimitry Andric       if (!BD->param_empty()) S += ", ";
40770b57cec5SDimitry Andric       S += "...";
40780b57cec5SDimitry Andric     }
40790b57cec5SDimitry Andric     S += ')';
40800b57cec5SDimitry Andric   }
40810b57cec5SDimitry Andric   S += " {\n";
40820b57cec5SDimitry Andric 
40830b57cec5SDimitry Andric   // Create local declarations to avoid rewriting all closure decl ref exprs.
40840b57cec5SDimitry Andric   // First, emit a declaration for all "by ref" decls.
40850b57cec5SDimitry Andric   for (SmallVectorImpl<ValueDecl *>::iterator I = BlockByRefDecls.begin(),
40860b57cec5SDimitry Andric        E = BlockByRefDecls.end(); I != E; ++I) {
40870b57cec5SDimitry Andric     S += "  ";
40880b57cec5SDimitry Andric     std::string Name = (*I)->getNameAsString();
40890b57cec5SDimitry Andric     std::string TypeString;
40900b57cec5SDimitry Andric     RewriteByRefString(TypeString, Name, (*I));
40910b57cec5SDimitry Andric     TypeString += " *";
40920b57cec5SDimitry Andric     Name = TypeString + Name;
40930b57cec5SDimitry Andric     S += Name + " = __cself->" + (*I)->getNameAsString() + "; // bound by ref\n";
40940b57cec5SDimitry Andric   }
40950b57cec5SDimitry Andric   // Next, emit a declaration for all "by copy" declarations.
40960b57cec5SDimitry Andric   for (SmallVectorImpl<ValueDecl *>::iterator I = BlockByCopyDecls.begin(),
40970b57cec5SDimitry Andric        E = BlockByCopyDecls.end(); I != E; ++I) {
40980b57cec5SDimitry Andric     S += "  ";
40990b57cec5SDimitry Andric     // Handle nested closure invocation. For example:
41000b57cec5SDimitry Andric     //
41010b57cec5SDimitry Andric     //   void (^myImportedClosure)(void);
41020b57cec5SDimitry Andric     //   myImportedClosure  = ^(void) { setGlobalInt(x + y); };
41030b57cec5SDimitry Andric     //
41040b57cec5SDimitry Andric     //   void (^anotherClosure)(void);
41050b57cec5SDimitry Andric     //   anotherClosure = ^(void) {
41060b57cec5SDimitry Andric     //     myImportedClosure(); // import and invoke the closure
41070b57cec5SDimitry Andric     //   };
41080b57cec5SDimitry Andric     //
41090b57cec5SDimitry Andric     if (isTopLevelBlockPointerType((*I)->getType())) {
41100b57cec5SDimitry Andric       RewriteBlockPointerTypeVariable(S, (*I));
41110b57cec5SDimitry Andric       S += " = (";
41120b57cec5SDimitry Andric       RewriteBlockPointerType(S, (*I)->getType());
41130b57cec5SDimitry Andric       S += ")";
41140b57cec5SDimitry Andric       S += "__cself->" + (*I)->getNameAsString() + "; // bound by copy\n";
41150b57cec5SDimitry Andric     }
41160b57cec5SDimitry Andric     else {
41170b57cec5SDimitry Andric       std::string Name = (*I)->getNameAsString();
41180b57cec5SDimitry Andric       QualType QT = (*I)->getType();
41190b57cec5SDimitry Andric       if (HasLocalVariableExternalStorage(*I))
41200b57cec5SDimitry Andric         QT = Context->getPointerType(QT);
41210b57cec5SDimitry Andric       QT.getAsStringInternal(Name, Context->getPrintingPolicy());
41220b57cec5SDimitry Andric       S += Name + " = __cself->" +
41230b57cec5SDimitry Andric                               (*I)->getNameAsString() + "; // bound by copy\n";
41240b57cec5SDimitry Andric     }
41250b57cec5SDimitry Andric   }
41260b57cec5SDimitry Andric   std::string RewrittenStr = RewrittenBlockExprs[CE];
41270b57cec5SDimitry Andric   const char *cstr = RewrittenStr.c_str();
41280b57cec5SDimitry Andric   while (*cstr++ != '{') ;
41290b57cec5SDimitry Andric   S += cstr;
41300b57cec5SDimitry Andric   S += "\n";
41310b57cec5SDimitry Andric   return S;
41320b57cec5SDimitry Andric }
41330b57cec5SDimitry Andric 
SynthesizeBlockHelperFuncs(BlockExpr * CE,int i,StringRef funcName,std::string Tag)41340b57cec5SDimitry Andric std::string RewriteModernObjC::SynthesizeBlockHelperFuncs(BlockExpr *CE, int i,
41350b57cec5SDimitry Andric                                                    StringRef funcName,
41360b57cec5SDimitry Andric                                                    std::string Tag) {
41370b57cec5SDimitry Andric   std::string StructRef = "struct " + Tag;
41380b57cec5SDimitry Andric   std::string S = "static void __";
41390b57cec5SDimitry Andric 
41400b57cec5SDimitry Andric   S += funcName;
41410b57cec5SDimitry Andric   S += "_block_copy_" + utostr(i);
41420b57cec5SDimitry Andric   S += "(" + StructRef;
41430b57cec5SDimitry Andric   S += "*dst, " + StructRef;
41440b57cec5SDimitry Andric   S += "*src) {";
41450b57cec5SDimitry Andric   for (ValueDecl *VD : ImportedBlockDecls) {
41460b57cec5SDimitry Andric     S += "_Block_object_assign((void*)&dst->";
41470b57cec5SDimitry Andric     S += VD->getNameAsString();
41480b57cec5SDimitry Andric     S += ", (void*)src->";
41490b57cec5SDimitry Andric     S += VD->getNameAsString();
41500b57cec5SDimitry Andric     if (BlockByRefDeclsPtrSet.count(VD))
41510b57cec5SDimitry Andric       S += ", " + utostr(BLOCK_FIELD_IS_BYREF) + "/*BLOCK_FIELD_IS_BYREF*/);";
41520b57cec5SDimitry Andric     else if (VD->getType()->isBlockPointerType())
41530b57cec5SDimitry Andric       S += ", " + utostr(BLOCK_FIELD_IS_BLOCK) + "/*BLOCK_FIELD_IS_BLOCK*/);";
41540b57cec5SDimitry Andric     else
41550b57cec5SDimitry Andric       S += ", " + utostr(BLOCK_FIELD_IS_OBJECT) + "/*BLOCK_FIELD_IS_OBJECT*/);";
41560b57cec5SDimitry Andric   }
41570b57cec5SDimitry Andric   S += "}\n";
41580b57cec5SDimitry Andric 
41590b57cec5SDimitry Andric   S += "\nstatic void __";
41600b57cec5SDimitry Andric   S += funcName;
41610b57cec5SDimitry Andric   S += "_block_dispose_" + utostr(i);
41620b57cec5SDimitry Andric   S += "(" + StructRef;
41630b57cec5SDimitry Andric   S += "*src) {";
41640b57cec5SDimitry Andric   for (ValueDecl *VD : ImportedBlockDecls) {
41650b57cec5SDimitry Andric     S += "_Block_object_dispose((void*)src->";
41660b57cec5SDimitry Andric     S += VD->getNameAsString();
41670b57cec5SDimitry Andric     if (BlockByRefDeclsPtrSet.count(VD))
41680b57cec5SDimitry Andric       S += ", " + utostr(BLOCK_FIELD_IS_BYREF) + "/*BLOCK_FIELD_IS_BYREF*/);";
41690b57cec5SDimitry Andric     else if (VD->getType()->isBlockPointerType())
41700b57cec5SDimitry Andric       S += ", " + utostr(BLOCK_FIELD_IS_BLOCK) + "/*BLOCK_FIELD_IS_BLOCK*/);";
41710b57cec5SDimitry Andric     else
41720b57cec5SDimitry Andric       S += ", " + utostr(BLOCK_FIELD_IS_OBJECT) + "/*BLOCK_FIELD_IS_OBJECT*/);";
41730b57cec5SDimitry Andric   }
41740b57cec5SDimitry Andric   S += "}\n";
41750b57cec5SDimitry Andric   return S;
41760b57cec5SDimitry Andric }
41770b57cec5SDimitry Andric 
SynthesizeBlockImpl(BlockExpr * CE,std::string Tag,std::string Desc)41780b57cec5SDimitry Andric std::string RewriteModernObjC::SynthesizeBlockImpl(BlockExpr *CE, std::string Tag,
41790b57cec5SDimitry Andric                                              std::string Desc) {
41800b57cec5SDimitry Andric   std::string S = "\nstruct " + Tag;
41810b57cec5SDimitry Andric   std::string Constructor = "  " + Tag;
41820b57cec5SDimitry Andric 
41830b57cec5SDimitry Andric   S += " {\n  struct __block_impl impl;\n";
41840b57cec5SDimitry Andric   S += "  struct " + Desc;
41850b57cec5SDimitry Andric   S += "* Desc;\n";
41860b57cec5SDimitry Andric 
41870b57cec5SDimitry Andric   Constructor += "(void *fp, "; // Invoke function pointer.
41880b57cec5SDimitry Andric   Constructor += "struct " + Desc; // Descriptor pointer.
41890b57cec5SDimitry Andric   Constructor += " *desc";
41900b57cec5SDimitry Andric 
41910b57cec5SDimitry Andric   if (BlockDeclRefs.size()) {
41920b57cec5SDimitry Andric     // Output all "by copy" declarations.
41930b57cec5SDimitry Andric     for (SmallVectorImpl<ValueDecl *>::iterator I = BlockByCopyDecls.begin(),
41940b57cec5SDimitry Andric          E = BlockByCopyDecls.end(); I != E; ++I) {
41950b57cec5SDimitry Andric       S += "  ";
41960b57cec5SDimitry Andric       std::string FieldName = (*I)->getNameAsString();
41970b57cec5SDimitry Andric       std::string ArgName = "_" + FieldName;
41980b57cec5SDimitry Andric       // Handle nested closure invocation. For example:
41990b57cec5SDimitry Andric       //
42000b57cec5SDimitry Andric       //   void (^myImportedBlock)(void);
42010b57cec5SDimitry Andric       //   myImportedBlock  = ^(void) { setGlobalInt(x + y); };
42020b57cec5SDimitry Andric       //
42030b57cec5SDimitry Andric       //   void (^anotherBlock)(void);
42040b57cec5SDimitry Andric       //   anotherBlock = ^(void) {
42050b57cec5SDimitry Andric       //     myImportedBlock(); // import and invoke the closure
42060b57cec5SDimitry Andric       //   };
42070b57cec5SDimitry Andric       //
42080b57cec5SDimitry Andric       if (isTopLevelBlockPointerType((*I)->getType())) {
42090b57cec5SDimitry Andric         S += "struct __block_impl *";
42100b57cec5SDimitry Andric         Constructor += ", void *" + ArgName;
42110b57cec5SDimitry Andric       } else {
42120b57cec5SDimitry Andric         QualType QT = (*I)->getType();
42130b57cec5SDimitry Andric         if (HasLocalVariableExternalStorage(*I))
42140b57cec5SDimitry Andric           QT = Context->getPointerType(QT);
42150b57cec5SDimitry Andric         QT.getAsStringInternal(FieldName, Context->getPrintingPolicy());
42160b57cec5SDimitry Andric         QT.getAsStringInternal(ArgName, Context->getPrintingPolicy());
42170b57cec5SDimitry Andric         Constructor += ", " + ArgName;
42180b57cec5SDimitry Andric       }
42190b57cec5SDimitry Andric       S += FieldName + ";\n";
42200b57cec5SDimitry Andric     }
42210b57cec5SDimitry Andric     // Output all "by ref" declarations.
42220b57cec5SDimitry Andric     for (SmallVectorImpl<ValueDecl *>::iterator I = BlockByRefDecls.begin(),
42230b57cec5SDimitry Andric          E = BlockByRefDecls.end(); I != E; ++I) {
42240b57cec5SDimitry Andric       S += "  ";
42250b57cec5SDimitry Andric       std::string FieldName = (*I)->getNameAsString();
42260b57cec5SDimitry Andric       std::string ArgName = "_" + FieldName;
42270b57cec5SDimitry Andric       {
42280b57cec5SDimitry Andric         std::string TypeString;
42290b57cec5SDimitry Andric         RewriteByRefString(TypeString, FieldName, (*I));
42300b57cec5SDimitry Andric         TypeString += " *";
42310b57cec5SDimitry Andric         FieldName = TypeString + FieldName;
42320b57cec5SDimitry Andric         ArgName = TypeString + ArgName;
42330b57cec5SDimitry Andric         Constructor += ", " + ArgName;
42340b57cec5SDimitry Andric       }
42350b57cec5SDimitry Andric       S += FieldName + "; // by ref\n";
42360b57cec5SDimitry Andric     }
42370b57cec5SDimitry Andric     // Finish writing the constructor.
42380b57cec5SDimitry Andric     Constructor += ", int flags=0)";
42390b57cec5SDimitry Andric     // Initialize all "by copy" arguments.
42400b57cec5SDimitry Andric     bool firsTime = true;
42410b57cec5SDimitry Andric     for (SmallVectorImpl<ValueDecl *>::iterator I = BlockByCopyDecls.begin(),
42420b57cec5SDimitry Andric          E = BlockByCopyDecls.end(); I != E; ++I) {
42430b57cec5SDimitry Andric       std::string Name = (*I)->getNameAsString();
42440b57cec5SDimitry Andric         if (firsTime) {
42450b57cec5SDimitry Andric           Constructor += " : ";
42460b57cec5SDimitry Andric           firsTime = false;
42470b57cec5SDimitry Andric         }
42480b57cec5SDimitry Andric         else
42490b57cec5SDimitry Andric           Constructor += ", ";
42500b57cec5SDimitry Andric         if (isTopLevelBlockPointerType((*I)->getType()))
42510b57cec5SDimitry Andric           Constructor += Name + "((struct __block_impl *)_" + Name + ")";
42520b57cec5SDimitry Andric         else
42530b57cec5SDimitry Andric           Constructor += Name + "(_" + Name + ")";
42540b57cec5SDimitry Andric     }
42550b57cec5SDimitry Andric     // Initialize all "by ref" arguments.
42560b57cec5SDimitry Andric     for (SmallVectorImpl<ValueDecl *>::iterator I = BlockByRefDecls.begin(),
42570b57cec5SDimitry Andric          E = BlockByRefDecls.end(); I != E; ++I) {
42580b57cec5SDimitry Andric       std::string Name = (*I)->getNameAsString();
42590b57cec5SDimitry Andric       if (firsTime) {
42600b57cec5SDimitry Andric         Constructor += " : ";
42610b57cec5SDimitry Andric         firsTime = false;
42620b57cec5SDimitry Andric       }
42630b57cec5SDimitry Andric       else
42640b57cec5SDimitry Andric         Constructor += ", ";
42650b57cec5SDimitry Andric       Constructor += Name + "(_" + Name + "->__forwarding)";
42660b57cec5SDimitry Andric     }
42670b57cec5SDimitry Andric 
42680b57cec5SDimitry Andric     Constructor += " {\n";
42690b57cec5SDimitry Andric     if (GlobalVarDecl)
42700b57cec5SDimitry Andric       Constructor += "    impl.isa = &_NSConcreteGlobalBlock;\n";
42710b57cec5SDimitry Andric     else
42720b57cec5SDimitry Andric       Constructor += "    impl.isa = &_NSConcreteStackBlock;\n";
42730b57cec5SDimitry Andric     Constructor += "    impl.Flags = flags;\n    impl.FuncPtr = fp;\n";
42740b57cec5SDimitry Andric 
42750b57cec5SDimitry Andric     Constructor += "    Desc = desc;\n";
42760b57cec5SDimitry Andric   } else {
42770b57cec5SDimitry Andric     // Finish writing the constructor.
42780b57cec5SDimitry Andric     Constructor += ", int flags=0) {\n";
42790b57cec5SDimitry Andric     if (GlobalVarDecl)
42800b57cec5SDimitry Andric       Constructor += "    impl.isa = &_NSConcreteGlobalBlock;\n";
42810b57cec5SDimitry Andric     else
42820b57cec5SDimitry Andric       Constructor += "    impl.isa = &_NSConcreteStackBlock;\n";
42830b57cec5SDimitry Andric     Constructor += "    impl.Flags = flags;\n    impl.FuncPtr = fp;\n";
42840b57cec5SDimitry Andric     Constructor += "    Desc = desc;\n";
42850b57cec5SDimitry Andric   }
42860b57cec5SDimitry Andric   Constructor += "  ";
42870b57cec5SDimitry Andric   Constructor += "}\n";
42880b57cec5SDimitry Andric   S += Constructor;
42890b57cec5SDimitry Andric   S += "};\n";
42900b57cec5SDimitry Andric   return S;
42910b57cec5SDimitry Andric }
42920b57cec5SDimitry Andric 
SynthesizeBlockDescriptor(std::string DescTag,std::string ImplTag,int i,StringRef FunName,unsigned hasCopy)42930b57cec5SDimitry Andric std::string RewriteModernObjC::SynthesizeBlockDescriptor(std::string DescTag,
42940b57cec5SDimitry Andric                                                    std::string ImplTag, int i,
42950b57cec5SDimitry Andric                                                    StringRef FunName,
42960b57cec5SDimitry Andric                                                    unsigned hasCopy) {
42970b57cec5SDimitry Andric   std::string S = "\nstatic struct " + DescTag;
42980b57cec5SDimitry Andric 
42990b57cec5SDimitry Andric   S += " {\n  size_t reserved;\n";
43000b57cec5SDimitry Andric   S += "  size_t Block_size;\n";
43010b57cec5SDimitry Andric   if (hasCopy) {
43020b57cec5SDimitry Andric     S += "  void (*copy)(struct ";
43030b57cec5SDimitry Andric     S += ImplTag; S += "*, struct ";
43040b57cec5SDimitry Andric     S += ImplTag; S += "*);\n";
43050b57cec5SDimitry Andric 
43060b57cec5SDimitry Andric     S += "  void (*dispose)(struct ";
43070b57cec5SDimitry Andric     S += ImplTag; S += "*);\n";
43080b57cec5SDimitry Andric   }
43090b57cec5SDimitry Andric   S += "} ";
43100b57cec5SDimitry Andric 
43110b57cec5SDimitry Andric   S += DescTag + "_DATA = { 0, sizeof(struct ";
43120b57cec5SDimitry Andric   S += ImplTag + ")";
43130b57cec5SDimitry Andric   if (hasCopy) {
43140b57cec5SDimitry Andric     S += ", __" + FunName.str() + "_block_copy_" + utostr(i);
43150b57cec5SDimitry Andric     S += ", __" + FunName.str() + "_block_dispose_" + utostr(i);
43160b57cec5SDimitry Andric   }
43170b57cec5SDimitry Andric   S += "};\n";
43180b57cec5SDimitry Andric   return S;
43190b57cec5SDimitry Andric }
43200b57cec5SDimitry Andric 
SynthesizeBlockLiterals(SourceLocation FunLocStart,StringRef FunName)43210b57cec5SDimitry Andric void RewriteModernObjC::SynthesizeBlockLiterals(SourceLocation FunLocStart,
43220b57cec5SDimitry Andric                                           StringRef FunName) {
43230b57cec5SDimitry Andric   bool RewriteSC = (GlobalVarDecl &&
43240b57cec5SDimitry Andric                     !Blocks.empty() &&
43250b57cec5SDimitry Andric                     GlobalVarDecl->getStorageClass() == SC_Static &&
43260b57cec5SDimitry Andric                     GlobalVarDecl->getType().getCVRQualifiers());
43270b57cec5SDimitry Andric   if (RewriteSC) {
43280b57cec5SDimitry Andric     std::string SC(" void __");
43290b57cec5SDimitry Andric     SC += GlobalVarDecl->getNameAsString();
43300b57cec5SDimitry Andric     SC += "() {}";
43310b57cec5SDimitry Andric     InsertText(FunLocStart, SC);
43320b57cec5SDimitry Andric   }
43330b57cec5SDimitry Andric 
43340b57cec5SDimitry Andric   // Insert closures that were part of the function.
43350b57cec5SDimitry Andric   for (unsigned i = 0, count=0; i < Blocks.size(); i++) {
43360b57cec5SDimitry Andric     CollectBlockDeclRefInfo(Blocks[i]);
43370b57cec5SDimitry Andric     // Need to copy-in the inner copied-in variables not actually used in this
43380b57cec5SDimitry Andric     // block.
43390b57cec5SDimitry Andric     for (int j = 0; j < InnerDeclRefsCount[i]; j++) {
43400b57cec5SDimitry Andric       DeclRefExpr *Exp = InnerDeclRefs[count++];
43410b57cec5SDimitry Andric       ValueDecl *VD = Exp->getDecl();
43420b57cec5SDimitry Andric       BlockDeclRefs.push_back(Exp);
43430b57cec5SDimitry Andric       if (!VD->hasAttr<BlocksAttr>()) {
43440b57cec5SDimitry Andric         if (!BlockByCopyDeclsPtrSet.count(VD)) {
43450b57cec5SDimitry Andric           BlockByCopyDeclsPtrSet.insert(VD);
43460b57cec5SDimitry Andric           BlockByCopyDecls.push_back(VD);
43470b57cec5SDimitry Andric         }
43480b57cec5SDimitry Andric         continue;
43490b57cec5SDimitry Andric       }
43500b57cec5SDimitry Andric 
43510b57cec5SDimitry Andric       if (!BlockByRefDeclsPtrSet.count(VD)) {
43520b57cec5SDimitry Andric         BlockByRefDeclsPtrSet.insert(VD);
43530b57cec5SDimitry Andric         BlockByRefDecls.push_back(VD);
43540b57cec5SDimitry Andric       }
43550b57cec5SDimitry Andric 
43560b57cec5SDimitry Andric       // imported objects in the inner blocks not used in the outer
43570b57cec5SDimitry Andric       // blocks must be copied/disposed in the outer block as well.
43580b57cec5SDimitry Andric       if (VD->getType()->isObjCObjectPointerType() ||
43590b57cec5SDimitry Andric           VD->getType()->isBlockPointerType())
43600b57cec5SDimitry Andric         ImportedBlockDecls.insert(VD);
43610b57cec5SDimitry Andric     }
43620b57cec5SDimitry Andric 
43630b57cec5SDimitry Andric     std::string ImplTag = "__" + FunName.str() + "_block_impl_" + utostr(i);
43640b57cec5SDimitry Andric     std::string DescTag = "__" + FunName.str() + "_block_desc_" + utostr(i);
43650b57cec5SDimitry Andric 
43660b57cec5SDimitry Andric     std::string CI = SynthesizeBlockImpl(Blocks[i], ImplTag, DescTag);
43670b57cec5SDimitry Andric 
43680b57cec5SDimitry Andric     InsertText(FunLocStart, CI);
43690b57cec5SDimitry Andric 
43700b57cec5SDimitry Andric     std::string CF = SynthesizeBlockFunc(Blocks[i], i, FunName, ImplTag);
43710b57cec5SDimitry Andric 
43720b57cec5SDimitry Andric     InsertText(FunLocStart, CF);
43730b57cec5SDimitry Andric 
43740b57cec5SDimitry Andric     if (ImportedBlockDecls.size()) {
43750b57cec5SDimitry Andric       std::string HF = SynthesizeBlockHelperFuncs(Blocks[i], i, FunName, ImplTag);
43760b57cec5SDimitry Andric       InsertText(FunLocStart, HF);
43770b57cec5SDimitry Andric     }
43780b57cec5SDimitry Andric     std::string BD = SynthesizeBlockDescriptor(DescTag, ImplTag, i, FunName,
43790b57cec5SDimitry Andric                                                ImportedBlockDecls.size() > 0);
43800b57cec5SDimitry Andric     InsertText(FunLocStart, BD);
43810b57cec5SDimitry Andric 
43820b57cec5SDimitry Andric     BlockDeclRefs.clear();
43830b57cec5SDimitry Andric     BlockByRefDecls.clear();
43840b57cec5SDimitry Andric     BlockByRefDeclsPtrSet.clear();
43850b57cec5SDimitry Andric     BlockByCopyDecls.clear();
43860b57cec5SDimitry Andric     BlockByCopyDeclsPtrSet.clear();
43870b57cec5SDimitry Andric     ImportedBlockDecls.clear();
43880b57cec5SDimitry Andric   }
43890b57cec5SDimitry Andric   if (RewriteSC) {
43900b57cec5SDimitry Andric     // Must insert any 'const/volatile/static here. Since it has been
43910b57cec5SDimitry Andric     // removed as result of rewriting of block literals.
43920b57cec5SDimitry Andric     std::string SC;
43930b57cec5SDimitry Andric     if (GlobalVarDecl->getStorageClass() == SC_Static)
43940b57cec5SDimitry Andric       SC = "static ";
43950b57cec5SDimitry Andric     if (GlobalVarDecl->getType().isConstQualified())
43960b57cec5SDimitry Andric       SC += "const ";
43970b57cec5SDimitry Andric     if (GlobalVarDecl->getType().isVolatileQualified())
43980b57cec5SDimitry Andric       SC += "volatile ";
43990b57cec5SDimitry Andric     if (GlobalVarDecl->getType().isRestrictQualified())
44000b57cec5SDimitry Andric       SC += "restrict ";
44010b57cec5SDimitry Andric     InsertText(FunLocStart, SC);
44020b57cec5SDimitry Andric   }
44030b57cec5SDimitry Andric   if (GlobalConstructionExp) {
44040b57cec5SDimitry Andric     // extra fancy dance for global literal expression.
44050b57cec5SDimitry Andric 
44060b57cec5SDimitry Andric     // Always the latest block expression on the block stack.
44070b57cec5SDimitry Andric     std::string Tag = "__";
44080b57cec5SDimitry Andric     Tag += FunName;
44090b57cec5SDimitry Andric     Tag += "_block_impl_";
44100b57cec5SDimitry Andric     Tag += utostr(Blocks.size()-1);
44110b57cec5SDimitry Andric     std::string globalBuf = "static ";
44120b57cec5SDimitry Andric     globalBuf += Tag; globalBuf += " ";
44130b57cec5SDimitry Andric     std::string SStr;
44140b57cec5SDimitry Andric 
44150b57cec5SDimitry Andric     llvm::raw_string_ostream constructorExprBuf(SStr);
44160b57cec5SDimitry Andric     GlobalConstructionExp->printPretty(constructorExprBuf, nullptr,
44170b57cec5SDimitry Andric                                        PrintingPolicy(LangOpts));
44180b57cec5SDimitry Andric     globalBuf += constructorExprBuf.str();
44190b57cec5SDimitry Andric     globalBuf += ";\n";
44200b57cec5SDimitry Andric     InsertText(FunLocStart, globalBuf);
44210b57cec5SDimitry Andric     GlobalConstructionExp = nullptr;
44220b57cec5SDimitry Andric   }
44230b57cec5SDimitry Andric 
44240b57cec5SDimitry Andric   Blocks.clear();
44250b57cec5SDimitry Andric   InnerDeclRefsCount.clear();
44260b57cec5SDimitry Andric   InnerDeclRefs.clear();
44270b57cec5SDimitry Andric   RewrittenBlockExprs.clear();
44280b57cec5SDimitry Andric }
44290b57cec5SDimitry Andric 
InsertBlockLiteralsWithinFunction(FunctionDecl * FD)44300b57cec5SDimitry Andric void RewriteModernObjC::InsertBlockLiteralsWithinFunction(FunctionDecl *FD) {
44310b57cec5SDimitry Andric   SourceLocation FunLocStart =
44320b57cec5SDimitry Andric     (!Blocks.empty()) ? getFunctionSourceLocation(*this, FD)
44330b57cec5SDimitry Andric                       : FD->getTypeSpecStartLoc();
44340b57cec5SDimitry Andric   StringRef FuncName = FD->getName();
44350b57cec5SDimitry Andric 
44360b57cec5SDimitry Andric   SynthesizeBlockLiterals(FunLocStart, FuncName);
44370b57cec5SDimitry Andric }
44380b57cec5SDimitry Andric 
BuildUniqueMethodName(std::string & Name,ObjCMethodDecl * MD)44390b57cec5SDimitry Andric static void BuildUniqueMethodName(std::string &Name,
44400b57cec5SDimitry Andric                                   ObjCMethodDecl *MD) {
44410b57cec5SDimitry Andric   ObjCInterfaceDecl *IFace = MD->getClassInterface();
44425ffd83dbSDimitry Andric   Name = std::string(IFace->getName());
44430b57cec5SDimitry Andric   Name += "__" + MD->getSelector().getAsString();
44440b57cec5SDimitry Andric   // Convert colons to underscores.
44450b57cec5SDimitry Andric   std::string::size_type loc = 0;
44460b57cec5SDimitry Andric   while ((loc = Name.find(':', loc)) != std::string::npos)
44470b57cec5SDimitry Andric     Name.replace(loc, 1, "_");
44480b57cec5SDimitry Andric }
44490b57cec5SDimitry Andric 
InsertBlockLiteralsWithinMethod(ObjCMethodDecl * MD)44500b57cec5SDimitry Andric void RewriteModernObjC::InsertBlockLiteralsWithinMethod(ObjCMethodDecl *MD) {
44510b57cec5SDimitry Andric   // fprintf(stderr,"In InsertBlockLiteralsWitinMethod\n");
44520b57cec5SDimitry Andric   // SourceLocation FunLocStart = MD->getBeginLoc();
44530b57cec5SDimitry Andric   SourceLocation FunLocStart = MD->getBeginLoc();
44540b57cec5SDimitry Andric   std::string FuncName;
44550b57cec5SDimitry Andric   BuildUniqueMethodName(FuncName, MD);
44560b57cec5SDimitry Andric   SynthesizeBlockLiterals(FunLocStart, FuncName);
44570b57cec5SDimitry Andric }
44580b57cec5SDimitry Andric 
GetBlockDeclRefExprs(Stmt * S)44590b57cec5SDimitry Andric void RewriteModernObjC::GetBlockDeclRefExprs(Stmt *S) {
44600b57cec5SDimitry Andric   for (Stmt *SubStmt : S->children())
44610b57cec5SDimitry Andric     if (SubStmt) {
44620b57cec5SDimitry Andric       if (BlockExpr *CBE = dyn_cast<BlockExpr>(SubStmt))
44630b57cec5SDimitry Andric         GetBlockDeclRefExprs(CBE->getBody());
44640b57cec5SDimitry Andric       else
44650b57cec5SDimitry Andric         GetBlockDeclRefExprs(SubStmt);
44660b57cec5SDimitry Andric     }
44670b57cec5SDimitry Andric   // Handle specific things.
44680b57cec5SDimitry Andric   if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(S))
44690b57cec5SDimitry Andric     if (DRE->refersToEnclosingVariableOrCapture() ||
44700b57cec5SDimitry Andric         HasLocalVariableExternalStorage(DRE->getDecl()))
44710b57cec5SDimitry Andric       // FIXME: Handle enums.
44720b57cec5SDimitry Andric       BlockDeclRefs.push_back(DRE);
44730b57cec5SDimitry Andric }
44740b57cec5SDimitry Andric 
GetInnerBlockDeclRefExprs(Stmt * S,SmallVectorImpl<DeclRefExpr * > & InnerBlockDeclRefs,llvm::SmallPtrSetImpl<const DeclContext * > & InnerContexts)44750b57cec5SDimitry Andric void RewriteModernObjC::GetInnerBlockDeclRefExprs(Stmt *S,
44760b57cec5SDimitry Andric                 SmallVectorImpl<DeclRefExpr *> &InnerBlockDeclRefs,
44770b57cec5SDimitry Andric                 llvm::SmallPtrSetImpl<const DeclContext *> &InnerContexts) {
44780b57cec5SDimitry Andric   for (Stmt *SubStmt : S->children())
44790b57cec5SDimitry Andric     if (SubStmt) {
44800b57cec5SDimitry Andric       if (BlockExpr *CBE = dyn_cast<BlockExpr>(SubStmt)) {
44810b57cec5SDimitry Andric         InnerContexts.insert(cast<DeclContext>(CBE->getBlockDecl()));
44820b57cec5SDimitry Andric         GetInnerBlockDeclRefExprs(CBE->getBody(),
44830b57cec5SDimitry Andric                                   InnerBlockDeclRefs,
44840b57cec5SDimitry Andric                                   InnerContexts);
44850b57cec5SDimitry Andric       }
44860b57cec5SDimitry Andric       else
44870b57cec5SDimitry Andric         GetInnerBlockDeclRefExprs(SubStmt, InnerBlockDeclRefs, InnerContexts);
44880b57cec5SDimitry Andric     }
44890b57cec5SDimitry Andric   // Handle specific things.
44900b57cec5SDimitry Andric   if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(S)) {
44910b57cec5SDimitry Andric     if (DRE->refersToEnclosingVariableOrCapture() ||
44920b57cec5SDimitry Andric         HasLocalVariableExternalStorage(DRE->getDecl())) {
44930b57cec5SDimitry Andric       if (!InnerContexts.count(DRE->getDecl()->getDeclContext()))
44940b57cec5SDimitry Andric         InnerBlockDeclRefs.push_back(DRE);
44950b57cec5SDimitry Andric       if (VarDecl *Var = cast<VarDecl>(DRE->getDecl()))
44960b57cec5SDimitry Andric         if (Var->isFunctionOrMethodVarDecl())
44970b57cec5SDimitry Andric           ImportedLocalExternalDecls.insert(Var);
44980b57cec5SDimitry Andric     }
44990b57cec5SDimitry Andric   }
45000b57cec5SDimitry Andric }
45010b57cec5SDimitry Andric 
45020b57cec5SDimitry Andric /// convertObjCTypeToCStyleType - This routine converts such objc types
45030b57cec5SDimitry Andric /// as qualified objects, and blocks to their closest c/c++ types that
45040b57cec5SDimitry Andric /// it can. It returns true if input type was modified.
convertObjCTypeToCStyleType(QualType & T)45050b57cec5SDimitry Andric bool RewriteModernObjC::convertObjCTypeToCStyleType(QualType &T) {
45060b57cec5SDimitry Andric   QualType oldT = T;
45070b57cec5SDimitry Andric   convertBlockPointerToFunctionPointer(T);
45080b57cec5SDimitry Andric   if (T->isFunctionPointerType()) {
45090b57cec5SDimitry Andric     QualType PointeeTy;
45100b57cec5SDimitry Andric     if (const PointerType* PT = T->getAs<PointerType>()) {
45110b57cec5SDimitry Andric       PointeeTy = PT->getPointeeType();
45120b57cec5SDimitry Andric       if (const FunctionType *FT = PointeeTy->getAs<FunctionType>()) {
45130b57cec5SDimitry Andric         T = convertFunctionTypeOfBlocks(FT);
45140b57cec5SDimitry Andric         T = Context->getPointerType(T);
45150b57cec5SDimitry Andric       }
45160b57cec5SDimitry Andric     }
45170b57cec5SDimitry Andric   }
45180b57cec5SDimitry Andric 
45190b57cec5SDimitry Andric   convertToUnqualifiedObjCType(T);
45200b57cec5SDimitry Andric   return T != oldT;
45210b57cec5SDimitry Andric }
45220b57cec5SDimitry Andric 
45230b57cec5SDimitry Andric /// convertFunctionTypeOfBlocks - This routine converts a function type
45240b57cec5SDimitry Andric /// whose result type may be a block pointer or whose argument type(s)
45250b57cec5SDimitry Andric /// might be block pointers to an equivalent function type replacing
45260b57cec5SDimitry Andric /// all block pointers to function pointers.
convertFunctionTypeOfBlocks(const FunctionType * FT)45270b57cec5SDimitry Andric QualType RewriteModernObjC::convertFunctionTypeOfBlocks(const FunctionType *FT) {
45280b57cec5SDimitry Andric   const FunctionProtoType *FTP = dyn_cast<FunctionProtoType>(FT);
45290b57cec5SDimitry Andric   // FTP will be null for closures that don't take arguments.
45300b57cec5SDimitry Andric   // Generate a funky cast.
45310b57cec5SDimitry Andric   SmallVector<QualType, 8> ArgTypes;
45320b57cec5SDimitry Andric   QualType Res = FT->getReturnType();
45330b57cec5SDimitry Andric   bool modified = convertObjCTypeToCStyleType(Res);
45340b57cec5SDimitry Andric 
45350b57cec5SDimitry Andric   if (FTP) {
45360b57cec5SDimitry Andric     for (auto &I : FTP->param_types()) {
45370b57cec5SDimitry Andric       QualType t = I;
45380b57cec5SDimitry Andric       // Make sure we convert "t (^)(...)" to "t (*)(...)".
45390b57cec5SDimitry Andric       if (convertObjCTypeToCStyleType(t))
45400b57cec5SDimitry Andric         modified = true;
45410b57cec5SDimitry Andric       ArgTypes.push_back(t);
45420b57cec5SDimitry Andric     }
45430b57cec5SDimitry Andric   }
45440b57cec5SDimitry Andric   QualType FuncType;
45450b57cec5SDimitry Andric   if (modified)
45460b57cec5SDimitry Andric     FuncType = getSimpleFunctionType(Res, ArgTypes);
45470b57cec5SDimitry Andric   else FuncType = QualType(FT, 0);
45480b57cec5SDimitry Andric   return FuncType;
45490b57cec5SDimitry Andric }
45500b57cec5SDimitry Andric 
SynthesizeBlockCall(CallExpr * Exp,const Expr * BlockExp)45510b57cec5SDimitry Andric Stmt *RewriteModernObjC::SynthesizeBlockCall(CallExpr *Exp, const Expr *BlockExp) {
45520b57cec5SDimitry Andric   // Navigate to relevant type information.
45530b57cec5SDimitry Andric   const BlockPointerType *CPT = nullptr;
45540b57cec5SDimitry Andric 
45550b57cec5SDimitry Andric   if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(BlockExp)) {
45560b57cec5SDimitry Andric     CPT = DRE->getType()->getAs<BlockPointerType>();
45570b57cec5SDimitry Andric   } else if (const MemberExpr *MExpr = dyn_cast<MemberExpr>(BlockExp)) {
45580b57cec5SDimitry Andric     CPT = MExpr->getType()->getAs<BlockPointerType>();
45590b57cec5SDimitry Andric   }
45600b57cec5SDimitry Andric   else if (const ParenExpr *PRE = dyn_cast<ParenExpr>(BlockExp)) {
45610b57cec5SDimitry Andric     return SynthesizeBlockCall(Exp, PRE->getSubExpr());
45620b57cec5SDimitry Andric   }
45630b57cec5SDimitry Andric   else if (const ImplicitCastExpr *IEXPR = dyn_cast<ImplicitCastExpr>(BlockExp))
45640b57cec5SDimitry Andric     CPT = IEXPR->getType()->getAs<BlockPointerType>();
45650b57cec5SDimitry Andric   else if (const ConditionalOperator *CEXPR =
45660b57cec5SDimitry Andric             dyn_cast<ConditionalOperator>(BlockExp)) {
45670b57cec5SDimitry Andric     Expr *LHSExp = CEXPR->getLHS();
45680b57cec5SDimitry Andric     Stmt *LHSStmt = SynthesizeBlockCall(Exp, LHSExp);
45690b57cec5SDimitry Andric     Expr *RHSExp = CEXPR->getRHS();
45700b57cec5SDimitry Andric     Stmt *RHSStmt = SynthesizeBlockCall(Exp, RHSExp);
45710b57cec5SDimitry Andric     Expr *CONDExp = CEXPR->getCond();
4572fe6060f1SDimitry Andric     ConditionalOperator *CondExpr = new (Context) ConditionalOperator(
4573fe6060f1SDimitry Andric         CONDExp, SourceLocation(), cast<Expr>(LHSStmt), SourceLocation(),
4574fe6060f1SDimitry Andric         cast<Expr>(RHSStmt), Exp->getType(), VK_PRValue, OK_Ordinary);
45750b57cec5SDimitry Andric     return CondExpr;
45760b57cec5SDimitry Andric   } else if (const ObjCIvarRefExpr *IRE = dyn_cast<ObjCIvarRefExpr>(BlockExp)) {
45770b57cec5SDimitry Andric     CPT = IRE->getType()->getAs<BlockPointerType>();
45780b57cec5SDimitry Andric   } else if (const PseudoObjectExpr *POE
45790b57cec5SDimitry Andric                = dyn_cast<PseudoObjectExpr>(BlockExp)) {
45800b57cec5SDimitry Andric     CPT = POE->getType()->castAs<BlockPointerType>();
45810b57cec5SDimitry Andric   } else {
45820b57cec5SDimitry Andric     assert(false && "RewriteBlockClass: Bad type");
45830b57cec5SDimitry Andric   }
45840b57cec5SDimitry Andric   assert(CPT && "RewriteBlockClass: Bad type");
45850b57cec5SDimitry Andric   const FunctionType *FT = CPT->getPointeeType()->getAs<FunctionType>();
45860b57cec5SDimitry Andric   assert(FT && "RewriteBlockClass: Bad type");
45870b57cec5SDimitry Andric   const FunctionProtoType *FTP = dyn_cast<FunctionProtoType>(FT);
45880b57cec5SDimitry Andric   // FTP will be null for closures that don't take arguments.
45890b57cec5SDimitry Andric 
45905f757f3fSDimitry Andric   RecordDecl *RD = RecordDecl::Create(*Context, TagTypeKind::Struct, TUDecl,
45910b57cec5SDimitry Andric                                       SourceLocation(), SourceLocation(),
45920b57cec5SDimitry Andric                                       &Context->Idents.get("__block_impl"));
45930b57cec5SDimitry Andric   QualType PtrBlock = Context->getPointerType(Context->getTagDeclType(RD));
45940b57cec5SDimitry Andric 
45950b57cec5SDimitry Andric   // Generate a funky cast.
45960b57cec5SDimitry Andric   SmallVector<QualType, 8> ArgTypes;
45970b57cec5SDimitry Andric 
45980b57cec5SDimitry Andric   // Push the block argument type.
45990b57cec5SDimitry Andric   ArgTypes.push_back(PtrBlock);
46000b57cec5SDimitry Andric   if (FTP) {
46010b57cec5SDimitry Andric     for (auto &I : FTP->param_types()) {
46020b57cec5SDimitry Andric       QualType t = I;
46030b57cec5SDimitry Andric       // Make sure we convert "t (^)(...)" to "t (*)(...)".
46040b57cec5SDimitry Andric       if (!convertBlockPointerToFunctionPointer(t))
46050b57cec5SDimitry Andric         convertToUnqualifiedObjCType(t);
46060b57cec5SDimitry Andric       ArgTypes.push_back(t);
46070b57cec5SDimitry Andric     }
46080b57cec5SDimitry Andric   }
46090b57cec5SDimitry Andric   // Now do the pointer to function cast.
46100b57cec5SDimitry Andric   QualType PtrToFuncCastType = getSimpleFunctionType(Exp->getType(), ArgTypes);
46110b57cec5SDimitry Andric 
46120b57cec5SDimitry Andric   PtrToFuncCastType = Context->getPointerType(PtrToFuncCastType);
46130b57cec5SDimitry Andric 
46140b57cec5SDimitry Andric   CastExpr *BlkCast = NoTypeInfoCStyleCastExpr(Context, PtrBlock,
46150b57cec5SDimitry Andric                                                CK_BitCast,
46160b57cec5SDimitry Andric                                                const_cast<Expr*>(BlockExp));
46170b57cec5SDimitry Andric   // Don't forget the parens to enforce the proper binding.
46180b57cec5SDimitry Andric   ParenExpr *PE = new (Context) ParenExpr(SourceLocation(), SourceLocation(),
46190b57cec5SDimitry Andric                                           BlkCast);
46200b57cec5SDimitry Andric   //PE->dump();
46210b57cec5SDimitry Andric 
46220b57cec5SDimitry Andric   FieldDecl *FD = FieldDecl::Create(*Context, nullptr, SourceLocation(),
46230b57cec5SDimitry Andric                                     SourceLocation(),
46240b57cec5SDimitry Andric                                     &Context->Idents.get("FuncPtr"),
46250b57cec5SDimitry Andric                                     Context->VoidPtrTy, nullptr,
46260b57cec5SDimitry Andric                                     /*BitWidth=*/nullptr, /*Mutable=*/true,
46270b57cec5SDimitry Andric                                     ICIS_NoInit);
46280b57cec5SDimitry Andric   MemberExpr *ME = MemberExpr::CreateImplicit(
46290b57cec5SDimitry Andric       *Context, PE, true, FD, FD->getType(), VK_LValue, OK_Ordinary);
46300b57cec5SDimitry Andric 
46310b57cec5SDimitry Andric   CastExpr *FunkCast = NoTypeInfoCStyleCastExpr(Context, PtrToFuncCastType,
46320b57cec5SDimitry Andric                                                 CK_BitCast, ME);
46330b57cec5SDimitry Andric   PE = new (Context) ParenExpr(SourceLocation(), SourceLocation(), FunkCast);
46340b57cec5SDimitry Andric 
46350b57cec5SDimitry Andric   SmallVector<Expr*, 8> BlkExprs;
46360b57cec5SDimitry Andric   // Add the implicit argument.
46370b57cec5SDimitry Andric   BlkExprs.push_back(BlkCast);
46380b57cec5SDimitry Andric   // Add the user arguments.
46390b57cec5SDimitry Andric   for (CallExpr::arg_iterator I = Exp->arg_begin(),
46400b57cec5SDimitry Andric        E = Exp->arg_end(); I != E; ++I) {
46410b57cec5SDimitry Andric     BlkExprs.push_back(*I);
46420b57cec5SDimitry Andric   }
4643e8d8bef9SDimitry Andric   CallExpr *CE =
4644fe6060f1SDimitry Andric       CallExpr::Create(*Context, PE, BlkExprs, Exp->getType(), VK_PRValue,
4645e8d8bef9SDimitry Andric                        SourceLocation(), FPOptionsOverride());
46460b57cec5SDimitry Andric   return CE;
46470b57cec5SDimitry Andric }
46480b57cec5SDimitry Andric 
46490b57cec5SDimitry Andric // We need to return the rewritten expression to handle cases where the
46500b57cec5SDimitry Andric // DeclRefExpr is embedded in another expression being rewritten.
46510b57cec5SDimitry Andric // For example:
46520b57cec5SDimitry Andric //
46530b57cec5SDimitry Andric // int main() {
46540b57cec5SDimitry Andric //    __block Foo *f;
46550b57cec5SDimitry Andric //    __block int i;
46560b57cec5SDimitry Andric //
46570b57cec5SDimitry Andric //    void (^myblock)() = ^() {
46580b57cec5SDimitry Andric //        [f test]; // f is a DeclRefExpr embedded in a message (which is being rewritten).
46590b57cec5SDimitry Andric //        i = 77;
46600b57cec5SDimitry Andric //    };
46610b57cec5SDimitry Andric //}
RewriteBlockDeclRefExpr(DeclRefExpr * DeclRefExp)46620b57cec5SDimitry Andric Stmt *RewriteModernObjC::RewriteBlockDeclRefExpr(DeclRefExpr *DeclRefExp) {
46630b57cec5SDimitry Andric   // Rewrite the byref variable into BYREFVAR->__forwarding->BYREFVAR
46640b57cec5SDimitry Andric   // for each DeclRefExp where BYREFVAR is name of the variable.
46650b57cec5SDimitry Andric   ValueDecl *VD = DeclRefExp->getDecl();
46660b57cec5SDimitry Andric   bool isArrow = DeclRefExp->refersToEnclosingVariableOrCapture() ||
46670b57cec5SDimitry Andric                  HasLocalVariableExternalStorage(DeclRefExp->getDecl());
46680b57cec5SDimitry Andric 
46690b57cec5SDimitry Andric   FieldDecl *FD = FieldDecl::Create(*Context, nullptr, SourceLocation(),
46700b57cec5SDimitry Andric                                     SourceLocation(),
46710b57cec5SDimitry Andric                                     &Context->Idents.get("__forwarding"),
46720b57cec5SDimitry Andric                                     Context->VoidPtrTy, nullptr,
46730b57cec5SDimitry Andric                                     /*BitWidth=*/nullptr, /*Mutable=*/true,
46740b57cec5SDimitry Andric                                     ICIS_NoInit);
46750b57cec5SDimitry Andric   MemberExpr *ME = MemberExpr::CreateImplicit(
46760b57cec5SDimitry Andric       *Context, DeclRefExp, isArrow, FD, FD->getType(), VK_LValue, OK_Ordinary);
46770b57cec5SDimitry Andric 
46780b57cec5SDimitry Andric   StringRef Name = VD->getName();
46790b57cec5SDimitry Andric   FD = FieldDecl::Create(*Context, nullptr, SourceLocation(), SourceLocation(),
46800b57cec5SDimitry Andric                          &Context->Idents.get(Name),
46810b57cec5SDimitry Andric                          Context->VoidPtrTy, nullptr,
46820b57cec5SDimitry Andric                          /*BitWidth=*/nullptr, /*Mutable=*/true,
46830b57cec5SDimitry Andric                          ICIS_NoInit);
46840b57cec5SDimitry Andric   ME = MemberExpr::CreateImplicit(*Context, ME, true, FD, DeclRefExp->getType(),
46850b57cec5SDimitry Andric                                   VK_LValue, OK_Ordinary);
46860b57cec5SDimitry Andric 
46870b57cec5SDimitry Andric   // Need parens to enforce precedence.
46880b57cec5SDimitry Andric   ParenExpr *PE = new (Context) ParenExpr(DeclRefExp->getExprLoc(),
46890b57cec5SDimitry Andric                                           DeclRefExp->getExprLoc(),
46900b57cec5SDimitry Andric                                           ME);
46910b57cec5SDimitry Andric   ReplaceStmt(DeclRefExp, PE);
46920b57cec5SDimitry Andric   return PE;
46930b57cec5SDimitry Andric }
46940b57cec5SDimitry Andric 
46950b57cec5SDimitry Andric // Rewrites the imported local variable V with external storage
46960b57cec5SDimitry Andric // (static, extern, etc.) as *V
46970b57cec5SDimitry Andric //
RewriteLocalVariableExternalStorage(DeclRefExpr * DRE)46980b57cec5SDimitry Andric Stmt *RewriteModernObjC::RewriteLocalVariableExternalStorage(DeclRefExpr *DRE) {
46990b57cec5SDimitry Andric   ValueDecl *VD = DRE->getDecl();
47000b57cec5SDimitry Andric   if (VarDecl *Var = dyn_cast<VarDecl>(VD))
47010b57cec5SDimitry Andric     if (!ImportedLocalExternalDecls.count(Var))
47020b57cec5SDimitry Andric       return DRE;
47035ffd83dbSDimitry Andric   Expr *Exp = UnaryOperator::Create(
47045ffd83dbSDimitry Andric       const_cast<ASTContext &>(*Context), DRE, UO_Deref, DRE->getType(),
47055ffd83dbSDimitry Andric       VK_LValue, OK_Ordinary, DRE->getLocation(), false, FPOptionsOverride());
47060b57cec5SDimitry Andric   // Need parens to enforce precedence.
47070b57cec5SDimitry Andric   ParenExpr *PE = new (Context) ParenExpr(SourceLocation(), SourceLocation(),
47080b57cec5SDimitry Andric                                           Exp);
47090b57cec5SDimitry Andric   ReplaceStmt(DRE, PE);
47100b57cec5SDimitry Andric   return PE;
47110b57cec5SDimitry Andric }
47120b57cec5SDimitry Andric 
RewriteCastExpr(CStyleCastExpr * CE)47130b57cec5SDimitry Andric void RewriteModernObjC::RewriteCastExpr(CStyleCastExpr *CE) {
47140b57cec5SDimitry Andric   SourceLocation LocStart = CE->getLParenLoc();
47150b57cec5SDimitry Andric   SourceLocation LocEnd = CE->getRParenLoc();
47160b57cec5SDimitry Andric 
47170b57cec5SDimitry Andric   // Need to avoid trying to rewrite synthesized casts.
47180b57cec5SDimitry Andric   if (LocStart.isInvalid())
47190b57cec5SDimitry Andric     return;
47200b57cec5SDimitry Andric   // Need to avoid trying to rewrite casts contained in macros.
47210b57cec5SDimitry Andric   if (!Rewriter::isRewritable(LocStart) || !Rewriter::isRewritable(LocEnd))
47220b57cec5SDimitry Andric     return;
47230b57cec5SDimitry Andric 
47240b57cec5SDimitry Andric   const char *startBuf = SM->getCharacterData(LocStart);
47250b57cec5SDimitry Andric   const char *endBuf = SM->getCharacterData(LocEnd);
47260b57cec5SDimitry Andric   QualType QT = CE->getType();
47270b57cec5SDimitry Andric   const Type* TypePtr = QT->getAs<Type>();
47280b57cec5SDimitry Andric   if (isa<TypeOfExprType>(TypePtr)) {
47290b57cec5SDimitry Andric     const TypeOfExprType *TypeOfExprTypePtr = cast<TypeOfExprType>(TypePtr);
47300b57cec5SDimitry Andric     QT = TypeOfExprTypePtr->getUnderlyingExpr()->getType();
47310b57cec5SDimitry Andric     std::string TypeAsString = "(";
47320b57cec5SDimitry Andric     RewriteBlockPointerType(TypeAsString, QT);
47330b57cec5SDimitry Andric     TypeAsString += ")";
47340b57cec5SDimitry Andric     ReplaceText(LocStart, endBuf-startBuf+1, TypeAsString);
47350b57cec5SDimitry Andric     return;
47360b57cec5SDimitry Andric   }
47370b57cec5SDimitry Andric   // advance the location to startArgList.
47380b57cec5SDimitry Andric   const char *argPtr = startBuf;
47390b57cec5SDimitry Andric 
47400b57cec5SDimitry Andric   while (*argPtr++ && (argPtr < endBuf)) {
47410b57cec5SDimitry Andric     switch (*argPtr) {
47420b57cec5SDimitry Andric     case '^':
47430b57cec5SDimitry Andric       // Replace the '^' with '*'.
47440b57cec5SDimitry Andric       LocStart = LocStart.getLocWithOffset(argPtr-startBuf);
47450b57cec5SDimitry Andric       ReplaceText(LocStart, 1, "*");
47460b57cec5SDimitry Andric       break;
47470b57cec5SDimitry Andric     }
47480b57cec5SDimitry Andric   }
47490b57cec5SDimitry Andric }
47500b57cec5SDimitry Andric 
RewriteImplicitCastObjCExpr(CastExpr * IC)47510b57cec5SDimitry Andric void RewriteModernObjC::RewriteImplicitCastObjCExpr(CastExpr *IC) {
47520b57cec5SDimitry Andric   CastKind CastKind = IC->getCastKind();
47530b57cec5SDimitry Andric   if (CastKind != CK_BlockPointerToObjCPointerCast &&
47540b57cec5SDimitry Andric       CastKind != CK_AnyPointerToBlockPointerCast)
47550b57cec5SDimitry Andric     return;
47560b57cec5SDimitry Andric 
47570b57cec5SDimitry Andric   QualType QT = IC->getType();
47580b57cec5SDimitry Andric   (void)convertBlockPointerToFunctionPointer(QT);
47590b57cec5SDimitry Andric   std::string TypeString(QT.getAsString(Context->getPrintingPolicy()));
47600b57cec5SDimitry Andric   std::string Str = "(";
47610b57cec5SDimitry Andric   Str += TypeString;
47620b57cec5SDimitry Andric   Str += ")";
47630b57cec5SDimitry Andric   InsertText(IC->getSubExpr()->getBeginLoc(), Str);
47640b57cec5SDimitry Andric }
47650b57cec5SDimitry Andric 
RewriteBlockPointerFunctionArgs(FunctionDecl * FD)47660b57cec5SDimitry Andric void RewriteModernObjC::RewriteBlockPointerFunctionArgs(FunctionDecl *FD) {
47670b57cec5SDimitry Andric   SourceLocation DeclLoc = FD->getLocation();
47680b57cec5SDimitry Andric   unsigned parenCount = 0;
47690b57cec5SDimitry Andric 
47700b57cec5SDimitry Andric   // We have 1 or more arguments that have closure pointers.
47710b57cec5SDimitry Andric   const char *startBuf = SM->getCharacterData(DeclLoc);
47720b57cec5SDimitry Andric   const char *startArgList = strchr(startBuf, '(');
47730b57cec5SDimitry Andric 
47740b57cec5SDimitry Andric   assert((*startArgList == '(') && "Rewriter fuzzy parser confused");
47750b57cec5SDimitry Andric 
47760b57cec5SDimitry Andric   parenCount++;
47770b57cec5SDimitry Andric   // advance the location to startArgList.
47780b57cec5SDimitry Andric   DeclLoc = DeclLoc.getLocWithOffset(startArgList-startBuf);
47790b57cec5SDimitry Andric   assert((DeclLoc.isValid()) && "Invalid DeclLoc");
47800b57cec5SDimitry Andric 
47810b57cec5SDimitry Andric   const char *argPtr = startArgList;
47820b57cec5SDimitry Andric 
47830b57cec5SDimitry Andric   while (*argPtr++ && parenCount) {
47840b57cec5SDimitry Andric     switch (*argPtr) {
47850b57cec5SDimitry Andric     case '^':
47860b57cec5SDimitry Andric       // Replace the '^' with '*'.
47870b57cec5SDimitry Andric       DeclLoc = DeclLoc.getLocWithOffset(argPtr-startArgList);
47880b57cec5SDimitry Andric       ReplaceText(DeclLoc, 1, "*");
47890b57cec5SDimitry Andric       break;
47900b57cec5SDimitry Andric     case '(':
47910b57cec5SDimitry Andric       parenCount++;
47920b57cec5SDimitry Andric       break;
47930b57cec5SDimitry Andric     case ')':
47940b57cec5SDimitry Andric       parenCount--;
47950b57cec5SDimitry Andric       break;
47960b57cec5SDimitry Andric     }
47970b57cec5SDimitry Andric   }
47980b57cec5SDimitry Andric }
47990b57cec5SDimitry Andric 
PointerTypeTakesAnyBlockArguments(QualType QT)48000b57cec5SDimitry Andric bool RewriteModernObjC::PointerTypeTakesAnyBlockArguments(QualType QT) {
48010b57cec5SDimitry Andric   const FunctionProtoType *FTP;
48020b57cec5SDimitry Andric   const PointerType *PT = QT->getAs<PointerType>();
48030b57cec5SDimitry Andric   if (PT) {
48040b57cec5SDimitry Andric     FTP = PT->getPointeeType()->getAs<FunctionProtoType>();
48050b57cec5SDimitry Andric   } else {
48060b57cec5SDimitry Andric     const BlockPointerType *BPT = QT->getAs<BlockPointerType>();
48070b57cec5SDimitry Andric     assert(BPT && "BlockPointerTypeTakeAnyBlockArguments(): not a block pointer type");
48080b57cec5SDimitry Andric     FTP = BPT->getPointeeType()->getAs<FunctionProtoType>();
48090b57cec5SDimitry Andric   }
48100b57cec5SDimitry Andric   if (FTP) {
48110b57cec5SDimitry Andric     for (const auto &I : FTP->param_types())
48120b57cec5SDimitry Andric       if (isTopLevelBlockPointerType(I))
48130b57cec5SDimitry Andric         return true;
48140b57cec5SDimitry Andric   }
48150b57cec5SDimitry Andric   return false;
48160b57cec5SDimitry Andric }
48170b57cec5SDimitry Andric 
PointerTypeTakesAnyObjCQualifiedType(QualType QT)48180b57cec5SDimitry Andric bool RewriteModernObjC::PointerTypeTakesAnyObjCQualifiedType(QualType QT) {
48190b57cec5SDimitry Andric   const FunctionProtoType *FTP;
48200b57cec5SDimitry Andric   const PointerType *PT = QT->getAs<PointerType>();
48210b57cec5SDimitry Andric   if (PT) {
48220b57cec5SDimitry Andric     FTP = PT->getPointeeType()->getAs<FunctionProtoType>();
48230b57cec5SDimitry Andric   } else {
48240b57cec5SDimitry Andric     const BlockPointerType *BPT = QT->getAs<BlockPointerType>();
48250b57cec5SDimitry Andric     assert(BPT && "BlockPointerTypeTakeAnyBlockArguments(): not a block pointer type");
48260b57cec5SDimitry Andric     FTP = BPT->getPointeeType()->getAs<FunctionProtoType>();
48270b57cec5SDimitry Andric   }
48280b57cec5SDimitry Andric   if (FTP) {
48290b57cec5SDimitry Andric     for (const auto &I : FTP->param_types()) {
48300b57cec5SDimitry Andric       if (I->isObjCQualifiedIdType())
48310b57cec5SDimitry Andric         return true;
48320b57cec5SDimitry Andric       if (I->isObjCObjectPointerType() &&
48330b57cec5SDimitry Andric           I->getPointeeType()->isObjCQualifiedInterfaceType())
48340b57cec5SDimitry Andric         return true;
48350b57cec5SDimitry Andric     }
48360b57cec5SDimitry Andric 
48370b57cec5SDimitry Andric   }
48380b57cec5SDimitry Andric   return false;
48390b57cec5SDimitry Andric }
48400b57cec5SDimitry Andric 
GetExtentOfArgList(const char * Name,const char * & LParen,const char * & RParen)48410b57cec5SDimitry Andric void RewriteModernObjC::GetExtentOfArgList(const char *Name, const char *&LParen,
48420b57cec5SDimitry Andric                                      const char *&RParen) {
48430b57cec5SDimitry Andric   const char *argPtr = strchr(Name, '(');
48440b57cec5SDimitry Andric   assert((*argPtr == '(') && "Rewriter fuzzy parser confused");
48450b57cec5SDimitry Andric 
48460b57cec5SDimitry Andric   LParen = argPtr; // output the start.
48470b57cec5SDimitry Andric   argPtr++; // skip past the left paren.
48480b57cec5SDimitry Andric   unsigned parenCount = 1;
48490b57cec5SDimitry Andric 
48500b57cec5SDimitry Andric   while (*argPtr && parenCount) {
48510b57cec5SDimitry Andric     switch (*argPtr) {
48520b57cec5SDimitry Andric     case '(': parenCount++; break;
48530b57cec5SDimitry Andric     case ')': parenCount--; break;
48540b57cec5SDimitry Andric     default: break;
48550b57cec5SDimitry Andric     }
48560b57cec5SDimitry Andric     if (parenCount) argPtr++;
48570b57cec5SDimitry Andric   }
48580b57cec5SDimitry Andric   assert((*argPtr == ')') && "Rewriter fuzzy parser confused");
48590b57cec5SDimitry Andric   RParen = argPtr; // output the end
48600b57cec5SDimitry Andric }
48610b57cec5SDimitry Andric 
RewriteBlockPointerDecl(NamedDecl * ND)48620b57cec5SDimitry Andric void RewriteModernObjC::RewriteBlockPointerDecl(NamedDecl *ND) {
48630b57cec5SDimitry Andric   if (FunctionDecl *FD = dyn_cast<FunctionDecl>(ND)) {
48640b57cec5SDimitry Andric     RewriteBlockPointerFunctionArgs(FD);
48650b57cec5SDimitry Andric     return;
48660b57cec5SDimitry Andric   }
48670b57cec5SDimitry Andric   // Handle Variables and Typedefs.
48680b57cec5SDimitry Andric   SourceLocation DeclLoc = ND->getLocation();
48690b57cec5SDimitry Andric   QualType DeclT;
48700b57cec5SDimitry Andric   if (VarDecl *VD = dyn_cast<VarDecl>(ND))
48710b57cec5SDimitry Andric     DeclT = VD->getType();
48720b57cec5SDimitry Andric   else if (TypedefNameDecl *TDD = dyn_cast<TypedefNameDecl>(ND))
48730b57cec5SDimitry Andric     DeclT = TDD->getUnderlyingType();
48740b57cec5SDimitry Andric   else if (FieldDecl *FD = dyn_cast<FieldDecl>(ND))
48750b57cec5SDimitry Andric     DeclT = FD->getType();
48760b57cec5SDimitry Andric   else
48770b57cec5SDimitry Andric     llvm_unreachable("RewriteBlockPointerDecl(): Decl type not yet handled");
48780b57cec5SDimitry Andric 
48790b57cec5SDimitry Andric   const char *startBuf = SM->getCharacterData(DeclLoc);
48800b57cec5SDimitry Andric   const char *endBuf = startBuf;
48810b57cec5SDimitry Andric   // scan backward (from the decl location) for the end of the previous decl.
48820b57cec5SDimitry Andric   while (*startBuf != '^' && *startBuf != ';' && startBuf != MainFileStart)
48830b57cec5SDimitry Andric     startBuf--;
48840b57cec5SDimitry Andric   SourceLocation Start = DeclLoc.getLocWithOffset(startBuf-endBuf);
48850b57cec5SDimitry Andric   std::string buf;
48860b57cec5SDimitry Andric   unsigned OrigLength=0;
48870b57cec5SDimitry Andric   // *startBuf != '^' if we are dealing with a pointer to function that
48880b57cec5SDimitry Andric   // may take block argument types (which will be handled below).
48890b57cec5SDimitry Andric   if (*startBuf == '^') {
48900b57cec5SDimitry Andric     // Replace the '^' with '*', computing a negative offset.
48910b57cec5SDimitry Andric     buf = '*';
48920b57cec5SDimitry Andric     startBuf++;
48930b57cec5SDimitry Andric     OrigLength++;
48940b57cec5SDimitry Andric   }
48950b57cec5SDimitry Andric   while (*startBuf != ')') {
48960b57cec5SDimitry Andric     buf += *startBuf;
48970b57cec5SDimitry Andric     startBuf++;
48980b57cec5SDimitry Andric     OrigLength++;
48990b57cec5SDimitry Andric   }
49000b57cec5SDimitry Andric   buf += ')';
49010b57cec5SDimitry Andric   OrigLength++;
49020b57cec5SDimitry Andric 
49030b57cec5SDimitry Andric   if (PointerTypeTakesAnyBlockArguments(DeclT) ||
49040b57cec5SDimitry Andric       PointerTypeTakesAnyObjCQualifiedType(DeclT)) {
49050b57cec5SDimitry Andric     // Replace the '^' with '*' for arguments.
49060b57cec5SDimitry Andric     // Replace id<P> with id/*<>*/
49070b57cec5SDimitry Andric     DeclLoc = ND->getLocation();
49080b57cec5SDimitry Andric     startBuf = SM->getCharacterData(DeclLoc);
49090b57cec5SDimitry Andric     const char *argListBegin, *argListEnd;
49100b57cec5SDimitry Andric     GetExtentOfArgList(startBuf, argListBegin, argListEnd);
49110b57cec5SDimitry Andric     while (argListBegin < argListEnd) {
49120b57cec5SDimitry Andric       if (*argListBegin == '^')
49130b57cec5SDimitry Andric         buf += '*';
49140b57cec5SDimitry Andric       else if (*argListBegin ==  '<') {
49150b57cec5SDimitry Andric         buf += "/*";
49160b57cec5SDimitry Andric         buf += *argListBegin++;
49170b57cec5SDimitry Andric         OrigLength++;
49180b57cec5SDimitry Andric         while (*argListBegin != '>') {
49190b57cec5SDimitry Andric           buf += *argListBegin++;
49200b57cec5SDimitry Andric           OrigLength++;
49210b57cec5SDimitry Andric         }
49220b57cec5SDimitry Andric         buf += *argListBegin;
49230b57cec5SDimitry Andric         buf += "*/";
49240b57cec5SDimitry Andric       }
49250b57cec5SDimitry Andric       else
49260b57cec5SDimitry Andric         buf += *argListBegin;
49270b57cec5SDimitry Andric       argListBegin++;
49280b57cec5SDimitry Andric       OrigLength++;
49290b57cec5SDimitry Andric     }
49300b57cec5SDimitry Andric     buf += ')';
49310b57cec5SDimitry Andric     OrigLength++;
49320b57cec5SDimitry Andric   }
49330b57cec5SDimitry Andric   ReplaceText(Start, OrigLength, buf);
49340b57cec5SDimitry Andric }
49350b57cec5SDimitry Andric 
49360b57cec5SDimitry Andric /// SynthesizeByrefCopyDestroyHelper - This routine synthesizes:
49370b57cec5SDimitry Andric /// void __Block_byref_id_object_copy(struct Block_byref_id_object *dst,
49380b57cec5SDimitry Andric ///                    struct Block_byref_id_object *src) {
49390b57cec5SDimitry Andric ///  _Block_object_assign (&_dest->object, _src->object,
49400b57cec5SDimitry Andric ///                        BLOCK_BYREF_CALLER | BLOCK_FIELD_IS_OBJECT
49410b57cec5SDimitry Andric ///                        [|BLOCK_FIELD_IS_WEAK]) // object
49420b57cec5SDimitry Andric ///  _Block_object_assign(&_dest->object, _src->object,
49430b57cec5SDimitry Andric ///                       BLOCK_BYREF_CALLER | BLOCK_FIELD_IS_BLOCK
49440b57cec5SDimitry Andric ///                       [|BLOCK_FIELD_IS_WEAK]) // block
49450b57cec5SDimitry Andric /// }
49460b57cec5SDimitry Andric /// And:
49470b57cec5SDimitry Andric /// void __Block_byref_id_object_dispose(struct Block_byref_id_object *_src) {
49480b57cec5SDimitry Andric ///  _Block_object_dispose(_src->object,
49490b57cec5SDimitry Andric ///                        BLOCK_BYREF_CALLER | BLOCK_FIELD_IS_OBJECT
49500b57cec5SDimitry Andric ///                        [|BLOCK_FIELD_IS_WEAK]) // object
49510b57cec5SDimitry Andric ///  _Block_object_dispose(_src->object,
49520b57cec5SDimitry Andric ///                         BLOCK_BYREF_CALLER | BLOCK_FIELD_IS_BLOCK
49530b57cec5SDimitry Andric ///                         [|BLOCK_FIELD_IS_WEAK]) // block
49540b57cec5SDimitry Andric /// }
49550b57cec5SDimitry Andric 
SynthesizeByrefCopyDestroyHelper(VarDecl * VD,int flag)49560b57cec5SDimitry Andric std::string RewriteModernObjC::SynthesizeByrefCopyDestroyHelper(VarDecl *VD,
49570b57cec5SDimitry Andric                                                           int flag) {
49580b57cec5SDimitry Andric   std::string S;
49590b57cec5SDimitry Andric   if (CopyDestroyCache.count(flag))
49600b57cec5SDimitry Andric     return S;
49610b57cec5SDimitry Andric   CopyDestroyCache.insert(flag);
49620b57cec5SDimitry Andric   S = "static void __Block_byref_id_object_copy_";
49630b57cec5SDimitry Andric   S += utostr(flag);
49640b57cec5SDimitry Andric   S += "(void *dst, void *src) {\n";
49650b57cec5SDimitry Andric 
49660b57cec5SDimitry Andric   // offset into the object pointer is computed as:
49670b57cec5SDimitry Andric   // void * + void* + int + int + void* + void *
49680b57cec5SDimitry Andric   unsigned IntSize =
49690b57cec5SDimitry Andric   static_cast<unsigned>(Context->getTypeSize(Context->IntTy));
49700b57cec5SDimitry Andric   unsigned VoidPtrSize =
49710b57cec5SDimitry Andric   static_cast<unsigned>(Context->getTypeSize(Context->VoidPtrTy));
49720b57cec5SDimitry Andric 
49730b57cec5SDimitry Andric   unsigned offset = (VoidPtrSize*4 + IntSize + IntSize)/Context->getCharWidth();
49740b57cec5SDimitry Andric   S += " _Block_object_assign((char*)dst + ";
49750b57cec5SDimitry Andric   S += utostr(offset);
49760b57cec5SDimitry Andric   S += ", *(void * *) ((char*)src + ";
49770b57cec5SDimitry Andric   S += utostr(offset);
49780b57cec5SDimitry Andric   S += "), ";
49790b57cec5SDimitry Andric   S += utostr(flag);
49800b57cec5SDimitry Andric   S += ");\n}\n";
49810b57cec5SDimitry Andric 
49820b57cec5SDimitry Andric   S += "static void __Block_byref_id_object_dispose_";
49830b57cec5SDimitry Andric   S += utostr(flag);
49840b57cec5SDimitry Andric   S += "(void *src) {\n";
49850b57cec5SDimitry Andric   S += " _Block_object_dispose(*(void * *) ((char*)src + ";
49860b57cec5SDimitry Andric   S += utostr(offset);
49870b57cec5SDimitry Andric   S += "), ";
49880b57cec5SDimitry Andric   S += utostr(flag);
49890b57cec5SDimitry Andric   S += ");\n}\n";
49900b57cec5SDimitry Andric   return S;
49910b57cec5SDimitry Andric }
49920b57cec5SDimitry Andric 
49930b57cec5SDimitry Andric /// RewriteByRefVar - For each __block typex ND variable this routine transforms
49940b57cec5SDimitry Andric /// the declaration into:
49950b57cec5SDimitry Andric /// struct __Block_byref_ND {
49960b57cec5SDimitry Andric /// void *__isa;                  // NULL for everything except __weak pointers
49970b57cec5SDimitry Andric /// struct __Block_byref_ND *__forwarding;
49980b57cec5SDimitry Andric /// int32_t __flags;
49990b57cec5SDimitry Andric /// int32_t __size;
50000b57cec5SDimitry Andric /// void *__Block_byref_id_object_copy; // If variable is __block ObjC object
50010b57cec5SDimitry Andric /// void *__Block_byref_id_object_dispose; // If variable is __block ObjC object
50020b57cec5SDimitry Andric /// typex ND;
50030b57cec5SDimitry Andric /// };
50040b57cec5SDimitry Andric ///
50050b57cec5SDimitry Andric /// It then replaces declaration of ND variable with:
50060b57cec5SDimitry Andric /// struct __Block_byref_ND ND = {__isa=0B, __forwarding=&ND, __flags=some_flag,
50070b57cec5SDimitry Andric ///                               __size=sizeof(struct __Block_byref_ND),
50080b57cec5SDimitry Andric ///                               ND=initializer-if-any};
50090b57cec5SDimitry Andric ///
50100b57cec5SDimitry Andric ///
RewriteByRefVar(VarDecl * ND,bool firstDecl,bool lastDecl)50110b57cec5SDimitry Andric void RewriteModernObjC::RewriteByRefVar(VarDecl *ND, bool firstDecl,
50120b57cec5SDimitry Andric                                         bool lastDecl) {
50130b57cec5SDimitry Andric   int flag = 0;
50140b57cec5SDimitry Andric   int isa = 0;
50150b57cec5SDimitry Andric   SourceLocation DeclLoc = ND->getTypeSpecStartLoc();
50160b57cec5SDimitry Andric   if (DeclLoc.isInvalid())
50170b57cec5SDimitry Andric     // If type location is missing, it is because of missing type (a warning).
50180b57cec5SDimitry Andric     // Use variable's location which is good for this case.
50190b57cec5SDimitry Andric     DeclLoc = ND->getLocation();
50200b57cec5SDimitry Andric   const char *startBuf = SM->getCharacterData(DeclLoc);
50210b57cec5SDimitry Andric   SourceLocation X = ND->getEndLoc();
50220b57cec5SDimitry Andric   X = SM->getExpansionLoc(X);
50230b57cec5SDimitry Andric   const char *endBuf = SM->getCharacterData(X);
50240b57cec5SDimitry Andric   std::string Name(ND->getNameAsString());
50250b57cec5SDimitry Andric   std::string ByrefType;
50260b57cec5SDimitry Andric   RewriteByRefString(ByrefType, Name, ND, true);
50270b57cec5SDimitry Andric   ByrefType += " {\n";
50280b57cec5SDimitry Andric   ByrefType += "  void *__isa;\n";
50290b57cec5SDimitry Andric   RewriteByRefString(ByrefType, Name, ND);
50300b57cec5SDimitry Andric   ByrefType += " *__forwarding;\n";
50310b57cec5SDimitry Andric   ByrefType += " int __flags;\n";
50320b57cec5SDimitry Andric   ByrefType += " int __size;\n";
50330b57cec5SDimitry Andric   // Add void *__Block_byref_id_object_copy;
50340b57cec5SDimitry Andric   // void *__Block_byref_id_object_dispose; if needed.
50350b57cec5SDimitry Andric   QualType Ty = ND->getType();
50360b57cec5SDimitry Andric   bool HasCopyAndDispose = Context->BlockRequiresCopying(Ty, ND);
50370b57cec5SDimitry Andric   if (HasCopyAndDispose) {
50380b57cec5SDimitry Andric     ByrefType += " void (*__Block_byref_id_object_copy)(void*, void*);\n";
50390b57cec5SDimitry Andric     ByrefType += " void (*__Block_byref_id_object_dispose)(void*);\n";
50400b57cec5SDimitry Andric   }
50410b57cec5SDimitry Andric 
50420b57cec5SDimitry Andric   QualType T = Ty;
50430b57cec5SDimitry Andric   (void)convertBlockPointerToFunctionPointer(T);
50440b57cec5SDimitry Andric   T.getAsStringInternal(Name, Context->getPrintingPolicy());
50450b57cec5SDimitry Andric 
50460b57cec5SDimitry Andric   ByrefType += " " + Name + ";\n";
50470b57cec5SDimitry Andric   ByrefType += "};\n";
50480b57cec5SDimitry Andric   // Insert this type in global scope. It is needed by helper function.
50490b57cec5SDimitry Andric   SourceLocation FunLocStart;
50500b57cec5SDimitry Andric   if (CurFunctionDef)
50510b57cec5SDimitry Andric      FunLocStart = getFunctionSourceLocation(*this, CurFunctionDef);
50520b57cec5SDimitry Andric   else {
50530b57cec5SDimitry Andric     assert(CurMethodDef && "RewriteByRefVar - CurMethodDef is null");
50540b57cec5SDimitry Andric     FunLocStart = CurMethodDef->getBeginLoc();
50550b57cec5SDimitry Andric   }
50560b57cec5SDimitry Andric   InsertText(FunLocStart, ByrefType);
50570b57cec5SDimitry Andric 
50580b57cec5SDimitry Andric   if (Ty.isObjCGCWeak()) {
50590b57cec5SDimitry Andric     flag |= BLOCK_FIELD_IS_WEAK;
50600b57cec5SDimitry Andric     isa = 1;
50610b57cec5SDimitry Andric   }
50620b57cec5SDimitry Andric   if (HasCopyAndDispose) {
50630b57cec5SDimitry Andric     flag = BLOCK_BYREF_CALLER;
50640b57cec5SDimitry Andric     QualType Ty = ND->getType();
50650b57cec5SDimitry Andric     // FIXME. Handle __weak variable (BLOCK_FIELD_IS_WEAK) as well.
50660b57cec5SDimitry Andric     if (Ty->isBlockPointerType())
50670b57cec5SDimitry Andric       flag |= BLOCK_FIELD_IS_BLOCK;
50680b57cec5SDimitry Andric     else
50690b57cec5SDimitry Andric       flag |= BLOCK_FIELD_IS_OBJECT;
50700b57cec5SDimitry Andric     std::string HF = SynthesizeByrefCopyDestroyHelper(ND, flag);
50710b57cec5SDimitry Andric     if (!HF.empty())
50720b57cec5SDimitry Andric       Preamble += HF;
50730b57cec5SDimitry Andric   }
50740b57cec5SDimitry Andric 
50750b57cec5SDimitry Andric   // struct __Block_byref_ND ND =
50760b57cec5SDimitry Andric   // {0, &ND, some_flag, __size=sizeof(struct __Block_byref_ND),
50770b57cec5SDimitry Andric   //  initializer-if-any};
50780b57cec5SDimitry Andric   bool hasInit = (ND->getInit() != nullptr);
50790b57cec5SDimitry Andric   // FIXME. rewriter does not support __block c++ objects which
50800b57cec5SDimitry Andric   // require construction.
50810b57cec5SDimitry Andric   if (hasInit)
50820b57cec5SDimitry Andric     if (CXXConstructExpr *CExp = dyn_cast<CXXConstructExpr>(ND->getInit())) {
50830b57cec5SDimitry Andric       CXXConstructorDecl *CXXDecl = CExp->getConstructor();
50840b57cec5SDimitry Andric       if (CXXDecl && CXXDecl->isDefaultConstructor())
50850b57cec5SDimitry Andric         hasInit = false;
50860b57cec5SDimitry Andric     }
50870b57cec5SDimitry Andric 
50880b57cec5SDimitry Andric   unsigned flags = 0;
50890b57cec5SDimitry Andric   if (HasCopyAndDispose)
50900b57cec5SDimitry Andric     flags |= BLOCK_HAS_COPY_DISPOSE;
50910b57cec5SDimitry Andric   Name = ND->getNameAsString();
50920b57cec5SDimitry Andric   ByrefType.clear();
50930b57cec5SDimitry Andric   RewriteByRefString(ByrefType, Name, ND);
50940b57cec5SDimitry Andric   std::string ForwardingCastType("(");
50950b57cec5SDimitry Andric   ForwardingCastType += ByrefType + " *)";
50960b57cec5SDimitry Andric   ByrefType += " " + Name + " = {(void*)";
50970b57cec5SDimitry Andric   ByrefType += utostr(isa);
50980b57cec5SDimitry Andric   ByrefType += "," +  ForwardingCastType + "&" + Name + ", ";
50990b57cec5SDimitry Andric   ByrefType += utostr(flags);
51000b57cec5SDimitry Andric   ByrefType += ", ";
51010b57cec5SDimitry Andric   ByrefType += "sizeof(";
51020b57cec5SDimitry Andric   RewriteByRefString(ByrefType, Name, ND);
51030b57cec5SDimitry Andric   ByrefType += ")";
51040b57cec5SDimitry Andric   if (HasCopyAndDispose) {
51050b57cec5SDimitry Andric     ByrefType += ", __Block_byref_id_object_copy_";
51060b57cec5SDimitry Andric     ByrefType += utostr(flag);
51070b57cec5SDimitry Andric     ByrefType += ", __Block_byref_id_object_dispose_";
51080b57cec5SDimitry Andric     ByrefType += utostr(flag);
51090b57cec5SDimitry Andric   }
51100b57cec5SDimitry Andric 
51110b57cec5SDimitry Andric   if (!firstDecl) {
51120b57cec5SDimitry Andric     // In multiple __block declarations, and for all but 1st declaration,
51130b57cec5SDimitry Andric     // find location of the separating comma. This would be start location
51140b57cec5SDimitry Andric     // where new text is to be inserted.
51150b57cec5SDimitry Andric     DeclLoc = ND->getLocation();
51160b57cec5SDimitry Andric     const char *startDeclBuf = SM->getCharacterData(DeclLoc);
51170b57cec5SDimitry Andric     const char *commaBuf = startDeclBuf;
51180b57cec5SDimitry Andric     while (*commaBuf != ',')
51190b57cec5SDimitry Andric       commaBuf--;
51200b57cec5SDimitry Andric     assert((*commaBuf == ',') && "RewriteByRefVar: can't find ','");
51210b57cec5SDimitry Andric     DeclLoc = DeclLoc.getLocWithOffset(commaBuf - startDeclBuf);
51220b57cec5SDimitry Andric     startBuf = commaBuf;
51230b57cec5SDimitry Andric   }
51240b57cec5SDimitry Andric 
51250b57cec5SDimitry Andric   if (!hasInit) {
51260b57cec5SDimitry Andric     ByrefType += "};\n";
51270b57cec5SDimitry Andric     unsigned nameSize = Name.size();
51280b57cec5SDimitry Andric     // for block or function pointer declaration. Name is already
51290b57cec5SDimitry Andric     // part of the declaration.
51300b57cec5SDimitry Andric     if (Ty->isBlockPointerType() || Ty->isFunctionPointerType())
51310b57cec5SDimitry Andric       nameSize = 1;
51320b57cec5SDimitry Andric     ReplaceText(DeclLoc, endBuf-startBuf+nameSize, ByrefType);
51330b57cec5SDimitry Andric   }
51340b57cec5SDimitry Andric   else {
51350b57cec5SDimitry Andric     ByrefType += ", ";
51360b57cec5SDimitry Andric     SourceLocation startLoc;
51370b57cec5SDimitry Andric     Expr *E = ND->getInit();
51380b57cec5SDimitry Andric     if (const CStyleCastExpr *ECE = dyn_cast<CStyleCastExpr>(E))
51390b57cec5SDimitry Andric       startLoc = ECE->getLParenLoc();
51400b57cec5SDimitry Andric     else
51410b57cec5SDimitry Andric       startLoc = E->getBeginLoc();
51420b57cec5SDimitry Andric     startLoc = SM->getExpansionLoc(startLoc);
51430b57cec5SDimitry Andric     endBuf = SM->getCharacterData(startLoc);
51440b57cec5SDimitry Andric     ReplaceText(DeclLoc, endBuf-startBuf, ByrefType);
51450b57cec5SDimitry Andric 
51460b57cec5SDimitry Andric     const char separator = lastDecl ? ';' : ',';
51470b57cec5SDimitry Andric     const char *startInitializerBuf = SM->getCharacterData(startLoc);
51480b57cec5SDimitry Andric     const char *separatorBuf = strchr(startInitializerBuf, separator);
51490b57cec5SDimitry Andric     assert((*separatorBuf == separator) &&
51500b57cec5SDimitry Andric            "RewriteByRefVar: can't find ';' or ','");
51510b57cec5SDimitry Andric     SourceLocation separatorLoc =
51520b57cec5SDimitry Andric       startLoc.getLocWithOffset(separatorBuf-startInitializerBuf);
51530b57cec5SDimitry Andric 
51540b57cec5SDimitry Andric     InsertText(separatorLoc, lastDecl ? "}" : "};\n");
51550b57cec5SDimitry Andric   }
51560b57cec5SDimitry Andric }
51570b57cec5SDimitry Andric 
CollectBlockDeclRefInfo(BlockExpr * Exp)51580b57cec5SDimitry Andric void RewriteModernObjC::CollectBlockDeclRefInfo(BlockExpr *Exp) {
51590b57cec5SDimitry Andric   // Add initializers for any closure decl refs.
51600b57cec5SDimitry Andric   GetBlockDeclRefExprs(Exp->getBody());
51610b57cec5SDimitry Andric   if (BlockDeclRefs.size()) {
51620b57cec5SDimitry Andric     // Unique all "by copy" declarations.
51630b57cec5SDimitry Andric     for (unsigned i = 0; i < BlockDeclRefs.size(); i++)
51640b57cec5SDimitry Andric       if (!BlockDeclRefs[i]->getDecl()->hasAttr<BlocksAttr>()) {
51650b57cec5SDimitry Andric         if (!BlockByCopyDeclsPtrSet.count(BlockDeclRefs[i]->getDecl())) {
51660b57cec5SDimitry Andric           BlockByCopyDeclsPtrSet.insert(BlockDeclRefs[i]->getDecl());
51670b57cec5SDimitry Andric           BlockByCopyDecls.push_back(BlockDeclRefs[i]->getDecl());
51680b57cec5SDimitry Andric         }
51690b57cec5SDimitry Andric       }
51700b57cec5SDimitry Andric     // Unique all "by ref" declarations.
51710b57cec5SDimitry Andric     for (unsigned i = 0; i < BlockDeclRefs.size(); i++)
51720b57cec5SDimitry Andric       if (BlockDeclRefs[i]->getDecl()->hasAttr<BlocksAttr>()) {
51730b57cec5SDimitry Andric         if (!BlockByRefDeclsPtrSet.count(BlockDeclRefs[i]->getDecl())) {
51740b57cec5SDimitry Andric           BlockByRefDeclsPtrSet.insert(BlockDeclRefs[i]->getDecl());
51750b57cec5SDimitry Andric           BlockByRefDecls.push_back(BlockDeclRefs[i]->getDecl());
51760b57cec5SDimitry Andric         }
51770b57cec5SDimitry Andric       }
51780b57cec5SDimitry Andric     // Find any imported blocks...they will need special attention.
51790b57cec5SDimitry Andric     for (unsigned i = 0; i < BlockDeclRefs.size(); i++)
51800b57cec5SDimitry Andric       if (BlockDeclRefs[i]->getDecl()->hasAttr<BlocksAttr>() ||
51810b57cec5SDimitry Andric           BlockDeclRefs[i]->getType()->isObjCObjectPointerType() ||
51820b57cec5SDimitry Andric           BlockDeclRefs[i]->getType()->isBlockPointerType())
51830b57cec5SDimitry Andric         ImportedBlockDecls.insert(BlockDeclRefs[i]->getDecl());
51840b57cec5SDimitry Andric   }
51850b57cec5SDimitry Andric }
51860b57cec5SDimitry Andric 
SynthBlockInitFunctionDecl(StringRef name)51870b57cec5SDimitry Andric FunctionDecl *RewriteModernObjC::SynthBlockInitFunctionDecl(StringRef name) {
51880b57cec5SDimitry Andric   IdentifierInfo *ID = &Context->Idents.get(name);
51890b57cec5SDimitry Andric   QualType FType = Context->getFunctionNoProtoType(Context->VoidPtrTy);
51900b57cec5SDimitry Andric   return FunctionDecl::Create(*Context, TUDecl, SourceLocation(),
51910b57cec5SDimitry Andric                               SourceLocation(), ID, FType, nullptr, SC_Extern,
51920b57cec5SDimitry Andric                               false, false);
51930b57cec5SDimitry Andric }
51940b57cec5SDimitry Andric 
SynthBlockInitExpr(BlockExpr * Exp,const SmallVectorImpl<DeclRefExpr * > & InnerBlockDeclRefs)51950b57cec5SDimitry Andric Stmt *RewriteModernObjC::SynthBlockInitExpr(BlockExpr *Exp,
51960b57cec5SDimitry Andric                      const SmallVectorImpl<DeclRefExpr *> &InnerBlockDeclRefs) {
51970b57cec5SDimitry Andric   const BlockDecl *block = Exp->getBlockDecl();
51980b57cec5SDimitry Andric 
51990b57cec5SDimitry Andric   Blocks.push_back(Exp);
52000b57cec5SDimitry Andric 
52010b57cec5SDimitry Andric   CollectBlockDeclRefInfo(Exp);
52020b57cec5SDimitry Andric 
52030b57cec5SDimitry Andric   // Add inner imported variables now used in current block.
52040b57cec5SDimitry Andric   int countOfInnerDecls = 0;
52050b57cec5SDimitry Andric   if (!InnerBlockDeclRefs.empty()) {
52060b57cec5SDimitry Andric     for (unsigned i = 0; i < InnerBlockDeclRefs.size(); i++) {
52070b57cec5SDimitry Andric       DeclRefExpr *Exp = InnerBlockDeclRefs[i];
52080b57cec5SDimitry Andric       ValueDecl *VD = Exp->getDecl();
52090b57cec5SDimitry Andric       if (!VD->hasAttr<BlocksAttr>() && !BlockByCopyDeclsPtrSet.count(VD)) {
52100b57cec5SDimitry Andric       // We need to save the copied-in variables in nested
52110b57cec5SDimitry Andric       // blocks because it is needed at the end for some of the API generations.
52120b57cec5SDimitry Andric       // See SynthesizeBlockLiterals routine.
52130b57cec5SDimitry Andric         InnerDeclRefs.push_back(Exp); countOfInnerDecls++;
52140b57cec5SDimitry Andric         BlockDeclRefs.push_back(Exp);
52150b57cec5SDimitry Andric         BlockByCopyDeclsPtrSet.insert(VD);
52160b57cec5SDimitry Andric         BlockByCopyDecls.push_back(VD);
52170b57cec5SDimitry Andric       }
52180b57cec5SDimitry Andric       if (VD->hasAttr<BlocksAttr>() && !BlockByRefDeclsPtrSet.count(VD)) {
52190b57cec5SDimitry Andric         InnerDeclRefs.push_back(Exp); countOfInnerDecls++;
52200b57cec5SDimitry Andric         BlockDeclRefs.push_back(Exp);
52210b57cec5SDimitry Andric         BlockByRefDeclsPtrSet.insert(VD);
52220b57cec5SDimitry Andric         BlockByRefDecls.push_back(VD);
52230b57cec5SDimitry Andric       }
52240b57cec5SDimitry Andric     }
52250b57cec5SDimitry Andric     // Find any imported blocks...they will need special attention.
52260b57cec5SDimitry Andric     for (unsigned i = 0; i < InnerBlockDeclRefs.size(); i++)
52270b57cec5SDimitry Andric       if (InnerBlockDeclRefs[i]->getDecl()->hasAttr<BlocksAttr>() ||
52280b57cec5SDimitry Andric           InnerBlockDeclRefs[i]->getType()->isObjCObjectPointerType() ||
52290b57cec5SDimitry Andric           InnerBlockDeclRefs[i]->getType()->isBlockPointerType())
52300b57cec5SDimitry Andric         ImportedBlockDecls.insert(InnerBlockDeclRefs[i]->getDecl());
52310b57cec5SDimitry Andric   }
52320b57cec5SDimitry Andric   InnerDeclRefsCount.push_back(countOfInnerDecls);
52330b57cec5SDimitry Andric 
52340b57cec5SDimitry Andric   std::string FuncName;
52350b57cec5SDimitry Andric 
52360b57cec5SDimitry Andric   if (CurFunctionDef)
52370b57cec5SDimitry Andric     FuncName = CurFunctionDef->getNameAsString();
52380b57cec5SDimitry Andric   else if (CurMethodDef)
52390b57cec5SDimitry Andric     BuildUniqueMethodName(FuncName, CurMethodDef);
52400b57cec5SDimitry Andric   else if (GlobalVarDecl)
52410b57cec5SDimitry Andric     FuncName = std::string(GlobalVarDecl->getNameAsString());
52420b57cec5SDimitry Andric 
52430b57cec5SDimitry Andric   bool GlobalBlockExpr =
52440b57cec5SDimitry Andric     block->getDeclContext()->getRedeclContext()->isFileContext();
52450b57cec5SDimitry Andric 
52460b57cec5SDimitry Andric   if (GlobalBlockExpr && !GlobalVarDecl) {
52470b57cec5SDimitry Andric     Diags.Report(block->getLocation(), GlobalBlockRewriteFailedDiag);
52480b57cec5SDimitry Andric     GlobalBlockExpr = false;
52490b57cec5SDimitry Andric   }
52500b57cec5SDimitry Andric 
52510b57cec5SDimitry Andric   std::string BlockNumber = utostr(Blocks.size()-1);
52520b57cec5SDimitry Andric 
52530b57cec5SDimitry Andric   std::string Func = "__" + FuncName + "_block_func_" + BlockNumber;
52540b57cec5SDimitry Andric 
52550b57cec5SDimitry Andric   // Get a pointer to the function type so we can cast appropriately.
52560b57cec5SDimitry Andric   QualType BFT = convertFunctionTypeOfBlocks(Exp->getFunctionType());
52570b57cec5SDimitry Andric   QualType FType = Context->getPointerType(BFT);
52580b57cec5SDimitry Andric 
52590b57cec5SDimitry Andric   FunctionDecl *FD;
52600b57cec5SDimitry Andric   Expr *NewRep;
52610b57cec5SDimitry Andric 
52620b57cec5SDimitry Andric   // Simulate a constructor call...
52630b57cec5SDimitry Andric   std::string Tag;
52640b57cec5SDimitry Andric 
52650b57cec5SDimitry Andric   if (GlobalBlockExpr)
52660b57cec5SDimitry Andric     Tag = "__global_";
52670b57cec5SDimitry Andric   else
52680b57cec5SDimitry Andric     Tag = "__";
52690b57cec5SDimitry Andric   Tag += FuncName + "_block_impl_" + BlockNumber;
52700b57cec5SDimitry Andric 
52710b57cec5SDimitry Andric   FD = SynthBlockInitFunctionDecl(Tag);
52720b57cec5SDimitry Andric   DeclRefExpr *DRE = new (Context)
5273fe6060f1SDimitry Andric       DeclRefExpr(*Context, FD, false, FType, VK_PRValue, SourceLocation());
52740b57cec5SDimitry Andric 
52750b57cec5SDimitry Andric   SmallVector<Expr*, 4> InitExprs;
52760b57cec5SDimitry Andric 
52770b57cec5SDimitry Andric   // Initialize the block function.
52780b57cec5SDimitry Andric   FD = SynthBlockInitFunctionDecl(Func);
52790b57cec5SDimitry Andric   DeclRefExpr *Arg = new (Context) DeclRefExpr(
52800b57cec5SDimitry Andric       *Context, FD, false, FD->getType(), VK_LValue, SourceLocation());
52810b57cec5SDimitry Andric   CastExpr *castExpr = NoTypeInfoCStyleCastExpr(Context, Context->VoidPtrTy,
52820b57cec5SDimitry Andric                                                 CK_BitCast, Arg);
52830b57cec5SDimitry Andric   InitExprs.push_back(castExpr);
52840b57cec5SDimitry Andric 
52850b57cec5SDimitry Andric   // Initialize the block descriptor.
52860b57cec5SDimitry Andric   std::string DescData = "__" + FuncName + "_block_desc_" + BlockNumber + "_DATA";
52870b57cec5SDimitry Andric 
52880b57cec5SDimitry Andric   VarDecl *NewVD = VarDecl::Create(
52890b57cec5SDimitry Andric       *Context, TUDecl, SourceLocation(), SourceLocation(),
52900b57cec5SDimitry Andric       &Context->Idents.get(DescData), Context->VoidPtrTy, nullptr, SC_Static);
52915ffd83dbSDimitry Andric   UnaryOperator *DescRefExpr = UnaryOperator::Create(
52925ffd83dbSDimitry Andric       const_cast<ASTContext &>(*Context),
52930b57cec5SDimitry Andric       new (Context) DeclRefExpr(*Context, NewVD, false, Context->VoidPtrTy,
52940b57cec5SDimitry Andric                                 VK_LValue, SourceLocation()),
5295fe6060f1SDimitry Andric       UO_AddrOf, Context->getPointerType(Context->VoidPtrTy), VK_PRValue,
52965ffd83dbSDimitry Andric       OK_Ordinary, SourceLocation(), false, FPOptionsOverride());
52970b57cec5SDimitry Andric   InitExprs.push_back(DescRefExpr);
52980b57cec5SDimitry Andric 
52990b57cec5SDimitry Andric   // Add initializers for any closure decl refs.
53000b57cec5SDimitry Andric   if (BlockDeclRefs.size()) {
53010b57cec5SDimitry Andric     Expr *Exp;
53020b57cec5SDimitry Andric     // Output all "by copy" declarations.
53030b57cec5SDimitry Andric     for (SmallVectorImpl<ValueDecl *>::iterator I = BlockByCopyDecls.begin(),
53040b57cec5SDimitry Andric          E = BlockByCopyDecls.end(); I != E; ++I) {
53050b57cec5SDimitry Andric       if (isObjCType((*I)->getType())) {
53060b57cec5SDimitry Andric         // FIXME: Conform to ABI ([[obj retain] autorelease]).
53070b57cec5SDimitry Andric         FD = SynthBlockInitFunctionDecl((*I)->getName());
53080b57cec5SDimitry Andric         Exp = new (Context) DeclRefExpr(*Context, FD, false, FD->getType(),
53090b57cec5SDimitry Andric                                         VK_LValue, SourceLocation());
53100b57cec5SDimitry Andric         if (HasLocalVariableExternalStorage(*I)) {
53110b57cec5SDimitry Andric           QualType QT = (*I)->getType();
53120b57cec5SDimitry Andric           QT = Context->getPointerType(QT);
5313fe6060f1SDimitry Andric           Exp = UnaryOperator::Create(const_cast<ASTContext &>(*Context), Exp,
5314fe6060f1SDimitry Andric                                       UO_AddrOf, QT, VK_PRValue, OK_Ordinary,
5315fe6060f1SDimitry Andric                                       SourceLocation(), false,
5316fe6060f1SDimitry Andric                                       FPOptionsOverride());
53170b57cec5SDimitry Andric         }
53180b57cec5SDimitry Andric       } else if (isTopLevelBlockPointerType((*I)->getType())) {
53190b57cec5SDimitry Andric         FD = SynthBlockInitFunctionDecl((*I)->getName());
53200b57cec5SDimitry Andric         Arg = new (Context) DeclRefExpr(*Context, FD, false, FD->getType(),
53210b57cec5SDimitry Andric                                         VK_LValue, SourceLocation());
53220b57cec5SDimitry Andric         Exp = NoTypeInfoCStyleCastExpr(Context, Context->VoidPtrTy,
53230b57cec5SDimitry Andric                                        CK_BitCast, Arg);
53240b57cec5SDimitry Andric       } else {
53250b57cec5SDimitry Andric         FD = SynthBlockInitFunctionDecl((*I)->getName());
53260b57cec5SDimitry Andric         Exp = new (Context) DeclRefExpr(*Context, FD, false, FD->getType(),
53270b57cec5SDimitry Andric                                         VK_LValue, SourceLocation());
53280b57cec5SDimitry Andric         if (HasLocalVariableExternalStorage(*I)) {
53290b57cec5SDimitry Andric           QualType QT = (*I)->getType();
53300b57cec5SDimitry Andric           QT = Context->getPointerType(QT);
5331fe6060f1SDimitry Andric           Exp = UnaryOperator::Create(const_cast<ASTContext &>(*Context), Exp,
5332fe6060f1SDimitry Andric                                       UO_AddrOf, QT, VK_PRValue, OK_Ordinary,
5333fe6060f1SDimitry Andric                                       SourceLocation(), false,
5334fe6060f1SDimitry Andric                                       FPOptionsOverride());
53350b57cec5SDimitry Andric         }
53360b57cec5SDimitry Andric 
53370b57cec5SDimitry Andric       }
53380b57cec5SDimitry Andric       InitExprs.push_back(Exp);
53390b57cec5SDimitry Andric     }
53400b57cec5SDimitry Andric     // Output all "by ref" declarations.
53410b57cec5SDimitry Andric     for (SmallVectorImpl<ValueDecl *>::iterator I = BlockByRefDecls.begin(),
53420b57cec5SDimitry Andric          E = BlockByRefDecls.end(); I != E; ++I) {
53430b57cec5SDimitry Andric       ValueDecl *ND = (*I);
53440b57cec5SDimitry Andric       std::string Name(ND->getNameAsString());
53450b57cec5SDimitry Andric       std::string RecName;
53460b57cec5SDimitry Andric       RewriteByRefString(RecName, Name, ND, true);
53470b57cec5SDimitry Andric       IdentifierInfo *II = &Context->Idents.get(RecName.c_str()
53480b57cec5SDimitry Andric                                                 + sizeof("struct"));
53495f757f3fSDimitry Andric       RecordDecl *RD =
53505f757f3fSDimitry Andric           RecordDecl::Create(*Context, TagTypeKind::Struct, TUDecl,
53515f757f3fSDimitry Andric                              SourceLocation(), SourceLocation(), II);
53520b57cec5SDimitry Andric       assert(RD && "SynthBlockInitExpr(): Can't find RecordDecl");
53530b57cec5SDimitry Andric       QualType castT = Context->getPointerType(Context->getTagDeclType(RD));
53540b57cec5SDimitry Andric 
53550b57cec5SDimitry Andric       FD = SynthBlockInitFunctionDecl((*I)->getName());
53560b57cec5SDimitry Andric       Exp = new (Context) DeclRefExpr(*Context, FD, false, FD->getType(),
53570b57cec5SDimitry Andric                                       VK_LValue, SourceLocation());
53580b57cec5SDimitry Andric       bool isNestedCapturedVar = false;
53590b57cec5SDimitry Andric       for (const auto &CI : block->captures()) {
53600b57cec5SDimitry Andric         const VarDecl *variable = CI.getVariable();
53610b57cec5SDimitry Andric         if (variable == ND && CI.isNested()) {
53620b57cec5SDimitry Andric           assert(CI.isByRef() &&
53630b57cec5SDimitry Andric                  "SynthBlockInitExpr - captured block variable is not byref");
53640b57cec5SDimitry Andric           isNestedCapturedVar = true;
53650b57cec5SDimitry Andric           break;
53660b57cec5SDimitry Andric         }
53670b57cec5SDimitry Andric       }
53680b57cec5SDimitry Andric       // captured nested byref variable has its address passed. Do not take
53690b57cec5SDimitry Andric       // its address again.
53700b57cec5SDimitry Andric       if (!isNestedCapturedVar)
53715ffd83dbSDimitry Andric         Exp = UnaryOperator::Create(
53725ffd83dbSDimitry Andric             const_cast<ASTContext &>(*Context), Exp, UO_AddrOf,
5373fe6060f1SDimitry Andric             Context->getPointerType(Exp->getType()), VK_PRValue, OK_Ordinary,
53745ffd83dbSDimitry Andric             SourceLocation(), false, FPOptionsOverride());
53750b57cec5SDimitry Andric       Exp = NoTypeInfoCStyleCastExpr(Context, castT, CK_BitCast, Exp);
53760b57cec5SDimitry Andric       InitExprs.push_back(Exp);
53770b57cec5SDimitry Andric     }
53780b57cec5SDimitry Andric   }
53790b57cec5SDimitry Andric   if (ImportedBlockDecls.size()) {
53800b57cec5SDimitry Andric     // generate BLOCK_HAS_COPY_DISPOSE(have helper funcs) | BLOCK_HAS_DESCRIPTOR
53810b57cec5SDimitry Andric     int flag = (BLOCK_HAS_COPY_DISPOSE | BLOCK_HAS_DESCRIPTOR);
53820b57cec5SDimitry Andric     unsigned IntSize =
53830b57cec5SDimitry Andric       static_cast<unsigned>(Context->getTypeSize(Context->IntTy));
53840b57cec5SDimitry Andric     Expr *FlagExp = IntegerLiteral::Create(*Context, llvm::APInt(IntSize, flag),
53850b57cec5SDimitry Andric                                            Context->IntTy, SourceLocation());
53860b57cec5SDimitry Andric     InitExprs.push_back(FlagExp);
53870b57cec5SDimitry Andric   }
53880b57cec5SDimitry Andric   NewRep = CallExpr::Create(*Context, DRE, InitExprs, FType, VK_LValue,
5389e8d8bef9SDimitry Andric                             SourceLocation(), FPOptionsOverride());
53900b57cec5SDimitry Andric 
53910b57cec5SDimitry Andric   if (GlobalBlockExpr) {
53920b57cec5SDimitry Andric     assert (!GlobalConstructionExp &&
53930b57cec5SDimitry Andric             "SynthBlockInitExpr - GlobalConstructionExp must be null");
53940b57cec5SDimitry Andric     GlobalConstructionExp = NewRep;
53950b57cec5SDimitry Andric     NewRep = DRE;
53960b57cec5SDimitry Andric   }
53970b57cec5SDimitry Andric 
53985ffd83dbSDimitry Andric   NewRep = UnaryOperator::Create(
53995ffd83dbSDimitry Andric       const_cast<ASTContext &>(*Context), NewRep, UO_AddrOf,
5400fe6060f1SDimitry Andric       Context->getPointerType(NewRep->getType()), VK_PRValue, OK_Ordinary,
54015ffd83dbSDimitry Andric       SourceLocation(), false, FPOptionsOverride());
54020b57cec5SDimitry Andric   NewRep = NoTypeInfoCStyleCastExpr(Context, FType, CK_BitCast,
54030b57cec5SDimitry Andric                                     NewRep);
54040b57cec5SDimitry Andric   // Put Paren around the call.
54050b57cec5SDimitry Andric   NewRep = new (Context) ParenExpr(SourceLocation(), SourceLocation(),
54060b57cec5SDimitry Andric                                    NewRep);
54070b57cec5SDimitry Andric 
54080b57cec5SDimitry Andric   BlockDeclRefs.clear();
54090b57cec5SDimitry Andric   BlockByRefDecls.clear();
54100b57cec5SDimitry Andric   BlockByRefDeclsPtrSet.clear();
54110b57cec5SDimitry Andric   BlockByCopyDecls.clear();
54120b57cec5SDimitry Andric   BlockByCopyDeclsPtrSet.clear();
54130b57cec5SDimitry Andric   ImportedBlockDecls.clear();
54140b57cec5SDimitry Andric   return NewRep;
54150b57cec5SDimitry Andric }
54160b57cec5SDimitry Andric 
IsDeclStmtInForeachHeader(DeclStmt * DS)54170b57cec5SDimitry Andric bool RewriteModernObjC::IsDeclStmtInForeachHeader(DeclStmt *DS) {
54180b57cec5SDimitry Andric   if (const ObjCForCollectionStmt * CS =
54190b57cec5SDimitry Andric       dyn_cast<ObjCForCollectionStmt>(Stmts.back()))
54200b57cec5SDimitry Andric         return CS->getElement() == DS;
54210b57cec5SDimitry Andric   return false;
54220b57cec5SDimitry Andric }
54230b57cec5SDimitry Andric 
54240b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
54250b57cec5SDimitry Andric // Function Body / Expression rewriting
54260b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
54270b57cec5SDimitry Andric 
RewriteFunctionBodyOrGlobalInitializer(Stmt * S)54280b57cec5SDimitry Andric Stmt *RewriteModernObjC::RewriteFunctionBodyOrGlobalInitializer(Stmt *S) {
54290b57cec5SDimitry Andric   if (isa<SwitchStmt>(S) || isa<WhileStmt>(S) ||
54300b57cec5SDimitry Andric       isa<DoStmt>(S) || isa<ForStmt>(S))
54310b57cec5SDimitry Andric     Stmts.push_back(S);
54320b57cec5SDimitry Andric   else if (isa<ObjCForCollectionStmt>(S)) {
54330b57cec5SDimitry Andric     Stmts.push_back(S);
54340b57cec5SDimitry Andric     ObjCBcLabelNo.push_back(++BcLabelCount);
54350b57cec5SDimitry Andric   }
54360b57cec5SDimitry Andric 
54370b57cec5SDimitry Andric   // Pseudo-object operations and ivar references need special
54380b57cec5SDimitry Andric   // treatment because we're going to recursively rewrite them.
54390b57cec5SDimitry Andric   if (PseudoObjectExpr *PseudoOp = dyn_cast<PseudoObjectExpr>(S)) {
54400b57cec5SDimitry Andric     if (isa<BinaryOperator>(PseudoOp->getSyntacticForm())) {
54410b57cec5SDimitry Andric       return RewritePropertyOrImplicitSetter(PseudoOp);
54420b57cec5SDimitry Andric     } else {
54430b57cec5SDimitry Andric       return RewritePropertyOrImplicitGetter(PseudoOp);
54440b57cec5SDimitry Andric     }
54450b57cec5SDimitry Andric   } else if (ObjCIvarRefExpr *IvarRefExpr = dyn_cast<ObjCIvarRefExpr>(S)) {
54460b57cec5SDimitry Andric     return RewriteObjCIvarRefExpr(IvarRefExpr);
54470b57cec5SDimitry Andric   }
54480b57cec5SDimitry Andric   else if (isa<OpaqueValueExpr>(S))
54490b57cec5SDimitry Andric     S = cast<OpaqueValueExpr>(S)->getSourceExpr();
54500b57cec5SDimitry Andric 
54510b57cec5SDimitry Andric   SourceRange OrigStmtRange = S->getSourceRange();
54520b57cec5SDimitry Andric 
54530b57cec5SDimitry Andric   // Perform a bottom up rewrite of all children.
54540b57cec5SDimitry Andric   for (Stmt *&childStmt : S->children())
54550b57cec5SDimitry Andric     if (childStmt) {
54560b57cec5SDimitry Andric       Stmt *newStmt = RewriteFunctionBodyOrGlobalInitializer(childStmt);
54570b57cec5SDimitry Andric       if (newStmt) {
54580b57cec5SDimitry Andric         childStmt = newStmt;
54590b57cec5SDimitry Andric       }
54600b57cec5SDimitry Andric     }
54610b57cec5SDimitry Andric 
54620b57cec5SDimitry Andric   if (BlockExpr *BE = dyn_cast<BlockExpr>(S)) {
54630b57cec5SDimitry Andric     SmallVector<DeclRefExpr *, 8> InnerBlockDeclRefs;
54640b57cec5SDimitry Andric     llvm::SmallPtrSet<const DeclContext *, 8> InnerContexts;
54650b57cec5SDimitry Andric     InnerContexts.insert(BE->getBlockDecl());
54660b57cec5SDimitry Andric     ImportedLocalExternalDecls.clear();
54670b57cec5SDimitry Andric     GetInnerBlockDeclRefExprs(BE->getBody(),
54680b57cec5SDimitry Andric                               InnerBlockDeclRefs, InnerContexts);
54690b57cec5SDimitry Andric     // Rewrite the block body in place.
54700b57cec5SDimitry Andric     Stmt *SaveCurrentBody = CurrentBody;
54710b57cec5SDimitry Andric     CurrentBody = BE->getBody();
54720b57cec5SDimitry Andric     PropParentMap = nullptr;
54730b57cec5SDimitry Andric     // block literal on rhs of a property-dot-sytax assignment
54740b57cec5SDimitry Andric     // must be replaced by its synthesize ast so getRewrittenText
54750b57cec5SDimitry Andric     // works as expected. In this case, what actually ends up on RHS
54760b57cec5SDimitry Andric     // is the blockTranscribed which is the helper function for the
54770b57cec5SDimitry Andric     // block literal; as in: self.c = ^() {[ace ARR];};
54780b57cec5SDimitry Andric     bool saveDisableReplaceStmt = DisableReplaceStmt;
54790b57cec5SDimitry Andric     DisableReplaceStmt = false;
54800b57cec5SDimitry Andric     RewriteFunctionBodyOrGlobalInitializer(BE->getBody());
54810b57cec5SDimitry Andric     DisableReplaceStmt = saveDisableReplaceStmt;
54820b57cec5SDimitry Andric     CurrentBody = SaveCurrentBody;
54830b57cec5SDimitry Andric     PropParentMap = nullptr;
54840b57cec5SDimitry Andric     ImportedLocalExternalDecls.clear();
54850b57cec5SDimitry Andric     // Now we snarf the rewritten text and stash it away for later use.
54860b57cec5SDimitry Andric     std::string Str = Rewrite.getRewrittenText(BE->getSourceRange());
54870b57cec5SDimitry Andric     RewrittenBlockExprs[BE] = Str;
54880b57cec5SDimitry Andric 
54890b57cec5SDimitry Andric     Stmt *blockTranscribed = SynthBlockInitExpr(BE, InnerBlockDeclRefs);
54900b57cec5SDimitry Andric 
54910b57cec5SDimitry Andric     //blockTranscribed->dump();
54920b57cec5SDimitry Andric     ReplaceStmt(S, blockTranscribed);
54930b57cec5SDimitry Andric     return blockTranscribed;
54940b57cec5SDimitry Andric   }
54950b57cec5SDimitry Andric   // Handle specific things.
54960b57cec5SDimitry Andric   if (ObjCEncodeExpr *AtEncode = dyn_cast<ObjCEncodeExpr>(S))
54970b57cec5SDimitry Andric     return RewriteAtEncode(AtEncode);
54980b57cec5SDimitry Andric 
54990b57cec5SDimitry Andric   if (ObjCSelectorExpr *AtSelector = dyn_cast<ObjCSelectorExpr>(S))
55000b57cec5SDimitry Andric     return RewriteAtSelector(AtSelector);
55010b57cec5SDimitry Andric 
55020b57cec5SDimitry Andric   if (ObjCStringLiteral *AtString = dyn_cast<ObjCStringLiteral>(S))
55030b57cec5SDimitry Andric     return RewriteObjCStringLiteral(AtString);
55040b57cec5SDimitry Andric 
55050b57cec5SDimitry Andric   if (ObjCBoolLiteralExpr *BoolLitExpr = dyn_cast<ObjCBoolLiteralExpr>(S))
55060b57cec5SDimitry Andric     return RewriteObjCBoolLiteralExpr(BoolLitExpr);
55070b57cec5SDimitry Andric 
55080b57cec5SDimitry Andric   if (ObjCBoxedExpr *BoxedExpr = dyn_cast<ObjCBoxedExpr>(S))
55090b57cec5SDimitry Andric     return RewriteObjCBoxedExpr(BoxedExpr);
55100b57cec5SDimitry Andric 
55110b57cec5SDimitry Andric   if (ObjCArrayLiteral *ArrayLitExpr = dyn_cast<ObjCArrayLiteral>(S))
55120b57cec5SDimitry Andric     return RewriteObjCArrayLiteralExpr(ArrayLitExpr);
55130b57cec5SDimitry Andric 
55140b57cec5SDimitry Andric   if (ObjCDictionaryLiteral *DictionaryLitExpr =
55150b57cec5SDimitry Andric         dyn_cast<ObjCDictionaryLiteral>(S))
55160b57cec5SDimitry Andric     return RewriteObjCDictionaryLiteralExpr(DictionaryLitExpr);
55170b57cec5SDimitry Andric 
55180b57cec5SDimitry Andric   if (ObjCMessageExpr *MessExpr = dyn_cast<ObjCMessageExpr>(S)) {
55190b57cec5SDimitry Andric #if 0
55200b57cec5SDimitry Andric     // Before we rewrite it, put the original message expression in a comment.
55210b57cec5SDimitry Andric     SourceLocation startLoc = MessExpr->getBeginLoc();
55220b57cec5SDimitry Andric     SourceLocation endLoc = MessExpr->getEndLoc();
55230b57cec5SDimitry Andric 
55240b57cec5SDimitry Andric     const char *startBuf = SM->getCharacterData(startLoc);
55250b57cec5SDimitry Andric     const char *endBuf = SM->getCharacterData(endLoc);
55260b57cec5SDimitry Andric 
55270b57cec5SDimitry Andric     std::string messString;
55280b57cec5SDimitry Andric     messString += "// ";
55290b57cec5SDimitry Andric     messString.append(startBuf, endBuf-startBuf+1);
55300b57cec5SDimitry Andric     messString += "\n";
55310b57cec5SDimitry Andric 
55320b57cec5SDimitry Andric     // FIXME: Missing definition of
55330b57cec5SDimitry Andric     // InsertText(clang::SourceLocation, char const*, unsigned int).
55340b57cec5SDimitry Andric     // InsertText(startLoc, messString);
55350b57cec5SDimitry Andric     // Tried this, but it didn't work either...
55360b57cec5SDimitry Andric     // ReplaceText(startLoc, 0, messString.c_str(), messString.size());
55370b57cec5SDimitry Andric #endif
55380b57cec5SDimitry Andric     return RewriteMessageExpr(MessExpr);
55390b57cec5SDimitry Andric   }
55400b57cec5SDimitry Andric 
55410b57cec5SDimitry Andric   if (ObjCAutoreleasePoolStmt *StmtAutoRelease =
55420b57cec5SDimitry Andric         dyn_cast<ObjCAutoreleasePoolStmt>(S)) {
55430b57cec5SDimitry Andric     return RewriteObjCAutoreleasePoolStmt(StmtAutoRelease);
55440b57cec5SDimitry Andric   }
55450b57cec5SDimitry Andric 
55460b57cec5SDimitry Andric   if (ObjCAtTryStmt *StmtTry = dyn_cast<ObjCAtTryStmt>(S))
55470b57cec5SDimitry Andric     return RewriteObjCTryStmt(StmtTry);
55480b57cec5SDimitry Andric 
55490b57cec5SDimitry Andric   if (ObjCAtSynchronizedStmt *StmtTry = dyn_cast<ObjCAtSynchronizedStmt>(S))
55500b57cec5SDimitry Andric     return RewriteObjCSynchronizedStmt(StmtTry);
55510b57cec5SDimitry Andric 
55520b57cec5SDimitry Andric   if (ObjCAtThrowStmt *StmtThrow = dyn_cast<ObjCAtThrowStmt>(S))
55530b57cec5SDimitry Andric     return RewriteObjCThrowStmt(StmtThrow);
55540b57cec5SDimitry Andric 
55550b57cec5SDimitry Andric   if (ObjCProtocolExpr *ProtocolExp = dyn_cast<ObjCProtocolExpr>(S))
55560b57cec5SDimitry Andric     return RewriteObjCProtocolExpr(ProtocolExp);
55570b57cec5SDimitry Andric 
55580b57cec5SDimitry Andric   if (ObjCForCollectionStmt *StmtForCollection =
55590b57cec5SDimitry Andric         dyn_cast<ObjCForCollectionStmt>(S))
55600b57cec5SDimitry Andric     return RewriteObjCForCollectionStmt(StmtForCollection,
55610b57cec5SDimitry Andric                                         OrigStmtRange.getEnd());
55620b57cec5SDimitry Andric   if (BreakStmt *StmtBreakStmt =
55630b57cec5SDimitry Andric       dyn_cast<BreakStmt>(S))
55640b57cec5SDimitry Andric     return RewriteBreakStmt(StmtBreakStmt);
55650b57cec5SDimitry Andric   if (ContinueStmt *StmtContinueStmt =
55660b57cec5SDimitry Andric       dyn_cast<ContinueStmt>(S))
55670b57cec5SDimitry Andric     return RewriteContinueStmt(StmtContinueStmt);
55680b57cec5SDimitry Andric 
55690b57cec5SDimitry Andric   // Need to check for protocol refs (id <P>, Foo <P> *) in variable decls
55700b57cec5SDimitry Andric   // and cast exprs.
55710b57cec5SDimitry Andric   if (DeclStmt *DS = dyn_cast<DeclStmt>(S)) {
55720b57cec5SDimitry Andric     // FIXME: What we're doing here is modifying the type-specifier that
55730b57cec5SDimitry Andric     // precedes the first Decl.  In the future the DeclGroup should have
55740b57cec5SDimitry Andric     // a separate type-specifier that we can rewrite.
55750b57cec5SDimitry Andric     // NOTE: We need to avoid rewriting the DeclStmt if it is within
55760b57cec5SDimitry Andric     // the context of an ObjCForCollectionStmt. For example:
55770b57cec5SDimitry Andric     //   NSArray *someArray;
55780b57cec5SDimitry Andric     //   for (id <FooProtocol> index in someArray) ;
55790b57cec5SDimitry Andric     // This is because RewriteObjCForCollectionStmt() does textual rewriting
55800b57cec5SDimitry Andric     // and it depends on the original text locations/positions.
55810b57cec5SDimitry Andric     if (Stmts.empty() || !IsDeclStmtInForeachHeader(DS))
55820b57cec5SDimitry Andric       RewriteObjCQualifiedInterfaceTypes(*DS->decl_begin());
55830b57cec5SDimitry Andric 
55840b57cec5SDimitry Andric     // Blocks rewrite rules.
55850b57cec5SDimitry Andric     for (DeclStmt::decl_iterator DI = DS->decl_begin(), DE = DS->decl_end();
55860b57cec5SDimitry Andric          DI != DE; ++DI) {
55870b57cec5SDimitry Andric       Decl *SD = *DI;
55880b57cec5SDimitry Andric       if (ValueDecl *ND = dyn_cast<ValueDecl>(SD)) {
55890b57cec5SDimitry Andric         if (isTopLevelBlockPointerType(ND->getType()))
55900b57cec5SDimitry Andric           RewriteBlockPointerDecl(ND);
55910b57cec5SDimitry Andric         else if (ND->getType()->isFunctionPointerType())
55920b57cec5SDimitry Andric           CheckFunctionPointerDecl(ND->getType(), ND);
55930b57cec5SDimitry Andric         if (VarDecl *VD = dyn_cast<VarDecl>(SD)) {
55940b57cec5SDimitry Andric           if (VD->hasAttr<BlocksAttr>()) {
55950b57cec5SDimitry Andric             static unsigned uniqueByrefDeclCount = 0;
55960b57cec5SDimitry Andric             assert(!BlockByRefDeclNo.count(ND) &&
55970b57cec5SDimitry Andric               "RewriteFunctionBodyOrGlobalInitializer: Duplicate byref decl");
55980b57cec5SDimitry Andric             BlockByRefDeclNo[ND] = uniqueByrefDeclCount++;
55990b57cec5SDimitry Andric             RewriteByRefVar(VD, (DI == DS->decl_begin()), ((DI+1) == DE));
56000b57cec5SDimitry Andric           }
56010b57cec5SDimitry Andric           else
56020b57cec5SDimitry Andric             RewriteTypeOfDecl(VD);
56030b57cec5SDimitry Andric         }
56040b57cec5SDimitry Andric       }
56050b57cec5SDimitry Andric       if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(SD)) {
56060b57cec5SDimitry Andric         if (isTopLevelBlockPointerType(TD->getUnderlyingType()))
56070b57cec5SDimitry Andric           RewriteBlockPointerDecl(TD);
56080b57cec5SDimitry Andric         else if (TD->getUnderlyingType()->isFunctionPointerType())
56090b57cec5SDimitry Andric           CheckFunctionPointerDecl(TD->getUnderlyingType(), TD);
56100b57cec5SDimitry Andric       }
56110b57cec5SDimitry Andric     }
56120b57cec5SDimitry Andric   }
56130b57cec5SDimitry Andric 
56140b57cec5SDimitry Andric   if (CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(S))
56150b57cec5SDimitry Andric     RewriteObjCQualifiedInterfaceTypes(CE);
56160b57cec5SDimitry Andric 
56170b57cec5SDimitry Andric   if (isa<SwitchStmt>(S) || isa<WhileStmt>(S) ||
56180b57cec5SDimitry Andric       isa<DoStmt>(S) || isa<ForStmt>(S)) {
56190b57cec5SDimitry Andric     assert(!Stmts.empty() && "Statement stack is empty");
56200b57cec5SDimitry Andric     assert ((isa<SwitchStmt>(Stmts.back()) || isa<WhileStmt>(Stmts.back()) ||
56210b57cec5SDimitry Andric              isa<DoStmt>(Stmts.back()) || isa<ForStmt>(Stmts.back()))
56220b57cec5SDimitry Andric             && "Statement stack mismatch");
56230b57cec5SDimitry Andric     Stmts.pop_back();
56240b57cec5SDimitry Andric   }
56250b57cec5SDimitry Andric   // Handle blocks rewriting.
56260b57cec5SDimitry Andric   if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(S)) {
56270b57cec5SDimitry Andric     ValueDecl *VD = DRE->getDecl();
56280b57cec5SDimitry Andric     if (VD->hasAttr<BlocksAttr>())
56290b57cec5SDimitry Andric       return RewriteBlockDeclRefExpr(DRE);
56300b57cec5SDimitry Andric     if (HasLocalVariableExternalStorage(VD))
56310b57cec5SDimitry Andric       return RewriteLocalVariableExternalStorage(DRE);
56320b57cec5SDimitry Andric   }
56330b57cec5SDimitry Andric 
56340b57cec5SDimitry Andric   if (CallExpr *CE = dyn_cast<CallExpr>(S)) {
56350b57cec5SDimitry Andric     if (CE->getCallee()->getType()->isBlockPointerType()) {
56360b57cec5SDimitry Andric       Stmt *BlockCall = SynthesizeBlockCall(CE, CE->getCallee());
56370b57cec5SDimitry Andric       ReplaceStmt(S, BlockCall);
56380b57cec5SDimitry Andric       return BlockCall;
56390b57cec5SDimitry Andric     }
56400b57cec5SDimitry Andric   }
56410b57cec5SDimitry Andric   if (CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(S)) {
56420b57cec5SDimitry Andric     RewriteCastExpr(CE);
56430b57cec5SDimitry Andric   }
56440b57cec5SDimitry Andric   if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(S)) {
56450b57cec5SDimitry Andric     RewriteImplicitCastObjCExpr(ICE);
56460b57cec5SDimitry Andric   }
56470b57cec5SDimitry Andric #if 0
56480b57cec5SDimitry Andric 
56490b57cec5SDimitry Andric   if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(S)) {
56500b57cec5SDimitry Andric     CastExpr *Replacement = new (Context) CastExpr(ICE->getType(),
56510b57cec5SDimitry Andric                                                    ICE->getSubExpr(),
56520b57cec5SDimitry Andric                                                    SourceLocation());
56530b57cec5SDimitry Andric     // Get the new text.
56540b57cec5SDimitry Andric     std::string SStr;
56550b57cec5SDimitry Andric     llvm::raw_string_ostream Buf(SStr);
56560b57cec5SDimitry Andric     Replacement->printPretty(Buf);
56570b57cec5SDimitry Andric     const std::string &Str = Buf.str();
56580b57cec5SDimitry Andric 
56590b57cec5SDimitry Andric     printf("CAST = %s\n", &Str[0]);
56600b57cec5SDimitry Andric     InsertText(ICE->getSubExpr()->getBeginLoc(), Str);
56610b57cec5SDimitry Andric     delete S;
56620b57cec5SDimitry Andric     return Replacement;
56630b57cec5SDimitry Andric   }
56640b57cec5SDimitry Andric #endif
56650b57cec5SDimitry Andric   // Return this stmt unmodified.
56660b57cec5SDimitry Andric   return S;
56670b57cec5SDimitry Andric }
56680b57cec5SDimitry Andric 
RewriteRecordBody(RecordDecl * RD)56690b57cec5SDimitry Andric void RewriteModernObjC::RewriteRecordBody(RecordDecl *RD) {
56700b57cec5SDimitry Andric   for (auto *FD : RD->fields()) {
56710b57cec5SDimitry Andric     if (isTopLevelBlockPointerType(FD->getType()))
56720b57cec5SDimitry Andric       RewriteBlockPointerDecl(FD);
56730b57cec5SDimitry Andric     if (FD->getType()->isObjCQualifiedIdType() ||
56740b57cec5SDimitry Andric         FD->getType()->isObjCQualifiedInterfaceType())
56750b57cec5SDimitry Andric       RewriteObjCQualifiedInterfaceTypes(FD);
56760b57cec5SDimitry Andric   }
56770b57cec5SDimitry Andric }
56780b57cec5SDimitry Andric 
56790b57cec5SDimitry Andric /// HandleDeclInMainFile - This is called for each top-level decl defined in the
56800b57cec5SDimitry Andric /// main file of the input.
HandleDeclInMainFile(Decl * D)56810b57cec5SDimitry Andric void RewriteModernObjC::HandleDeclInMainFile(Decl *D) {
56820b57cec5SDimitry Andric   switch (D->getKind()) {
56830b57cec5SDimitry Andric     case Decl::Function: {
56840b57cec5SDimitry Andric       FunctionDecl *FD = cast<FunctionDecl>(D);
56850b57cec5SDimitry Andric       if (FD->isOverloadedOperator())
56860b57cec5SDimitry Andric         return;
56870b57cec5SDimitry Andric 
56880b57cec5SDimitry Andric       // Since function prototypes don't have ParmDecl's, we check the function
56890b57cec5SDimitry Andric       // prototype. This enables us to rewrite function declarations and
56900b57cec5SDimitry Andric       // definitions using the same code.
56910b57cec5SDimitry Andric       RewriteBlocksInFunctionProtoType(FD->getType(), FD);
56920b57cec5SDimitry Andric 
56930b57cec5SDimitry Andric       if (!FD->isThisDeclarationADefinition())
56940b57cec5SDimitry Andric         break;
56950b57cec5SDimitry Andric 
56960b57cec5SDimitry Andric       // FIXME: If this should support Obj-C++, support CXXTryStmt
56970b57cec5SDimitry Andric       if (CompoundStmt *Body = dyn_cast_or_null<CompoundStmt>(FD->getBody())) {
56980b57cec5SDimitry Andric         CurFunctionDef = FD;
56990b57cec5SDimitry Andric         CurrentBody = Body;
57000b57cec5SDimitry Andric         Body =
57010b57cec5SDimitry Andric         cast_or_null<CompoundStmt>(RewriteFunctionBodyOrGlobalInitializer(Body));
57020b57cec5SDimitry Andric         FD->setBody(Body);
57030b57cec5SDimitry Andric         CurrentBody = nullptr;
57040b57cec5SDimitry Andric         if (PropParentMap) {
57050b57cec5SDimitry Andric           delete PropParentMap;
57060b57cec5SDimitry Andric           PropParentMap = nullptr;
57070b57cec5SDimitry Andric         }
57080b57cec5SDimitry Andric         // This synthesizes and inserts the block "impl" struct, invoke function,
57090b57cec5SDimitry Andric         // and any copy/dispose helper functions.
57100b57cec5SDimitry Andric         InsertBlockLiteralsWithinFunction(FD);
57110b57cec5SDimitry Andric         RewriteLineDirective(D);
57120b57cec5SDimitry Andric         CurFunctionDef = nullptr;
57130b57cec5SDimitry Andric       }
57140b57cec5SDimitry Andric       break;
57150b57cec5SDimitry Andric     }
57160b57cec5SDimitry Andric     case Decl::ObjCMethod: {
57170b57cec5SDimitry Andric       ObjCMethodDecl *MD = cast<ObjCMethodDecl>(D);
57180b57cec5SDimitry Andric       if (CompoundStmt *Body = MD->getCompoundBody()) {
57190b57cec5SDimitry Andric         CurMethodDef = MD;
57200b57cec5SDimitry Andric         CurrentBody = Body;
57210b57cec5SDimitry Andric         Body =
57220b57cec5SDimitry Andric           cast_or_null<CompoundStmt>(RewriteFunctionBodyOrGlobalInitializer(Body));
57230b57cec5SDimitry Andric         MD->setBody(Body);
57240b57cec5SDimitry Andric         CurrentBody = nullptr;
57250b57cec5SDimitry Andric         if (PropParentMap) {
57260b57cec5SDimitry Andric           delete PropParentMap;
57270b57cec5SDimitry Andric           PropParentMap = nullptr;
57280b57cec5SDimitry Andric         }
57290b57cec5SDimitry Andric         InsertBlockLiteralsWithinMethod(MD);
57300b57cec5SDimitry Andric         RewriteLineDirective(D);
57310b57cec5SDimitry Andric         CurMethodDef = nullptr;
57320b57cec5SDimitry Andric       }
57330b57cec5SDimitry Andric       break;
57340b57cec5SDimitry Andric     }
57350b57cec5SDimitry Andric     case Decl::ObjCImplementation: {
57360b57cec5SDimitry Andric       ObjCImplementationDecl *CI = cast<ObjCImplementationDecl>(D);
57370b57cec5SDimitry Andric       ClassImplementation.push_back(CI);
57380b57cec5SDimitry Andric       break;
57390b57cec5SDimitry Andric     }
57400b57cec5SDimitry Andric     case Decl::ObjCCategoryImpl: {
57410b57cec5SDimitry Andric       ObjCCategoryImplDecl *CI = cast<ObjCCategoryImplDecl>(D);
57420b57cec5SDimitry Andric       CategoryImplementation.push_back(CI);
57430b57cec5SDimitry Andric       break;
57440b57cec5SDimitry Andric     }
57450b57cec5SDimitry Andric     case Decl::Var: {
57460b57cec5SDimitry Andric       VarDecl *VD = cast<VarDecl>(D);
57470b57cec5SDimitry Andric       RewriteObjCQualifiedInterfaceTypes(VD);
57480b57cec5SDimitry Andric       if (isTopLevelBlockPointerType(VD->getType()))
57490b57cec5SDimitry Andric         RewriteBlockPointerDecl(VD);
57500b57cec5SDimitry Andric       else if (VD->getType()->isFunctionPointerType()) {
57510b57cec5SDimitry Andric         CheckFunctionPointerDecl(VD->getType(), VD);
57520b57cec5SDimitry Andric         if (VD->getInit()) {
57530b57cec5SDimitry Andric           if (CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(VD->getInit())) {
57540b57cec5SDimitry Andric             RewriteCastExpr(CE);
57550b57cec5SDimitry Andric           }
57560b57cec5SDimitry Andric         }
57570b57cec5SDimitry Andric       } else if (VD->getType()->isRecordType()) {
5758a7dea167SDimitry Andric         RecordDecl *RD = VD->getType()->castAs<RecordType>()->getDecl();
57590b57cec5SDimitry Andric         if (RD->isCompleteDefinition())
57600b57cec5SDimitry Andric           RewriteRecordBody(RD);
57610b57cec5SDimitry Andric       }
57620b57cec5SDimitry Andric       if (VD->getInit()) {
57630b57cec5SDimitry Andric         GlobalVarDecl = VD;
57640b57cec5SDimitry Andric         CurrentBody = VD->getInit();
57650b57cec5SDimitry Andric         RewriteFunctionBodyOrGlobalInitializer(VD->getInit());
57660b57cec5SDimitry Andric         CurrentBody = nullptr;
57670b57cec5SDimitry Andric         if (PropParentMap) {
57680b57cec5SDimitry Andric           delete PropParentMap;
57690b57cec5SDimitry Andric           PropParentMap = nullptr;
57700b57cec5SDimitry Andric         }
57710b57cec5SDimitry Andric         SynthesizeBlockLiterals(VD->getTypeSpecStartLoc(), VD->getName());
57720b57cec5SDimitry Andric         GlobalVarDecl = nullptr;
57730b57cec5SDimitry Andric 
57740b57cec5SDimitry Andric         // This is needed for blocks.
57750b57cec5SDimitry Andric         if (CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(VD->getInit())) {
57760b57cec5SDimitry Andric             RewriteCastExpr(CE);
57770b57cec5SDimitry Andric         }
57780b57cec5SDimitry Andric       }
57790b57cec5SDimitry Andric       break;
57800b57cec5SDimitry Andric     }
57810b57cec5SDimitry Andric     case Decl::TypeAlias:
57820b57cec5SDimitry Andric     case Decl::Typedef: {
57830b57cec5SDimitry Andric       if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(D)) {
57840b57cec5SDimitry Andric         if (isTopLevelBlockPointerType(TD->getUnderlyingType()))
57850b57cec5SDimitry Andric           RewriteBlockPointerDecl(TD);
57860b57cec5SDimitry Andric         else if (TD->getUnderlyingType()->isFunctionPointerType())
57870b57cec5SDimitry Andric           CheckFunctionPointerDecl(TD->getUnderlyingType(), TD);
57880b57cec5SDimitry Andric         else
57890b57cec5SDimitry Andric           RewriteObjCQualifiedInterfaceTypes(TD);
57900b57cec5SDimitry Andric       }
57910b57cec5SDimitry Andric       break;
57920b57cec5SDimitry Andric     }
57930b57cec5SDimitry Andric     case Decl::CXXRecord:
57940b57cec5SDimitry Andric     case Decl::Record: {
57950b57cec5SDimitry Andric       RecordDecl *RD = cast<RecordDecl>(D);
57960b57cec5SDimitry Andric       if (RD->isCompleteDefinition())
57970b57cec5SDimitry Andric         RewriteRecordBody(RD);
57980b57cec5SDimitry Andric       break;
57990b57cec5SDimitry Andric     }
58000b57cec5SDimitry Andric     default:
58010b57cec5SDimitry Andric       break;
58020b57cec5SDimitry Andric   }
58030b57cec5SDimitry Andric   // Nothing yet.
58040b57cec5SDimitry Andric }
58050b57cec5SDimitry Andric 
58060b57cec5SDimitry Andric /// Write_ProtocolExprReferencedMetadata - This routine writer out the
58070b57cec5SDimitry Andric /// protocol reference symbols in the for of:
58080b57cec5SDimitry Andric /// struct _protocol_t *PROTOCOL_REF = &PROTOCOL_METADATA.
Write_ProtocolExprReferencedMetadata(ASTContext * Context,ObjCProtocolDecl * PDecl,std::string & Result)58090b57cec5SDimitry Andric static void Write_ProtocolExprReferencedMetadata(ASTContext *Context,
58100b57cec5SDimitry Andric                                                  ObjCProtocolDecl *PDecl,
58110b57cec5SDimitry Andric                                                  std::string &Result) {
58120b57cec5SDimitry Andric   // Also output .objc_protorefs$B section and its meta-data.
58130b57cec5SDimitry Andric   if (Context->getLangOpts().MicrosoftExt)
58140b57cec5SDimitry Andric     Result += "static ";
58150b57cec5SDimitry Andric   Result += "struct _protocol_t *";
58160b57cec5SDimitry Andric   Result += "_OBJC_PROTOCOL_REFERENCE_$_";
58170b57cec5SDimitry Andric   Result += PDecl->getNameAsString();
58180b57cec5SDimitry Andric   Result += " = &";
58190b57cec5SDimitry Andric   Result += "_OBJC_PROTOCOL_"; Result += PDecl->getNameAsString();
58200b57cec5SDimitry Andric   Result += ";\n";
58210b57cec5SDimitry Andric }
58220b57cec5SDimitry Andric 
HandleTranslationUnit(ASTContext & C)58230b57cec5SDimitry Andric void RewriteModernObjC::HandleTranslationUnit(ASTContext &C) {
58240b57cec5SDimitry Andric   if (Diags.hasErrorOccurred())
58250b57cec5SDimitry Andric     return;
58260b57cec5SDimitry Andric 
58270b57cec5SDimitry Andric   RewriteInclude();
58280b57cec5SDimitry Andric 
58290b57cec5SDimitry Andric   for (unsigned i = 0, e = FunctionDefinitionsSeen.size(); i < e; i++) {
58300b57cec5SDimitry Andric     // translation of function bodies were postponed until all class and
58310b57cec5SDimitry Andric     // their extensions and implementations are seen. This is because, we
58320b57cec5SDimitry Andric     // cannot build grouping structs for bitfields until they are all seen.
58330b57cec5SDimitry Andric     FunctionDecl *FDecl = FunctionDefinitionsSeen[i];
58340b57cec5SDimitry Andric     HandleTopLevelSingleDecl(FDecl);
58350b57cec5SDimitry Andric   }
58360b57cec5SDimitry Andric 
58370b57cec5SDimitry Andric   // Here's a great place to add any extra declarations that may be needed.
58380b57cec5SDimitry Andric   // Write out meta data for each @protocol(<expr>).
58390b57cec5SDimitry Andric   for (ObjCProtocolDecl *ProtDecl : ProtocolExprDecls) {
58400b57cec5SDimitry Andric     RewriteObjCProtocolMetaData(ProtDecl, Preamble);
58410b57cec5SDimitry Andric     Write_ProtocolExprReferencedMetadata(Context, ProtDecl, Preamble);
58420b57cec5SDimitry Andric   }
58430b57cec5SDimitry Andric 
58440b57cec5SDimitry Andric   InsertText(SM->getLocForStartOfFile(MainFileID), Preamble, false);
58450b57cec5SDimitry Andric 
58460b57cec5SDimitry Andric   if (ClassImplementation.size() || CategoryImplementation.size())
58470b57cec5SDimitry Andric     RewriteImplementations();
58480b57cec5SDimitry Andric 
58490b57cec5SDimitry Andric   for (unsigned i = 0, e = ObjCInterfacesSeen.size(); i < e; i++) {
58500b57cec5SDimitry Andric     ObjCInterfaceDecl *CDecl = ObjCInterfacesSeen[i];
58510b57cec5SDimitry Andric     // Write struct declaration for the class matching its ivar declarations.
58520b57cec5SDimitry Andric     // Note that for modern abi, this is postponed until the end of TU
58530b57cec5SDimitry Andric     // because class extensions and the implementation might declare their own
58540b57cec5SDimitry Andric     // private ivars.
58550b57cec5SDimitry Andric     RewriteInterfaceDecl(CDecl);
58560b57cec5SDimitry Andric   }
58570b57cec5SDimitry Andric 
58580b57cec5SDimitry Andric   // Get the buffer corresponding to MainFileID.  If we haven't changed it, then
58590b57cec5SDimitry Andric   // we are done.
58600b57cec5SDimitry Andric   if (const RewriteBuffer *RewriteBuf =
58610b57cec5SDimitry Andric       Rewrite.getRewriteBufferFor(MainFileID)) {
58620b57cec5SDimitry Andric     //printf("Changed:\n");
58630b57cec5SDimitry Andric     *OutFile << std::string(RewriteBuf->begin(), RewriteBuf->end());
58640b57cec5SDimitry Andric   } else {
58650b57cec5SDimitry Andric     llvm::errs() << "No changes\n";
58660b57cec5SDimitry Andric   }
58670b57cec5SDimitry Andric 
58680b57cec5SDimitry Andric   if (ClassImplementation.size() || CategoryImplementation.size() ||
58690b57cec5SDimitry Andric       ProtocolExprDecls.size()) {
58700b57cec5SDimitry Andric     // Rewrite Objective-c meta data*
58710b57cec5SDimitry Andric     std::string ResultStr;
58720b57cec5SDimitry Andric     RewriteMetaDataIntoBuffer(ResultStr);
58730b57cec5SDimitry Andric     // Emit metadata.
58740b57cec5SDimitry Andric     *OutFile << ResultStr;
58750b57cec5SDimitry Andric   }
58760b57cec5SDimitry Andric   // Emit ImageInfo;
58770b57cec5SDimitry Andric   {
58780b57cec5SDimitry Andric     std::string ResultStr;
58790b57cec5SDimitry Andric     WriteImageInfo(ResultStr);
58800b57cec5SDimitry Andric     *OutFile << ResultStr;
58810b57cec5SDimitry Andric   }
58820b57cec5SDimitry Andric   OutFile->flush();
58830b57cec5SDimitry Andric }
58840b57cec5SDimitry Andric 
Initialize(ASTContext & context)58850b57cec5SDimitry Andric void RewriteModernObjC::Initialize(ASTContext &context) {
58860b57cec5SDimitry Andric   InitializeCommon(context);
58870b57cec5SDimitry Andric 
58880b57cec5SDimitry Andric   Preamble += "#ifndef __OBJC2__\n";
58890b57cec5SDimitry Andric   Preamble += "#define __OBJC2__\n";
58900b57cec5SDimitry Andric   Preamble += "#endif\n";
58910b57cec5SDimitry Andric 
58920b57cec5SDimitry Andric   // declaring objc_selector outside the parameter list removes a silly
58930b57cec5SDimitry Andric   // scope related warning...
58940b57cec5SDimitry Andric   if (IsHeader)
58950b57cec5SDimitry Andric     Preamble = "#pragma once\n";
58960b57cec5SDimitry Andric   Preamble += "struct objc_selector; struct objc_class;\n";
58970b57cec5SDimitry Andric   Preamble += "struct __rw_objc_super { \n\tstruct objc_object *object; ";
58980b57cec5SDimitry Andric   Preamble += "\n\tstruct objc_object *superClass; ";
58990b57cec5SDimitry Andric   // Add a constructor for creating temporary objects.
59000b57cec5SDimitry Andric   Preamble += "\n\t__rw_objc_super(struct objc_object *o, struct objc_object *s) ";
59010b57cec5SDimitry Andric   Preamble += ": object(o), superClass(s) {} ";
59020b57cec5SDimitry Andric   Preamble += "\n};\n";
59030b57cec5SDimitry Andric 
59040b57cec5SDimitry Andric   if (LangOpts.MicrosoftExt) {
59050b57cec5SDimitry Andric     // Define all sections using syntax that makes sense.
59060b57cec5SDimitry Andric     // These are currently generated.
59070b57cec5SDimitry Andric     Preamble += "\n#pragma section(\".objc_classlist$B\", long, read, write)\n";
59080b57cec5SDimitry Andric     Preamble += "#pragma section(\".objc_catlist$B\", long, read, write)\n";
59090b57cec5SDimitry Andric     Preamble += "#pragma section(\".objc_imageinfo$B\", long, read, write)\n";
59100b57cec5SDimitry Andric     Preamble += "#pragma section(\".objc_nlclslist$B\", long, read, write)\n";
59110b57cec5SDimitry Andric     Preamble += "#pragma section(\".objc_nlcatlist$B\", long, read, write)\n";
59120b57cec5SDimitry Andric     // These are generated but not necessary for functionality.
59130b57cec5SDimitry Andric     Preamble += "#pragma section(\".cat_cls_meth$B\", long, read, write)\n";
59140b57cec5SDimitry Andric     Preamble += "#pragma section(\".inst_meth$B\", long, read, write)\n";
59150b57cec5SDimitry Andric     Preamble += "#pragma section(\".cls_meth$B\", long, read, write)\n";
59160b57cec5SDimitry Andric     Preamble += "#pragma section(\".objc_ivar$B\", long, read, write)\n";
59170b57cec5SDimitry Andric 
59180b57cec5SDimitry Andric     // These need be generated for performance. Currently they are not,
59190b57cec5SDimitry Andric     // using API calls instead.
59200b57cec5SDimitry Andric     Preamble += "#pragma section(\".objc_selrefs$B\", long, read, write)\n";
59210b57cec5SDimitry Andric     Preamble += "#pragma section(\".objc_classrefs$B\", long, read, write)\n";
59220b57cec5SDimitry Andric     Preamble += "#pragma section(\".objc_superrefs$B\", long, read, write)\n";
59230b57cec5SDimitry Andric 
59240b57cec5SDimitry Andric   }
59250b57cec5SDimitry Andric   Preamble += "#ifndef _REWRITER_typedef_Protocol\n";
59260b57cec5SDimitry Andric   Preamble += "typedef struct objc_object Protocol;\n";
59270b57cec5SDimitry Andric   Preamble += "#define _REWRITER_typedef_Protocol\n";
59280b57cec5SDimitry Andric   Preamble += "#endif\n";
59290b57cec5SDimitry Andric   if (LangOpts.MicrosoftExt) {
59300b57cec5SDimitry Andric     Preamble += "#define __OBJC_RW_DLLIMPORT extern \"C\" __declspec(dllimport)\n";
59310b57cec5SDimitry Andric     Preamble += "#define __OBJC_RW_STATICIMPORT extern \"C\"\n";
59320b57cec5SDimitry Andric   }
59330b57cec5SDimitry Andric   else
59340b57cec5SDimitry Andric     Preamble += "#define __OBJC_RW_DLLIMPORT extern\n";
59350b57cec5SDimitry Andric 
59360b57cec5SDimitry Andric   Preamble += "__OBJC_RW_DLLIMPORT void objc_msgSend(void);\n";
59370b57cec5SDimitry Andric   Preamble += "__OBJC_RW_DLLIMPORT void objc_msgSendSuper(void);\n";
59380b57cec5SDimitry Andric   Preamble += "__OBJC_RW_DLLIMPORT void objc_msgSend_stret(void);\n";
59390b57cec5SDimitry Andric   Preamble += "__OBJC_RW_DLLIMPORT void objc_msgSendSuper_stret(void);\n";
59400b57cec5SDimitry Andric   Preamble += "__OBJC_RW_DLLIMPORT void objc_msgSend_fpret(void);\n";
59410b57cec5SDimitry Andric 
59420b57cec5SDimitry Andric   Preamble += "__OBJC_RW_DLLIMPORT struct objc_class *objc_getClass";
59430b57cec5SDimitry Andric   Preamble += "(const char *);\n";
59440b57cec5SDimitry Andric   Preamble += "__OBJC_RW_DLLIMPORT struct objc_class *class_getSuperclass";
59450b57cec5SDimitry Andric   Preamble += "(struct objc_class *);\n";
59460b57cec5SDimitry Andric   Preamble += "__OBJC_RW_DLLIMPORT struct objc_class *objc_getMetaClass";
59470b57cec5SDimitry Andric   Preamble += "(const char *);\n";
59480b57cec5SDimitry Andric   Preamble += "__OBJC_RW_DLLIMPORT void objc_exception_throw( struct objc_object *);\n";
59490b57cec5SDimitry Andric   // @synchronized hooks.
59500b57cec5SDimitry Andric   Preamble += "__OBJC_RW_DLLIMPORT int objc_sync_enter( struct objc_object *);\n";
59510b57cec5SDimitry Andric   Preamble += "__OBJC_RW_DLLIMPORT int objc_sync_exit( struct objc_object *);\n";
59520b57cec5SDimitry Andric   Preamble += "__OBJC_RW_DLLIMPORT Protocol *objc_getProtocol(const char *);\n";
59530b57cec5SDimitry Andric   Preamble += "#ifdef _WIN64\n";
59540b57cec5SDimitry Andric   Preamble += "typedef unsigned long long  _WIN_NSUInteger;\n";
59550b57cec5SDimitry Andric   Preamble += "#else\n";
59560b57cec5SDimitry Andric   Preamble += "typedef unsigned int _WIN_NSUInteger;\n";
59570b57cec5SDimitry Andric   Preamble += "#endif\n";
59580b57cec5SDimitry Andric   Preamble += "#ifndef __FASTENUMERATIONSTATE\n";
59590b57cec5SDimitry Andric   Preamble += "struct __objcFastEnumerationState {\n\t";
59600b57cec5SDimitry Andric   Preamble += "unsigned long state;\n\t";
59610b57cec5SDimitry Andric   Preamble += "void **itemsPtr;\n\t";
59620b57cec5SDimitry Andric   Preamble += "unsigned long *mutationsPtr;\n\t";
59630b57cec5SDimitry Andric   Preamble += "unsigned long extra[5];\n};\n";
59640b57cec5SDimitry Andric   Preamble += "__OBJC_RW_DLLIMPORT void objc_enumerationMutation(struct objc_object *);\n";
59650b57cec5SDimitry Andric   Preamble += "#define __FASTENUMERATIONSTATE\n";
59660b57cec5SDimitry Andric   Preamble += "#endif\n";
59670b57cec5SDimitry Andric   Preamble += "#ifndef __NSCONSTANTSTRINGIMPL\n";
59680b57cec5SDimitry Andric   Preamble += "struct __NSConstantStringImpl {\n";
59690b57cec5SDimitry Andric   Preamble += "  int *isa;\n";
59700b57cec5SDimitry Andric   Preamble += "  int flags;\n";
59710b57cec5SDimitry Andric   Preamble += "  char *str;\n";
59720b57cec5SDimitry Andric   Preamble += "#if _WIN64\n";
59730b57cec5SDimitry Andric   Preamble += "  long long length;\n";
59740b57cec5SDimitry Andric   Preamble += "#else\n";
59750b57cec5SDimitry Andric   Preamble += "  long length;\n";
59760b57cec5SDimitry Andric   Preamble += "#endif\n";
59770b57cec5SDimitry Andric   Preamble += "};\n";
59780b57cec5SDimitry Andric   Preamble += "#ifdef CF_EXPORT_CONSTANT_STRING\n";
59790b57cec5SDimitry Andric   Preamble += "extern \"C\" __declspec(dllexport) int __CFConstantStringClassReference[];\n";
59800b57cec5SDimitry Andric   Preamble += "#else\n";
59810b57cec5SDimitry Andric   Preamble += "__OBJC_RW_DLLIMPORT int __CFConstantStringClassReference[];\n";
59820b57cec5SDimitry Andric   Preamble += "#endif\n";
59830b57cec5SDimitry Andric   Preamble += "#define __NSCONSTANTSTRINGIMPL\n";
59840b57cec5SDimitry Andric   Preamble += "#endif\n";
59850b57cec5SDimitry Andric   // Blocks preamble.
59860b57cec5SDimitry Andric   Preamble += "#ifndef BLOCK_IMPL\n";
59870b57cec5SDimitry Andric   Preamble += "#define BLOCK_IMPL\n";
59880b57cec5SDimitry Andric   Preamble += "struct __block_impl {\n";
59890b57cec5SDimitry Andric   Preamble += "  void *isa;\n";
59900b57cec5SDimitry Andric   Preamble += "  int Flags;\n";
59910b57cec5SDimitry Andric   Preamble += "  int Reserved;\n";
59920b57cec5SDimitry Andric   Preamble += "  void *FuncPtr;\n";
59930b57cec5SDimitry Andric   Preamble += "};\n";
59940b57cec5SDimitry Andric   Preamble += "// Runtime copy/destroy helper functions (from Block_private.h)\n";
59950b57cec5SDimitry Andric   Preamble += "#ifdef __OBJC_EXPORT_BLOCKS\n";
59960b57cec5SDimitry Andric   Preamble += "extern \"C\" __declspec(dllexport) "
59970b57cec5SDimitry Andric   "void _Block_object_assign(void *, const void *, const int);\n";
59980b57cec5SDimitry Andric   Preamble += "extern \"C\" __declspec(dllexport) void _Block_object_dispose(const void *, const int);\n";
59990b57cec5SDimitry Andric   Preamble += "extern \"C\" __declspec(dllexport) void *_NSConcreteGlobalBlock[32];\n";
60000b57cec5SDimitry Andric   Preamble += "extern \"C\" __declspec(dllexport) void *_NSConcreteStackBlock[32];\n";
60010b57cec5SDimitry Andric   Preamble += "#else\n";
60020b57cec5SDimitry Andric   Preamble += "__OBJC_RW_DLLIMPORT void _Block_object_assign(void *, const void *, const int);\n";
60030b57cec5SDimitry Andric   Preamble += "__OBJC_RW_DLLIMPORT void _Block_object_dispose(const void *, const int);\n";
60040b57cec5SDimitry Andric   Preamble += "__OBJC_RW_DLLIMPORT void *_NSConcreteGlobalBlock[32];\n";
60050b57cec5SDimitry Andric   Preamble += "__OBJC_RW_DLLIMPORT void *_NSConcreteStackBlock[32];\n";
60060b57cec5SDimitry Andric   Preamble += "#endif\n";
60070b57cec5SDimitry Andric   Preamble += "#endif\n";
60080b57cec5SDimitry Andric   if (LangOpts.MicrosoftExt) {
60090b57cec5SDimitry Andric     Preamble += "#undef __OBJC_RW_DLLIMPORT\n";
60100b57cec5SDimitry Andric     Preamble += "#undef __OBJC_RW_STATICIMPORT\n";
60110b57cec5SDimitry Andric     Preamble += "#ifndef KEEP_ATTRIBUTES\n";  // We use this for clang tests.
60120b57cec5SDimitry Andric     Preamble += "#define __attribute__(X)\n";
60130b57cec5SDimitry Andric     Preamble += "#endif\n";
60140b57cec5SDimitry Andric     Preamble += "#ifndef __weak\n";
60150b57cec5SDimitry Andric     Preamble += "#define __weak\n";
60160b57cec5SDimitry Andric     Preamble += "#endif\n";
60170b57cec5SDimitry Andric     Preamble += "#ifndef __block\n";
60180b57cec5SDimitry Andric     Preamble += "#define __block\n";
60190b57cec5SDimitry Andric     Preamble += "#endif\n";
60200b57cec5SDimitry Andric   }
60210b57cec5SDimitry Andric   else {
60220b57cec5SDimitry Andric     Preamble += "#define __block\n";
60230b57cec5SDimitry Andric     Preamble += "#define __weak\n";
60240b57cec5SDimitry Andric   }
60250b57cec5SDimitry Andric 
60260b57cec5SDimitry Andric   // Declarations required for modern objective-c array and dictionary literals.
60270b57cec5SDimitry Andric   Preamble += "\n#include <stdarg.h>\n";
60280b57cec5SDimitry Andric   Preamble += "struct __NSContainer_literal {\n";
60290b57cec5SDimitry Andric   Preamble += "  void * *arr;\n";
60300b57cec5SDimitry Andric   Preamble += "  __NSContainer_literal (unsigned int count, ...) {\n";
60310b57cec5SDimitry Andric   Preamble += "\tva_list marker;\n";
60320b57cec5SDimitry Andric   Preamble += "\tva_start(marker, count);\n";
60330b57cec5SDimitry Andric   Preamble += "\tarr = new void *[count];\n";
60340b57cec5SDimitry Andric   Preamble += "\tfor (unsigned i = 0; i < count; i++)\n";
60350b57cec5SDimitry Andric   Preamble += "\t  arr[i] = va_arg(marker, void *);\n";
60360b57cec5SDimitry Andric   Preamble += "\tva_end( marker );\n";
60370b57cec5SDimitry Andric   Preamble += "  };\n";
60380b57cec5SDimitry Andric   Preamble += "  ~__NSContainer_literal() {\n";
60390b57cec5SDimitry Andric   Preamble += "\tdelete[] arr;\n";
60400b57cec5SDimitry Andric   Preamble += "  }\n";
60410b57cec5SDimitry Andric   Preamble += "};\n";
60420b57cec5SDimitry Andric 
60430b57cec5SDimitry Andric   // Declaration required for implementation of @autoreleasepool statement.
60440b57cec5SDimitry Andric   Preamble += "extern \"C\" __declspec(dllimport) void * objc_autoreleasePoolPush(void);\n";
60450b57cec5SDimitry Andric   Preamble += "extern \"C\" __declspec(dllimport) void objc_autoreleasePoolPop(void *);\n\n";
60460b57cec5SDimitry Andric   Preamble += "struct __AtAutoreleasePool {\n";
60470b57cec5SDimitry Andric   Preamble += "  __AtAutoreleasePool() {atautoreleasepoolobj = objc_autoreleasePoolPush();}\n";
60480b57cec5SDimitry Andric   Preamble += "  ~__AtAutoreleasePool() {objc_autoreleasePoolPop(atautoreleasepoolobj);}\n";
60490b57cec5SDimitry Andric   Preamble += "  void * atautoreleasepoolobj;\n";
60500b57cec5SDimitry Andric   Preamble += "};\n";
60510b57cec5SDimitry Andric 
60520b57cec5SDimitry Andric   // NOTE! Windows uses LLP64 for 64bit mode. So, cast pointer to long long
60530b57cec5SDimitry Andric   // as this avoids warning in any 64bit/32bit compilation model.
60540b57cec5SDimitry Andric   Preamble += "\n#define __OFFSETOFIVAR__(TYPE, MEMBER) ((long long) &((TYPE *)0)->MEMBER)\n";
60550b57cec5SDimitry Andric }
60560b57cec5SDimitry Andric 
60570b57cec5SDimitry Andric /// RewriteIvarOffsetComputation - This routine synthesizes computation of
60580b57cec5SDimitry Andric /// ivar offset.
RewriteIvarOffsetComputation(ObjCIvarDecl * ivar,std::string & Result)60590b57cec5SDimitry Andric void RewriteModernObjC::RewriteIvarOffsetComputation(ObjCIvarDecl *ivar,
60600b57cec5SDimitry Andric                                                          std::string &Result) {
60610b57cec5SDimitry Andric   Result += "__OFFSETOFIVAR__(struct ";
60620b57cec5SDimitry Andric   Result += ivar->getContainingInterface()->getNameAsString();
60630b57cec5SDimitry Andric   if (LangOpts.MicrosoftExt)
60640b57cec5SDimitry Andric     Result += "_IMPL";
60650b57cec5SDimitry Andric   Result += ", ";
60660b57cec5SDimitry Andric   if (ivar->isBitField())
60670b57cec5SDimitry Andric     ObjCIvarBitfieldGroupDecl(ivar, Result);
60680b57cec5SDimitry Andric   else
60690b57cec5SDimitry Andric     Result += ivar->getNameAsString();
60700b57cec5SDimitry Andric   Result += ")";
60710b57cec5SDimitry Andric }
60720b57cec5SDimitry Andric 
60730b57cec5SDimitry Andric /// WriteModernMetadataDeclarations - Writes out metadata declarations for modern ABI.
60740b57cec5SDimitry Andric /// struct _prop_t {
60750b57cec5SDimitry Andric ///   const char *name;
60760b57cec5SDimitry Andric ///   char *attributes;
60770b57cec5SDimitry Andric /// }
60780b57cec5SDimitry Andric 
60790b57cec5SDimitry Andric /// struct _prop_list_t {
60800b57cec5SDimitry Andric ///   uint32_t entsize;      // sizeof(struct _prop_t)
60810b57cec5SDimitry Andric ///   uint32_t count_of_properties;
60820b57cec5SDimitry Andric ///   struct _prop_t prop_list[count_of_properties];
60830b57cec5SDimitry Andric /// }
60840b57cec5SDimitry Andric 
60850b57cec5SDimitry Andric /// struct _protocol_t;
60860b57cec5SDimitry Andric 
60870b57cec5SDimitry Andric /// struct _protocol_list_t {
60880b57cec5SDimitry Andric ///   long protocol_count;   // Note, this is 32/64 bit
60890b57cec5SDimitry Andric ///   struct _protocol_t * protocol_list[protocol_count];
60900b57cec5SDimitry Andric /// }
60910b57cec5SDimitry Andric 
60920b57cec5SDimitry Andric /// struct _objc_method {
60930b57cec5SDimitry Andric ///   SEL _cmd;
60940b57cec5SDimitry Andric ///   const char *method_type;
60950b57cec5SDimitry Andric ///   char *_imp;
60960b57cec5SDimitry Andric /// }
60970b57cec5SDimitry Andric 
60980b57cec5SDimitry Andric /// struct _method_list_t {
60990b57cec5SDimitry Andric ///   uint32_t entsize;  // sizeof(struct _objc_method)
61000b57cec5SDimitry Andric ///   uint32_t method_count;
61010b57cec5SDimitry Andric ///   struct _objc_method method_list[method_count];
61020b57cec5SDimitry Andric /// }
61030b57cec5SDimitry Andric 
61040b57cec5SDimitry Andric /// struct _protocol_t {
61050b57cec5SDimitry Andric ///   id isa;  // NULL
61060b57cec5SDimitry Andric ///   const char *protocol_name;
61070b57cec5SDimitry Andric ///   const struct _protocol_list_t * protocol_list; // super protocols
61080b57cec5SDimitry Andric ///   const struct method_list_t *instance_methods;
61090b57cec5SDimitry Andric ///   const struct method_list_t *class_methods;
61100b57cec5SDimitry Andric ///   const struct method_list_t *optionalInstanceMethods;
61110b57cec5SDimitry Andric ///   const struct method_list_t *optionalClassMethods;
61120b57cec5SDimitry Andric ///   const struct _prop_list_t * properties;
61130b57cec5SDimitry Andric ///   const uint32_t size;  // sizeof(struct _protocol_t)
61140b57cec5SDimitry Andric ///   const uint32_t flags;  // = 0
61150b57cec5SDimitry Andric ///   const char ** extendedMethodTypes;
61160b57cec5SDimitry Andric /// }
61170b57cec5SDimitry Andric 
61180b57cec5SDimitry Andric /// struct _ivar_t {
61190b57cec5SDimitry Andric ///   unsigned long int *offset;  // pointer to ivar offset location
61200b57cec5SDimitry Andric ///   const char *name;
61210b57cec5SDimitry Andric ///   const char *type;
61220b57cec5SDimitry Andric ///   uint32_t alignment;
61230b57cec5SDimitry Andric ///   uint32_t size;
61240b57cec5SDimitry Andric /// }
61250b57cec5SDimitry Andric 
61260b57cec5SDimitry Andric /// struct _ivar_list_t {
61270b57cec5SDimitry Andric ///   uint32 entsize;  // sizeof(struct _ivar_t)
61280b57cec5SDimitry Andric ///   uint32 count;
61290b57cec5SDimitry Andric ///   struct _ivar_t list[count];
61300b57cec5SDimitry Andric /// }
61310b57cec5SDimitry Andric 
61320b57cec5SDimitry Andric /// struct _class_ro_t {
61330b57cec5SDimitry Andric ///   uint32_t flags;
61340b57cec5SDimitry Andric ///   uint32_t instanceStart;
61350b57cec5SDimitry Andric ///   uint32_t instanceSize;
61360b57cec5SDimitry Andric ///   uint32_t reserved;  // only when building for 64bit targets
61370b57cec5SDimitry Andric ///   const uint8_t *ivarLayout;
61380b57cec5SDimitry Andric ///   const char *name;
61390b57cec5SDimitry Andric ///   const struct _method_list_t *baseMethods;
61400b57cec5SDimitry Andric ///   const struct _protocol_list_t *baseProtocols;
61410b57cec5SDimitry Andric ///   const struct _ivar_list_t *ivars;
61420b57cec5SDimitry Andric ///   const uint8_t *weakIvarLayout;
61430b57cec5SDimitry Andric ///   const struct _prop_list_t *properties;
61440b57cec5SDimitry Andric /// }
61450b57cec5SDimitry Andric 
61460b57cec5SDimitry Andric /// struct _class_t {
61470b57cec5SDimitry Andric ///   struct _class_t *isa;
61480b57cec5SDimitry Andric ///   struct _class_t *superclass;
61490b57cec5SDimitry Andric ///   void *cache;
61500b57cec5SDimitry Andric ///   IMP *vtable;
61510b57cec5SDimitry Andric ///   struct _class_ro_t *ro;
61520b57cec5SDimitry Andric /// }
61530b57cec5SDimitry Andric 
61540b57cec5SDimitry Andric /// struct _category_t {
61550b57cec5SDimitry Andric ///   const char *name;
61560b57cec5SDimitry Andric ///   struct _class_t *cls;
61570b57cec5SDimitry Andric ///   const struct _method_list_t *instance_methods;
61580b57cec5SDimitry Andric ///   const struct _method_list_t *class_methods;
61590b57cec5SDimitry Andric ///   const struct _protocol_list_t *protocols;
61600b57cec5SDimitry Andric ///   const struct _prop_list_t *properties;
61610b57cec5SDimitry Andric /// }
61620b57cec5SDimitry Andric 
61630b57cec5SDimitry Andric /// MessageRefTy - LLVM for:
61640b57cec5SDimitry Andric /// struct _message_ref_t {
61650b57cec5SDimitry Andric ///   IMP messenger;
61660b57cec5SDimitry Andric ///   SEL name;
61670b57cec5SDimitry Andric /// };
61680b57cec5SDimitry Andric 
61690b57cec5SDimitry Andric /// SuperMessageRefTy - LLVM for:
61700b57cec5SDimitry Andric /// struct _super_message_ref_t {
61710b57cec5SDimitry Andric ///   SUPER_IMP messenger;
61720b57cec5SDimitry Andric ///   SEL name;
61730b57cec5SDimitry Andric /// };
61740b57cec5SDimitry Andric 
WriteModernMetadataDeclarations(ASTContext * Context,std::string & Result)61750b57cec5SDimitry Andric static void WriteModernMetadataDeclarations(ASTContext *Context, std::string &Result) {
61760b57cec5SDimitry Andric   static bool meta_data_declared = false;
61770b57cec5SDimitry Andric   if (meta_data_declared)
61780b57cec5SDimitry Andric     return;
61790b57cec5SDimitry Andric 
61800b57cec5SDimitry Andric   Result += "\nstruct _prop_t {\n";
61810b57cec5SDimitry Andric   Result += "\tconst char *name;\n";
61820b57cec5SDimitry Andric   Result += "\tconst char *attributes;\n";
61830b57cec5SDimitry Andric   Result += "};\n";
61840b57cec5SDimitry Andric 
61850b57cec5SDimitry Andric   Result += "\nstruct _protocol_t;\n";
61860b57cec5SDimitry Andric 
61870b57cec5SDimitry Andric   Result += "\nstruct _objc_method {\n";
61880b57cec5SDimitry Andric   Result += "\tstruct objc_selector * _cmd;\n";
61890b57cec5SDimitry Andric   Result += "\tconst char *method_type;\n";
61900b57cec5SDimitry Andric   Result += "\tvoid  *_imp;\n";
61910b57cec5SDimitry Andric   Result += "};\n";
61920b57cec5SDimitry Andric 
61930b57cec5SDimitry Andric   Result += "\nstruct _protocol_t {\n";
61940b57cec5SDimitry Andric   Result += "\tvoid * isa;  // NULL\n";
61950b57cec5SDimitry Andric   Result += "\tconst char *protocol_name;\n";
61960b57cec5SDimitry Andric   Result += "\tconst struct _protocol_list_t * protocol_list; // super protocols\n";
61970b57cec5SDimitry Andric   Result += "\tconst struct method_list_t *instance_methods;\n";
61980b57cec5SDimitry Andric   Result += "\tconst struct method_list_t *class_methods;\n";
61990b57cec5SDimitry Andric   Result += "\tconst struct method_list_t *optionalInstanceMethods;\n";
62000b57cec5SDimitry Andric   Result += "\tconst struct method_list_t *optionalClassMethods;\n";
62010b57cec5SDimitry Andric   Result += "\tconst struct _prop_list_t * properties;\n";
62020b57cec5SDimitry Andric   Result += "\tconst unsigned int size;  // sizeof(struct _protocol_t)\n";
62030b57cec5SDimitry Andric   Result += "\tconst unsigned int flags;  // = 0\n";
62040b57cec5SDimitry Andric   Result += "\tconst char ** extendedMethodTypes;\n";
62050b57cec5SDimitry Andric   Result += "};\n";
62060b57cec5SDimitry Andric 
62070b57cec5SDimitry Andric   Result += "\nstruct _ivar_t {\n";
62080b57cec5SDimitry Andric   Result += "\tunsigned long int *offset;  // pointer to ivar offset location\n";
62090b57cec5SDimitry Andric   Result += "\tconst char *name;\n";
62100b57cec5SDimitry Andric   Result += "\tconst char *type;\n";
62110b57cec5SDimitry Andric   Result += "\tunsigned int alignment;\n";
62120b57cec5SDimitry Andric   Result += "\tunsigned int  size;\n";
62130b57cec5SDimitry Andric   Result += "};\n";
62140b57cec5SDimitry Andric 
62150b57cec5SDimitry Andric   Result += "\nstruct _class_ro_t {\n";
62160b57cec5SDimitry Andric   Result += "\tunsigned int flags;\n";
62170b57cec5SDimitry Andric   Result += "\tunsigned int instanceStart;\n";
62180b57cec5SDimitry Andric   Result += "\tunsigned int instanceSize;\n";
62190b57cec5SDimitry Andric   const llvm::Triple &Triple(Context->getTargetInfo().getTriple());
62200b57cec5SDimitry Andric   if (Triple.getArch() == llvm::Triple::x86_64)
62210b57cec5SDimitry Andric     Result += "\tunsigned int reserved;\n";
62220b57cec5SDimitry Andric   Result += "\tconst unsigned char *ivarLayout;\n";
62230b57cec5SDimitry Andric   Result += "\tconst char *name;\n";
62240b57cec5SDimitry Andric   Result += "\tconst struct _method_list_t *baseMethods;\n";
62250b57cec5SDimitry Andric   Result += "\tconst struct _objc_protocol_list *baseProtocols;\n";
62260b57cec5SDimitry Andric   Result += "\tconst struct _ivar_list_t *ivars;\n";
62270b57cec5SDimitry Andric   Result += "\tconst unsigned char *weakIvarLayout;\n";
62280b57cec5SDimitry Andric   Result += "\tconst struct _prop_list_t *properties;\n";
62290b57cec5SDimitry Andric   Result += "};\n";
62300b57cec5SDimitry Andric 
62310b57cec5SDimitry Andric   Result += "\nstruct _class_t {\n";
62320b57cec5SDimitry Andric   Result += "\tstruct _class_t *isa;\n";
62330b57cec5SDimitry Andric   Result += "\tstruct _class_t *superclass;\n";
62340b57cec5SDimitry Andric   Result += "\tvoid *cache;\n";
62350b57cec5SDimitry Andric   Result += "\tvoid *vtable;\n";
62360b57cec5SDimitry Andric   Result += "\tstruct _class_ro_t *ro;\n";
62370b57cec5SDimitry Andric   Result += "};\n";
62380b57cec5SDimitry Andric 
62390b57cec5SDimitry Andric   Result += "\nstruct _category_t {\n";
62400b57cec5SDimitry Andric   Result += "\tconst char *name;\n";
62410b57cec5SDimitry Andric   Result += "\tstruct _class_t *cls;\n";
62420b57cec5SDimitry Andric   Result += "\tconst struct _method_list_t *instance_methods;\n";
62430b57cec5SDimitry Andric   Result += "\tconst struct _method_list_t *class_methods;\n";
62440b57cec5SDimitry Andric   Result += "\tconst struct _protocol_list_t *protocols;\n";
62450b57cec5SDimitry Andric   Result += "\tconst struct _prop_list_t *properties;\n";
62460b57cec5SDimitry Andric   Result += "};\n";
62470b57cec5SDimitry Andric 
62480b57cec5SDimitry Andric   Result += "extern \"C\" __declspec(dllimport) struct objc_cache _objc_empty_cache;\n";
62490b57cec5SDimitry Andric   Result += "#pragma warning(disable:4273)\n";
62500b57cec5SDimitry Andric   meta_data_declared = true;
62510b57cec5SDimitry Andric }
62520b57cec5SDimitry Andric 
Write_protocol_list_t_TypeDecl(std::string & Result,long super_protocol_count)62530b57cec5SDimitry Andric static void Write_protocol_list_t_TypeDecl(std::string &Result,
62540b57cec5SDimitry Andric                                            long super_protocol_count) {
62550b57cec5SDimitry Andric   Result += "struct /*_protocol_list_t*/"; Result += " {\n";
62560b57cec5SDimitry Andric   Result += "\tlong protocol_count;  // Note, this is 32/64 bit\n";
62570b57cec5SDimitry Andric   Result += "\tstruct _protocol_t *super_protocols[";
62580b57cec5SDimitry Andric   Result += utostr(super_protocol_count); Result += "];\n";
62590b57cec5SDimitry Andric   Result += "}";
62600b57cec5SDimitry Andric }
62610b57cec5SDimitry Andric 
Write_method_list_t_TypeDecl(std::string & Result,unsigned int method_count)62620b57cec5SDimitry Andric static void Write_method_list_t_TypeDecl(std::string &Result,
62630b57cec5SDimitry Andric                                          unsigned int method_count) {
62640b57cec5SDimitry Andric   Result += "struct /*_method_list_t*/"; Result += " {\n";
62650b57cec5SDimitry Andric   Result += "\tunsigned int entsize;  // sizeof(struct _objc_method)\n";
62660b57cec5SDimitry Andric   Result += "\tunsigned int method_count;\n";
62670b57cec5SDimitry Andric   Result += "\tstruct _objc_method method_list[";
62680b57cec5SDimitry Andric   Result += utostr(method_count); Result += "];\n";
62690b57cec5SDimitry Andric   Result += "}";
62700b57cec5SDimitry Andric }
62710b57cec5SDimitry Andric 
Write__prop_list_t_TypeDecl(std::string & Result,unsigned int property_count)62720b57cec5SDimitry Andric static void Write__prop_list_t_TypeDecl(std::string &Result,
62730b57cec5SDimitry Andric                                         unsigned int property_count) {
62740b57cec5SDimitry Andric   Result += "struct /*_prop_list_t*/"; Result += " {\n";
62750b57cec5SDimitry Andric   Result += "\tunsigned int entsize;  // sizeof(struct _prop_t)\n";
62760b57cec5SDimitry Andric   Result += "\tunsigned int count_of_properties;\n";
62770b57cec5SDimitry Andric   Result += "\tstruct _prop_t prop_list[";
62780b57cec5SDimitry Andric   Result += utostr(property_count); Result += "];\n";
62790b57cec5SDimitry Andric   Result += "}";
62800b57cec5SDimitry Andric }
62810b57cec5SDimitry Andric 
Write__ivar_list_t_TypeDecl(std::string & Result,unsigned int ivar_count)62820b57cec5SDimitry Andric static void Write__ivar_list_t_TypeDecl(std::string &Result,
62830b57cec5SDimitry Andric                                         unsigned int ivar_count) {
62840b57cec5SDimitry Andric   Result += "struct /*_ivar_list_t*/"; Result += " {\n";
62850b57cec5SDimitry Andric   Result += "\tunsigned int entsize;  // sizeof(struct _prop_t)\n";
62860b57cec5SDimitry Andric   Result += "\tunsigned int count;\n";
62870b57cec5SDimitry Andric   Result += "\tstruct _ivar_t ivar_list[";
62880b57cec5SDimitry Andric   Result += utostr(ivar_count); Result += "];\n";
62890b57cec5SDimitry Andric   Result += "}";
62900b57cec5SDimitry Andric }
62910b57cec5SDimitry Andric 
Write_protocol_list_initializer(ASTContext * Context,std::string & Result,ArrayRef<ObjCProtocolDecl * > SuperProtocols,StringRef VarName,StringRef ProtocolName)62920b57cec5SDimitry Andric static void Write_protocol_list_initializer(ASTContext *Context, std::string &Result,
62930b57cec5SDimitry Andric                                             ArrayRef<ObjCProtocolDecl *> SuperProtocols,
62940b57cec5SDimitry Andric                                             StringRef VarName,
62950b57cec5SDimitry Andric                                             StringRef ProtocolName) {
62960b57cec5SDimitry Andric   if (SuperProtocols.size() > 0) {
62970b57cec5SDimitry Andric     Result += "\nstatic ";
62980b57cec5SDimitry Andric     Write_protocol_list_t_TypeDecl(Result, SuperProtocols.size());
62990b57cec5SDimitry Andric     Result += " "; Result += VarName;
63000b57cec5SDimitry Andric     Result += ProtocolName;
63010b57cec5SDimitry Andric     Result += " __attribute__ ((used, section (\"__DATA,__objc_const\"))) = {\n";
63020b57cec5SDimitry Andric     Result += "\t"; Result += utostr(SuperProtocols.size()); Result += ",\n";
63030b57cec5SDimitry Andric     for (unsigned i = 0, e = SuperProtocols.size(); i < e; i++) {
63040b57cec5SDimitry Andric       ObjCProtocolDecl *SuperPD = SuperProtocols[i];
63050b57cec5SDimitry Andric       Result += "\t&"; Result += "_OBJC_PROTOCOL_";
63060b57cec5SDimitry Andric       Result += SuperPD->getNameAsString();
63070b57cec5SDimitry Andric       if (i == e-1)
63080b57cec5SDimitry Andric         Result += "\n};\n";
63090b57cec5SDimitry Andric       else
63100b57cec5SDimitry Andric         Result += ",\n";
63110b57cec5SDimitry Andric     }
63120b57cec5SDimitry Andric   }
63130b57cec5SDimitry Andric }
63140b57cec5SDimitry Andric 
Write_method_list_t_initializer(RewriteModernObjC & RewriteObj,ASTContext * Context,std::string & Result,ArrayRef<ObjCMethodDecl * > Methods,StringRef VarName,StringRef TopLevelDeclName,bool MethodImpl)63150b57cec5SDimitry Andric static void Write_method_list_t_initializer(RewriteModernObjC &RewriteObj,
63160b57cec5SDimitry Andric                                             ASTContext *Context, std::string &Result,
63170b57cec5SDimitry Andric                                             ArrayRef<ObjCMethodDecl *> Methods,
63180b57cec5SDimitry Andric                                             StringRef VarName,
63190b57cec5SDimitry Andric                                             StringRef TopLevelDeclName,
63200b57cec5SDimitry Andric                                             bool MethodImpl) {
63210b57cec5SDimitry Andric   if (Methods.size() > 0) {
63220b57cec5SDimitry Andric     Result += "\nstatic ";
63230b57cec5SDimitry Andric     Write_method_list_t_TypeDecl(Result, Methods.size());
63240b57cec5SDimitry Andric     Result += " "; Result += VarName;
63250b57cec5SDimitry Andric     Result += TopLevelDeclName;
63260b57cec5SDimitry Andric     Result += " __attribute__ ((used, section (\"__DATA,__objc_const\"))) = {\n";
63270b57cec5SDimitry Andric     Result += "\t"; Result += "sizeof(_objc_method)"; Result += ",\n";
63280b57cec5SDimitry Andric     Result += "\t"; Result += utostr(Methods.size()); Result += ",\n";
63290b57cec5SDimitry Andric     for (unsigned i = 0, e = Methods.size(); i < e; i++) {
63300b57cec5SDimitry Andric       ObjCMethodDecl *MD = Methods[i];
63310b57cec5SDimitry Andric       if (i == 0)
63320b57cec5SDimitry Andric         Result += "\t{{(struct objc_selector *)\"";
63330b57cec5SDimitry Andric       else
63340b57cec5SDimitry Andric         Result += "\t{(struct objc_selector *)\"";
63350b57cec5SDimitry Andric       Result += (MD)->getSelector().getAsString(); Result += "\"";
63360b57cec5SDimitry Andric       Result += ", ";
63370b57cec5SDimitry Andric       std::string MethodTypeString = Context->getObjCEncodingForMethodDecl(MD);
63380b57cec5SDimitry Andric       Result += "\""; Result += MethodTypeString; Result += "\"";
63390b57cec5SDimitry Andric       Result += ", ";
63400b57cec5SDimitry Andric       if (!MethodImpl)
63410b57cec5SDimitry Andric         Result += "0";
63420b57cec5SDimitry Andric       else {
63430b57cec5SDimitry Andric         Result += "(void *)";
63440b57cec5SDimitry Andric         Result += RewriteObj.MethodInternalNames[MD];
63450b57cec5SDimitry Andric       }
63460b57cec5SDimitry Andric       if (i  == e-1)
63470b57cec5SDimitry Andric         Result += "}}\n";
63480b57cec5SDimitry Andric       else
63490b57cec5SDimitry Andric         Result += "},\n";
63500b57cec5SDimitry Andric     }
63510b57cec5SDimitry Andric     Result += "};\n";
63520b57cec5SDimitry Andric   }
63530b57cec5SDimitry Andric }
63540b57cec5SDimitry Andric 
Write_prop_list_t_initializer(RewriteModernObjC & RewriteObj,ASTContext * Context,std::string & Result,ArrayRef<ObjCPropertyDecl * > Properties,const Decl * Container,StringRef VarName,StringRef ProtocolName)63550b57cec5SDimitry Andric static void Write_prop_list_t_initializer(RewriteModernObjC &RewriteObj,
63560b57cec5SDimitry Andric                                            ASTContext *Context, std::string &Result,
63570b57cec5SDimitry Andric                                            ArrayRef<ObjCPropertyDecl *> Properties,
63580b57cec5SDimitry Andric                                            const Decl *Container,
63590b57cec5SDimitry Andric                                            StringRef VarName,
63600b57cec5SDimitry Andric                                            StringRef ProtocolName) {
63610b57cec5SDimitry Andric   if (Properties.size() > 0) {
63620b57cec5SDimitry Andric     Result += "\nstatic ";
63630b57cec5SDimitry Andric     Write__prop_list_t_TypeDecl(Result, Properties.size());
63640b57cec5SDimitry Andric     Result += " "; Result += VarName;
63650b57cec5SDimitry Andric     Result += ProtocolName;
63660b57cec5SDimitry Andric     Result += " __attribute__ ((used, section (\"__DATA,__objc_const\"))) = {\n";
63670b57cec5SDimitry Andric     Result += "\t"; Result += "sizeof(_prop_t)"; Result += ",\n";
63680b57cec5SDimitry Andric     Result += "\t"; Result += utostr(Properties.size()); Result += ",\n";
63690b57cec5SDimitry Andric     for (unsigned i = 0, e = Properties.size(); i < e; i++) {
63700b57cec5SDimitry Andric       ObjCPropertyDecl *PropDecl = Properties[i];
63710b57cec5SDimitry Andric       if (i == 0)
63720b57cec5SDimitry Andric         Result += "\t{{\"";
63730b57cec5SDimitry Andric       else
63740b57cec5SDimitry Andric         Result += "\t{\"";
63750b57cec5SDimitry Andric       Result += PropDecl->getName(); Result += "\",";
63760b57cec5SDimitry Andric       std::string PropertyTypeString =
63770b57cec5SDimitry Andric         Context->getObjCEncodingForPropertyDecl(PropDecl, Container);
63780b57cec5SDimitry Andric       std::string QuotePropertyTypeString;
63790b57cec5SDimitry Andric       RewriteObj.QuoteDoublequotes(PropertyTypeString, QuotePropertyTypeString);
63800b57cec5SDimitry Andric       Result += "\""; Result += QuotePropertyTypeString; Result += "\"";
63810b57cec5SDimitry Andric       if (i  == e-1)
63820b57cec5SDimitry Andric         Result += "}}\n";
63830b57cec5SDimitry Andric       else
63840b57cec5SDimitry Andric         Result += "},\n";
63850b57cec5SDimitry Andric     }
63860b57cec5SDimitry Andric     Result += "};\n";
63870b57cec5SDimitry Andric   }
63880b57cec5SDimitry Andric }
63890b57cec5SDimitry Andric 
63900b57cec5SDimitry Andric // Metadata flags
63910b57cec5SDimitry Andric enum MetaDataDlags {
63920b57cec5SDimitry Andric   CLS = 0x0,
63930b57cec5SDimitry Andric   CLS_META = 0x1,
63940b57cec5SDimitry Andric   CLS_ROOT = 0x2,
63950b57cec5SDimitry Andric   OBJC2_CLS_HIDDEN = 0x10,
63960b57cec5SDimitry Andric   CLS_EXCEPTION = 0x20,
63970b57cec5SDimitry Andric 
63980b57cec5SDimitry Andric   /// (Obsolete) ARC-specific: this class has a .release_ivars method
63990b57cec5SDimitry Andric   CLS_HAS_IVAR_RELEASER = 0x40,
64000b57cec5SDimitry Andric   /// class was compiled with -fobjc-arr
64010b57cec5SDimitry Andric   CLS_COMPILED_BY_ARC = 0x80  // (1<<7)
64020b57cec5SDimitry Andric };
64030b57cec5SDimitry Andric 
Write__class_ro_t_initializer(ASTContext * Context,std::string & Result,unsigned int flags,const std::string & InstanceStart,const std::string & InstanceSize,ArrayRef<ObjCMethodDecl * > baseMethods,ArrayRef<ObjCProtocolDecl * > baseProtocols,ArrayRef<ObjCIvarDecl * > ivars,ArrayRef<ObjCPropertyDecl * > Properties,StringRef VarName,StringRef ClassName)64040b57cec5SDimitry Andric static void Write__class_ro_t_initializer(ASTContext *Context, std::string &Result,
64050b57cec5SDimitry Andric                                           unsigned int flags,
64060b57cec5SDimitry Andric                                           const std::string &InstanceStart,
64070b57cec5SDimitry Andric                                           const std::string &InstanceSize,
64080b57cec5SDimitry Andric                                           ArrayRef<ObjCMethodDecl *>baseMethods,
64090b57cec5SDimitry Andric                                           ArrayRef<ObjCProtocolDecl *>baseProtocols,
64100b57cec5SDimitry Andric                                           ArrayRef<ObjCIvarDecl *>ivars,
64110b57cec5SDimitry Andric                                           ArrayRef<ObjCPropertyDecl *>Properties,
64120b57cec5SDimitry Andric                                           StringRef VarName,
64130b57cec5SDimitry Andric                                           StringRef ClassName) {
64140b57cec5SDimitry Andric   Result += "\nstatic struct _class_ro_t ";
64150b57cec5SDimitry Andric   Result += VarName; Result += ClassName;
64160b57cec5SDimitry Andric   Result += " __attribute__ ((used, section (\"__DATA,__objc_const\"))) = {\n";
64170b57cec5SDimitry Andric   Result += "\t";
64180b57cec5SDimitry Andric   Result += llvm::utostr(flags); Result += ", ";
64190b57cec5SDimitry Andric   Result += InstanceStart; Result += ", ";
64200b57cec5SDimitry Andric   Result += InstanceSize; Result += ", \n";
64210b57cec5SDimitry Andric   Result += "\t";
64220b57cec5SDimitry Andric   const llvm::Triple &Triple(Context->getTargetInfo().getTriple());
64230b57cec5SDimitry Andric   if (Triple.getArch() == llvm::Triple::x86_64)
64240b57cec5SDimitry Andric     // uint32_t const reserved; // only when building for 64bit targets
64250b57cec5SDimitry Andric     Result += "(unsigned int)0, \n\t";
64260b57cec5SDimitry Andric   // const uint8_t * const ivarLayout;
64270b57cec5SDimitry Andric   Result += "0, \n\t";
64280b57cec5SDimitry Andric   Result += "\""; Result += ClassName; Result += "\",\n\t";
64290b57cec5SDimitry Andric   bool metaclass = ((flags & CLS_META) != 0);
64300b57cec5SDimitry Andric   if (baseMethods.size() > 0) {
64310b57cec5SDimitry Andric     Result += "(const struct _method_list_t *)&";
64320b57cec5SDimitry Andric     if (metaclass)
64330b57cec5SDimitry Andric       Result += "_OBJC_$_CLASS_METHODS_";
64340b57cec5SDimitry Andric     else
64350b57cec5SDimitry Andric       Result += "_OBJC_$_INSTANCE_METHODS_";
64360b57cec5SDimitry Andric     Result += ClassName;
64370b57cec5SDimitry Andric     Result += ",\n\t";
64380b57cec5SDimitry Andric   }
64390b57cec5SDimitry Andric   else
64400b57cec5SDimitry Andric     Result += "0, \n\t";
64410b57cec5SDimitry Andric 
64420b57cec5SDimitry Andric   if (!metaclass && baseProtocols.size() > 0) {
64430b57cec5SDimitry Andric     Result += "(const struct _objc_protocol_list *)&";
64440b57cec5SDimitry Andric     Result += "_OBJC_CLASS_PROTOCOLS_$_"; Result += ClassName;
64450b57cec5SDimitry Andric     Result += ",\n\t";
64460b57cec5SDimitry Andric   }
64470b57cec5SDimitry Andric   else
64480b57cec5SDimitry Andric     Result += "0, \n\t";
64490b57cec5SDimitry Andric 
64500b57cec5SDimitry Andric   if (!metaclass && ivars.size() > 0) {
64510b57cec5SDimitry Andric     Result += "(const struct _ivar_list_t *)&";
64520b57cec5SDimitry Andric     Result += "_OBJC_$_INSTANCE_VARIABLES_"; Result += ClassName;
64530b57cec5SDimitry Andric     Result += ",\n\t";
64540b57cec5SDimitry Andric   }
64550b57cec5SDimitry Andric   else
64560b57cec5SDimitry Andric     Result += "0, \n\t";
64570b57cec5SDimitry Andric 
64580b57cec5SDimitry Andric   // weakIvarLayout
64590b57cec5SDimitry Andric   Result += "0, \n\t";
64600b57cec5SDimitry Andric   if (!metaclass && Properties.size() > 0) {
64610b57cec5SDimitry Andric     Result += "(const struct _prop_list_t *)&";
64620b57cec5SDimitry Andric     Result += "_OBJC_$_PROP_LIST_"; Result += ClassName;
64630b57cec5SDimitry Andric     Result += ",\n";
64640b57cec5SDimitry Andric   }
64650b57cec5SDimitry Andric   else
64660b57cec5SDimitry Andric     Result += "0, \n";
64670b57cec5SDimitry Andric 
64680b57cec5SDimitry Andric   Result += "};\n";
64690b57cec5SDimitry Andric }
64700b57cec5SDimitry Andric 
Write_class_t(ASTContext * Context,std::string & Result,StringRef VarName,const ObjCInterfaceDecl * CDecl,bool metaclass)64710b57cec5SDimitry Andric static void Write_class_t(ASTContext *Context, std::string &Result,
64720b57cec5SDimitry Andric                           StringRef VarName,
64730b57cec5SDimitry Andric                           const ObjCInterfaceDecl *CDecl, bool metaclass) {
64740b57cec5SDimitry Andric   bool rootClass = (!CDecl->getSuperClass());
64750b57cec5SDimitry Andric   const ObjCInterfaceDecl *RootClass = CDecl;
64760b57cec5SDimitry Andric 
64770b57cec5SDimitry Andric   if (!rootClass) {
64780b57cec5SDimitry Andric     // Find the Root class
64790b57cec5SDimitry Andric     RootClass = CDecl->getSuperClass();
64800b57cec5SDimitry Andric     while (RootClass->getSuperClass()) {
64810b57cec5SDimitry Andric       RootClass = RootClass->getSuperClass();
64820b57cec5SDimitry Andric     }
64830b57cec5SDimitry Andric   }
64840b57cec5SDimitry Andric 
64850b57cec5SDimitry Andric   if (metaclass && rootClass) {
64860b57cec5SDimitry Andric     // Need to handle a case of use of forward declaration.
64870b57cec5SDimitry Andric     Result += "\n";
64880b57cec5SDimitry Andric     Result += "extern \"C\" ";
64890b57cec5SDimitry Andric     if (CDecl->getImplementation())
64900b57cec5SDimitry Andric       Result += "__declspec(dllexport) ";
64910b57cec5SDimitry Andric     else
64920b57cec5SDimitry Andric       Result += "__declspec(dllimport) ";
64930b57cec5SDimitry Andric 
64940b57cec5SDimitry Andric     Result += "struct _class_t OBJC_CLASS_$_";
64950b57cec5SDimitry Andric     Result += CDecl->getNameAsString();
64960b57cec5SDimitry Andric     Result += ";\n";
64970b57cec5SDimitry Andric   }
64980b57cec5SDimitry Andric   // Also, for possibility of 'super' metadata class not having been defined yet.
64990b57cec5SDimitry Andric   if (!rootClass) {
65000b57cec5SDimitry Andric     ObjCInterfaceDecl *SuperClass = CDecl->getSuperClass();
65010b57cec5SDimitry Andric     Result += "\n";
65020b57cec5SDimitry Andric     Result += "extern \"C\" ";
65030b57cec5SDimitry Andric     if (SuperClass->getImplementation())
65040b57cec5SDimitry Andric       Result += "__declspec(dllexport) ";
65050b57cec5SDimitry Andric     else
65060b57cec5SDimitry Andric       Result += "__declspec(dllimport) ";
65070b57cec5SDimitry Andric 
65080b57cec5SDimitry Andric     Result += "struct _class_t ";
65090b57cec5SDimitry Andric     Result += VarName;
65100b57cec5SDimitry Andric     Result += SuperClass->getNameAsString();
65110b57cec5SDimitry Andric     Result += ";\n";
65120b57cec5SDimitry Andric 
65130b57cec5SDimitry Andric     if (metaclass && RootClass != SuperClass) {
65140b57cec5SDimitry Andric       Result += "extern \"C\" ";
65150b57cec5SDimitry Andric       if (RootClass->getImplementation())
65160b57cec5SDimitry Andric         Result += "__declspec(dllexport) ";
65170b57cec5SDimitry Andric       else
65180b57cec5SDimitry Andric         Result += "__declspec(dllimport) ";
65190b57cec5SDimitry Andric 
65200b57cec5SDimitry Andric       Result += "struct _class_t ";
65210b57cec5SDimitry Andric       Result += VarName;
65220b57cec5SDimitry Andric       Result += RootClass->getNameAsString();
65230b57cec5SDimitry Andric       Result += ";\n";
65240b57cec5SDimitry Andric     }
65250b57cec5SDimitry Andric   }
65260b57cec5SDimitry Andric 
65270b57cec5SDimitry Andric   Result += "\nextern \"C\" __declspec(dllexport) struct _class_t ";
65280b57cec5SDimitry Andric   Result += VarName; Result += CDecl->getNameAsString();
65290b57cec5SDimitry Andric   Result += " __attribute__ ((used, section (\"__DATA,__objc_data\"))) = {\n";
65300b57cec5SDimitry Andric   Result += "\t";
65310b57cec5SDimitry Andric   if (metaclass) {
65320b57cec5SDimitry Andric     if (!rootClass) {
65330b57cec5SDimitry Andric       Result += "0, // &"; Result += VarName;
65340b57cec5SDimitry Andric       Result += RootClass->getNameAsString();
65350b57cec5SDimitry Andric       Result += ",\n\t";
65360b57cec5SDimitry Andric       Result += "0, // &"; Result += VarName;
65370b57cec5SDimitry Andric       Result += CDecl->getSuperClass()->getNameAsString();
65380b57cec5SDimitry Andric       Result += ",\n\t";
65390b57cec5SDimitry Andric     }
65400b57cec5SDimitry Andric     else {
65410b57cec5SDimitry Andric       Result += "0, // &"; Result += VarName;
65420b57cec5SDimitry Andric       Result += CDecl->getNameAsString();
65430b57cec5SDimitry Andric       Result += ",\n\t";
65440b57cec5SDimitry Andric       Result += "0, // &OBJC_CLASS_$_"; Result += CDecl->getNameAsString();
65450b57cec5SDimitry Andric       Result += ",\n\t";
65460b57cec5SDimitry Andric     }
65470b57cec5SDimitry Andric   }
65480b57cec5SDimitry Andric   else {
65490b57cec5SDimitry Andric     Result += "0, // &OBJC_METACLASS_$_";
65500b57cec5SDimitry Andric     Result += CDecl->getNameAsString();
65510b57cec5SDimitry Andric     Result += ",\n\t";
65520b57cec5SDimitry Andric     if (!rootClass) {
65530b57cec5SDimitry Andric       Result += "0, // &"; Result += VarName;
65540b57cec5SDimitry Andric       Result += CDecl->getSuperClass()->getNameAsString();
65550b57cec5SDimitry Andric       Result += ",\n\t";
65560b57cec5SDimitry Andric     }
65570b57cec5SDimitry Andric     else
65580b57cec5SDimitry Andric       Result += "0,\n\t";
65590b57cec5SDimitry Andric   }
65600b57cec5SDimitry Andric   Result += "0, // (void *)&_objc_empty_cache,\n\t";
65610b57cec5SDimitry Andric   Result += "0, // unused, was (void *)&_objc_empty_vtable,\n\t";
65620b57cec5SDimitry Andric   if (metaclass)
65630b57cec5SDimitry Andric     Result += "&_OBJC_METACLASS_RO_$_";
65640b57cec5SDimitry Andric   else
65650b57cec5SDimitry Andric     Result += "&_OBJC_CLASS_RO_$_";
65660b57cec5SDimitry Andric   Result += CDecl->getNameAsString();
65670b57cec5SDimitry Andric   Result += ",\n};\n";
65680b57cec5SDimitry Andric 
65690b57cec5SDimitry Andric   // Add static function to initialize some of the meta-data fields.
65700b57cec5SDimitry Andric   // avoid doing it twice.
65710b57cec5SDimitry Andric   if (metaclass)
65720b57cec5SDimitry Andric     return;
65730b57cec5SDimitry Andric 
65740b57cec5SDimitry Andric   const ObjCInterfaceDecl *SuperClass =
65750b57cec5SDimitry Andric     rootClass ? CDecl : CDecl->getSuperClass();
65760b57cec5SDimitry Andric 
65770b57cec5SDimitry Andric   Result += "static void OBJC_CLASS_SETUP_$_";
65780b57cec5SDimitry Andric   Result += CDecl->getNameAsString();
65790b57cec5SDimitry Andric   Result += "(void ) {\n";
65800b57cec5SDimitry Andric   Result += "\tOBJC_METACLASS_$_"; Result += CDecl->getNameAsString();
65810b57cec5SDimitry Andric   Result += ".isa = "; Result += "&OBJC_METACLASS_$_";
65820b57cec5SDimitry Andric   Result += RootClass->getNameAsString(); Result += ";\n";
65830b57cec5SDimitry Andric 
65840b57cec5SDimitry Andric   Result += "\tOBJC_METACLASS_$_"; Result += CDecl->getNameAsString();
65850b57cec5SDimitry Andric   Result += ".superclass = ";
65860b57cec5SDimitry Andric   if (rootClass)
65870b57cec5SDimitry Andric     Result += "&OBJC_CLASS_$_";
65880b57cec5SDimitry Andric   else
65890b57cec5SDimitry Andric      Result += "&OBJC_METACLASS_$_";
65900b57cec5SDimitry Andric 
65910b57cec5SDimitry Andric   Result += SuperClass->getNameAsString(); Result += ";\n";
65920b57cec5SDimitry Andric 
65930b57cec5SDimitry Andric   Result += "\tOBJC_METACLASS_$_"; Result += CDecl->getNameAsString();
65940b57cec5SDimitry Andric   Result += ".cache = "; Result += "&_objc_empty_cache"; Result += ";\n";
65950b57cec5SDimitry Andric 
65960b57cec5SDimitry Andric   Result += "\tOBJC_CLASS_$_"; Result += CDecl->getNameAsString();
65970b57cec5SDimitry Andric   Result += ".isa = "; Result += "&OBJC_METACLASS_$_";
65980b57cec5SDimitry Andric   Result += CDecl->getNameAsString(); Result += ";\n";
65990b57cec5SDimitry Andric 
66000b57cec5SDimitry Andric   if (!rootClass) {
66010b57cec5SDimitry Andric     Result += "\tOBJC_CLASS_$_"; Result += CDecl->getNameAsString();
66020b57cec5SDimitry Andric     Result += ".superclass = "; Result += "&OBJC_CLASS_$_";
66030b57cec5SDimitry Andric     Result += SuperClass->getNameAsString(); Result += ";\n";
66040b57cec5SDimitry Andric   }
66050b57cec5SDimitry Andric 
66060b57cec5SDimitry Andric   Result += "\tOBJC_CLASS_$_"; Result += CDecl->getNameAsString();
66070b57cec5SDimitry Andric   Result += ".cache = "; Result += "&_objc_empty_cache"; Result += ";\n";
66080b57cec5SDimitry Andric   Result += "}\n";
66090b57cec5SDimitry Andric }
66100b57cec5SDimitry Andric 
Write_category_t(RewriteModernObjC & RewriteObj,ASTContext * Context,std::string & Result,ObjCCategoryDecl * CatDecl,ObjCInterfaceDecl * ClassDecl,ArrayRef<ObjCMethodDecl * > InstanceMethods,ArrayRef<ObjCMethodDecl * > ClassMethods,ArrayRef<ObjCProtocolDecl * > RefedProtocols,ArrayRef<ObjCPropertyDecl * > ClassProperties)66110b57cec5SDimitry Andric static void Write_category_t(RewriteModernObjC &RewriteObj, ASTContext *Context,
66120b57cec5SDimitry Andric                              std::string &Result,
66130b57cec5SDimitry Andric                              ObjCCategoryDecl *CatDecl,
66140b57cec5SDimitry Andric                              ObjCInterfaceDecl *ClassDecl,
66150b57cec5SDimitry Andric                              ArrayRef<ObjCMethodDecl *> InstanceMethods,
66160b57cec5SDimitry Andric                              ArrayRef<ObjCMethodDecl *> ClassMethods,
66170b57cec5SDimitry Andric                              ArrayRef<ObjCProtocolDecl *> RefedProtocols,
66180b57cec5SDimitry Andric                              ArrayRef<ObjCPropertyDecl *> ClassProperties) {
66190b57cec5SDimitry Andric   StringRef CatName = CatDecl->getName();
66200b57cec5SDimitry Andric   StringRef ClassName = ClassDecl->getName();
66210b57cec5SDimitry Andric   // must declare an extern class object in case this class is not implemented
66220b57cec5SDimitry Andric   // in this TU.
66230b57cec5SDimitry Andric   Result += "\n";
66240b57cec5SDimitry Andric   Result += "extern \"C\" ";
66250b57cec5SDimitry Andric   if (ClassDecl->getImplementation())
66260b57cec5SDimitry Andric     Result += "__declspec(dllexport) ";
66270b57cec5SDimitry Andric   else
66280b57cec5SDimitry Andric     Result += "__declspec(dllimport) ";
66290b57cec5SDimitry Andric 
66300b57cec5SDimitry Andric   Result += "struct _class_t ";
66310b57cec5SDimitry Andric   Result += "OBJC_CLASS_$_"; Result += ClassName;
66320b57cec5SDimitry Andric   Result += ";\n";
66330b57cec5SDimitry Andric 
66340b57cec5SDimitry Andric   Result += "\nstatic struct _category_t ";
66350b57cec5SDimitry Andric   Result += "_OBJC_$_CATEGORY_";
66360b57cec5SDimitry Andric   Result += ClassName; Result += "_$_"; Result += CatName;
66370b57cec5SDimitry Andric   Result += " __attribute__ ((used, section (\"__DATA,__objc_const\"))) = \n";
66380b57cec5SDimitry Andric   Result += "{\n";
66390b57cec5SDimitry Andric   Result += "\t\""; Result += ClassName; Result += "\",\n";
66400b57cec5SDimitry Andric   Result += "\t0, // &"; Result += "OBJC_CLASS_$_"; Result += ClassName;
66410b57cec5SDimitry Andric   Result += ",\n";
66420b57cec5SDimitry Andric   if (InstanceMethods.size() > 0) {
66430b57cec5SDimitry Andric     Result += "\t(const struct _method_list_t *)&";
66440b57cec5SDimitry Andric     Result += "_OBJC_$_CATEGORY_INSTANCE_METHODS_";
66450b57cec5SDimitry Andric     Result += ClassName; Result += "_$_"; Result += CatName;
66460b57cec5SDimitry Andric     Result += ",\n";
66470b57cec5SDimitry Andric   }
66480b57cec5SDimitry Andric   else
66490b57cec5SDimitry Andric     Result += "\t0,\n";
66500b57cec5SDimitry Andric 
66510b57cec5SDimitry Andric   if (ClassMethods.size() > 0) {
66520b57cec5SDimitry Andric     Result += "\t(const struct _method_list_t *)&";
66530b57cec5SDimitry Andric     Result += "_OBJC_$_CATEGORY_CLASS_METHODS_";
66540b57cec5SDimitry Andric     Result += ClassName; Result += "_$_"; Result += CatName;
66550b57cec5SDimitry Andric     Result += ",\n";
66560b57cec5SDimitry Andric   }
66570b57cec5SDimitry Andric   else
66580b57cec5SDimitry Andric     Result += "\t0,\n";
66590b57cec5SDimitry Andric 
66600b57cec5SDimitry Andric   if (RefedProtocols.size() > 0) {
66610b57cec5SDimitry Andric     Result += "\t(const struct _protocol_list_t *)&";
66620b57cec5SDimitry Andric     Result += "_OBJC_CATEGORY_PROTOCOLS_$_";
66630b57cec5SDimitry Andric     Result += ClassName; Result += "_$_"; Result += CatName;
66640b57cec5SDimitry Andric     Result += ",\n";
66650b57cec5SDimitry Andric   }
66660b57cec5SDimitry Andric   else
66670b57cec5SDimitry Andric     Result += "\t0,\n";
66680b57cec5SDimitry Andric 
66690b57cec5SDimitry Andric   if (ClassProperties.size() > 0) {
66700b57cec5SDimitry Andric     Result += "\t(const struct _prop_list_t *)&";  Result += "_OBJC_$_PROP_LIST_";
66710b57cec5SDimitry Andric     Result += ClassName; Result += "_$_"; Result += CatName;
66720b57cec5SDimitry Andric     Result += ",\n";
66730b57cec5SDimitry Andric   }
66740b57cec5SDimitry Andric   else
66750b57cec5SDimitry Andric     Result += "\t0,\n";
66760b57cec5SDimitry Andric 
66770b57cec5SDimitry Andric   Result += "};\n";
66780b57cec5SDimitry Andric 
66790b57cec5SDimitry Andric   // Add static function to initialize the class pointer in the category structure.
66800b57cec5SDimitry Andric   Result += "static void OBJC_CATEGORY_SETUP_$_";
66810b57cec5SDimitry Andric   Result += ClassDecl->getNameAsString();
66820b57cec5SDimitry Andric   Result += "_$_";
66830b57cec5SDimitry Andric   Result += CatName;
66840b57cec5SDimitry Andric   Result += "(void ) {\n";
66850b57cec5SDimitry Andric   Result += "\t_OBJC_$_CATEGORY_";
66860b57cec5SDimitry Andric   Result += ClassDecl->getNameAsString();
66870b57cec5SDimitry Andric   Result += "_$_";
66880b57cec5SDimitry Andric   Result += CatName;
66890b57cec5SDimitry Andric   Result += ".cls = "; Result += "&OBJC_CLASS_$_"; Result += ClassName;
66900b57cec5SDimitry Andric   Result += ";\n}\n";
66910b57cec5SDimitry Andric }
66920b57cec5SDimitry Andric 
Write__extendedMethodTypes_initializer(RewriteModernObjC & RewriteObj,ASTContext * Context,std::string & Result,ArrayRef<ObjCMethodDecl * > Methods,StringRef VarName,StringRef ProtocolName)66930b57cec5SDimitry Andric static void Write__extendedMethodTypes_initializer(RewriteModernObjC &RewriteObj,
66940b57cec5SDimitry Andric                                            ASTContext *Context, std::string &Result,
66950b57cec5SDimitry Andric                                            ArrayRef<ObjCMethodDecl *> Methods,
66960b57cec5SDimitry Andric                                            StringRef VarName,
66970b57cec5SDimitry Andric                                            StringRef ProtocolName) {
66980b57cec5SDimitry Andric   if (Methods.size() == 0)
66990b57cec5SDimitry Andric     return;
67000b57cec5SDimitry Andric 
67010b57cec5SDimitry Andric   Result += "\nstatic const char *";
67020b57cec5SDimitry Andric   Result += VarName; Result += ProtocolName;
67030b57cec5SDimitry Andric   Result += " [] __attribute__ ((used, section (\"__DATA,__objc_const\"))) = \n";
67040b57cec5SDimitry Andric   Result += "{\n";
67050b57cec5SDimitry Andric   for (unsigned i = 0, e = Methods.size(); i < e; i++) {
67060b57cec5SDimitry Andric     ObjCMethodDecl *MD = Methods[i];
67070b57cec5SDimitry Andric     std::string MethodTypeString =
67080b57cec5SDimitry Andric       Context->getObjCEncodingForMethodDecl(MD, true);
67090b57cec5SDimitry Andric     std::string QuoteMethodTypeString;
67100b57cec5SDimitry Andric     RewriteObj.QuoteDoublequotes(MethodTypeString, QuoteMethodTypeString);
67110b57cec5SDimitry Andric     Result += "\t\""; Result += QuoteMethodTypeString; Result += "\"";
67120b57cec5SDimitry Andric     if (i == e-1)
67130b57cec5SDimitry Andric       Result += "\n};\n";
67140b57cec5SDimitry Andric     else {
67150b57cec5SDimitry Andric       Result += ",\n";
67160b57cec5SDimitry Andric     }
67170b57cec5SDimitry Andric   }
67180b57cec5SDimitry Andric }
67190b57cec5SDimitry Andric 
Write_IvarOffsetVar(RewriteModernObjC & RewriteObj,ASTContext * Context,std::string & Result,ArrayRef<ObjCIvarDecl * > Ivars,ObjCInterfaceDecl * CDecl)67200b57cec5SDimitry Andric static void Write_IvarOffsetVar(RewriteModernObjC &RewriteObj,
67210b57cec5SDimitry Andric                                 ASTContext *Context,
67220b57cec5SDimitry Andric                                 std::string &Result,
67230b57cec5SDimitry Andric                                 ArrayRef<ObjCIvarDecl *> Ivars,
67240b57cec5SDimitry Andric                                 ObjCInterfaceDecl *CDecl) {
6725bdd1243dSDimitry Andric   // FIXME. visibility of offset symbols may have to be set; for Darwin
67260b57cec5SDimitry Andric   // this is what happens:
67270b57cec5SDimitry Andric   /**
67280b57cec5SDimitry Andric    if (Ivar->getAccessControl() == ObjCIvarDecl::Private ||
67290b57cec5SDimitry Andric        Ivar->getAccessControl() == ObjCIvarDecl::Package ||
67300b57cec5SDimitry Andric        Class->getVisibility() == HiddenVisibility)
67310b57cec5SDimitry Andric      Visibility should be: HiddenVisibility;
67320b57cec5SDimitry Andric    else
67330b57cec5SDimitry Andric      Visibility should be: DefaultVisibility;
67340b57cec5SDimitry Andric   */
67350b57cec5SDimitry Andric 
67360b57cec5SDimitry Andric   Result += "\n";
67370b57cec5SDimitry Andric   for (unsigned i =0, e = Ivars.size(); i < e; i++) {
67380b57cec5SDimitry Andric     ObjCIvarDecl *IvarDecl = Ivars[i];
67390b57cec5SDimitry Andric     if (Context->getLangOpts().MicrosoftExt)
67400b57cec5SDimitry Andric       Result += "__declspec(allocate(\".objc_ivar$B\")) ";
67410b57cec5SDimitry Andric 
67420b57cec5SDimitry Andric     if (!Context->getLangOpts().MicrosoftExt ||
67430b57cec5SDimitry Andric         IvarDecl->getAccessControl() == ObjCIvarDecl::Private ||
67440b57cec5SDimitry Andric         IvarDecl->getAccessControl() == ObjCIvarDecl::Package)
67450b57cec5SDimitry Andric       Result += "extern \"C\" unsigned long int ";
67460b57cec5SDimitry Andric     else
67470b57cec5SDimitry Andric       Result += "extern \"C\" __declspec(dllexport) unsigned long int ";
67480b57cec5SDimitry Andric     if (Ivars[i]->isBitField())
67490b57cec5SDimitry Andric       RewriteObj.ObjCIvarBitfieldGroupOffset(IvarDecl, Result);
67500b57cec5SDimitry Andric     else
67510b57cec5SDimitry Andric       WriteInternalIvarName(CDecl, IvarDecl, Result);
67520b57cec5SDimitry Andric     Result += " __attribute__ ((used, section (\"__DATA,__objc_ivar\")))";
67530b57cec5SDimitry Andric     Result += " = ";
67540b57cec5SDimitry Andric     RewriteObj.RewriteIvarOffsetComputation(IvarDecl, Result);
67550b57cec5SDimitry Andric     Result += ";\n";
67560b57cec5SDimitry Andric     if (Ivars[i]->isBitField()) {
67570b57cec5SDimitry Andric       // skip over rest of the ivar bitfields.
67580b57cec5SDimitry Andric       SKIP_BITFIELDS(i , e, Ivars);
67590b57cec5SDimitry Andric     }
67600b57cec5SDimitry Andric   }
67610b57cec5SDimitry Andric }
67620b57cec5SDimitry Andric 
Write__ivar_list_t_initializer(RewriteModernObjC & RewriteObj,ASTContext * Context,std::string & Result,ArrayRef<ObjCIvarDecl * > OriginalIvars,StringRef VarName,ObjCInterfaceDecl * CDecl)67630b57cec5SDimitry Andric static void Write__ivar_list_t_initializer(RewriteModernObjC &RewriteObj,
67640b57cec5SDimitry Andric                                            ASTContext *Context, std::string &Result,
67650b57cec5SDimitry Andric                                            ArrayRef<ObjCIvarDecl *> OriginalIvars,
67660b57cec5SDimitry Andric                                            StringRef VarName,
67670b57cec5SDimitry Andric                                            ObjCInterfaceDecl *CDecl) {
67680b57cec5SDimitry Andric   if (OriginalIvars.size() > 0) {
67690b57cec5SDimitry Andric     Write_IvarOffsetVar(RewriteObj, Context, Result, OriginalIvars, CDecl);
67700b57cec5SDimitry Andric     SmallVector<ObjCIvarDecl *, 8> Ivars;
67710b57cec5SDimitry Andric     // strip off all but the first ivar bitfield from each group of ivars.
67720b57cec5SDimitry Andric     // Such ivars in the ivar list table will be replaced by their grouping struct
67730b57cec5SDimitry Andric     // 'ivar'.
67740b57cec5SDimitry Andric     for (unsigned i = 0, e = OriginalIvars.size(); i < e; i++) {
67750b57cec5SDimitry Andric       if (OriginalIvars[i]->isBitField()) {
67760b57cec5SDimitry Andric         Ivars.push_back(OriginalIvars[i]);
67770b57cec5SDimitry Andric         // skip over rest of the ivar bitfields.
67780b57cec5SDimitry Andric         SKIP_BITFIELDS(i , e, OriginalIvars);
67790b57cec5SDimitry Andric       }
67800b57cec5SDimitry Andric       else
67810b57cec5SDimitry Andric         Ivars.push_back(OriginalIvars[i]);
67820b57cec5SDimitry Andric     }
67830b57cec5SDimitry Andric 
67840b57cec5SDimitry Andric     Result += "\nstatic ";
67850b57cec5SDimitry Andric     Write__ivar_list_t_TypeDecl(Result, Ivars.size());
67860b57cec5SDimitry Andric     Result += " "; Result += VarName;
67870b57cec5SDimitry Andric     Result += CDecl->getNameAsString();
67880b57cec5SDimitry Andric     Result += " __attribute__ ((used, section (\"__DATA,__objc_const\"))) = {\n";
67890b57cec5SDimitry Andric     Result += "\t"; Result += "sizeof(_ivar_t)"; Result += ",\n";
67900b57cec5SDimitry Andric     Result += "\t"; Result += utostr(Ivars.size()); Result += ",\n";
67910b57cec5SDimitry Andric     for (unsigned i =0, e = Ivars.size(); i < e; i++) {
67920b57cec5SDimitry Andric       ObjCIvarDecl *IvarDecl = Ivars[i];
67930b57cec5SDimitry Andric       if (i == 0)
67940b57cec5SDimitry Andric         Result += "\t{{";
67950b57cec5SDimitry Andric       else
67960b57cec5SDimitry Andric         Result += "\t {";
67970b57cec5SDimitry Andric       Result += "(unsigned long int *)&";
67980b57cec5SDimitry Andric       if (Ivars[i]->isBitField())
67990b57cec5SDimitry Andric         RewriteObj.ObjCIvarBitfieldGroupOffset(IvarDecl, Result);
68000b57cec5SDimitry Andric       else
68010b57cec5SDimitry Andric         WriteInternalIvarName(CDecl, IvarDecl, Result);
68020b57cec5SDimitry Andric       Result += ", ";
68030b57cec5SDimitry Andric 
68040b57cec5SDimitry Andric       Result += "\"";
68050b57cec5SDimitry Andric       if (Ivars[i]->isBitField())
68060b57cec5SDimitry Andric         RewriteObj.ObjCIvarBitfieldGroupDecl(Ivars[i], Result);
68070b57cec5SDimitry Andric       else
68080b57cec5SDimitry Andric         Result += IvarDecl->getName();
68090b57cec5SDimitry Andric       Result += "\", ";
68100b57cec5SDimitry Andric 
68110b57cec5SDimitry Andric       QualType IVQT = IvarDecl->getType();
68120b57cec5SDimitry Andric       if (IvarDecl->isBitField())
68130b57cec5SDimitry Andric         IVQT = RewriteObj.GetGroupRecordTypeForObjCIvarBitfield(IvarDecl);
68140b57cec5SDimitry Andric 
68150b57cec5SDimitry Andric       std::string IvarTypeString, QuoteIvarTypeString;
68160b57cec5SDimitry Andric       Context->getObjCEncodingForType(IVQT, IvarTypeString,
68170b57cec5SDimitry Andric                                       IvarDecl);
68180b57cec5SDimitry Andric       RewriteObj.QuoteDoublequotes(IvarTypeString, QuoteIvarTypeString);
68190b57cec5SDimitry Andric       Result += "\""; Result += QuoteIvarTypeString; Result += "\", ";
68200b57cec5SDimitry Andric 
68210b57cec5SDimitry Andric       // FIXME. this alignment represents the host alignment and need be changed to
68220b57cec5SDimitry Andric       // represent the target alignment.
68230b57cec5SDimitry Andric       unsigned Align = Context->getTypeAlign(IVQT)/8;
68240b57cec5SDimitry Andric       Align = llvm::Log2_32(Align);
68250b57cec5SDimitry Andric       Result += llvm::utostr(Align); Result += ", ";
68260b57cec5SDimitry Andric       CharUnits Size = Context->getTypeSizeInChars(IVQT);
68270b57cec5SDimitry Andric       Result += llvm::utostr(Size.getQuantity());
68280b57cec5SDimitry Andric       if (i  == e-1)
68290b57cec5SDimitry Andric         Result += "}}\n";
68300b57cec5SDimitry Andric       else
68310b57cec5SDimitry Andric         Result += "},\n";
68320b57cec5SDimitry Andric     }
68330b57cec5SDimitry Andric     Result += "};\n";
68340b57cec5SDimitry Andric   }
68350b57cec5SDimitry Andric }
68360b57cec5SDimitry Andric 
68370b57cec5SDimitry Andric /// RewriteObjCProtocolMetaData - Rewrite protocols meta-data.
RewriteObjCProtocolMetaData(ObjCProtocolDecl * PDecl,std::string & Result)68380b57cec5SDimitry Andric void RewriteModernObjC::RewriteObjCProtocolMetaData(ObjCProtocolDecl *PDecl,
68390b57cec5SDimitry Andric                                                     std::string &Result) {
68400b57cec5SDimitry Andric 
68410b57cec5SDimitry Andric   // Do not synthesize the protocol more than once.
68420b57cec5SDimitry Andric   if (ObjCSynthesizedProtocols.count(PDecl->getCanonicalDecl()))
68430b57cec5SDimitry Andric     return;
68440b57cec5SDimitry Andric   WriteModernMetadataDeclarations(Context, Result);
68450b57cec5SDimitry Andric 
68460b57cec5SDimitry Andric   if (ObjCProtocolDecl *Def = PDecl->getDefinition())
68470b57cec5SDimitry Andric     PDecl = Def;
68480b57cec5SDimitry Andric   // Must write out all protocol definitions in current qualifier list,
68490b57cec5SDimitry Andric   // and in their nested qualifiers before writing out current definition.
68500b57cec5SDimitry Andric   for (auto *I : PDecl->protocols())
68510b57cec5SDimitry Andric     RewriteObjCProtocolMetaData(I, Result);
68520b57cec5SDimitry Andric 
68530b57cec5SDimitry Andric   // Construct method lists.
68540b57cec5SDimitry Andric   std::vector<ObjCMethodDecl *> InstanceMethods, ClassMethods;
68550b57cec5SDimitry Andric   std::vector<ObjCMethodDecl *> OptInstanceMethods, OptClassMethods;
68560b57cec5SDimitry Andric   for (auto *MD : PDecl->instance_methods()) {
68575f757f3fSDimitry Andric     if (MD->getImplementationControl() == ObjCImplementationControl::Optional) {
68580b57cec5SDimitry Andric       OptInstanceMethods.push_back(MD);
68590b57cec5SDimitry Andric     } else {
68600b57cec5SDimitry Andric       InstanceMethods.push_back(MD);
68610b57cec5SDimitry Andric     }
68620b57cec5SDimitry Andric   }
68630b57cec5SDimitry Andric 
68640b57cec5SDimitry Andric   for (auto *MD : PDecl->class_methods()) {
68655f757f3fSDimitry Andric     if (MD->getImplementationControl() == ObjCImplementationControl::Optional) {
68660b57cec5SDimitry Andric       OptClassMethods.push_back(MD);
68670b57cec5SDimitry Andric     } else {
68680b57cec5SDimitry Andric       ClassMethods.push_back(MD);
68690b57cec5SDimitry Andric     }
68700b57cec5SDimitry Andric   }
68710b57cec5SDimitry Andric   std::vector<ObjCMethodDecl *> AllMethods;
68720b57cec5SDimitry Andric   for (unsigned i = 0, e = InstanceMethods.size(); i < e; i++)
68730b57cec5SDimitry Andric     AllMethods.push_back(InstanceMethods[i]);
68740b57cec5SDimitry Andric   for (unsigned i = 0, e = ClassMethods.size(); i < e; i++)
68750b57cec5SDimitry Andric     AllMethods.push_back(ClassMethods[i]);
68760b57cec5SDimitry Andric   for (unsigned i = 0, e = OptInstanceMethods.size(); i < e; i++)
68770b57cec5SDimitry Andric     AllMethods.push_back(OptInstanceMethods[i]);
68780b57cec5SDimitry Andric   for (unsigned i = 0, e = OptClassMethods.size(); i < e; i++)
68790b57cec5SDimitry Andric     AllMethods.push_back(OptClassMethods[i]);
68800b57cec5SDimitry Andric 
68810b57cec5SDimitry Andric   Write__extendedMethodTypes_initializer(*this, Context, Result,
68820b57cec5SDimitry Andric                                          AllMethods,
68830b57cec5SDimitry Andric                                          "_OBJC_PROTOCOL_METHOD_TYPES_",
68840b57cec5SDimitry Andric                                          PDecl->getNameAsString());
68850b57cec5SDimitry Andric   // Protocol's super protocol list
68860b57cec5SDimitry Andric   SmallVector<ObjCProtocolDecl *, 8> SuperProtocols(PDecl->protocols());
68870b57cec5SDimitry Andric   Write_protocol_list_initializer(Context, Result, SuperProtocols,
68880b57cec5SDimitry Andric                                   "_OBJC_PROTOCOL_REFS_",
68890b57cec5SDimitry Andric                                   PDecl->getNameAsString());
68900b57cec5SDimitry Andric 
68910b57cec5SDimitry Andric   Write_method_list_t_initializer(*this, Context, Result, InstanceMethods,
68920b57cec5SDimitry Andric                                   "_OBJC_PROTOCOL_INSTANCE_METHODS_",
68930b57cec5SDimitry Andric                                   PDecl->getNameAsString(), false);
68940b57cec5SDimitry Andric 
68950b57cec5SDimitry Andric   Write_method_list_t_initializer(*this, Context, Result, ClassMethods,
68960b57cec5SDimitry Andric                                   "_OBJC_PROTOCOL_CLASS_METHODS_",
68970b57cec5SDimitry Andric                                   PDecl->getNameAsString(), false);
68980b57cec5SDimitry Andric 
68990b57cec5SDimitry Andric   Write_method_list_t_initializer(*this, Context, Result, OptInstanceMethods,
69000b57cec5SDimitry Andric                                   "_OBJC_PROTOCOL_OPT_INSTANCE_METHODS_",
69010b57cec5SDimitry Andric                                   PDecl->getNameAsString(), false);
69020b57cec5SDimitry Andric 
69030b57cec5SDimitry Andric   Write_method_list_t_initializer(*this, Context, Result, OptClassMethods,
69040b57cec5SDimitry Andric                                   "_OBJC_PROTOCOL_OPT_CLASS_METHODS_",
69050b57cec5SDimitry Andric                                   PDecl->getNameAsString(), false);
69060b57cec5SDimitry Andric 
69070b57cec5SDimitry Andric   // Protocol's property metadata.
69080b57cec5SDimitry Andric   SmallVector<ObjCPropertyDecl *, 8> ProtocolProperties(
69090b57cec5SDimitry Andric       PDecl->instance_properties());
69100b57cec5SDimitry Andric   Write_prop_list_t_initializer(*this, Context, Result, ProtocolProperties,
69110b57cec5SDimitry Andric                                  /* Container */nullptr,
69120b57cec5SDimitry Andric                                  "_OBJC_PROTOCOL_PROPERTIES_",
69130b57cec5SDimitry Andric                                  PDecl->getNameAsString());
69140b57cec5SDimitry Andric 
69150b57cec5SDimitry Andric   // Writer out root metadata for current protocol: struct _protocol_t
69160b57cec5SDimitry Andric   Result += "\n";
69170b57cec5SDimitry Andric   if (LangOpts.MicrosoftExt)
69180b57cec5SDimitry Andric     Result += "static ";
69190b57cec5SDimitry Andric   Result += "struct _protocol_t _OBJC_PROTOCOL_";
69200b57cec5SDimitry Andric   Result += PDecl->getNameAsString();
69210b57cec5SDimitry Andric   Result += " __attribute__ ((used)) = {\n";
69220b57cec5SDimitry Andric   Result += "\t0,\n"; // id is; is null
69230b57cec5SDimitry Andric   Result += "\t\""; Result += PDecl->getNameAsString(); Result += "\",\n";
69240b57cec5SDimitry Andric   if (SuperProtocols.size() > 0) {
69250b57cec5SDimitry Andric     Result += "\t(const struct _protocol_list_t *)&"; Result += "_OBJC_PROTOCOL_REFS_";
69260b57cec5SDimitry Andric     Result += PDecl->getNameAsString(); Result += ",\n";
69270b57cec5SDimitry Andric   }
69280b57cec5SDimitry Andric   else
69290b57cec5SDimitry Andric     Result += "\t0,\n";
69300b57cec5SDimitry Andric   if (InstanceMethods.size() > 0) {
69310b57cec5SDimitry Andric     Result += "\t(const struct method_list_t *)&_OBJC_PROTOCOL_INSTANCE_METHODS_";
69320b57cec5SDimitry Andric     Result += PDecl->getNameAsString(); Result += ",\n";
69330b57cec5SDimitry Andric   }
69340b57cec5SDimitry Andric   else
69350b57cec5SDimitry Andric     Result += "\t0,\n";
69360b57cec5SDimitry Andric 
69370b57cec5SDimitry Andric   if (ClassMethods.size() > 0) {
69380b57cec5SDimitry Andric     Result += "\t(const struct method_list_t *)&_OBJC_PROTOCOL_CLASS_METHODS_";
69390b57cec5SDimitry Andric     Result += PDecl->getNameAsString(); Result += ",\n";
69400b57cec5SDimitry Andric   }
69410b57cec5SDimitry Andric   else
69420b57cec5SDimitry Andric     Result += "\t0,\n";
69430b57cec5SDimitry Andric 
69440b57cec5SDimitry Andric   if (OptInstanceMethods.size() > 0) {
69450b57cec5SDimitry Andric     Result += "\t(const struct method_list_t *)&_OBJC_PROTOCOL_OPT_INSTANCE_METHODS_";
69460b57cec5SDimitry Andric     Result += PDecl->getNameAsString(); Result += ",\n";
69470b57cec5SDimitry Andric   }
69480b57cec5SDimitry Andric   else
69490b57cec5SDimitry Andric     Result += "\t0,\n";
69500b57cec5SDimitry Andric 
69510b57cec5SDimitry Andric   if (OptClassMethods.size() > 0) {
69520b57cec5SDimitry Andric     Result += "\t(const struct method_list_t *)&_OBJC_PROTOCOL_OPT_CLASS_METHODS_";
69530b57cec5SDimitry Andric     Result += PDecl->getNameAsString(); Result += ",\n";
69540b57cec5SDimitry Andric   }
69550b57cec5SDimitry Andric   else
69560b57cec5SDimitry Andric     Result += "\t0,\n";
69570b57cec5SDimitry Andric 
69580b57cec5SDimitry Andric   if (ProtocolProperties.size() > 0) {
69590b57cec5SDimitry Andric     Result += "\t(const struct _prop_list_t *)&_OBJC_PROTOCOL_PROPERTIES_";
69600b57cec5SDimitry Andric     Result += PDecl->getNameAsString(); Result += ",\n";
69610b57cec5SDimitry Andric   }
69620b57cec5SDimitry Andric   else
69630b57cec5SDimitry Andric     Result += "\t0,\n";
69640b57cec5SDimitry Andric 
69650b57cec5SDimitry Andric   Result += "\t"; Result += "sizeof(_protocol_t)"; Result += ",\n";
69660b57cec5SDimitry Andric   Result += "\t0,\n";
69670b57cec5SDimitry Andric 
69680b57cec5SDimitry Andric   if (AllMethods.size() > 0) {
69690b57cec5SDimitry Andric     Result += "\t(const char **)&"; Result += "_OBJC_PROTOCOL_METHOD_TYPES_";
69700b57cec5SDimitry Andric     Result += PDecl->getNameAsString();
69710b57cec5SDimitry Andric     Result += "\n};\n";
69720b57cec5SDimitry Andric   }
69730b57cec5SDimitry Andric   else
69740b57cec5SDimitry Andric     Result += "\t0\n};\n";
69750b57cec5SDimitry Andric 
69760b57cec5SDimitry Andric   if (LangOpts.MicrosoftExt)
69770b57cec5SDimitry Andric     Result += "static ";
69780b57cec5SDimitry Andric   Result += "struct _protocol_t *";
69790b57cec5SDimitry Andric   Result += "_OBJC_LABEL_PROTOCOL_$_"; Result += PDecl->getNameAsString();
69800b57cec5SDimitry Andric   Result += " = &_OBJC_PROTOCOL_"; Result += PDecl->getNameAsString();
69810b57cec5SDimitry Andric   Result += ";\n";
69820b57cec5SDimitry Andric 
69830b57cec5SDimitry Andric   // Mark this protocol as having been generated.
69840b57cec5SDimitry Andric   if (!ObjCSynthesizedProtocols.insert(PDecl->getCanonicalDecl()).second)
69850b57cec5SDimitry Andric     llvm_unreachable("protocol already synthesized");
69860b57cec5SDimitry Andric }
69870b57cec5SDimitry Andric 
69880b57cec5SDimitry Andric /// hasObjCExceptionAttribute - Return true if this class or any super
69890b57cec5SDimitry Andric /// class has the __objc_exception__ attribute.
69900b57cec5SDimitry Andric /// FIXME. Move this to ASTContext.cpp as it is also used for IRGen.
hasObjCExceptionAttribute(ASTContext & Context,const ObjCInterfaceDecl * OID)69910b57cec5SDimitry Andric static bool hasObjCExceptionAttribute(ASTContext &Context,
69920b57cec5SDimitry Andric                                       const ObjCInterfaceDecl *OID) {
69930b57cec5SDimitry Andric   if (OID->hasAttr<ObjCExceptionAttr>())
69940b57cec5SDimitry Andric     return true;
69950b57cec5SDimitry Andric   if (const ObjCInterfaceDecl *Super = OID->getSuperClass())
69960b57cec5SDimitry Andric     return hasObjCExceptionAttribute(Context, Super);
69970b57cec5SDimitry Andric   return false;
69980b57cec5SDimitry Andric }
69990b57cec5SDimitry Andric 
RewriteObjCClassMetaData(ObjCImplementationDecl * IDecl,std::string & Result)70000b57cec5SDimitry Andric void RewriteModernObjC::RewriteObjCClassMetaData(ObjCImplementationDecl *IDecl,
70010b57cec5SDimitry Andric                                            std::string &Result) {
70020b57cec5SDimitry Andric   ObjCInterfaceDecl *CDecl = IDecl->getClassInterface();
70030b57cec5SDimitry Andric 
70040b57cec5SDimitry Andric   // Explicitly declared @interface's are already synthesized.
70050b57cec5SDimitry Andric   if (CDecl->isImplicitInterfaceDecl())
70060b57cec5SDimitry Andric     assert(false &&
70070b57cec5SDimitry Andric            "Legacy implicit interface rewriting not supported in moder abi");
70080b57cec5SDimitry Andric 
70090b57cec5SDimitry Andric   WriteModernMetadataDeclarations(Context, Result);
70100b57cec5SDimitry Andric   SmallVector<ObjCIvarDecl *, 8> IVars;
70110b57cec5SDimitry Andric 
70120b57cec5SDimitry Andric   for (ObjCIvarDecl *IVD = CDecl->all_declared_ivar_begin();
70130b57cec5SDimitry Andric       IVD; IVD = IVD->getNextIvar()) {
70140b57cec5SDimitry Andric     // Ignore unnamed bit-fields.
70150b57cec5SDimitry Andric     if (!IVD->getDeclName())
70160b57cec5SDimitry Andric       continue;
70170b57cec5SDimitry Andric     IVars.push_back(IVD);
70180b57cec5SDimitry Andric   }
70190b57cec5SDimitry Andric 
70200b57cec5SDimitry Andric   Write__ivar_list_t_initializer(*this, Context, Result, IVars,
70210b57cec5SDimitry Andric                                  "_OBJC_$_INSTANCE_VARIABLES_",
70220b57cec5SDimitry Andric                                  CDecl);
70230b57cec5SDimitry Andric 
70240b57cec5SDimitry Andric   // Build _objc_method_list for class's instance methods if needed
70250b57cec5SDimitry Andric   SmallVector<ObjCMethodDecl *, 32> InstanceMethods(IDecl->instance_methods());
70260b57cec5SDimitry Andric 
70270b57cec5SDimitry Andric   // If any of our property implementations have associated getters or
70280b57cec5SDimitry Andric   // setters, produce metadata for them as well.
70290b57cec5SDimitry Andric   for (const auto *Prop : IDecl->property_impls()) {
70300b57cec5SDimitry Andric     if (Prop->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic)
70310b57cec5SDimitry Andric       continue;
70320b57cec5SDimitry Andric     if (!Prop->getPropertyIvarDecl())
70330b57cec5SDimitry Andric       continue;
70340b57cec5SDimitry Andric     ObjCPropertyDecl *PD = Prop->getPropertyDecl();
70350b57cec5SDimitry Andric     if (!PD)
70360b57cec5SDimitry Andric       continue;
7037480093f4SDimitry Andric     if (ObjCMethodDecl *Getter = Prop->getGetterMethodDecl())
70380b57cec5SDimitry Andric       if (mustSynthesizeSetterGetterMethod(IDecl, PD, true /*getter*/))
70390b57cec5SDimitry Andric         InstanceMethods.push_back(Getter);
70400b57cec5SDimitry Andric     if (PD->isReadOnly())
70410b57cec5SDimitry Andric       continue;
7042480093f4SDimitry Andric     if (ObjCMethodDecl *Setter = Prop->getSetterMethodDecl())
70430b57cec5SDimitry Andric       if (mustSynthesizeSetterGetterMethod(IDecl, PD, false /*setter*/))
70440b57cec5SDimitry Andric         InstanceMethods.push_back(Setter);
70450b57cec5SDimitry Andric   }
70460b57cec5SDimitry Andric 
70470b57cec5SDimitry Andric   Write_method_list_t_initializer(*this, Context, Result, InstanceMethods,
70480b57cec5SDimitry Andric                                   "_OBJC_$_INSTANCE_METHODS_",
70490b57cec5SDimitry Andric                                   IDecl->getNameAsString(), true);
70500b57cec5SDimitry Andric 
70510b57cec5SDimitry Andric   SmallVector<ObjCMethodDecl *, 32> ClassMethods(IDecl->class_methods());
70520b57cec5SDimitry Andric 
70530b57cec5SDimitry Andric   Write_method_list_t_initializer(*this, Context, Result, ClassMethods,
70540b57cec5SDimitry Andric                                   "_OBJC_$_CLASS_METHODS_",
70550b57cec5SDimitry Andric                                   IDecl->getNameAsString(), true);
70560b57cec5SDimitry Andric 
70570b57cec5SDimitry Andric   // Protocols referenced in class declaration?
70580b57cec5SDimitry Andric   // Protocol's super protocol list
70590b57cec5SDimitry Andric   std::vector<ObjCProtocolDecl *> RefedProtocols;
70600b57cec5SDimitry Andric   const ObjCList<ObjCProtocolDecl> &Protocols = CDecl->getReferencedProtocols();
70610b57cec5SDimitry Andric   for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
70620b57cec5SDimitry Andric        E = Protocols.end();
70630b57cec5SDimitry Andric        I != E; ++I) {
70640b57cec5SDimitry Andric     RefedProtocols.push_back(*I);
70650b57cec5SDimitry Andric     // Must write out all protocol definitions in current qualifier list,
70660b57cec5SDimitry Andric     // and in their nested qualifiers before writing out current definition.
70670b57cec5SDimitry Andric     RewriteObjCProtocolMetaData(*I, Result);
70680b57cec5SDimitry Andric   }
70690b57cec5SDimitry Andric 
70700b57cec5SDimitry Andric   Write_protocol_list_initializer(Context, Result,
70710b57cec5SDimitry Andric                                   RefedProtocols,
70720b57cec5SDimitry Andric                                   "_OBJC_CLASS_PROTOCOLS_$_",
70730b57cec5SDimitry Andric                                   IDecl->getNameAsString());
70740b57cec5SDimitry Andric 
70750b57cec5SDimitry Andric   // Protocol's property metadata.
70760b57cec5SDimitry Andric   SmallVector<ObjCPropertyDecl *, 8> ClassProperties(
70770b57cec5SDimitry Andric       CDecl->instance_properties());
70780b57cec5SDimitry Andric   Write_prop_list_t_initializer(*this, Context, Result, ClassProperties,
70790b57cec5SDimitry Andric                                  /* Container */IDecl,
70800b57cec5SDimitry Andric                                  "_OBJC_$_PROP_LIST_",
70810b57cec5SDimitry Andric                                  CDecl->getNameAsString());
70820b57cec5SDimitry Andric 
70830b57cec5SDimitry Andric   // Data for initializing _class_ro_t  metaclass meta-data
70840b57cec5SDimitry Andric   uint32_t flags = CLS_META;
70850b57cec5SDimitry Andric   std::string InstanceSize;
70860b57cec5SDimitry Andric   std::string InstanceStart;
70870b57cec5SDimitry Andric 
70880b57cec5SDimitry Andric   bool classIsHidden = CDecl->getVisibility() == HiddenVisibility;
70890b57cec5SDimitry Andric   if (classIsHidden)
70900b57cec5SDimitry Andric     flags |= OBJC2_CLS_HIDDEN;
70910b57cec5SDimitry Andric 
70920b57cec5SDimitry Andric   if (!CDecl->getSuperClass())
70930b57cec5SDimitry Andric     // class is root
70940b57cec5SDimitry Andric     flags |= CLS_ROOT;
70950b57cec5SDimitry Andric   InstanceSize = "sizeof(struct _class_t)";
70960b57cec5SDimitry Andric   InstanceStart = InstanceSize;
70970b57cec5SDimitry Andric   Write__class_ro_t_initializer(Context, Result, flags,
70980b57cec5SDimitry Andric                                 InstanceStart, InstanceSize,
70990b57cec5SDimitry Andric                                 ClassMethods,
71000b57cec5SDimitry Andric                                 nullptr,
71010b57cec5SDimitry Andric                                 nullptr,
71020b57cec5SDimitry Andric                                 nullptr,
71030b57cec5SDimitry Andric                                 "_OBJC_METACLASS_RO_$_",
71040b57cec5SDimitry Andric                                 CDecl->getNameAsString());
71050b57cec5SDimitry Andric 
71060b57cec5SDimitry Andric   // Data for initializing _class_ro_t meta-data
71070b57cec5SDimitry Andric   flags = CLS;
71080b57cec5SDimitry Andric   if (classIsHidden)
71090b57cec5SDimitry Andric     flags |= OBJC2_CLS_HIDDEN;
71100b57cec5SDimitry Andric 
71110b57cec5SDimitry Andric   if (hasObjCExceptionAttribute(*Context, CDecl))
71120b57cec5SDimitry Andric     flags |= CLS_EXCEPTION;
71130b57cec5SDimitry Andric 
71140b57cec5SDimitry Andric   if (!CDecl->getSuperClass())
71150b57cec5SDimitry Andric     // class is root
71160b57cec5SDimitry Andric     flags |= CLS_ROOT;
71170b57cec5SDimitry Andric 
71180b57cec5SDimitry Andric   InstanceSize.clear();
71190b57cec5SDimitry Andric   InstanceStart.clear();
71200b57cec5SDimitry Andric   if (!ObjCSynthesizedStructs.count(CDecl)) {
71210b57cec5SDimitry Andric     InstanceSize = "0";
71220b57cec5SDimitry Andric     InstanceStart = "0";
71230b57cec5SDimitry Andric   }
71240b57cec5SDimitry Andric   else {
71250b57cec5SDimitry Andric     InstanceSize = "sizeof(struct ";
71260b57cec5SDimitry Andric     InstanceSize += CDecl->getNameAsString();
71270b57cec5SDimitry Andric     InstanceSize += "_IMPL)";
71280b57cec5SDimitry Andric 
71290b57cec5SDimitry Andric     ObjCIvarDecl *IVD = CDecl->all_declared_ivar_begin();
71300b57cec5SDimitry Andric     if (IVD) {
71310b57cec5SDimitry Andric       RewriteIvarOffsetComputation(IVD, InstanceStart);
71320b57cec5SDimitry Andric     }
71330b57cec5SDimitry Andric     else
71340b57cec5SDimitry Andric       InstanceStart = InstanceSize;
71350b57cec5SDimitry Andric   }
71360b57cec5SDimitry Andric   Write__class_ro_t_initializer(Context, Result, flags,
71370b57cec5SDimitry Andric                                 InstanceStart, InstanceSize,
71380b57cec5SDimitry Andric                                 InstanceMethods,
71390b57cec5SDimitry Andric                                 RefedProtocols,
71400b57cec5SDimitry Andric                                 IVars,
71410b57cec5SDimitry Andric                                 ClassProperties,
71420b57cec5SDimitry Andric                                 "_OBJC_CLASS_RO_$_",
71430b57cec5SDimitry Andric                                 CDecl->getNameAsString());
71440b57cec5SDimitry Andric 
71450b57cec5SDimitry Andric   Write_class_t(Context, Result,
71460b57cec5SDimitry Andric                 "OBJC_METACLASS_$_",
71470b57cec5SDimitry Andric                 CDecl, /*metaclass*/true);
71480b57cec5SDimitry Andric 
71490b57cec5SDimitry Andric   Write_class_t(Context, Result,
71500b57cec5SDimitry Andric                 "OBJC_CLASS_$_",
71510b57cec5SDimitry Andric                 CDecl, /*metaclass*/false);
71520b57cec5SDimitry Andric 
71530b57cec5SDimitry Andric   if (ImplementationIsNonLazy(IDecl))
71540b57cec5SDimitry Andric     DefinedNonLazyClasses.push_back(CDecl);
71550b57cec5SDimitry Andric }
71560b57cec5SDimitry Andric 
RewriteClassSetupInitHook(std::string & Result)71570b57cec5SDimitry Andric void RewriteModernObjC::RewriteClassSetupInitHook(std::string &Result) {
71580b57cec5SDimitry Andric   int ClsDefCount = ClassImplementation.size();
71590b57cec5SDimitry Andric   if (!ClsDefCount)
71600b57cec5SDimitry Andric     return;
71610b57cec5SDimitry Andric   Result += "#pragma section(\".objc_inithooks$B\", long, read, write)\n";
71620b57cec5SDimitry Andric   Result += "__declspec(allocate(\".objc_inithooks$B\")) ";
71630b57cec5SDimitry Andric   Result += "static void *OBJC_CLASS_SETUP[] = {\n";
71640b57cec5SDimitry Andric   for (int i = 0; i < ClsDefCount; i++) {
71650b57cec5SDimitry Andric     ObjCImplementationDecl *IDecl = ClassImplementation[i];
71660b57cec5SDimitry Andric     ObjCInterfaceDecl *CDecl = IDecl->getClassInterface();
71670b57cec5SDimitry Andric     Result += "\t(void *)&OBJC_CLASS_SETUP_$_";
71680b57cec5SDimitry Andric     Result  += CDecl->getName(); Result += ",\n";
71690b57cec5SDimitry Andric   }
71700b57cec5SDimitry Andric   Result += "};\n";
71710b57cec5SDimitry Andric }
71720b57cec5SDimitry Andric 
RewriteMetaDataIntoBuffer(std::string & Result)71730b57cec5SDimitry Andric void RewriteModernObjC::RewriteMetaDataIntoBuffer(std::string &Result) {
71740b57cec5SDimitry Andric   int ClsDefCount = ClassImplementation.size();
71750b57cec5SDimitry Andric   int CatDefCount = CategoryImplementation.size();
71760b57cec5SDimitry Andric 
71770b57cec5SDimitry Andric   // For each implemented class, write out all its meta data.
71780b57cec5SDimitry Andric   for (int i = 0; i < ClsDefCount; i++)
71790b57cec5SDimitry Andric     RewriteObjCClassMetaData(ClassImplementation[i], Result);
71800b57cec5SDimitry Andric 
71810b57cec5SDimitry Andric   RewriteClassSetupInitHook(Result);
71820b57cec5SDimitry Andric 
71830b57cec5SDimitry Andric   // For each implemented category, write out all its meta data.
71840b57cec5SDimitry Andric   for (int i = 0; i < CatDefCount; i++)
71850b57cec5SDimitry Andric     RewriteObjCCategoryImplDecl(CategoryImplementation[i], Result);
71860b57cec5SDimitry Andric 
71870b57cec5SDimitry Andric   RewriteCategorySetupInitHook(Result);
71880b57cec5SDimitry Andric 
71890b57cec5SDimitry Andric   if (ClsDefCount > 0) {
71900b57cec5SDimitry Andric     if (LangOpts.MicrosoftExt)
71910b57cec5SDimitry Andric       Result += "__declspec(allocate(\".objc_classlist$B\")) ";
71920b57cec5SDimitry Andric     Result += "static struct _class_t *L_OBJC_LABEL_CLASS_$ [";
71930b57cec5SDimitry Andric     Result += llvm::utostr(ClsDefCount); Result += "]";
71940b57cec5SDimitry Andric     Result +=
71950b57cec5SDimitry Andric       " __attribute__((used, section (\"__DATA, __objc_classlist,"
71960b57cec5SDimitry Andric       "regular,no_dead_strip\")))= {\n";
71970b57cec5SDimitry Andric     for (int i = 0; i < ClsDefCount; i++) {
71980b57cec5SDimitry Andric       Result += "\t&OBJC_CLASS_$_";
71990b57cec5SDimitry Andric       Result += ClassImplementation[i]->getNameAsString();
72000b57cec5SDimitry Andric       Result += ",\n";
72010b57cec5SDimitry Andric     }
72020b57cec5SDimitry Andric     Result += "};\n";
72030b57cec5SDimitry Andric 
72040b57cec5SDimitry Andric     if (!DefinedNonLazyClasses.empty()) {
72050b57cec5SDimitry Andric       if (LangOpts.MicrosoftExt)
72060b57cec5SDimitry Andric         Result += "__declspec(allocate(\".objc_nlclslist$B\")) \n";
72070b57cec5SDimitry Andric       Result += "static struct _class_t *_OBJC_LABEL_NONLAZY_CLASS_$[] = {\n\t";
72080b57cec5SDimitry Andric       for (unsigned i = 0, e = DefinedNonLazyClasses.size(); i < e; i++) {
72090b57cec5SDimitry Andric         Result += "\t&OBJC_CLASS_$_"; Result += DefinedNonLazyClasses[i]->getNameAsString();
72100b57cec5SDimitry Andric         Result += ",\n";
72110b57cec5SDimitry Andric       }
72120b57cec5SDimitry Andric       Result += "};\n";
72130b57cec5SDimitry Andric     }
72140b57cec5SDimitry Andric   }
72150b57cec5SDimitry Andric 
72160b57cec5SDimitry Andric   if (CatDefCount > 0) {
72170b57cec5SDimitry Andric     if (LangOpts.MicrosoftExt)
72180b57cec5SDimitry Andric       Result += "__declspec(allocate(\".objc_catlist$B\")) ";
72190b57cec5SDimitry Andric     Result += "static struct _category_t *L_OBJC_LABEL_CATEGORY_$ [";
72200b57cec5SDimitry Andric     Result += llvm::utostr(CatDefCount); Result += "]";
72210b57cec5SDimitry Andric     Result +=
72220b57cec5SDimitry Andric     " __attribute__((used, section (\"__DATA, __objc_catlist,"
72230b57cec5SDimitry Andric     "regular,no_dead_strip\")))= {\n";
72240b57cec5SDimitry Andric     for (int i = 0; i < CatDefCount; i++) {
72250b57cec5SDimitry Andric       Result += "\t&_OBJC_$_CATEGORY_";
72260b57cec5SDimitry Andric       Result +=
72270b57cec5SDimitry Andric         CategoryImplementation[i]->getClassInterface()->getNameAsString();
72280b57cec5SDimitry Andric       Result += "_$_";
72290b57cec5SDimitry Andric       Result += CategoryImplementation[i]->getNameAsString();
72300b57cec5SDimitry Andric       Result += ",\n";
72310b57cec5SDimitry Andric     }
72320b57cec5SDimitry Andric     Result += "};\n";
72330b57cec5SDimitry Andric   }
72340b57cec5SDimitry Andric 
72350b57cec5SDimitry Andric   if (!DefinedNonLazyCategories.empty()) {
72360b57cec5SDimitry Andric     if (LangOpts.MicrosoftExt)
72370b57cec5SDimitry Andric       Result += "__declspec(allocate(\".objc_nlcatlist$B\")) \n";
72380b57cec5SDimitry Andric     Result += "static struct _category_t *_OBJC_LABEL_NONLAZY_CATEGORY_$[] = {\n\t";
72390b57cec5SDimitry Andric     for (unsigned i = 0, e = DefinedNonLazyCategories.size(); i < e; i++) {
72400b57cec5SDimitry Andric       Result += "\t&_OBJC_$_CATEGORY_";
72410b57cec5SDimitry Andric       Result +=
72420b57cec5SDimitry Andric         DefinedNonLazyCategories[i]->getClassInterface()->getNameAsString();
72430b57cec5SDimitry Andric       Result += "_$_";
72440b57cec5SDimitry Andric       Result += DefinedNonLazyCategories[i]->getNameAsString();
72450b57cec5SDimitry Andric       Result += ",\n";
72460b57cec5SDimitry Andric     }
72470b57cec5SDimitry Andric     Result += "};\n";
72480b57cec5SDimitry Andric   }
72490b57cec5SDimitry Andric }
72500b57cec5SDimitry Andric 
WriteImageInfo(std::string & Result)72510b57cec5SDimitry Andric void RewriteModernObjC::WriteImageInfo(std::string &Result) {
72520b57cec5SDimitry Andric   if (LangOpts.MicrosoftExt)
72530b57cec5SDimitry Andric     Result += "__declspec(allocate(\".objc_imageinfo$B\")) \n";
72540b57cec5SDimitry Andric 
72550b57cec5SDimitry Andric   Result += "static struct IMAGE_INFO { unsigned version; unsigned flag; } ";
72560b57cec5SDimitry Andric   // version 0, ObjCABI is 2
72570b57cec5SDimitry Andric   Result += "_OBJC_IMAGE_INFO = { 0, 2 };\n";
72580b57cec5SDimitry Andric }
72590b57cec5SDimitry Andric 
72600b57cec5SDimitry Andric /// RewriteObjCCategoryImplDecl - Rewrite metadata for each category
72610b57cec5SDimitry Andric /// implementation.
RewriteObjCCategoryImplDecl(ObjCCategoryImplDecl * IDecl,std::string & Result)72620b57cec5SDimitry Andric void RewriteModernObjC::RewriteObjCCategoryImplDecl(ObjCCategoryImplDecl *IDecl,
72630b57cec5SDimitry Andric                                               std::string &Result) {
72640b57cec5SDimitry Andric   WriteModernMetadataDeclarations(Context, Result);
72650b57cec5SDimitry Andric   ObjCInterfaceDecl *ClassDecl = IDecl->getClassInterface();
72660b57cec5SDimitry Andric   // Find category declaration for this implementation.
72670b57cec5SDimitry Andric   ObjCCategoryDecl *CDecl
72680b57cec5SDimitry Andric     = ClassDecl->FindCategoryDeclaration(IDecl->getIdentifier());
72690b57cec5SDimitry Andric 
72700b57cec5SDimitry Andric   std::string FullCategoryName = ClassDecl->getNameAsString();
72710b57cec5SDimitry Andric   FullCategoryName += "_$_";
72720b57cec5SDimitry Andric   FullCategoryName += CDecl->getNameAsString();
72730b57cec5SDimitry Andric 
72740b57cec5SDimitry Andric   // Build _objc_method_list for class's instance methods if needed
72750b57cec5SDimitry Andric   SmallVector<ObjCMethodDecl *, 32> InstanceMethods(IDecl->instance_methods());
72760b57cec5SDimitry Andric 
72770b57cec5SDimitry Andric   // If any of our property implementations have associated getters or
72780b57cec5SDimitry Andric   // setters, produce metadata for them as well.
72790b57cec5SDimitry Andric   for (const auto *Prop : IDecl->property_impls()) {
72800b57cec5SDimitry Andric     if (Prop->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic)
72810b57cec5SDimitry Andric       continue;
72820b57cec5SDimitry Andric     if (!Prop->getPropertyIvarDecl())
72830b57cec5SDimitry Andric       continue;
72840b57cec5SDimitry Andric     ObjCPropertyDecl *PD = Prop->getPropertyDecl();
72850b57cec5SDimitry Andric     if (!PD)
72860b57cec5SDimitry Andric       continue;
7287480093f4SDimitry Andric     if (ObjCMethodDecl *Getter = Prop->getGetterMethodDecl())
72880b57cec5SDimitry Andric       InstanceMethods.push_back(Getter);
72890b57cec5SDimitry Andric     if (PD->isReadOnly())
72900b57cec5SDimitry Andric       continue;
7291480093f4SDimitry Andric     if (ObjCMethodDecl *Setter = Prop->getSetterMethodDecl())
72920b57cec5SDimitry Andric       InstanceMethods.push_back(Setter);
72930b57cec5SDimitry Andric   }
72940b57cec5SDimitry Andric 
72950b57cec5SDimitry Andric   Write_method_list_t_initializer(*this, Context, Result, InstanceMethods,
72960b57cec5SDimitry Andric                                   "_OBJC_$_CATEGORY_INSTANCE_METHODS_",
72970b57cec5SDimitry Andric                                   FullCategoryName, true);
72980b57cec5SDimitry Andric 
72990b57cec5SDimitry Andric   SmallVector<ObjCMethodDecl *, 32> ClassMethods(IDecl->class_methods());
73000b57cec5SDimitry Andric 
73010b57cec5SDimitry Andric   Write_method_list_t_initializer(*this, Context, Result, ClassMethods,
73020b57cec5SDimitry Andric                                   "_OBJC_$_CATEGORY_CLASS_METHODS_",
73030b57cec5SDimitry Andric                                   FullCategoryName, true);
73040b57cec5SDimitry Andric 
73050b57cec5SDimitry Andric   // Protocols referenced in class declaration?
73060b57cec5SDimitry Andric   // Protocol's super protocol list
73070b57cec5SDimitry Andric   SmallVector<ObjCProtocolDecl *, 8> RefedProtocols(CDecl->protocols());
73080b57cec5SDimitry Andric   for (auto *I : CDecl->protocols())
73090b57cec5SDimitry Andric     // Must write out all protocol definitions in current qualifier list,
73100b57cec5SDimitry Andric     // and in their nested qualifiers before writing out current definition.
73110b57cec5SDimitry Andric     RewriteObjCProtocolMetaData(I, Result);
73120b57cec5SDimitry Andric 
73130b57cec5SDimitry Andric   Write_protocol_list_initializer(Context, Result,
73140b57cec5SDimitry Andric                                   RefedProtocols,
73150b57cec5SDimitry Andric                                   "_OBJC_CATEGORY_PROTOCOLS_$_",
73160b57cec5SDimitry Andric                                   FullCategoryName);
73170b57cec5SDimitry Andric 
73180b57cec5SDimitry Andric   // Protocol's property metadata.
73190b57cec5SDimitry Andric   SmallVector<ObjCPropertyDecl *, 8> ClassProperties(
73200b57cec5SDimitry Andric       CDecl->instance_properties());
73210b57cec5SDimitry Andric   Write_prop_list_t_initializer(*this, Context, Result, ClassProperties,
73220b57cec5SDimitry Andric                                 /* Container */IDecl,
73230b57cec5SDimitry Andric                                 "_OBJC_$_PROP_LIST_",
73240b57cec5SDimitry Andric                                 FullCategoryName);
73250b57cec5SDimitry Andric 
73260b57cec5SDimitry Andric   Write_category_t(*this, Context, Result,
73270b57cec5SDimitry Andric                    CDecl,
73280b57cec5SDimitry Andric                    ClassDecl,
73290b57cec5SDimitry Andric                    InstanceMethods,
73300b57cec5SDimitry Andric                    ClassMethods,
73310b57cec5SDimitry Andric                    RefedProtocols,
73320b57cec5SDimitry Andric                    ClassProperties);
73330b57cec5SDimitry Andric 
73340b57cec5SDimitry Andric   // Determine if this category is also "non-lazy".
73350b57cec5SDimitry Andric   if (ImplementationIsNonLazy(IDecl))
73360b57cec5SDimitry Andric     DefinedNonLazyCategories.push_back(CDecl);
73370b57cec5SDimitry Andric }
73380b57cec5SDimitry Andric 
RewriteCategorySetupInitHook(std::string & Result)73390b57cec5SDimitry Andric void RewriteModernObjC::RewriteCategorySetupInitHook(std::string &Result) {
73400b57cec5SDimitry Andric   int CatDefCount = CategoryImplementation.size();
73410b57cec5SDimitry Andric   if (!CatDefCount)
73420b57cec5SDimitry Andric     return;
73430b57cec5SDimitry Andric   Result += "#pragma section(\".objc_inithooks$B\", long, read, write)\n";
73440b57cec5SDimitry Andric   Result += "__declspec(allocate(\".objc_inithooks$B\")) ";
73450b57cec5SDimitry Andric   Result += "static void *OBJC_CATEGORY_SETUP[] = {\n";
73460b57cec5SDimitry Andric   for (int i = 0; i < CatDefCount; i++) {
73470b57cec5SDimitry Andric     ObjCCategoryImplDecl *IDecl = CategoryImplementation[i];
73480b57cec5SDimitry Andric     ObjCCategoryDecl *CatDecl= IDecl->getCategoryDecl();
73490b57cec5SDimitry Andric     ObjCInterfaceDecl *ClassDecl = IDecl->getClassInterface();
73500b57cec5SDimitry Andric     Result += "\t(void *)&OBJC_CATEGORY_SETUP_$_";
73510b57cec5SDimitry Andric     Result += ClassDecl->getName();
73520b57cec5SDimitry Andric     Result += "_$_";
73530b57cec5SDimitry Andric     Result += CatDecl->getName();
73540b57cec5SDimitry Andric     Result += ",\n";
73550b57cec5SDimitry Andric   }
73560b57cec5SDimitry Andric   Result += "};\n";
73570b57cec5SDimitry Andric }
73580b57cec5SDimitry Andric 
73590b57cec5SDimitry Andric // RewriteObjCMethodsMetaData - Rewrite methods metadata for instance or
73600b57cec5SDimitry Andric /// class methods.
73610b57cec5SDimitry Andric template<typename MethodIterator>
RewriteObjCMethodsMetaData(MethodIterator MethodBegin,MethodIterator MethodEnd,bool IsInstanceMethod,StringRef prefix,StringRef ClassName,std::string & Result)73620b57cec5SDimitry Andric void RewriteModernObjC::RewriteObjCMethodsMetaData(MethodIterator MethodBegin,
73630b57cec5SDimitry Andric                                              MethodIterator MethodEnd,
73640b57cec5SDimitry Andric                                              bool IsInstanceMethod,
73650b57cec5SDimitry Andric                                              StringRef prefix,
73660b57cec5SDimitry Andric                                              StringRef ClassName,
73670b57cec5SDimitry Andric                                              std::string &Result) {
73680b57cec5SDimitry Andric   if (MethodBegin == MethodEnd) return;
73690b57cec5SDimitry Andric 
73700b57cec5SDimitry Andric   if (!objc_impl_method) {
73710b57cec5SDimitry Andric     /* struct _objc_method {
73720b57cec5SDimitry Andric      SEL _cmd;
73730b57cec5SDimitry Andric      char *method_types;
73740b57cec5SDimitry Andric      void *_imp;
73750b57cec5SDimitry Andric      }
73760b57cec5SDimitry Andric      */
73770b57cec5SDimitry Andric     Result += "\nstruct _objc_method {\n";
73780b57cec5SDimitry Andric     Result += "\tSEL _cmd;\n";
73790b57cec5SDimitry Andric     Result += "\tchar *method_types;\n";
73800b57cec5SDimitry Andric     Result += "\tvoid *_imp;\n";
73810b57cec5SDimitry Andric     Result += "};\n";
73820b57cec5SDimitry Andric 
73830b57cec5SDimitry Andric     objc_impl_method = true;
73840b57cec5SDimitry Andric   }
73850b57cec5SDimitry Andric 
73860b57cec5SDimitry Andric   // Build _objc_method_list for class's methods if needed
73870b57cec5SDimitry Andric 
73880b57cec5SDimitry Andric   /* struct  {
73890b57cec5SDimitry Andric    struct _objc_method_list *next_method;
73900b57cec5SDimitry Andric    int method_count;
73910b57cec5SDimitry Andric    struct _objc_method method_list[];
73920b57cec5SDimitry Andric    }
73930b57cec5SDimitry Andric    */
73940b57cec5SDimitry Andric   unsigned NumMethods = std::distance(MethodBegin, MethodEnd);
73950b57cec5SDimitry Andric   Result += "\n";
73960b57cec5SDimitry Andric   if (LangOpts.MicrosoftExt) {
73970b57cec5SDimitry Andric     if (IsInstanceMethod)
73980b57cec5SDimitry Andric       Result += "__declspec(allocate(\".inst_meth$B\")) ";
73990b57cec5SDimitry Andric     else
74000b57cec5SDimitry Andric       Result += "__declspec(allocate(\".cls_meth$B\")) ";
74010b57cec5SDimitry Andric   }
74020b57cec5SDimitry Andric   Result += "static struct {\n";
74030b57cec5SDimitry Andric   Result += "\tstruct _objc_method_list *next_method;\n";
74040b57cec5SDimitry Andric   Result += "\tint method_count;\n";
74050b57cec5SDimitry Andric   Result += "\tstruct _objc_method method_list[";
74060b57cec5SDimitry Andric   Result += utostr(NumMethods);
74070b57cec5SDimitry Andric   Result += "];\n} _OBJC_";
74080b57cec5SDimitry Andric   Result += prefix;
74090b57cec5SDimitry Andric   Result += IsInstanceMethod ? "INSTANCE" : "CLASS";
74100b57cec5SDimitry Andric   Result += "_METHODS_";
74110b57cec5SDimitry Andric   Result += ClassName;
74120b57cec5SDimitry Andric   Result += " __attribute__ ((used, section (\"__OBJC, __";
74130b57cec5SDimitry Andric   Result += IsInstanceMethod ? "inst" : "cls";
74140b57cec5SDimitry Andric   Result += "_meth\")))= ";
74150b57cec5SDimitry Andric   Result += "{\n\t0, " + utostr(NumMethods) + "\n";
74160b57cec5SDimitry Andric 
74170b57cec5SDimitry Andric   Result += "\t,{{(SEL)\"";
74180b57cec5SDimitry Andric   Result += (*MethodBegin)->getSelector().getAsString().c_str();
74190b57cec5SDimitry Andric   std::string MethodTypeString;
74200b57cec5SDimitry Andric   Context->getObjCEncodingForMethodDecl(*MethodBegin, MethodTypeString);
74210b57cec5SDimitry Andric   Result += "\", \"";
74220b57cec5SDimitry Andric   Result += MethodTypeString;
74230b57cec5SDimitry Andric   Result += "\", (void *)";
74240b57cec5SDimitry Andric   Result += MethodInternalNames[*MethodBegin];
74250b57cec5SDimitry Andric   Result += "}\n";
74260b57cec5SDimitry Andric   for (++MethodBegin; MethodBegin != MethodEnd; ++MethodBegin) {
74270b57cec5SDimitry Andric     Result += "\t  ,{(SEL)\"";
74280b57cec5SDimitry Andric     Result += (*MethodBegin)->getSelector().getAsString().c_str();
74290b57cec5SDimitry Andric     std::string MethodTypeString;
74300b57cec5SDimitry Andric     Context->getObjCEncodingForMethodDecl(*MethodBegin, MethodTypeString);
74310b57cec5SDimitry Andric     Result += "\", \"";
74320b57cec5SDimitry Andric     Result += MethodTypeString;
74330b57cec5SDimitry Andric     Result += "\", (void *)";
74340b57cec5SDimitry Andric     Result += MethodInternalNames[*MethodBegin];
74350b57cec5SDimitry Andric     Result += "}\n";
74360b57cec5SDimitry Andric   }
74370b57cec5SDimitry Andric   Result += "\t }\n};\n";
74380b57cec5SDimitry Andric }
74390b57cec5SDimitry Andric 
RewriteObjCIvarRefExpr(ObjCIvarRefExpr * IV)74400b57cec5SDimitry Andric Stmt *RewriteModernObjC::RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV) {
74410b57cec5SDimitry Andric   SourceRange OldRange = IV->getSourceRange();
74420b57cec5SDimitry Andric   Expr *BaseExpr = IV->getBase();
74430b57cec5SDimitry Andric 
74440b57cec5SDimitry Andric   // Rewrite the base, but without actually doing replaces.
74450b57cec5SDimitry Andric   {
74460b57cec5SDimitry Andric     DisableReplaceStmtScope S(*this);
74470b57cec5SDimitry Andric     BaseExpr = cast<Expr>(RewriteFunctionBodyOrGlobalInitializer(BaseExpr));
74480b57cec5SDimitry Andric     IV->setBase(BaseExpr);
74490b57cec5SDimitry Andric   }
74500b57cec5SDimitry Andric 
74510b57cec5SDimitry Andric   ObjCIvarDecl *D = IV->getDecl();
74520b57cec5SDimitry Andric 
74530b57cec5SDimitry Andric   Expr *Replacement = IV;
74540b57cec5SDimitry Andric 
74550b57cec5SDimitry Andric     if (BaseExpr->getType()->isObjCObjectPointerType()) {
74560b57cec5SDimitry Andric       const ObjCInterfaceType *iFaceDecl =
74570b57cec5SDimitry Andric         dyn_cast<ObjCInterfaceType>(BaseExpr->getType()->getPointeeType());
74580b57cec5SDimitry Andric       assert(iFaceDecl && "RewriteObjCIvarRefExpr - iFaceDecl is null");
74590b57cec5SDimitry Andric       // lookup which class implements the instance variable.
74600b57cec5SDimitry Andric       ObjCInterfaceDecl *clsDeclared = nullptr;
74610b57cec5SDimitry Andric       iFaceDecl->getDecl()->lookupInstanceVariable(D->getIdentifier(),
74620b57cec5SDimitry Andric                                                    clsDeclared);
74630b57cec5SDimitry Andric       assert(clsDeclared && "RewriteObjCIvarRefExpr(): Can't find class");
74640b57cec5SDimitry Andric 
74650b57cec5SDimitry Andric       // Build name of symbol holding ivar offset.
74660b57cec5SDimitry Andric       std::string IvarOffsetName;
74670b57cec5SDimitry Andric       if (D->isBitField())
74680b57cec5SDimitry Andric         ObjCIvarBitfieldGroupOffset(D, IvarOffsetName);
74690b57cec5SDimitry Andric       else
74700b57cec5SDimitry Andric         WriteInternalIvarName(clsDeclared, D, IvarOffsetName);
74710b57cec5SDimitry Andric 
74720b57cec5SDimitry Andric       ReferencedIvars[clsDeclared].insert(D);
74730b57cec5SDimitry Andric 
74740b57cec5SDimitry Andric       // cast offset to "char *".
74750b57cec5SDimitry Andric       CastExpr *castExpr = NoTypeInfoCStyleCastExpr(Context,
74760b57cec5SDimitry Andric                                                     Context->getPointerType(Context->CharTy),
74770b57cec5SDimitry Andric                                                     CK_BitCast,
74780b57cec5SDimitry Andric                                                     BaseExpr);
74790b57cec5SDimitry Andric       VarDecl *NewVD = VarDecl::Create(*Context, TUDecl, SourceLocation(),
74800b57cec5SDimitry Andric                                        SourceLocation(), &Context->Idents.get(IvarOffsetName),
74810b57cec5SDimitry Andric                                        Context->UnsignedLongTy, nullptr,
74820b57cec5SDimitry Andric                                        SC_Extern);
74830b57cec5SDimitry Andric       DeclRefExpr *DRE = new (Context)
74840b57cec5SDimitry Andric           DeclRefExpr(*Context, NewVD, false, Context->UnsignedLongTy,
74850b57cec5SDimitry Andric                       VK_LValue, SourceLocation());
74865ffd83dbSDimitry Andric       BinaryOperator *addExpr = BinaryOperator::Create(
74875ffd83dbSDimitry Andric           *Context, castExpr, DRE, BO_Add,
7488fe6060f1SDimitry Andric           Context->getPointerType(Context->CharTy), VK_PRValue, OK_Ordinary,
74895ffd83dbSDimitry Andric           SourceLocation(), FPOptionsOverride());
74900b57cec5SDimitry Andric       // Don't forget the parens to enforce the proper binding.
74910b57cec5SDimitry Andric       ParenExpr *PE = new (Context) ParenExpr(SourceLocation(),
74920b57cec5SDimitry Andric                                               SourceLocation(),
74930b57cec5SDimitry Andric                                               addExpr);
74940b57cec5SDimitry Andric       QualType IvarT = D->getType();
74950b57cec5SDimitry Andric       if (D->isBitField())
74960b57cec5SDimitry Andric         IvarT = GetGroupRecordTypeForObjCIvarBitfield(D);
74970b57cec5SDimitry Andric 
7498bdd1243dSDimitry Andric       if (!IvarT->getAs<TypedefType>() && IvarT->isRecordType()) {
7499a7dea167SDimitry Andric         RecordDecl *RD = IvarT->castAs<RecordType>()->getDecl();
75000b57cec5SDimitry Andric         RD = RD->getDefinition();
75010b57cec5SDimitry Andric         if (RD && !RD->getDeclName().getAsIdentifierInfo()) {
75020b57cec5SDimitry Andric           // decltype(((Foo_IMPL*)0)->bar) *
75035ffd83dbSDimitry Andric           auto *CDecl = cast<ObjCContainerDecl>(D->getDeclContext());
75040b57cec5SDimitry Andric           // ivar in class extensions requires special treatment.
75050b57cec5SDimitry Andric           if (ObjCCategoryDecl *CatDecl = dyn_cast<ObjCCategoryDecl>(CDecl))
75060b57cec5SDimitry Andric             CDecl = CatDecl->getClassInterface();
75075ffd83dbSDimitry Andric           std::string RecName = std::string(CDecl->getName());
75080b57cec5SDimitry Andric           RecName += "_IMPL";
75090b57cec5SDimitry Andric           RecordDecl *RD = RecordDecl::Create(
75105f757f3fSDimitry Andric               *Context, TagTypeKind::Struct, TUDecl, SourceLocation(),
75115f757f3fSDimitry Andric               SourceLocation(), &Context->Idents.get(RecName));
75120b57cec5SDimitry Andric           QualType PtrStructIMPL = Context->getPointerType(Context->getTagDeclType(RD));
75130b57cec5SDimitry Andric           unsigned UnsignedIntSize =
75140b57cec5SDimitry Andric             static_cast<unsigned>(Context->getTypeSize(Context->UnsignedIntTy));
75150b57cec5SDimitry Andric           Expr *Zero = IntegerLiteral::Create(*Context,
75160b57cec5SDimitry Andric                                               llvm::APInt(UnsignedIntSize, 0),
75170b57cec5SDimitry Andric                                               Context->UnsignedIntTy, SourceLocation());
75180b57cec5SDimitry Andric           Zero = NoTypeInfoCStyleCastExpr(Context, PtrStructIMPL, CK_BitCast, Zero);
75190b57cec5SDimitry Andric           ParenExpr *PE = new (Context) ParenExpr(SourceLocation(), SourceLocation(),
75200b57cec5SDimitry Andric                                                   Zero);
75210b57cec5SDimitry Andric           FieldDecl *FD = FieldDecl::Create(*Context, nullptr, SourceLocation(),
75220b57cec5SDimitry Andric                                             SourceLocation(),
75230b57cec5SDimitry Andric                                             &Context->Idents.get(D->getNameAsString()),
75240b57cec5SDimitry Andric                                             IvarT, nullptr,
75250b57cec5SDimitry Andric                                             /*BitWidth=*/nullptr,
75260b57cec5SDimitry Andric                                             /*Mutable=*/true, ICIS_NoInit);
75270b57cec5SDimitry Andric           MemberExpr *ME = MemberExpr::CreateImplicit(
75280b57cec5SDimitry Andric               *Context, PE, true, FD, FD->getType(), VK_LValue, OK_Ordinary);
75290b57cec5SDimitry Andric           IvarT = Context->getDecltypeType(ME, ME->getType());
75300b57cec5SDimitry Andric         }
75310b57cec5SDimitry Andric       }
75320b57cec5SDimitry Andric       convertObjCTypeToCStyleType(IvarT);
75330b57cec5SDimitry Andric       QualType castT = Context->getPointerType(IvarT);
75340b57cec5SDimitry Andric 
75350b57cec5SDimitry Andric       castExpr = NoTypeInfoCStyleCastExpr(Context,
75360b57cec5SDimitry Andric                                           castT,
75370b57cec5SDimitry Andric                                           CK_BitCast,
75380b57cec5SDimitry Andric                                           PE);
75390b57cec5SDimitry Andric 
75405ffd83dbSDimitry Andric       Expr *Exp = UnaryOperator::Create(
75415ffd83dbSDimitry Andric           const_cast<ASTContext &>(*Context), castExpr, UO_Deref, IvarT,
75425ffd83dbSDimitry Andric           VK_LValue, OK_Ordinary, SourceLocation(), false, FPOptionsOverride());
75430b57cec5SDimitry Andric       PE = new (Context) ParenExpr(OldRange.getBegin(),
75440b57cec5SDimitry Andric                                    OldRange.getEnd(),
75450b57cec5SDimitry Andric                                    Exp);
75460b57cec5SDimitry Andric 
75470b57cec5SDimitry Andric       if (D->isBitField()) {
75480b57cec5SDimitry Andric         FieldDecl *FD = FieldDecl::Create(*Context, nullptr, SourceLocation(),
75490b57cec5SDimitry Andric                                           SourceLocation(),
75500b57cec5SDimitry Andric                                           &Context->Idents.get(D->getNameAsString()),
75510b57cec5SDimitry Andric                                           D->getType(), nullptr,
75520b57cec5SDimitry Andric                                           /*BitWidth=*/D->getBitWidth(),
75530b57cec5SDimitry Andric                                           /*Mutable=*/true, ICIS_NoInit);
75540b57cec5SDimitry Andric         MemberExpr *ME =
75550b57cec5SDimitry Andric             MemberExpr::CreateImplicit(*Context, PE, /*isArrow*/ false, FD,
75560b57cec5SDimitry Andric                                        FD->getType(), VK_LValue, OK_Ordinary);
75570b57cec5SDimitry Andric         Replacement = ME;
75580b57cec5SDimitry Andric 
75590b57cec5SDimitry Andric       }
75600b57cec5SDimitry Andric       else
75610b57cec5SDimitry Andric         Replacement = PE;
75620b57cec5SDimitry Andric     }
75630b57cec5SDimitry Andric 
75640b57cec5SDimitry Andric     ReplaceStmtWithRange(IV, Replacement, OldRange);
75650b57cec5SDimitry Andric     return Replacement;
75660b57cec5SDimitry Andric }
75670b57cec5SDimitry Andric 
75680b57cec5SDimitry Andric #endif // CLANG_ENABLE_OBJC_REWRITER
7569