164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian//===--- RewriteObjC.cpp - Playground for the code rewriter ---------------===//
264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian//
364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian//                     The LLVM Compiler Infrastructure
464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian//
564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian// This file is distributed under the University of Illinois Open Source
664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian// License. See LICENSE.TXT for details.
764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian//
864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian//===----------------------------------------------------------------------===//
964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian//
1064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian// Hacks and fun related to the code rewriter.
1164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian//
1264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian//===----------------------------------------------------------------------===//
1364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
14305c613af6cfc40e519c75d9d2c84c6fa9a841c0Ted Kremenek#include "clang/Rewrite/Frontend/ASTConsumers.h"
1564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian#include "clang/AST/AST.h"
1664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian#include "clang/AST/ASTConsumer.h"
172fa67efeaf66a9332c30a026dc1c21bef6c33a6cBenjamin Kramer#include "clang/AST/Attr.h"
1864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian#include "clang/AST/ParentMap.h"
193f6f51e28231f65de9c2dd150a2d757b2162cfa3Jordan Rose#include "clang/Basic/CharInfo.h"
2064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian#include "clang/Basic/Diagnostic.h"
212fa67efeaf66a9332c30a026dc1c21bef6c33a6cBenjamin Kramer#include "clang/Basic/IdentifierTable.h"
222fa67efeaf66a9332c30a026dc1c21bef6c33a6cBenjamin Kramer#include "clang/Basic/SourceManager.h"
239852f58f50b4fc20914fbce5b4454135a42343f4Benjamin Kramer#include "clang/Basic/TargetInfo.h"
2464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian#include "clang/Lex/Lexer.h"
2555fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "clang/Rewrite/Core/Rewriter.h"
262fa67efeaf66a9332c30a026dc1c21bef6c33a6cBenjamin Kramer#include "llvm/ADT/DenseSet.h"
272fa67efeaf66a9332c30a026dc1c21bef6c33a6cBenjamin Kramer#include "llvm/ADT/SmallPtrSet.h"
282fa67efeaf66a9332c30a026dc1c21bef6c33a6cBenjamin Kramer#include "llvm/ADT/StringExtras.h"
2964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian#include "llvm/Support/MemoryBuffer.h"
3064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian#include "llvm/Support/raw_ostream.h"
31651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines#include <memory>
3264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
33176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines#ifdef CLANG_ENABLE_OBJC_REWRITER
34176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines
3564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanianusing namespace clang;
3664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanianusing llvm::utostr;
3764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
3864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahaniannamespace {
3964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  class RewriteModernObjC : public ASTConsumer {
4064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  protected:
4164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
4264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    enum {
4364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      BLOCK_FIELD_IS_OBJECT   =  3,  /* id, NSObject, __attribute__((NSObject)),
4464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                        block, ... */
4564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      BLOCK_FIELD_IS_BLOCK    =  7,  /* a block variable */
4664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      BLOCK_FIELD_IS_BYREF    =  8,  /* the on stack structure holding the
4764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                        __block variable */
4864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      BLOCK_FIELD_IS_WEAK     = 16,  /* declared __weak, only used in byref copy
4964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                        helpers */
5064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      BLOCK_BYREF_CALLER      = 128, /* called from __block (byref) copy/dispose
5164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                        support routines */
5264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      BLOCK_BYREF_CURRENT_MAX = 256
5364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    };
5464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
5564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    enum {
5664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      BLOCK_NEEDS_FREE =        (1 << 24),
5764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      BLOCK_HAS_COPY_DISPOSE =  (1 << 25),
5864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      BLOCK_HAS_CXX_OBJ =       (1 << 26),
5964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      BLOCK_IS_GC =             (1 << 27),
6064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      BLOCK_IS_GLOBAL =         (1 << 28),
6164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      BLOCK_HAS_DESCRIPTOR =    (1 << 29)
6264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    };
6364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
6464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    Rewriter Rewrite;
6564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    DiagnosticsEngine &Diags;
6664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    const LangOptions &LangOpts;
6764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    ASTContext *Context;
6864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    SourceManager *SM;
6964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    TranslationUnitDecl *TUDecl;
7064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    FileID MainFileID;
7164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    const char *MainFileStart, *MainFileEnd;
7264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    Stmt *CurrentBody;
7364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    ParentMap *PropParentMap; // created lazily.
7464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    std::string InFileName;
7564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    raw_ostream* OutFile;
7664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    std::string Preamble;
7764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
7864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    TypeDecl *ProtocolTypeDecl;
7964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    VarDecl *GlobalVarDecl;
80df474ec64a86bb88c7543875634d3fc628105bb5Fariborz Jahanian    Expr *GlobalConstructionExp;
8164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    unsigned RewriteFailedDiag;
82d13c2c291f9fec2ed0e12a65f1638710ca979bb0Fariborz Jahanian    unsigned GlobalBlockRewriteFailedDiag;
8364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    // ObjC string constant support.
8464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    unsigned NumObjCStringLiterals;
8564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    VarDecl *ConstantStringClassReference;
8664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    RecordDecl *NSStringRecord;
8764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
8864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    // ObjC foreach break/continue generation support.
8964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    int BcLabelCount;
9064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
9164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    unsigned TryFinallyContainsReturnDiag;
9264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    // Needed for super.
9364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    ObjCMethodDecl *CurMethodDef;
9464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    RecordDecl *SuperStructDecl;
9564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    RecordDecl *ConstantStringDecl;
9664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
9764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    FunctionDecl *MsgSendFunctionDecl;
9864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    FunctionDecl *MsgSendSuperFunctionDecl;
9964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    FunctionDecl *MsgSendStretFunctionDecl;
10064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    FunctionDecl *MsgSendSuperStretFunctionDecl;
10164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    FunctionDecl *MsgSendFpretFunctionDecl;
10264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    FunctionDecl *GetClassFunctionDecl;
10364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    FunctionDecl *GetMetaClassFunctionDecl;
10464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    FunctionDecl *GetSuperClassFunctionDecl;
10564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    FunctionDecl *SelGetUidFunctionDecl;
10664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    FunctionDecl *CFStringFunctionDecl;
107e575359c34a9248c55ec0c03a8fc945f1ee4cb01Benjamin Kramer    FunctionDecl *SuperConstructorFunctionDecl;
10864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    FunctionDecl *CurFunctionDef;
10964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
11064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    /* Misc. containers needed for meta-data rewrite. */
11164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    SmallVector<ObjCImplementationDecl *, 8> ClassImplementation;
11264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    SmallVector<ObjCCategoryImplDecl *, 8> CategoryImplementation;
11364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    llvm::SmallPtrSet<ObjCInterfaceDecl*, 8> ObjCSynthesizedStructs;
11464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    llvm::SmallPtrSet<ObjCProtocolDecl*, 8> ObjCSynthesizedProtocols;
115cf4c60feae11b2f6a135d7cd8ecf97a5040951c3Fariborz Jahanian    llvm::SmallPtrSet<ObjCInterfaceDecl*, 8> ObjCWrittenInterfaces;
1168fba894335b979e6d213c685bca959168c1f2182Fariborz Jahanian    llvm::SmallPtrSet<TagDecl*, 32> GlobalDefinedTags;
117cf4c60feae11b2f6a135d7cd8ecf97a5040951c3Fariborz Jahanian    SmallVector<ObjCInterfaceDecl*, 32> ObjCInterfacesSeen;
11888f7f75e35425f3f228473c4c84a2445793a39c1Fariborz Jahanian    /// DefinedNonLazyClasses - List of defined "non-lazy" classes.
11988f7f75e35425f3f228473c4c84a2445793a39c1Fariborz Jahanian    SmallVector<ObjCInterfaceDecl*, 8> DefinedNonLazyClasses;
12088f7f75e35425f3f228473c4c84a2445793a39c1Fariborz Jahanian
12188f7f75e35425f3f228473c4c84a2445793a39c1Fariborz Jahanian    /// DefinedNonLazyCategories - List of defined "non-lazy" categories.
122cfa88f893915ceb8ae4ce2f17c46c24a4d67502fDmitri Gribenko    SmallVector<ObjCCategoryDecl *, 8> DefinedNonLazyCategories;
12388f7f75e35425f3f228473c4c84a2445793a39c1Fariborz Jahanian
12464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    SmallVector<Stmt *, 32> Stmts;
12564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    SmallVector<int, 8> ObjCBcLabelNo;
12664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    // Remember all the @protocol(<expr>) expressions.
12764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    llvm::SmallPtrSet<ObjCProtocolDecl *, 32> ProtocolExprDecls;
12864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
12964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    llvm::DenseSet<uint64_t> CopyDestroyCache;
13064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
13164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    // Block expressions.
13264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    SmallVector<BlockExpr *, 32> Blocks;
13364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    SmallVector<int, 32> InnerDeclRefsCount;
134f4b88a45902af1802a1cb42ba48b1c474474f228John McCall    SmallVector<DeclRefExpr *, 32> InnerDeclRefs;
13564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
136f4b88a45902af1802a1cb42ba48b1c474474f228John McCall    SmallVector<DeclRefExpr *, 32> BlockDeclRefs;
13764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
138cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian
13964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    // Block related declarations.
14064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    SmallVector<ValueDecl *, 8> BlockByCopyDecls;
14164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    llvm::SmallPtrSet<ValueDecl *, 8> BlockByCopyDeclsPtrSet;
14264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    SmallVector<ValueDecl *, 8> BlockByRefDecls;
14364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    llvm::SmallPtrSet<ValueDecl *, 8> BlockByRefDeclsPtrSet;
14464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    llvm::DenseMap<ValueDecl *, unsigned> BlockByRefDeclNo;
14564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    llvm::SmallPtrSet<ValueDecl *, 8> ImportedBlockDecls;
14664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    llvm::SmallPtrSet<VarDecl *, 8> ImportedLocalExternalDecls;
14764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
14864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    llvm::DenseMap<BlockExpr *, std::string> RewrittenBlockExprs;
14972c88f13f79e2012b8a5f84cf48c6af779dfd1baFariborz Jahanian    llvm::DenseMap<ObjCInterfaceDecl *,
15072c88f13f79e2012b8a5f84cf48c6af779dfd1baFariborz Jahanian                    llvm::SmallPtrSet<ObjCIvarDecl *, 8> > ReferencedIvars;
15172c88f13f79e2012b8a5f84cf48c6af779dfd1baFariborz Jahanian
152cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian    // ivar bitfield grouping containers
153cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian    llvm::DenseSet<const ObjCInterfaceDecl *> ObjCInterefaceHasBitfieldGroups;
154cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian    llvm::DenseMap<const ObjCIvarDecl* , unsigned> IvarGroupNumber;
155cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian    // This container maps an <class, group number for ivar> tuple to the type
156cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian    // of the struct where the bitfield belongs.
157cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian    llvm::DenseMap<std::pair<const ObjCInterfaceDecl*, unsigned>, QualType> GroupRecordType;
15831c4a4b0171aac01d2a6aedb4960ade7ee7d998aFariborz Jahanian    SmallVector<FunctionDecl*, 32> FunctionDefinitionsSeen;
159cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian
16064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    // This maps an original source AST to it's rewritten form. This allows
16164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    // us to avoid rewriting the same node twice (which is very uncommon).
16264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    // This is needed to support some of the exotic property rewriting.
16364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    llvm::DenseMap<Stmt *, Stmt *> ReplacedNodes;
16464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
16564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    // Needed for header files being rewritten
16664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    bool IsHeader;
16764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    bool SilenceRewriteMacroWarning;
168ada7191795dde85a620008094fbe5464abdb916bFariborz Jahanian    bool GenerateLineInfo;
16964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    bool objc_impl_method;
17064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
17164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    bool DisableReplaceStmt;
17264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    class DisableReplaceStmtScope {
17364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      RewriteModernObjC &R;
17464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      bool SavedValue;
17564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
17664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    public:
17764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      DisableReplaceStmtScope(RewriteModernObjC &R)
17864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        : R(R), SavedValue(R.DisableReplaceStmt) {
17964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        R.DisableReplaceStmt = true;
18064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      }
18164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      ~DisableReplaceStmtScope() {
18264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        R.DisableReplaceStmt = SavedValue;
18364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      }
18464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    };
18564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    void InitializeCommon(ASTContext &context);
18664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
18764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  public:
18890af4e22a8fb83f159b512bfd48fb77699337b3dFariborz Jahanian    llvm::DenseMap<ObjCMethodDecl*, std::string> MethodInternalNames;
18964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    // Top Level Driver code.
190651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    bool HandleTopLevelDecl(DeclGroupRef D) override {
19164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      for (DeclGroupRef::iterator I = D.begin(), E = D.end(); I != E; ++I) {
19264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        if (ObjCInterfaceDecl *Class = dyn_cast<ObjCInterfaceDecl>(*I)) {
19364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian          if (!Class->isThisDeclarationADefinition()) {
19464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian            RewriteForwardClassDecl(D);
19564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian            break;
196cf4c60feae11b2f6a135d7cd8ecf97a5040951c3Fariborz Jahanian          } else {
197cf4c60feae11b2f6a135d7cd8ecf97a5040951c3Fariborz Jahanian            // Keep track of all interface declarations seen.
198f329527bbeae86c8eac6eea6efaa20e807c16679Fariborz Jahanian            ObjCInterfacesSeen.push_back(Class);
199cf4c60feae11b2f6a135d7cd8ecf97a5040951c3Fariborz Jahanian            break;
20064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian          }
20164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        }
20264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
20364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        if (ObjCProtocolDecl *Proto = dyn_cast<ObjCProtocolDecl>(*I)) {
20464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian          if (!Proto->isThisDeclarationADefinition()) {
20564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian            RewriteForwardProtocolDecl(D);
20664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian            break;
20764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian          }
20864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        }
20964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
21031c4a4b0171aac01d2a6aedb4960ade7ee7d998aFariborz Jahanian        if (FunctionDecl *FDecl = dyn_cast<FunctionDecl>(*I)) {
21131c4a4b0171aac01d2a6aedb4960ade7ee7d998aFariborz Jahanian          // Under modern abi, we cannot translate body of the function
21231c4a4b0171aac01d2a6aedb4960ade7ee7d998aFariborz Jahanian          // yet until all class extensions and its implementation is seen.
21331c4a4b0171aac01d2a6aedb4960ade7ee7d998aFariborz Jahanian          // This is because they may introduce new bitfields which must go
21431c4a4b0171aac01d2a6aedb4960ade7ee7d998aFariborz Jahanian          // into their grouping struct.
21531c4a4b0171aac01d2a6aedb4960ade7ee7d998aFariborz Jahanian          if (FDecl->isThisDeclarationADefinition() &&
21631c4a4b0171aac01d2a6aedb4960ade7ee7d998aFariborz Jahanian              // Not c functions defined inside an objc container.
21731c4a4b0171aac01d2a6aedb4960ade7ee7d998aFariborz Jahanian              !FDecl->isTopLevelDeclInObjCContainer()) {
21831c4a4b0171aac01d2a6aedb4960ade7ee7d998aFariborz Jahanian            FunctionDefinitionsSeen.push_back(FDecl);
21931c4a4b0171aac01d2a6aedb4960ade7ee7d998aFariborz Jahanian            break;
22031c4a4b0171aac01d2a6aedb4960ade7ee7d998aFariborz Jahanian          }
22131c4a4b0171aac01d2a6aedb4960ade7ee7d998aFariborz Jahanian        }
22264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        HandleTopLevelSingleDecl(*I);
22364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      }
22464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      return true;
22564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    }
226651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
227651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    void HandleTopLevelDeclInObjCContainer(DeclGroupRef D) override {
228040cd82aadd48ba50e9742881d648d53ddd2a6c9Fariborz Jahanian      for (DeclGroupRef::iterator I = D.begin(), E = D.end(); I != E; ++I) {
229040cd82aadd48ba50e9742881d648d53ddd2a6c9Fariborz Jahanian        if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(*I)) {
230040cd82aadd48ba50e9742881d648d53ddd2a6c9Fariborz Jahanian          if (isTopLevelBlockPointerType(TD->getUnderlyingType()))
231040cd82aadd48ba50e9742881d648d53ddd2a6c9Fariborz Jahanian            RewriteBlockPointerDecl(TD);
232040cd82aadd48ba50e9742881d648d53ddd2a6c9Fariborz Jahanian          else if (TD->getUnderlyingType()->isFunctionPointerType())
233040cd82aadd48ba50e9742881d648d53ddd2a6c9Fariborz Jahanian            CheckFunctionPointerDecl(TD->getUnderlyingType(), TD);
234040cd82aadd48ba50e9742881d648d53ddd2a6c9Fariborz Jahanian          else
235040cd82aadd48ba50e9742881d648d53ddd2a6c9Fariborz Jahanian            RewriteObjCQualifiedInterfaceTypes(TD);
236040cd82aadd48ba50e9742881d648d53ddd2a6c9Fariborz Jahanian        }
237040cd82aadd48ba50e9742881d648d53ddd2a6c9Fariborz Jahanian      }
238040cd82aadd48ba50e9742881d648d53ddd2a6c9Fariborz Jahanian      return;
239040cd82aadd48ba50e9742881d648d53ddd2a6c9Fariborz Jahanian    }
240040cd82aadd48ba50e9742881d648d53ddd2a6c9Fariborz Jahanian
24164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    void HandleTopLevelSingleDecl(Decl *D);
24264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    void HandleDeclInMainFile(Decl *D);
24364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    RewriteModernObjC(std::string inFile, raw_ostream *OS,
24464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                DiagnosticsEngine &D, const LangOptions &LOpts,
245ada7191795dde85a620008094fbe5464abdb916bFariborz Jahanian                bool silenceMacroWarn, bool LineInfo);
24633337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar
24733337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar    ~RewriteModernObjC() override {}
248651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
249651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    void HandleTranslationUnit(ASTContext &C) override;
25064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
25164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    void ReplaceStmt(Stmt *Old, Stmt *New) {
252176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      ReplaceStmtWithRange(Old, New, Old->getSourceRange());
25364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    }
25464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
25564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    void ReplaceStmtWithRange(Stmt *Old, Stmt *New, SourceRange SrcRange) {
256c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      assert(Old != nullptr && New != nullptr && "Expected non-null Stmt's");
257176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines
258176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      Stmt *ReplacingStmt = ReplacedNodes[Old];
259176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      if (ReplacingStmt)
260176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines        return; // We can't rewrite the same node twice.
261176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines
26264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      if (DisableReplaceStmt)
26364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        return;
26464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
26564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      // Measure the old text.
26664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      int Size = Rewrite.getRangeSize(SrcRange);
26764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      if (Size == -1) {
26864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        Diags.Report(Context->getFullLoc(Old->getLocStart()), RewriteFailedDiag)
26964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                     << Old->getSourceRange();
27064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        return;
27164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      }
27264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      // Get the new text.
27364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      std::string SStr;
27464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      llvm::raw_string_ostream S(SStr);
2756bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      New->printPretty(S, nullptr, PrintingPolicy(LangOpts));
27664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      const std::string &Str = S.str();
27764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
27864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      // If replacement succeeded or warning disabled return with no warning.
27964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      if (!Rewrite.ReplaceText(SrcRange.getBegin(), Size, Str)) {
28064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        ReplacedNodes[Old] = New;
28164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        return;
28264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      }
28364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      if (SilenceRewriteMacroWarning)
28464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        return;
28564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      Diags.Report(Context->getFullLoc(Old->getLocStart()), RewriteFailedDiag)
28664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                   << Old->getSourceRange();
28764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    }
28864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
28964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    void InsertText(SourceLocation Loc, StringRef Str,
29064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                    bool InsertAfter = true) {
29164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      // If insertion succeeded or warning disabled return with no warning.
29264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      if (!Rewrite.InsertText(Loc, Str, InsertAfter) ||
29364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian          SilenceRewriteMacroWarning)
29464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        return;
29564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
29664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      Diags.Report(Context->getFullLoc(Loc), RewriteFailedDiag);
29764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    }
29864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
29964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    void ReplaceText(SourceLocation Start, unsigned OrigLength,
30064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                     StringRef Str) {
30164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      // If removal succeeded or warning disabled return with no warning.
30264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      if (!Rewrite.ReplaceText(Start, OrigLength, Str) ||
30364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian          SilenceRewriteMacroWarning)
30464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        return;
30564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
30664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      Diags.Report(Context->getFullLoc(Start), RewriteFailedDiag);
30764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    }
30864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
30964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    // Syntactic Rewriting.
31064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    void RewriteRecordBody(RecordDecl *RD);
31164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    void RewriteInclude();
3129620596ca2ca19e365af4e4d4968cb4d9228c4fcFariborz Jahanian    void RewriteLineDirective(const Decl *D);
313f616ae2d1356dadde26ff553eb689e5455d65808Fariborz Jahanian    void ConvertSourceLocationToLineDirective(SourceLocation Loc,
314f616ae2d1356dadde26ff553eb689e5455d65808Fariborz Jahanian                                              std::string &LineString);
31564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    void RewriteForwardClassDecl(DeclGroupRef D);
3166b9240e058bf3451685df73fc8ce181b3046e92bCraig Topper    void RewriteForwardClassDecl(const SmallVectorImpl<Decl *> &DG);
31764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    void RewriteForwardClassEpilogue(ObjCInterfaceDecl *ClassDecl,
31864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                     const std::string &typedefString);
31964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    void RewriteImplementations();
32064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    void RewritePropertyImplDecl(ObjCPropertyImplDecl *PID,
32164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                 ObjCImplementationDecl *IMD,
32264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                 ObjCCategoryImplDecl *CID);
32364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    void RewriteInterfaceDecl(ObjCInterfaceDecl *Dcl);
32464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    void RewriteImplementationDecl(Decl *Dcl);
32564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    void RewriteObjCMethodDecl(const ObjCInterfaceDecl *IDecl,
32664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                               ObjCMethodDecl *MDecl, std::string &ResultStr);
32764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    void RewriteTypeIntoString(QualType T, std::string &ResultStr,
32864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                               const FunctionType *&FPRetType);
32964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    void RewriteByRefString(std::string &ResultStr, const std::string &Name,
33064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                            ValueDecl *VD, bool def=false);
33164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    void RewriteCategoryDecl(ObjCCategoryDecl *Dcl);
33264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    void RewriteProtocolDecl(ObjCProtocolDecl *Dcl);
33364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    void RewriteForwardProtocolDecl(DeclGroupRef D);
3346b9240e058bf3451685df73fc8ce181b3046e92bCraig Topper    void RewriteForwardProtocolDecl(const SmallVectorImpl<Decl *> &DG);
33564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    void RewriteMethodDeclaration(ObjCMethodDecl *Method);
33664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    void RewriteProperty(ObjCPropertyDecl *prop);
33764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    void RewriteFunctionDecl(FunctionDecl *FD);
33864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    void RewriteBlockPointerType(std::string& Str, QualType Type);
33964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    void RewriteBlockPointerTypeVariable(std::string& Str, ValueDecl *VD);
340b75f8de7ddc4f9365dad90ef21a463e94dcdcbdaFariborz Jahanian    void RewriteBlockLiteralFunctionDecl(FunctionDecl *FD);
34164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    void RewriteObjCQualifiedInterfaceTypes(Decl *Dcl);
34264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    void RewriteTypeOfDecl(VarDecl *VD);
34364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    void RewriteObjCQualifiedInterfaceTypes(Expr *E);
344163d3cef334169e41225d94a4c353e0d7159570bFariborz Jahanian
345163d3cef334169e41225d94a4c353e0d7159570bFariborz Jahanian    std::string getIvarAccessString(ObjCIvarDecl *D);
34664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
34764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    // Expression Rewriting.
34864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    Stmt *RewriteFunctionBodyOrGlobalInitializer(Stmt *S);
34964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    Stmt *RewriteAtEncode(ObjCEncodeExpr *Exp);
35064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    Stmt *RewritePropertyOrImplicitGetter(PseudoObjectExpr *Pseudo);
35164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    Stmt *RewritePropertyOrImplicitSetter(PseudoObjectExpr *Pseudo);
35264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    Stmt *RewriteAtSelector(ObjCSelectorExpr *Exp);
35364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    Stmt *RewriteMessageExpr(ObjCMessageExpr *Exp);
35464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    Stmt *RewriteObjCStringLiteral(ObjCStringLiteral *Exp);
35555947042d86773b7e16aec12070e1ffe62bff4a6Fariborz Jahanian    Stmt *RewriteObjCBoolLiteralExpr(ObjCBoolLiteralExpr *Exp);
356eb382ec1507cf2c8c12d7443d0b67c076223aec6Patrick Beard    Stmt *RewriteObjCBoxedExpr(ObjCBoxedExpr *Exp);
35786cff6080ba1db907009885adb5c6c64007e8b48Fariborz Jahanian    Stmt *RewriteObjCArrayLiteralExpr(ObjCArrayLiteral *Exp);
358e35abe1fd3f867ae51d5c68d98578d537eb6becaFariborz Jahanian    Stmt *RewriteObjCDictionaryLiteralExpr(ObjCDictionaryLiteral *Exp);
35964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    Stmt *RewriteObjCProtocolExpr(ObjCProtocolExpr *Exp);
36064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    Stmt *RewriteObjCTryStmt(ObjCAtTryStmt *S);
361042b91d53980048619d1e61431387ebe84d384f4Fariborz Jahanian    Stmt *RewriteObjCAutoreleasePoolStmt(ObjCAutoreleasePoolStmt  *S);
36264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    Stmt *RewriteObjCSynchronizedStmt(ObjCAtSynchronizedStmt *S);
36364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    Stmt *RewriteObjCThrowStmt(ObjCAtThrowStmt *S);
36464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    Stmt *RewriteObjCForCollectionStmt(ObjCForCollectionStmt *S,
36564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                       SourceLocation OrigEnd);
36664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    Stmt *RewriteBreakStmt(BreakStmt *S);
36764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    Stmt *RewriteContinueStmt(ContinueStmt *S);
36864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    void RewriteCastExpr(CStyleCastExpr *CE);
369f1ee68710ae8ca93a35ab11995ed5df321ade9ecFariborz Jahanian    void RewriteImplicitCastObjCExpr(CastExpr *IE);
370b3f904f79bbe55f3e088d7174d64d20d186914a1Fariborz Jahanian    void RewriteLinkageSpec(LinkageSpecDecl *LSD);
37164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
372cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian    // Computes ivar bitfield group no.
373cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian    unsigned ObjCIvarBitfieldGroupNo(ObjCIvarDecl *IV);
374cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian    // Names field decl. for ivar bitfield group.
375cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian    void ObjCIvarBitfieldGroupDecl(ObjCIvarDecl *IV, std::string &Result);
376cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian    // Names struct type for ivar bitfield group.
377cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian    void ObjCIvarBitfieldGroupType(ObjCIvarDecl *IV, std::string &Result);
378cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian    // Names symbol for ivar bitfield group field offset.
379cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian    void ObjCIvarBitfieldGroupOffset(ObjCIvarDecl *IV, std::string &Result);
380cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian    // Given an ivar bitfield, it builds (or finds) its group record type.
381cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian    QualType GetGroupRecordTypeForObjCIvarBitfield(ObjCIvarDecl *IV);
382cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian    QualType SynthesizeBitfieldGroupStructType(
383cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian                                    ObjCIvarDecl *IV,
384cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian                                    SmallVectorImpl<ObjCIvarDecl *> &IVars);
385cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian
38664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    // Block rewriting.
38764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    void RewriteBlocksInFunctionProtoType(QualType funcType, NamedDecl *D);
38864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
38964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    // Block specific rewrite rules.
39064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    void RewriteBlockPointerDecl(NamedDecl *VD);
3914fe261cb0a6420b103335acc1f6bcb7b72188184Fariborz Jahanian    void RewriteByRefVar(VarDecl *VD, bool firstDecl, bool lastDecl);
392f4b88a45902af1802a1cb42ba48b1c474474f228John McCall    Stmt *RewriteBlockDeclRefExpr(DeclRefExpr *VD);
39364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    Stmt *RewriteLocalVariableExternalStorage(DeclRefExpr *DRE);
39464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    void RewriteBlockPointerFunctionArgs(FunctionDecl *FD);
39564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
39664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    void RewriteObjCInternalStruct(ObjCInterfaceDecl *CDecl,
39764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                      std::string &Result);
39864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
39915f87771cae0c31da45c05b34841d0a2ca70bc87Fariborz Jahanian    void RewriteObjCFieldDecl(FieldDecl *fieldDecl, std::string &Result);
400b68258fba663cd6a75bf44114e4eb2849551a45fFariborz Jahanian    bool IsTagDefinedInsideClass(ObjCContainerDecl *IDecl, TagDecl *Tag,
4018fba894335b979e6d213c685bca959168c1f2182Fariborz Jahanian                                 bool &IsNamedDefinition);
4028fba894335b979e6d213c685bca959168c1f2182Fariborz Jahanian    void RewriteLocallyDefinedNamedAggregates(FieldDecl *fieldDecl,
4038fba894335b979e6d213c685bca959168c1f2182Fariborz Jahanian                                              std::string &Result);
40415f87771cae0c31da45c05b34841d0a2ca70bc87Fariborz Jahanian
40597c1fd651c24638a4989b4e1f8eb2e629c2073d1Fariborz Jahanian    bool RewriteObjCFieldDeclType(QualType &Type, std::string &Result);
40697c1fd651c24638a4989b4e1f8eb2e629c2073d1Fariborz Jahanian
40772c88f13f79e2012b8a5f84cf48c6af779dfd1baFariborz Jahanian    void RewriteIvarOffsetSymbols(ObjCInterfaceDecl *CDecl,
40872c88f13f79e2012b8a5f84cf48c6af779dfd1baFariborz Jahanian                                  std::string &Result);
409651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
410651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    void Initialize(ASTContext &context) override;
411651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
41248d798ce32447607144db70a484cdb99c1180663Benjamin Kramer    // Misc. AST transformation routines. Sometimes they end up calling
41364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    // rewriting routines on the new ASTs.
41464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    CallExpr *SynthesizeCallToFunctionDecl(FunctionDecl *FD,
41564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                           Expr **args, unsigned nargs,
41664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                           SourceLocation StartLoc=SourceLocation(),
41764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                           SourceLocation EndLoc=SourceLocation());
418be8d55ce4a20b86d9337dcb28759e068cb3510f3Fariborz Jahanian
419be8d55ce4a20b86d9337dcb28759e068cb3510f3Fariborz Jahanian    Expr *SynthMsgSendStretCallExpr(FunctionDecl *MsgSendStretFlavor,
420be8d55ce4a20b86d9337dcb28759e068cb3510f3Fariborz Jahanian                                        QualType returnType,
421be8d55ce4a20b86d9337dcb28759e068cb3510f3Fariborz Jahanian                                        SmallVectorImpl<QualType> &ArgTypes,
422be8d55ce4a20b86d9337dcb28759e068cb3510f3Fariborz Jahanian                                        SmallVectorImpl<Expr*> &MsgExprs,
423be8d55ce4a20b86d9337dcb28759e068cb3510f3Fariborz Jahanian                                        ObjCMethodDecl *Method);
42464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
42564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    Stmt *SynthMessageExpr(ObjCMessageExpr *Exp,
42664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                           SourceLocation StartLoc=SourceLocation(),
42764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                           SourceLocation EndLoc=SourceLocation());
42864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
42964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    void SynthCountByEnumWithState(std::string &buf);
43064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    void SynthMsgSendFunctionDecl();
43164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    void SynthMsgSendSuperFunctionDecl();
43264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    void SynthMsgSendStretFunctionDecl();
43364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    void SynthMsgSendFpretFunctionDecl();
43464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    void SynthMsgSendSuperStretFunctionDecl();
43564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    void SynthGetClassFunctionDecl();
43664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    void SynthGetMetaClassFunctionDecl();
43764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    void SynthGetSuperClassFunctionDecl();
43864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    void SynthSelGetUidFunctionDecl();
439e575359c34a9248c55ec0c03a8fc945f1ee4cb01Benjamin Kramer    void SynthSuperConstructorFunctionDecl();
44064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
44164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    // Rewriting metadata
44264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    template<typename MethodIterator>
44364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    void RewriteObjCMethodsMetaData(MethodIterator MethodBegin,
44464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                    MethodIterator MethodEnd,
44564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                    bool IsInstanceMethod,
44664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                    StringRef prefix,
44764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                    StringRef ClassName,
44864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                    std::string &Result);
449da9624a77352bc61b9713c31edd671c02a3ff260Fariborz Jahanian    void RewriteObjCProtocolMetaData(ObjCProtocolDecl *Protocol,
450da9624a77352bc61b9713c31edd671c02a3ff260Fariborz Jahanian                                     std::string &Result);
451b4ee88060a5c277085ec6da9890e4c7da3651f86Fariborz Jahanian    void RewriteObjCProtocolListMetaData(
45264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                   const ObjCList<ObjCProtocolDecl> &Prots,
45364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                   StringRef prefix, StringRef ClassName, std::string &Result);
454b4ee88060a5c277085ec6da9890e4c7da3651f86Fariborz Jahanian    void RewriteObjCClassMetaData(ObjCImplementationDecl *IDecl,
45564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                          std::string &Result);
456b4ee88060a5c277085ec6da9890e4c7da3651f86Fariborz Jahanian    void RewriteClassSetupInitHook(std::string &Result);
457e0335786c17a6ca45966f66094146e9d8ba2d54aFariborz Jahanian
458b4ee88060a5c277085ec6da9890e4c7da3651f86Fariborz Jahanian    void RewriteMetaDataIntoBuffer(std::string &Result);
459b4ee88060a5c277085ec6da9890e4c7da3651f86Fariborz Jahanian    void WriteImageInfo(std::string &Result);
460b4ee88060a5c277085ec6da9890e4c7da3651f86Fariborz Jahanian    void RewriteObjCCategoryImplDecl(ObjCCategoryImplDecl *CDecl,
46164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                             std::string &Result);
462b4ee88060a5c277085ec6da9890e4c7da3651f86Fariborz Jahanian    void RewriteCategorySetupInitHook(std::string &Result);
46364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
46464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    // Rewriting ivar
465b4ee88060a5c277085ec6da9890e4c7da3651f86Fariborz Jahanian    void RewriteIvarOffsetComputation(ObjCIvarDecl *ivar,
46664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                              std::string &Result);
467b4ee88060a5c277085ec6da9890e4c7da3651f86Fariborz Jahanian    Stmt *RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV);
46864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
46964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
47064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    std::string SynthesizeByrefCopyDestroyHelper(VarDecl *VD, int flag);
47164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    std::string SynthesizeBlockHelperFuncs(BlockExpr *CE, int i,
47264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                      StringRef funcName, std::string Tag);
47364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    std::string SynthesizeBlockFunc(BlockExpr *CE, int i,
47464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                      StringRef funcName, std::string Tag);
47564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    std::string SynthesizeBlockImpl(BlockExpr *CE,
47664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                    std::string Tag, std::string Desc);
47764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    std::string SynthesizeBlockDescriptor(std::string DescTag,
47864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                          std::string ImplTag,
47964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                          int i, StringRef funcName,
48064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                          unsigned hasCopy);
48164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    Stmt *SynthesizeBlockCall(CallExpr *Exp, const Expr* BlockExp);
48264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    void SynthesizeBlockLiterals(SourceLocation FunLocStart,
48364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                 StringRef FunName);
48464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    FunctionDecl *SynthBlockInitFunctionDecl(StringRef name);
48564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    Stmt *SynthBlockInitExpr(BlockExpr *Exp,
4866b9240e058bf3451685df73fc8ce181b3046e92bCraig Topper                      const SmallVectorImpl<DeclRefExpr *> &InnerBlockDeclRefs);
48764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
48864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    // Misc. helper routines.
48964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    QualType getProtocolType();
49064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    void WarnAboutReturnGotoStmts(Stmt *S);
49164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    void CheckFunctionPointerDecl(QualType dType, NamedDecl *ND);
49264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    void InsertBlockLiteralsWithinFunction(FunctionDecl *FD);
49364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    void InsertBlockLiteralsWithinMethod(ObjCMethodDecl *MD);
49464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
49564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    bool IsDeclStmtInForeachHeader(DeclStmt *DS);
49664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    void CollectBlockDeclRefInfo(BlockExpr *Exp);
49764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    void GetBlockDeclRefExprs(Stmt *S);
4986b9240e058bf3451685df73fc8ce181b3046e92bCraig Topper    void GetInnerBlockDeclRefExprs(Stmt *S,
4996b9240e058bf3451685df73fc8ce181b3046e92bCraig Topper                SmallVectorImpl<DeclRefExpr *> &InnerBlockDeclRefs,
500176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines                llvm::SmallPtrSetImpl<const DeclContext *> &InnerContexts);
50164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
50264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    // We avoid calling Type::isBlockPointerType(), since it operates on the
50364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    // canonical type. We only care if the top-level type is a closure pointer.
50464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    bool isTopLevelBlockPointerType(QualType T) {
50564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      return isa<BlockPointerType>(T);
50664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    }
50764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
50864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    /// convertBlockPointerToFunctionPointer - Converts a block-pointer type
50964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    /// to a function pointer type and upon success, returns true; false
51064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    /// otherwise.
51164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    bool convertBlockPointerToFunctionPointer(QualType &T) {
51264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      if (isTopLevelBlockPointerType(T)) {
51364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        const BlockPointerType *BPT = T->getAs<BlockPointerType>();
51464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        T = Context->getPointerType(BPT->getPointeeType());
51564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        return true;
51664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      }
51764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      return false;
51864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    }
51964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
520164d6f8c7e040cb766b071ce92320a18dafbece1Fariborz Jahanian    bool convertObjCTypeToCStyleType(QualType &T);
521164d6f8c7e040cb766b071ce92320a18dafbece1Fariborz Jahanian
52264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    bool needToScanForQualifiers(QualType T);
52364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    QualType getSuperStructType();
52464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    QualType getConstantStringStructType();
52564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    QualType convertFunctionTypeOfBlocks(const FunctionType *FT);
52664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    bool BufferContainsPPDirectives(const char *startBuf, const char *endBuf);
52764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
52864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    void convertToUnqualifiedObjCType(QualType &T) {
529e35abe1fd3f867ae51d5c68d98578d537eb6becaFariborz Jahanian      if (T->isObjCQualifiedIdType()) {
530e35abe1fd3f867ae51d5c68d98578d537eb6becaFariborz Jahanian        bool isConst = T.isConstQualified();
531e35abe1fd3f867ae51d5c68d98578d537eb6becaFariborz Jahanian        T = isConst ? Context->getObjCIdType().withConst()
532e35abe1fd3f867ae51d5c68d98578d537eb6becaFariborz Jahanian                    : Context->getObjCIdType();
533e35abe1fd3f867ae51d5c68d98578d537eb6becaFariborz Jahanian      }
53464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      else if (T->isObjCQualifiedClassType())
53564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        T = Context->getObjCClassType();
53664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      else if (T->isObjCObjectPointerType() &&
53764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian               T->getPointeeType()->isObjCQualifiedInterfaceType()) {
53864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        if (const ObjCObjectPointerType * OBJPT =
53964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian              T->getAsObjCInterfacePointerType()) {
54064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian          const ObjCInterfaceType *IFaceT = OBJPT->getInterfaceType();
54164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian          T = QualType(IFaceT, 0);
54264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian          T = Context->getPointerType(T);
54364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        }
54464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian     }
54564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    }
54664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
54764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    // FIXME: This predicate seems like it would be useful to add to ASTContext.
54864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    bool isObjCType(QualType T) {
54964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      if (!LangOpts.ObjC1 && !LangOpts.ObjC2)
55064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        return false;
55164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
55264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      QualType OCT = Context->getCanonicalType(T).getUnqualifiedType();
55364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
55464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      if (OCT == Context->getCanonicalType(Context->getObjCIdType()) ||
55564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian          OCT == Context->getCanonicalType(Context->getObjCClassType()))
55664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        return true;
55764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
55864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      if (const PointerType *PT = OCT->getAs<PointerType>()) {
55964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        if (isa<ObjCInterfaceType>(PT->getPointeeType()) ||
56064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian            PT->getPointeeType()->isObjCQualifiedIdType())
56164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian          return true;
56264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      }
56364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      return false;
56464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    }
56564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    bool PointerTypeTakesAnyBlockArguments(QualType QT);
56664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    bool PointerTypeTakesAnyObjCQualifiedType(QualType QT);
56764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    void GetExtentOfArgList(const char *Name, const char *&LParen,
56864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                            const char *&RParen);
56964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
57064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    void QuoteDoublequotes(std::string &From, std::string &To) {
57164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      for (unsigned i = 0; i < From.length(); i++) {
57264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        if (From[i] == '"')
57364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian          To += "\\\"";
57464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        else
57564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian          To += From[i];
57664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      }
57764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    }
57864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
57964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    QualType getSimpleFunctionType(QualType result,
580bea522ff43a3f11c7a2bc7949119dbb9fce19e39Jordan Rose                                   ArrayRef<QualType> args,
58164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                   bool variadic = false) {
58264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      if (result == Context->getObjCInstanceType())
58364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        result =  Context->getObjCIdType();
58464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      FunctionProtoType::ExtProtoInfo fpi;
58564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      fpi.Variadic = variadic;
586bea522ff43a3f11c7a2bc7949119dbb9fce19e39Jordan Rose      return Context->getFunctionType(result, args, fpi);
58764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    }
58864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
58964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    // Helper function: create a CStyleCastExpr with trivial type source info.
59064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    CStyleCastExpr* NoTypeInfoCStyleCastExpr(ASTContext *Ctx, QualType Ty,
59164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                             CastKind Kind, Expr *E) {
59264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      TypeSourceInfo *TInfo = Ctx->getTrivialTypeSourceInfo(Ty, SourceLocation());
5936bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      return CStyleCastExpr::Create(*Ctx, Ty, VK_RValue, Kind, E, nullptr,
5946bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines                                    TInfo, SourceLocation(), SourceLocation());
59564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    }
59688f7f75e35425f3f228473c4c84a2445793a39c1Fariborz Jahanian
59788f7f75e35425f3f228473c4c84a2445793a39c1Fariborz Jahanian    bool ImplementationIsNonLazy(const ObjCImplDecl *OD) const {
59888f7f75e35425f3f228473c4c84a2445793a39c1Fariborz Jahanian      IdentifierInfo* II = &Context->Idents.get("load");
59988f7f75e35425f3f228473c4c84a2445793a39c1Fariborz Jahanian      Selector LoadSel = Context->Selectors.getSelector(0, &II);
6006bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      return OD->getClassMethod(LoadSel) != nullptr;
60188f7f75e35425f3f228473c4c84a2445793a39c1Fariborz Jahanian    }
602651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
603651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    StringLiteral *getStringLiteral(StringRef Str) {
604651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      QualType StrType = Context->getConstantArrayType(
605651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines          Context->CharTy, llvm::APInt(32, Str.size() + 1), ArrayType::Normal,
606651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines          0);
607651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      return StringLiteral::Create(*Context, Str, StringLiteral::Ascii,
608651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                                   /*Pascal=*/false, StrType, SourceLocation());
609651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    }
61064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  };
61164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
61264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian}
61364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
61464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanianvoid RewriteModernObjC::RewriteBlocksInFunctionProtoType(QualType funcType,
61564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                                   NamedDecl *D) {
61664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  if (const FunctionProtoType *fproto
61764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      = dyn_cast<FunctionProtoType>(funcType.IgnoreParens())) {
618651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    for (const auto &I : fproto->param_types())
619651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      if (isTopLevelBlockPointerType(I)) {
62064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        // All the args are checked/rewritten. Don't call twice!
62164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        RewriteBlockPointerDecl(D);
62264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        break;
62364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      }
62464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  }
62564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian}
62664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
62764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanianvoid RewriteModernObjC::CheckFunctionPointerDecl(QualType funcType, NamedDecl *ND) {
62864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  const PointerType *PT = funcType->getAs<PointerType>();
62964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  if (PT && PointerTypeTakesAnyBlockArguments(funcType))
63064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    RewriteBlocksInFunctionProtoType(PT->getPointeeType(), ND);
63164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian}
63264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
63364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanianstatic bool IsHeaderFile(const std::string &Filename) {
63464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  std::string::size_type DotPos = Filename.rfind('.');
63564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
63664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  if (DotPos == std::string::npos) {
63764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    // no file extension
63864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    return false;
63964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  }
64064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
64164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  std::string Ext = std::string(Filename.begin()+DotPos+1, Filename.end());
64264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  // C header: .h
64364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  // C++ header: .hh or .H;
64464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  return Ext == "h" || Ext == "hh" || Ext == "H";
64564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian}
64664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
64764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz JahanianRewriteModernObjC::RewriteModernObjC(std::string inFile, raw_ostream* OS,
64864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                         DiagnosticsEngine &D, const LangOptions &LOpts,
649ada7191795dde85a620008094fbe5464abdb916bFariborz Jahanian                         bool silenceMacroWarn,
650ada7191795dde85a620008094fbe5464abdb916bFariborz Jahanian                         bool LineInfo)
65164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      : Diags(D), LangOpts(LOpts), InFileName(inFile), OutFile(OS),
652ada7191795dde85a620008094fbe5464abdb916bFariborz Jahanian        SilenceRewriteMacroWarning(silenceMacroWarn), GenerateLineInfo(LineInfo) {
65364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  IsHeader = IsHeaderFile(inFile);
65464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  RewriteFailedDiag = Diags.getCustomDiagID(DiagnosticsEngine::Warning,
65564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian               "rewriting sub-expression within a macro (may not be correct)");
656d13c2c291f9fec2ed0e12a65f1638710ca979bb0Fariborz Jahanian  // FIXME. This should be an error. But if block is not called, it is OK. And it
657d13c2c291f9fec2ed0e12a65f1638710ca979bb0Fariborz Jahanian  // may break including some headers.
658d13c2c291f9fec2ed0e12a65f1638710ca979bb0Fariborz Jahanian  GlobalBlockRewriteFailedDiag = Diags.getCustomDiagID(DiagnosticsEngine::Warning,
659d13c2c291f9fec2ed0e12a65f1638710ca979bb0Fariborz Jahanian    "rewriting block literal declared in global scope is not implemented");
660d13c2c291f9fec2ed0e12a65f1638710ca979bb0Fariborz Jahanian
66164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  TryFinallyContainsReturnDiag = Diags.getCustomDiagID(
66264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian               DiagnosticsEngine::Warning,
66364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian               "rewriter doesn't support user-specified control flow semantics "
66464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian               "for @try/@finally (code may not execute properly)");
66564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian}
66664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
667176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hinesstd::unique_ptr<ASTConsumer> clang::CreateModernObjCRewriter(
668176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    const std::string &InFile, raw_ostream *OS, DiagnosticsEngine &Diags,
669176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    const LangOptions &LOpts, bool SilenceRewriteMacroWarning, bool LineInfo) {
670176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  return llvm::make_unique<RewriteModernObjC>(
671176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      InFile, OS, Diags, LOpts, SilenceRewriteMacroWarning, LineInfo);
67264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian}
67364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
67464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanianvoid RewriteModernObjC::InitializeCommon(ASTContext &context) {
67564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  Context = &context;
67664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  SM = &Context->getSourceManager();
67764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  TUDecl = Context->getTranslationUnitDecl();
6786bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  MsgSendFunctionDecl = nullptr;
6796bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  MsgSendSuperFunctionDecl = nullptr;
6806bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  MsgSendStretFunctionDecl = nullptr;
6816bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  MsgSendSuperStretFunctionDecl = nullptr;
6826bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  MsgSendFpretFunctionDecl = nullptr;
6836bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  GetClassFunctionDecl = nullptr;
6846bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  GetMetaClassFunctionDecl = nullptr;
6856bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  GetSuperClassFunctionDecl = nullptr;
6866bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  SelGetUidFunctionDecl = nullptr;
6876bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  CFStringFunctionDecl = nullptr;
6886bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  ConstantStringClassReference = nullptr;
6896bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  NSStringRecord = nullptr;
6906bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  CurMethodDef = nullptr;
6916bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  CurFunctionDef = nullptr;
6926bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  GlobalVarDecl = nullptr;
6936bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  GlobalConstructionExp = nullptr;
6946bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  SuperStructDecl = nullptr;
6956bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  ProtocolTypeDecl = nullptr;
6966bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  ConstantStringDecl = nullptr;
69764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  BcLabelCount = 0;
6986bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  SuperConstructorFunctionDecl = nullptr;
69964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  NumObjCStringLiterals = 0;
7006bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  PropParentMap = nullptr;
7016bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  CurrentBody = nullptr;
70264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  DisableReplaceStmt = false;
70364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  objc_impl_method = false;
70464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
70564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  // Get the ID and start/end of the main file.
70664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  MainFileID = SM->getMainFileID();
70764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  const llvm::MemoryBuffer *MainBuf = SM->getBuffer(MainFileID);
70864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  MainFileStart = MainBuf->getBufferStart();
70964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  MainFileEnd = MainBuf->getBufferEnd();
71064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
7114e4d08403ca5cfd4d558fa2936215d3a4e5a528dDavid Blaikie  Rewrite.setSourceMgr(Context->getSourceManager(), Context->getLangOpts());
71264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian}
71364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
71464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian//===----------------------------------------------------------------------===//
71564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian// Top Level Driver Code
71664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian//===----------------------------------------------------------------------===//
71764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
71864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanianvoid RewriteModernObjC::HandleTopLevelSingleDecl(Decl *D) {
71964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  if (Diags.hasErrorOccurred())
72064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    return;
72164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
72264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  // Two cases: either the decl could be in the main file, or it could be in a
72364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  // #included file.  If the former, rewrite it now.  If the later, check to see
72464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  // if we rewrote the #include/#import.
72564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  SourceLocation Loc = D->getLocation();
72664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  Loc = SM->getExpansionLoc(Loc);
72764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
72864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  // If this is for a builtin, ignore it.
72964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  if (Loc.isInvalid()) return;
73064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
73164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  // Look for built-in declarations that we need to refer during the rewrite.
73264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
73364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    RewriteFunctionDecl(FD);
73464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  } else if (VarDecl *FVD = dyn_cast<VarDecl>(D)) {
73564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    // declared in <Foundation/NSString.h>
73664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    if (FVD->getName() == "_NSConstantStringClassReference") {
73764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      ConstantStringClassReference = FVD;
73864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      return;
73964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    }
74064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  } else if (ObjCCategoryDecl *CD = dyn_cast<ObjCCategoryDecl>(D)) {
74164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    RewriteCategoryDecl(CD);
74264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  } else if (ObjCProtocolDecl *PD = dyn_cast<ObjCProtocolDecl>(D)) {
74364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    if (PD->isThisDeclarationADefinition())
74464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      RewriteProtocolDecl(PD);
74564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  } else if (LinkageSpecDecl *LSD = dyn_cast<LinkageSpecDecl>(D)) {
7468e86b2d03e6e58ef9a58d1d3ad70726ae7a3b4fdFariborz Jahanian    // FIXME. This will not work in all situations and leaving it out
7478e86b2d03e6e58ef9a58d1d3ad70726ae7a3b4fdFariborz Jahanian    // is harmless.
7488e86b2d03e6e58ef9a58d1d3ad70726ae7a3b4fdFariborz Jahanian    // RewriteLinkageSpec(LSD);
7498e86b2d03e6e58ef9a58d1d3ad70726ae7a3b4fdFariborz Jahanian
75064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    // Recurse into linkage specifications
75164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    for (DeclContext::decl_iterator DI = LSD->decls_begin(),
75264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                 DIEnd = LSD->decls_end();
75364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian         DI != DIEnd; ) {
75464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      if (ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>((*DI))) {
75564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        if (!IFace->isThisDeclarationADefinition()) {
75664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian          SmallVector<Decl *, 8> DG;
75764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian          SourceLocation StartLoc = IFace->getLocStart();
75864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian          do {
75964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian            if (isa<ObjCInterfaceDecl>(*DI) &&
76064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                !cast<ObjCInterfaceDecl>(*DI)->isThisDeclarationADefinition() &&
76164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                StartLoc == (*DI)->getLocStart())
76264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian              DG.push_back(*DI);
76364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian            else
76464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian              break;
76564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
76664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian            ++DI;
76764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian          } while (DI != DIEnd);
76864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian          RewriteForwardClassDecl(DG);
76964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian          continue;
77064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        }
771b3f904f79bbe55f3e088d7174d64d20d186914a1Fariborz Jahanian        else {
772b3f904f79bbe55f3e088d7174d64d20d186914a1Fariborz Jahanian          // Keep track of all interface declarations seen.
773b3f904f79bbe55f3e088d7174d64d20d186914a1Fariborz Jahanian          ObjCInterfacesSeen.push_back(IFace);
774b3f904f79bbe55f3e088d7174d64d20d186914a1Fariborz Jahanian          ++DI;
775b3f904f79bbe55f3e088d7174d64d20d186914a1Fariborz Jahanian          continue;
776b3f904f79bbe55f3e088d7174d64d20d186914a1Fariborz Jahanian        }
77764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      }
77864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
77964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      if (ObjCProtocolDecl *Proto = dyn_cast<ObjCProtocolDecl>((*DI))) {
78064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        if (!Proto->isThisDeclarationADefinition()) {
78164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian          SmallVector<Decl *, 8> DG;
78264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian          SourceLocation StartLoc = Proto->getLocStart();
78364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian          do {
78464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian            if (isa<ObjCProtocolDecl>(*DI) &&
78564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                !cast<ObjCProtocolDecl>(*DI)->isThisDeclarationADefinition() &&
78664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                StartLoc == (*DI)->getLocStart())
78764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian              DG.push_back(*DI);
78864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian            else
78964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian              break;
79064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
79164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian            ++DI;
79264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian          } while (DI != DIEnd);
79364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian          RewriteForwardProtocolDecl(DG);
79464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian          continue;
79564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        }
79664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      }
79764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
79864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      HandleTopLevelSingleDecl(*DI);
79964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      ++DI;
80064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    }
80164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  }
80264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  // If we have a decl in the main file, see if we should rewrite it.
80324146975f1af8c1b4b14e8545f218129d0e7dfebEli Friedman  if (SM->isWrittenInMainFile(Loc))
80464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    return HandleDeclInMainFile(D);
80564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian}
80664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
80764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian//===----------------------------------------------------------------------===//
80864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian// Syntactic (non-AST) Rewriting Code
80964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian//===----------------------------------------------------------------------===//
81064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
81164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanianvoid RewriteModernObjC::RewriteInclude() {
81264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  SourceLocation LocStart = SM->getLocForStartOfFile(MainFileID);
81364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  StringRef MainBuf = SM->getBufferData(MainFileID);
81464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  const char *MainBufStart = MainBuf.begin();
81564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  const char *MainBufEnd = MainBuf.end();
81664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  size_t ImportLen = strlen("import");
81764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
81864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  // Loop over the whole file, looking for includes.
81964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  for (const char *BufPtr = MainBufStart; BufPtr < MainBufEnd; ++BufPtr) {
82064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    if (*BufPtr == '#') {
82164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      if (++BufPtr == MainBufEnd)
82264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        return;
82364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      while (*BufPtr == ' ' || *BufPtr == '\t')
82464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        if (++BufPtr == MainBufEnd)
82564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian          return;
82664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      if (!strncmp(BufPtr, "import", ImportLen)) {
82764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        // replace import with include
82864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        SourceLocation ImportLoc =
82964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian          LocStart.getLocWithOffset(BufPtr-MainBufStart);
83064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        ReplaceText(ImportLoc, ImportLen, "include");
83164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        BufPtr += ImportLen;
83264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      }
83364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    }
83464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  }
83564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian}
83664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
837163d3cef334169e41225d94a4c353e0d7159570bFariborz Jahanianstatic void WriteInternalIvarName(const ObjCInterfaceDecl *IDecl,
838163d3cef334169e41225d94a4c353e0d7159570bFariborz Jahanian                                  ObjCIvarDecl *IvarDecl, std::string &Result) {
839163d3cef334169e41225d94a4c353e0d7159570bFariborz Jahanian  Result += "OBJC_IVAR_$_";
840163d3cef334169e41225d94a4c353e0d7159570bFariborz Jahanian  Result += IDecl->getName();
841163d3cef334169e41225d94a4c353e0d7159570bFariborz Jahanian  Result += "$";
842163d3cef334169e41225d94a4c353e0d7159570bFariborz Jahanian  Result += IvarDecl->getName();
843163d3cef334169e41225d94a4c353e0d7159570bFariborz Jahanian}
844163d3cef334169e41225d94a4c353e0d7159570bFariborz Jahanian
845163d3cef334169e41225d94a4c353e0d7159570bFariborz Jahanianstd::string
846163d3cef334169e41225d94a4c353e0d7159570bFariborz JahanianRewriteModernObjC::getIvarAccessString(ObjCIvarDecl *D) {
847163d3cef334169e41225d94a4c353e0d7159570bFariborz Jahanian  const ObjCInterfaceDecl *ClassDecl = D->getContainingInterface();
848163d3cef334169e41225d94a4c353e0d7159570bFariborz Jahanian
849163d3cef334169e41225d94a4c353e0d7159570bFariborz Jahanian  // Build name of symbol holding ivar offset.
850163d3cef334169e41225d94a4c353e0d7159570bFariborz Jahanian  std::string IvarOffsetName;
851cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian  if (D->isBitField())
852cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian    ObjCIvarBitfieldGroupOffset(D, IvarOffsetName);
853cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian  else
854cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian    WriteInternalIvarName(ClassDecl, D, IvarOffsetName);
855163d3cef334169e41225d94a4c353e0d7159570bFariborz Jahanian
856163d3cef334169e41225d94a4c353e0d7159570bFariborz Jahanian
857163d3cef334169e41225d94a4c353e0d7159570bFariborz Jahanian  std::string S = "(*(";
858163d3cef334169e41225d94a4c353e0d7159570bFariborz Jahanian  QualType IvarT = D->getType();
859cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian  if (D->isBitField())
860cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian    IvarT = GetGroupRecordTypeForObjCIvarBitfield(D);
861163d3cef334169e41225d94a4c353e0d7159570bFariborz Jahanian
862163d3cef334169e41225d94a4c353e0d7159570bFariborz Jahanian  if (!isa<TypedefType>(IvarT) && IvarT->isRecordType()) {
863163d3cef334169e41225d94a4c353e0d7159570bFariborz Jahanian    RecordDecl *RD = IvarT->getAs<RecordType>()->getDecl();
864163d3cef334169e41225d94a4c353e0d7159570bFariborz Jahanian    RD = RD->getDefinition();
865163d3cef334169e41225d94a4c353e0d7159570bFariborz Jahanian    if (RD && !RD->getDeclName().getAsIdentifierInfo()) {
866163d3cef334169e41225d94a4c353e0d7159570bFariborz Jahanian      // decltype(((Foo_IMPL*)0)->bar) *
867163d3cef334169e41225d94a4c353e0d7159570bFariborz Jahanian      ObjCContainerDecl *CDecl =
868163d3cef334169e41225d94a4c353e0d7159570bFariborz Jahanian      dyn_cast<ObjCContainerDecl>(D->getDeclContext());
869163d3cef334169e41225d94a4c353e0d7159570bFariborz Jahanian      // ivar in class extensions requires special treatment.
870163d3cef334169e41225d94a4c353e0d7159570bFariborz Jahanian      if (ObjCCategoryDecl *CatDecl = dyn_cast<ObjCCategoryDecl>(CDecl))
871163d3cef334169e41225d94a4c353e0d7159570bFariborz Jahanian        CDecl = CatDecl->getClassInterface();
872163d3cef334169e41225d94a4c353e0d7159570bFariborz Jahanian      std::string RecName = CDecl->getName();
873163d3cef334169e41225d94a4c353e0d7159570bFariborz Jahanian      RecName += "_IMPL";
874163d3cef334169e41225d94a4c353e0d7159570bFariborz Jahanian      RecordDecl *RD = RecordDecl::Create(*Context, TTK_Struct, TUDecl,
875163d3cef334169e41225d94a4c353e0d7159570bFariborz Jahanian                                          SourceLocation(), SourceLocation(),
876163d3cef334169e41225d94a4c353e0d7159570bFariborz Jahanian                                          &Context->Idents.get(RecName.c_str()));
877163d3cef334169e41225d94a4c353e0d7159570bFariborz Jahanian      QualType PtrStructIMPL = Context->getPointerType(Context->getTagDeclType(RD));
878163d3cef334169e41225d94a4c353e0d7159570bFariborz Jahanian      unsigned UnsignedIntSize =
879163d3cef334169e41225d94a4c353e0d7159570bFariborz Jahanian      static_cast<unsigned>(Context->getTypeSize(Context->UnsignedIntTy));
880163d3cef334169e41225d94a4c353e0d7159570bFariborz Jahanian      Expr *Zero = IntegerLiteral::Create(*Context,
881163d3cef334169e41225d94a4c353e0d7159570bFariborz Jahanian                                          llvm::APInt(UnsignedIntSize, 0),
882163d3cef334169e41225d94a4c353e0d7159570bFariborz Jahanian                                          Context->UnsignedIntTy, SourceLocation());
883163d3cef334169e41225d94a4c353e0d7159570bFariborz Jahanian      Zero = NoTypeInfoCStyleCastExpr(Context, PtrStructIMPL, CK_BitCast, Zero);
884163d3cef334169e41225d94a4c353e0d7159570bFariborz Jahanian      ParenExpr *PE = new (Context) ParenExpr(SourceLocation(), SourceLocation(),
885163d3cef334169e41225d94a4c353e0d7159570bFariborz Jahanian                                              Zero);
8866bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      FieldDecl *FD = FieldDecl::Create(*Context, nullptr, SourceLocation(),
887163d3cef334169e41225d94a4c353e0d7159570bFariborz Jahanian                                        SourceLocation(),
888163d3cef334169e41225d94a4c353e0d7159570bFariborz Jahanian                                        &Context->Idents.get(D->getNameAsString()),
88933337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar                                        IvarT, nullptr,
89033337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar                                        /*BitWidth=*/nullptr, /*Mutable=*/true,
89133337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar                                        ICIS_NoInit);
89233337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar      MemberExpr *ME = new (Context)
89333337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar          MemberExpr(PE, true, SourceLocation(), FD, SourceLocation(),
89433337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar                     FD->getType(), VK_LValue, OK_Ordinary);
89533337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar      IvarT = Context->getDecltypeType(ME, ME->getType());
89633337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar    }
89733337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  }
898163d3cef334169e41225d94a4c353e0d7159570bFariborz Jahanian  convertObjCTypeToCStyleType(IvarT);
899163d3cef334169e41225d94a4c353e0d7159570bFariborz Jahanian  QualType castT = Context->getPointerType(IvarT);
900163d3cef334169e41225d94a4c353e0d7159570bFariborz Jahanian  std::string TypeString(castT.getAsString(Context->getPrintingPolicy()));
901163d3cef334169e41225d94a4c353e0d7159570bFariborz Jahanian  S += TypeString;
902163d3cef334169e41225d94a4c353e0d7159570bFariborz Jahanian  S += ")";
903163d3cef334169e41225d94a4c353e0d7159570bFariborz Jahanian
904163d3cef334169e41225d94a4c353e0d7159570bFariborz Jahanian  // ((char *)self + IVAR_OFFSET_SYMBOL_NAME)
905163d3cef334169e41225d94a4c353e0d7159570bFariborz Jahanian  S += "((char *)self + ";
906163d3cef334169e41225d94a4c353e0d7159570bFariborz Jahanian  S += IvarOffsetName;
907163d3cef334169e41225d94a4c353e0d7159570bFariborz Jahanian  S += "))";
908cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian  if (D->isBitField()) {
909cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian    S += ".";
910cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian    S += D->getNameAsString();
911cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian  }
912163d3cef334169e41225d94a4c353e0d7159570bFariborz Jahanian  ReferencedIvars[const_cast<ObjCInterfaceDecl *>(ClassDecl)].insert(D);
91364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  return S;
91464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian}
91564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
916301e2e40f9d56c2fa01d3021a4d8e2d343fafd35Fariborz Jahanian/// mustSynthesizeSetterGetterMethod - returns true if setter or getter has not
917301e2e40f9d56c2fa01d3021a4d8e2d343fafd35Fariborz Jahanian/// been found in the class implementation. In this case, it must be synthesized.
918301e2e40f9d56c2fa01d3021a4d8e2d343fafd35Fariborz Jahanianstatic bool mustSynthesizeSetterGetterMethod(ObjCImplementationDecl *IMP,
919301e2e40f9d56c2fa01d3021a4d8e2d343fafd35Fariborz Jahanian                                             ObjCPropertyDecl *PD,
920301e2e40f9d56c2fa01d3021a4d8e2d343fafd35Fariborz Jahanian                                             bool getter) {
921301e2e40f9d56c2fa01d3021a4d8e2d343fafd35Fariborz Jahanian  return getter ? !IMP->getInstanceMethod(PD->getGetterName())
922301e2e40f9d56c2fa01d3021a4d8e2d343fafd35Fariborz Jahanian                : !IMP->getInstanceMethod(PD->getSetterName());
923301e2e40f9d56c2fa01d3021a4d8e2d343fafd35Fariborz Jahanian
924301e2e40f9d56c2fa01d3021a4d8e2d343fafd35Fariborz Jahanian}
925301e2e40f9d56c2fa01d3021a4d8e2d343fafd35Fariborz Jahanian
92664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanianvoid RewriteModernObjC::RewritePropertyImplDecl(ObjCPropertyImplDecl *PID,
92764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                          ObjCImplementationDecl *IMD,
92864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                          ObjCCategoryImplDecl *CID) {
92964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  static bool objcGetPropertyDefined = false;
93064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  static bool objcSetPropertyDefined = false;
931301e2e40f9d56c2fa01d3021a4d8e2d343fafd35Fariborz Jahanian  SourceLocation startGetterSetterLoc;
932301e2e40f9d56c2fa01d3021a4d8e2d343fafd35Fariborz Jahanian
933301e2e40f9d56c2fa01d3021a4d8e2d343fafd35Fariborz Jahanian  if (PID->getLocStart().isValid()) {
934301e2e40f9d56c2fa01d3021a4d8e2d343fafd35Fariborz Jahanian    SourceLocation startLoc = PID->getLocStart();
935301e2e40f9d56c2fa01d3021a4d8e2d343fafd35Fariborz Jahanian    InsertText(startLoc, "// ");
936301e2e40f9d56c2fa01d3021a4d8e2d343fafd35Fariborz Jahanian    const char *startBuf = SM->getCharacterData(startLoc);
937301e2e40f9d56c2fa01d3021a4d8e2d343fafd35Fariborz Jahanian    assert((*startBuf == '@') && "bogus @synthesize location");
938301e2e40f9d56c2fa01d3021a4d8e2d343fafd35Fariborz Jahanian    const char *semiBuf = strchr(startBuf, ';');
939301e2e40f9d56c2fa01d3021a4d8e2d343fafd35Fariborz Jahanian    assert((*semiBuf == ';') && "@synthesize: can't find ';'");
940301e2e40f9d56c2fa01d3021a4d8e2d343fafd35Fariborz Jahanian    startGetterSetterLoc = startLoc.getLocWithOffset(semiBuf-startBuf+1);
941301e2e40f9d56c2fa01d3021a4d8e2d343fafd35Fariborz Jahanian  }
942301e2e40f9d56c2fa01d3021a4d8e2d343fafd35Fariborz Jahanian  else
943301e2e40f9d56c2fa01d3021a4d8e2d343fafd35Fariborz Jahanian    startGetterSetterLoc = IMD ? IMD->getLocEnd() : CID->getLocEnd();
94464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
94564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  if (PID->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic)
94664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    return; // FIXME: is this correct?
94764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
94864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  // Generate the 'getter' function.
94964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  ObjCPropertyDecl *PD = PID->getPropertyDecl();
95064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  ObjCIvarDecl *OID = PID->getPropertyIvarDecl();
95162bbe07f5aed5a2f9ae55ef480c4268cb4435d99Jordan Rose  assert(IMD && OID && "Synthesized ivars must be attached to @implementation");
95264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
953ad017fa7a4df7389d245d02a49b3c79ed70bedb9Bill Wendling  unsigned Attributes = PD->getPropertyAttributes();
954301e2e40f9d56c2fa01d3021a4d8e2d343fafd35Fariborz Jahanian  if (mustSynthesizeSetterGetterMethod(IMD, PD, true /*getter*/)) {
955ad017fa7a4df7389d245d02a49b3c79ed70bedb9Bill Wendling    bool GenGetProperty = !(Attributes & ObjCPropertyDecl::OBJC_PR_nonatomic) &&
956ad017fa7a4df7389d245d02a49b3c79ed70bedb9Bill Wendling                          (Attributes & (ObjCPropertyDecl::OBJC_PR_retain |
95764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                         ObjCPropertyDecl::OBJC_PR_copy));
95864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    std::string Getr;
95964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    if (GenGetProperty && !objcGetPropertyDefined) {
96064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      objcGetPropertyDefined = true;
96164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      // FIXME. Is this attribute correct in all cases?
96264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      Getr = "\nextern \"C\" __declspec(dllimport) "
96364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian            "id objc_getProperty(id, SEL, long, bool);\n";
96464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    }
96564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    RewriteObjCMethodDecl(OID->getContainingInterface(),
96664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                          PD->getGetterMethodDecl(), Getr);
96764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    Getr += "{ ";
96864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    // Synthesize an explicit cast to gain access to the ivar.
96964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    // See objc-act.c:objc_synthesize_new_getter() for details.
97064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    if (GenGetProperty) {
97164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      // return objc_getProperty(self, _cmd, offsetof(ClassDecl, OID), 1)
97264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      Getr += "typedef ";
9736bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      const FunctionType *FPRetType = nullptr;
974651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      RewriteTypeIntoString(PD->getGetterMethodDecl()->getReturnType(), Getr,
97564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                            FPRetType);
97664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      Getr += " _TYPE";
97764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      if (FPRetType) {
97864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        Getr += ")"; // close the precedence "scope" for "*".
97964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
98064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        // Now, emit the argument types (if any).
98164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        if (const FunctionProtoType *FT = dyn_cast<FunctionProtoType>(FPRetType)){
98264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian          Getr += "(";
983651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines          for (unsigned i = 0, e = FT->getNumParams(); i != e; ++i) {
98464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian            if (i) Getr += ", ";
985651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines            std::string ParamStr =
986651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                FT->getParamType(i).getAsString(Context->getPrintingPolicy());
98764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian            Getr += ParamStr;
98864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian          }
98964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian          if (FT->isVariadic()) {
990651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines            if (FT->getNumParams())
991651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines              Getr += ", ";
99264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian            Getr += "...";
99364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian          }
99464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian          Getr += ")";
99564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        } else
99664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian          Getr += "()";
99764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      }
99864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      Getr += ";\n";
99964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      Getr += "return (_TYPE)";
100064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      Getr += "objc_getProperty(self, _cmd, ";
100164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      RewriteIvarOffsetComputation(OID, Getr);
100264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      Getr += ", 1)";
100364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    }
100464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    else
100564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      Getr += "return " + getIvarAccessString(OID);
100664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    Getr += "; }";
1007301e2e40f9d56c2fa01d3021a4d8e2d343fafd35Fariborz Jahanian    InsertText(startGetterSetterLoc, Getr);
100864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  }
100964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
1010301e2e40f9d56c2fa01d3021a4d8e2d343fafd35Fariborz Jahanian  if (PD->isReadOnly() ||
1011301e2e40f9d56c2fa01d3021a4d8e2d343fafd35Fariborz Jahanian      !mustSynthesizeSetterGetterMethod(IMD, PD, false /*setter*/))
101264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    return;
101364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
101464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  // Generate the 'setter' function.
101564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  std::string Setr;
1016ad017fa7a4df7389d245d02a49b3c79ed70bedb9Bill Wendling  bool GenSetProperty = Attributes & (ObjCPropertyDecl::OBJC_PR_retain |
101764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                      ObjCPropertyDecl::OBJC_PR_copy);
101864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  if (GenSetProperty && !objcSetPropertyDefined) {
101964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    objcSetPropertyDefined = true;
102064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    // FIXME. Is this attribute correct in all cases?
102164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    Setr = "\nextern \"C\" __declspec(dllimport) "
102264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    "void objc_setProperty (id, SEL, long, id, bool, bool);\n";
102364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  }
102464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
102564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  RewriteObjCMethodDecl(OID->getContainingInterface(),
102664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                        PD->getSetterMethodDecl(), Setr);
102764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  Setr += "{ ";
102864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  // Synthesize an explicit cast to initialize the ivar.
102964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  // See objc-act.c:objc_synthesize_new_setter() for details.
103064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  if (GenSetProperty) {
103164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    Setr += "objc_setProperty (self, _cmd, ";
103264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    RewriteIvarOffsetComputation(OID, Setr);
103364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    Setr += ", (id)";
103464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    Setr += PD->getName();
103564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    Setr += ", ";
1036ad017fa7a4df7389d245d02a49b3c79ed70bedb9Bill Wendling    if (Attributes & ObjCPropertyDecl::OBJC_PR_nonatomic)
103764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      Setr += "0, ";
103864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    else
103964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      Setr += "1, ";
1040ad017fa7a4df7389d245d02a49b3c79ed70bedb9Bill Wendling    if (Attributes & ObjCPropertyDecl::OBJC_PR_copy)
104164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      Setr += "1)";
104264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    else
104364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      Setr += "0)";
104464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  }
104564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  else {
104664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    Setr += getIvarAccessString(OID) + " = ";
104764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    Setr += PD->getName();
104864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  }
1049301e2e40f9d56c2fa01d3021a4d8e2d343fafd35Fariborz Jahanian  Setr += "; }\n";
1050301e2e40f9d56c2fa01d3021a4d8e2d343fafd35Fariborz Jahanian  InsertText(startGetterSetterLoc, Setr);
105164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian}
105264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
105364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanianstatic void RewriteOneForwardClassDecl(ObjCInterfaceDecl *ForwardDecl,
105464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                       std::string &typedefString) {
1055bfaa111e7106ad15a73513d953a1a19a7b626f10Fariborz Jahanian  typedefString += "\n#ifndef _REWRITER_typedef_";
105664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  typedefString += ForwardDecl->getNameAsString();
105764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  typedefString += "\n";
105864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  typedefString += "#define _REWRITER_typedef_";
105964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  typedefString += ForwardDecl->getNameAsString();
106064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  typedefString += "\n";
106164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  typedefString += "typedef struct objc_object ";
106264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  typedefString += ForwardDecl->getNameAsString();
1063c38503b4c1cda42154700016d60c6467af438a15Fariborz Jahanian  // typedef struct { } _objc_exc_Classname;
1064c38503b4c1cda42154700016d60c6467af438a15Fariborz Jahanian  typedefString += ";\ntypedef struct {} _objc_exc_";
1065c38503b4c1cda42154700016d60c6467af438a15Fariborz Jahanian  typedefString += ForwardDecl->getNameAsString();
106664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  typedefString += ";\n#endif\n";
106764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian}
106864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
106964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanianvoid RewriteModernObjC::RewriteForwardClassEpilogue(ObjCInterfaceDecl *ClassDecl,
107064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                              const std::string &typedefString) {
107164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    SourceLocation startLoc = ClassDecl->getLocStart();
107264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    const char *startBuf = SM->getCharacterData(startLoc);
107364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    const char *semiPtr = strchr(startBuf, ';');
107464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    // Replace the @class with typedefs corresponding to the classes.
107564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    ReplaceText(startLoc, semiPtr-startBuf+1, typedefString);
107664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian}
107764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
107864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanianvoid RewriteModernObjC::RewriteForwardClassDecl(DeclGroupRef D) {
107964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  std::string typedefString;
108064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  for (DeclGroupRef::iterator I = D.begin(), E = D.end(); I != E; ++I) {
10812330df43c89dfbcf888a1b0d608f71546f29b6cfFariborz Jahanian    if (ObjCInterfaceDecl *ForwardDecl = dyn_cast<ObjCInterfaceDecl>(*I)) {
10822330df43c89dfbcf888a1b0d608f71546f29b6cfFariborz Jahanian      if (I == D.begin()) {
10832330df43c89dfbcf888a1b0d608f71546f29b6cfFariborz Jahanian        // Translate to typedef's that forward reference structs with the same name
10842330df43c89dfbcf888a1b0d608f71546f29b6cfFariborz Jahanian        // as the class. As a convenience, we include the original declaration
10852330df43c89dfbcf888a1b0d608f71546f29b6cfFariborz Jahanian        // as a comment.
10862330df43c89dfbcf888a1b0d608f71546f29b6cfFariborz Jahanian        typedefString += "// @class ";
10872330df43c89dfbcf888a1b0d608f71546f29b6cfFariborz Jahanian        typedefString += ForwardDecl->getNameAsString();
10882330df43c89dfbcf888a1b0d608f71546f29b6cfFariborz Jahanian        typedefString += ";";
10892330df43c89dfbcf888a1b0d608f71546f29b6cfFariborz Jahanian      }
10902330df43c89dfbcf888a1b0d608f71546f29b6cfFariborz Jahanian      RewriteOneForwardClassDecl(ForwardDecl, typedefString);
109164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    }
10922330df43c89dfbcf888a1b0d608f71546f29b6cfFariborz Jahanian    else
10932330df43c89dfbcf888a1b0d608f71546f29b6cfFariborz Jahanian      HandleTopLevelSingleDecl(*I);
109464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  }
109564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  DeclGroupRef::iterator I = D.begin();
109664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  RewriteForwardClassEpilogue(cast<ObjCInterfaceDecl>(*I), typedefString);
109764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian}
109864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
109964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanianvoid RewriteModernObjC::RewriteForwardClassDecl(
11006b9240e058bf3451685df73fc8ce181b3046e92bCraig Topper                                const SmallVectorImpl<Decl *> &D) {
110164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  std::string typedefString;
110264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  for (unsigned i = 0; i < D.size(); i++) {
110364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    ObjCInterfaceDecl *ForwardDecl = cast<ObjCInterfaceDecl>(D[i]);
110464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    if (i == 0) {
110564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      typedefString += "// @class ";
110664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      typedefString += ForwardDecl->getNameAsString();
1107bfaa111e7106ad15a73513d953a1a19a7b626f10Fariborz Jahanian      typedefString += ";";
110864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    }
110964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    RewriteOneForwardClassDecl(ForwardDecl, typedefString);
111064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  }
111164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  RewriteForwardClassEpilogue(cast<ObjCInterfaceDecl>(D[0]), typedefString);
111264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian}
111364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
111464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanianvoid RewriteModernObjC::RewriteMethodDeclaration(ObjCMethodDecl *Method) {
111564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  // When method is a synthesized one, such as a getter/setter there is
111664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  // nothing to rewrite.
111764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  if (Method->isImplicit())
111864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    return;
111964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  SourceLocation LocStart = Method->getLocStart();
112064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  SourceLocation LocEnd = Method->getLocEnd();
112164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
112264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  if (SM->getExpansionLineNumber(LocEnd) >
112364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      SM->getExpansionLineNumber(LocStart)) {
112464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    InsertText(LocStart, "#if 0\n");
112564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    ReplaceText(LocEnd, 1, ";\n#endif\n");
112664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  } else {
112764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    InsertText(LocStart, "// ");
112864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  }
112964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian}
113064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
113164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanianvoid RewriteModernObjC::RewriteProperty(ObjCPropertyDecl *prop) {
113264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  SourceLocation Loc = prop->getAtLoc();
113364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
113464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  ReplaceText(Loc, 0, "// ");
113564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  // FIXME: handle properties that are declared across multiple lines.
113664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian}
113764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
113864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanianvoid RewriteModernObjC::RewriteCategoryDecl(ObjCCategoryDecl *CatDecl) {
113964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  SourceLocation LocStart = CatDecl->getLocStart();
114064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
114164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  // FIXME: handle category headers that are declared across multiple lines.
1142b68258fba663cd6a75bf44114e4eb2849551a45fFariborz Jahanian  if (CatDecl->getIvarRBraceLoc().isValid()) {
1143b68258fba663cd6a75bf44114e4eb2849551a45fFariborz Jahanian    ReplaceText(LocStart, 1, "/** ");
1144b68258fba663cd6a75bf44114e4eb2849551a45fFariborz Jahanian    ReplaceText(CatDecl->getIvarRBraceLoc(), 1, "**/ ");
1145b68258fba663cd6a75bf44114e4eb2849551a45fFariborz Jahanian  }
1146b68258fba663cd6a75bf44114e4eb2849551a45fFariborz Jahanian  else {
1147d2aea120011da5d411e486a9674e9fb05d22f51bFariborz Jahanian    ReplaceText(LocStart, 0, "// ");
1148b68258fba663cd6a75bf44114e4eb2849551a45fFariborz Jahanian  }
1149af300298ab86752fa64e339ba34195888a830756Fariborz Jahanian
1150651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  for (auto *I : CatDecl->properties())
1151651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    RewriteProperty(I);
115264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
1153651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  for (auto *I : CatDecl->instance_methods())
1154651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    RewriteMethodDeclaration(I);
1155651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  for (auto *I : CatDecl->class_methods())
1156651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    RewriteMethodDeclaration(I);
115764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
115864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  // Lastly, comment out the @end.
115964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  ReplaceText(CatDecl->getAtEndRange().getBegin(),
1160f9f30791dd20472675de012105219cd975ad1076Fariborz Jahanian              strlen("@end"), "/* @end */\n");
116164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian}
116264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
116364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanianvoid RewriteModernObjC::RewriteProtocolDecl(ObjCProtocolDecl *PDecl) {
116464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  SourceLocation LocStart = PDecl->getLocStart();
116564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  assert(PDecl->isThisDeclarationADefinition());
116664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
116764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  // FIXME: handle protocol headers that are declared across multiple lines.
116864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  ReplaceText(LocStart, 0, "// ");
116964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
1170651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  for (auto *I : PDecl->instance_methods())
1171651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    RewriteMethodDeclaration(I);
1172651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  for (auto *I : PDecl->class_methods())
1173651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    RewriteMethodDeclaration(I);
1174651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  for (auto *I : PDecl->properties())
1175651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    RewriteProperty(I);
117664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
117764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  // Lastly, comment out the @end.
117864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  SourceLocation LocEnd = PDecl->getAtEndRange().getBegin();
1179f9f30791dd20472675de012105219cd975ad1076Fariborz Jahanian  ReplaceText(LocEnd, strlen("@end"), "/* @end */\n");
118064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
118164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  // Must comment out @optional/@required
118264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  const char *startBuf = SM->getCharacterData(LocStart);
118364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  const char *endBuf = SM->getCharacterData(LocEnd);
118464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  for (const char *p = startBuf; p < endBuf; p++) {
118564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    if (*p == '@' && !strncmp(p+1, "optional", strlen("optional"))) {
118664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      SourceLocation OptionalLoc = LocStart.getLocWithOffset(p-startBuf);
118764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      ReplaceText(OptionalLoc, strlen("@optional"), "/* @optional */");
118864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
118964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    }
119064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    else if (*p == '@' && !strncmp(p+1, "required", strlen("required"))) {
119164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      SourceLocation OptionalLoc = LocStart.getLocWithOffset(p-startBuf);
119264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      ReplaceText(OptionalLoc, strlen("@required"), "/* @required */");
119364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
119464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    }
119564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  }
119664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian}
119764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
119864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanianvoid RewriteModernObjC::RewriteForwardProtocolDecl(DeclGroupRef D) {
119964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  SourceLocation LocStart = (*D.begin())->getLocStart();
120064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  if (LocStart.isInvalid())
120164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    llvm_unreachable("Invalid SourceLocation");
120264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  // FIXME: handle forward protocol that are declared across multiple lines.
120364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  ReplaceText(LocStart, 0, "// ");
120464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian}
120564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
120664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanianvoid
12076b9240e058bf3451685df73fc8ce181b3046e92bCraig TopperRewriteModernObjC::RewriteForwardProtocolDecl(const SmallVectorImpl<Decl *> &DG) {
120864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  SourceLocation LocStart = DG[0]->getLocStart();
120964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  if (LocStart.isInvalid())
121064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    llvm_unreachable("Invalid SourceLocation");
121164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  // FIXME: handle forward protocol that are declared across multiple lines.
121264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  ReplaceText(LocStart, 0, "// ");
121364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian}
121464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
1215b3f904f79bbe55f3e088d7174d64d20d186914a1Fariborz Jahanianvoid
1216b3f904f79bbe55f3e088d7174d64d20d186914a1Fariborz JahanianRewriteModernObjC::RewriteLinkageSpec(LinkageSpecDecl *LSD) {
1217b3f904f79bbe55f3e088d7174d64d20d186914a1Fariborz Jahanian  SourceLocation LocStart = LSD->getExternLoc();
1218b3f904f79bbe55f3e088d7174d64d20d186914a1Fariborz Jahanian  if (LocStart.isInvalid())
1219b3f904f79bbe55f3e088d7174d64d20d186914a1Fariborz Jahanian    llvm_unreachable("Invalid extern SourceLocation");
1220b3f904f79bbe55f3e088d7174d64d20d186914a1Fariborz Jahanian
1221b3f904f79bbe55f3e088d7174d64d20d186914a1Fariborz Jahanian  ReplaceText(LocStart, 0, "// ");
1222b3f904f79bbe55f3e088d7174d64d20d186914a1Fariborz Jahanian  if (!LSD->hasBraces())
1223b3f904f79bbe55f3e088d7174d64d20d186914a1Fariborz Jahanian    return;
1224b3f904f79bbe55f3e088d7174d64d20d186914a1Fariborz Jahanian  // FIXME. We don't rewrite well if '{' is not on same line as 'extern'.
1225b3f904f79bbe55f3e088d7174d64d20d186914a1Fariborz Jahanian  SourceLocation LocRBrace = LSD->getRBraceLoc();
1226b3f904f79bbe55f3e088d7174d64d20d186914a1Fariborz Jahanian  if (LocRBrace.isInvalid())
1227b3f904f79bbe55f3e088d7174d64d20d186914a1Fariborz Jahanian    llvm_unreachable("Invalid rbrace SourceLocation");
1228b3f904f79bbe55f3e088d7174d64d20d186914a1Fariborz Jahanian  ReplaceText(LocRBrace, 0, "// ");
1229b3f904f79bbe55f3e088d7174d64d20d186914a1Fariborz Jahanian}
1230b3f904f79bbe55f3e088d7174d64d20d186914a1Fariborz Jahanian
123164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanianvoid RewriteModernObjC::RewriteTypeIntoString(QualType T, std::string &ResultStr,
123264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                        const FunctionType *&FPRetType) {
123364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  if (T->isObjCQualifiedIdType())
123464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    ResultStr += "id";
123564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  else if (T->isFunctionPointerType() ||
123664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian           T->isBlockPointerType()) {
123764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    // needs special handling, since pointer-to-functions have special
123864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    // syntax (where a decaration models use).
123964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    QualType retType = T;
124064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    QualType PointeeTy;
124164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    if (const PointerType* PT = retType->getAs<PointerType>())
124264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      PointeeTy = PT->getPointeeType();
124364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    else if (const BlockPointerType *BPT = retType->getAs<BlockPointerType>())
124464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      PointeeTy = BPT->getPointeeType();
124564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    if ((FPRetType = PointeeTy->getAs<FunctionType>())) {
1246651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      ResultStr +=
1247651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines          FPRetType->getReturnType().getAsString(Context->getPrintingPolicy());
124864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      ResultStr += "(*";
124964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    }
125064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  } else
125164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    ResultStr += T.getAsString(Context->getPrintingPolicy());
125264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian}
125364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
125464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanianvoid RewriteModernObjC::RewriteObjCMethodDecl(const ObjCInterfaceDecl *IDecl,
125564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                        ObjCMethodDecl *OMD,
125664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                        std::string &ResultStr) {
125764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  //fprintf(stderr,"In RewriteObjCMethodDecl\n");
12586bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  const FunctionType *FPRetType = nullptr;
125964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  ResultStr += "\nstatic ";
1260651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  RewriteTypeIntoString(OMD->getReturnType(), ResultStr, FPRetType);
126164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  ResultStr += " ";
126264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
126364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  // Unique method name
126464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  std::string NameStr;
126564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
126664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  if (OMD->isInstanceMethod())
126764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    NameStr += "_I_";
126864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  else
126964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    NameStr += "_C_";
127064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
127164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  NameStr += IDecl->getNameAsString();
127264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  NameStr += "_";
127364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
127464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  if (ObjCCategoryImplDecl *CID =
127564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      dyn_cast<ObjCCategoryImplDecl>(OMD->getDeclContext())) {
127664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    NameStr += CID->getNameAsString();
127764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    NameStr += "_";
127864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  }
127964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  // Append selector names, replacing ':' with '_'
128064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  {
128164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    std::string selString = OMD->getSelector().getAsString();
128264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    int len = selString.size();
128364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    for (int i = 0; i < len; i++)
128464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      if (selString[i] == ':')
128564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        selString[i] = '_';
128664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    NameStr += selString;
128764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  }
128864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  // Remember this name for metadata emission
128964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  MethodInternalNames[OMD] = NameStr;
129064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  ResultStr += NameStr;
129164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
129264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  // Rewrite arguments
129364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  ResultStr += "(";
129464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
129564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  // invisible arguments
129664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  if (OMD->isInstanceMethod()) {
129764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    QualType selfTy = Context->getObjCInterfaceType(IDecl);
129864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    selfTy = Context->getPointerType(selfTy);
129964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    if (!LangOpts.MicrosoftExt) {
130064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      if (ObjCSynthesizedStructs.count(const_cast<ObjCInterfaceDecl*>(IDecl)))
130164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        ResultStr += "struct ";
130264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    }
130364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    // When rewriting for Microsoft, explicitly omit the structure name.
130464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    ResultStr += IDecl->getNameAsString();
130564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    ResultStr += " *";
130664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  }
130764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  else
130864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    ResultStr += Context->getObjCClassType().getAsString(
130964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      Context->getPrintingPolicy());
131064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
131164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  ResultStr += " self, ";
131264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  ResultStr += Context->getObjCSelType().getAsString(Context->getPrintingPolicy());
131364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  ResultStr += " _cmd";
131464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
131564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  // Method arguments.
1316651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  for (const auto *PDecl : OMD->params()) {
131764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    ResultStr += ", ";
131864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    if (PDecl->getType()->isObjCQualifiedIdType()) {
131964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      ResultStr += "id ";
132064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      ResultStr += PDecl->getNameAsString();
132164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    } else {
132264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      std::string Name = PDecl->getNameAsString();
132364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      QualType QT = PDecl->getType();
132464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      // Make sure we convert "t (^)(...)" to "t (*)(...)".
13252610f90135571be7bf983c80a1cf7bfa0844dc57Fariborz Jahanian      (void)convertBlockPointerToFunctionPointer(QT);
13262610f90135571be7bf983c80a1cf7bfa0844dc57Fariborz Jahanian      QT.getAsStringInternal(Name, Context->getPrintingPolicy());
132764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      ResultStr += Name;
132864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    }
132964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  }
133064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  if (OMD->isVariadic())
133164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    ResultStr += ", ...";
133264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  ResultStr += ") ";
133364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
133464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  if (FPRetType) {
133564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    ResultStr += ")"; // close the precedence "scope" for "*".
133664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
133764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    // Now, emit the argument types (if any).
133864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    if (const FunctionProtoType *FT = dyn_cast<FunctionProtoType>(FPRetType)) {
133964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      ResultStr += "(";
1340651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      for (unsigned i = 0, e = FT->getNumParams(); i != e; ++i) {
134164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        if (i) ResultStr += ", ";
1342651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines        std::string ParamStr =
1343651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines            FT->getParamType(i).getAsString(Context->getPrintingPolicy());
134464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        ResultStr += ParamStr;
134564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      }
134664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      if (FT->isVariadic()) {
1347651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines        if (FT->getNumParams())
1348651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines          ResultStr += ", ";
134964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        ResultStr += "...";
135064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      }
135164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      ResultStr += ")";
135264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    } else {
135364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      ResultStr += "()";
135464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    }
135564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  }
135664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian}
135764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanianvoid RewriteModernObjC::RewriteImplementationDecl(Decl *OID) {
135864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  ObjCImplementationDecl *IMD = dyn_cast<ObjCImplementationDecl>(OID);
135964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  ObjCCategoryImplDecl *CID = dyn_cast<ObjCCategoryImplDecl>(OID);
136064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
1361d2aea120011da5d411e486a9674e9fb05d22f51bFariborz Jahanian  if (IMD) {
1362b68258fba663cd6a75bf44114e4eb2849551a45fFariborz Jahanian    if (IMD->getIvarRBraceLoc().isValid()) {
1363b68258fba663cd6a75bf44114e4eb2849551a45fFariborz Jahanian      ReplaceText(IMD->getLocStart(), 1, "/** ");
1364b68258fba663cd6a75bf44114e4eb2849551a45fFariborz Jahanian      ReplaceText(IMD->getIvarRBraceLoc(), 1, "**/ ");
1365b68258fba663cd6a75bf44114e4eb2849551a45fFariborz Jahanian    }
1366b68258fba663cd6a75bf44114e4eb2849551a45fFariborz Jahanian    else {
1367b68258fba663cd6a75bf44114e4eb2849551a45fFariborz Jahanian      InsertText(IMD->getLocStart(), "// ");
1368d2aea120011da5d411e486a9674e9fb05d22f51bFariborz Jahanian    }
1369d2aea120011da5d411e486a9674e9fb05d22f51bFariborz Jahanian  }
1370d2aea120011da5d411e486a9674e9fb05d22f51bFariborz Jahanian  else
1371d2aea120011da5d411e486a9674e9fb05d22f51bFariborz Jahanian    InsertText(CID->getLocStart(), "// ");
137264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
1373651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  for (auto *OMD : IMD ? IMD->instance_methods() : CID->instance_methods()) {
137464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    std::string ResultStr;
137564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    RewriteObjCMethodDecl(OMD->getClassInterface(), OMD, ResultStr);
137664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    SourceLocation LocStart = OMD->getLocStart();
137764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    SourceLocation LocEnd = OMD->getCompoundBody()->getLocStart();
137864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
137964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    const char *startBuf = SM->getCharacterData(LocStart);
138064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    const char *endBuf = SM->getCharacterData(LocEnd);
138164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    ReplaceText(LocStart, endBuf-startBuf, ResultStr);
138264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  }
138364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
1384651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  for (auto *OMD : IMD ? IMD->class_methods() : CID->class_methods()) {
138564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    std::string ResultStr;
138664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    RewriteObjCMethodDecl(OMD->getClassInterface(), OMD, ResultStr);
138764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    SourceLocation LocStart = OMD->getLocStart();
138864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    SourceLocation LocEnd = OMD->getCompoundBody()->getLocStart();
138964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
139064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    const char *startBuf = SM->getCharacterData(LocStart);
139164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    const char *endBuf = SM->getCharacterData(LocEnd);
139264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    ReplaceText(LocStart, endBuf-startBuf, ResultStr);
139364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  }
1394651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  for (auto *I : IMD ? IMD->property_impls() : CID->property_impls())
1395651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    RewritePropertyImplDecl(I, IMD, CID);
139664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
139764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  InsertText(IMD ? IMD->getLocEnd() : CID->getLocEnd(), "// ");
139864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian}
139964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
140064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanianvoid RewriteModernObjC::RewriteInterfaceDecl(ObjCInterfaceDecl *ClassDecl) {
14018f1fed036eb78b747725560c10ad29d370d6ef62Fariborz Jahanian  // Do not synthesize more than once.
14028f1fed036eb78b747725560c10ad29d370d6ef62Fariborz Jahanian  if (ObjCSynthesizedStructs.count(ClassDecl))
14038f1fed036eb78b747725560c10ad29d370d6ef62Fariborz Jahanian    return;
14048f1fed036eb78b747725560c10ad29d370d6ef62Fariborz Jahanian  // Make sure super class's are written before current class is written.
14058f1fed036eb78b747725560c10ad29d370d6ef62Fariborz Jahanian  ObjCInterfaceDecl *SuperClass = ClassDecl->getSuperClass();
14068f1fed036eb78b747725560c10ad29d370d6ef62Fariborz Jahanian  while (SuperClass) {
14078f1fed036eb78b747725560c10ad29d370d6ef62Fariborz Jahanian    RewriteInterfaceDecl(SuperClass);
14088f1fed036eb78b747725560c10ad29d370d6ef62Fariborz Jahanian    SuperClass = SuperClass->getSuperClass();
14098f1fed036eb78b747725560c10ad29d370d6ef62Fariborz Jahanian  }
141064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  std::string ResultStr;
1411cf4c60feae11b2f6a135d7cd8ecf97a5040951c3Fariborz Jahanian  if (!ObjCWrittenInterfaces.count(ClassDecl->getCanonicalDecl())) {
141264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    // we haven't seen a forward decl - generate a typedef.
1413c38503b4c1cda42154700016d60c6467af438a15Fariborz Jahanian    RewriteOneForwardClassDecl(ClassDecl, ResultStr);
141472c88f13f79e2012b8a5f84cf48c6af779dfd1baFariborz Jahanian    RewriteIvarOffsetSymbols(ClassDecl, ResultStr);
141572c88f13f79e2012b8a5f84cf48c6af779dfd1baFariborz Jahanian
14164339bb3a71b6463415708553fda16aa7e44d07ebFariborz Jahanian    RewriteObjCInternalStruct(ClassDecl, ResultStr);
1417cf4c60feae11b2f6a135d7cd8ecf97a5040951c3Fariborz Jahanian    // Mark this typedef as having been written into its c++ equivalent.
1418cf4c60feae11b2f6a135d7cd8ecf97a5040951c3Fariborz Jahanian    ObjCWrittenInterfaces.insert(ClassDecl->getCanonicalDecl());
14194339bb3a71b6463415708553fda16aa7e44d07ebFariborz Jahanian
1420651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    for (auto *I : ClassDecl->properties())
1421651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      RewriteProperty(I);
1422651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    for (auto *I : ClassDecl->instance_methods())
1423651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      RewriteMethodDeclaration(I);
1424651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    for (auto *I : ClassDecl->class_methods())
1425651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      RewriteMethodDeclaration(I);
142664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
14274339bb3a71b6463415708553fda16aa7e44d07ebFariborz Jahanian    // Lastly, comment out the @end.
14284339bb3a71b6463415708553fda16aa7e44d07ebFariborz Jahanian    ReplaceText(ClassDecl->getAtEndRange().getBegin(), strlen("@end"),
1429f9f30791dd20472675de012105219cd975ad1076Fariborz Jahanian                "/* @end */\n");
14304339bb3a71b6463415708553fda16aa7e44d07ebFariborz Jahanian  }
143164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian}
143264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
143364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz JahanianStmt *RewriteModernObjC::RewritePropertyOrImplicitSetter(PseudoObjectExpr *PseudoOp) {
143464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  SourceRange OldRange = PseudoOp->getSourceRange();
143564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
143664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  // We just magically know some things about the structure of this
143764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  // expression.
143864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  ObjCMessageExpr *OldMsg =
143964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    cast<ObjCMessageExpr>(PseudoOp->getSemanticExpr(
144064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                            PseudoOp->getNumSemanticExprs() - 1));
144164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
144264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  // Because the rewriter doesn't allow us to rewrite rewritten code,
144364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  // we need to suppress rewriting the sub-statements.
144488ec6100812d8f551a824d7884e21aaa68138330Fariborz Jahanian  Expr *Base;
144588ec6100812d8f551a824d7884e21aaa68138330Fariborz Jahanian  SmallVector<Expr*, 2> Args;
144664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  {
144764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    DisableReplaceStmtScope S(*this);
144864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
144964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    // Rebuild the base expression if we have one.
14506bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    Base = nullptr;
145164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    if (OldMsg->getReceiverKind() == ObjCMessageExpr::Instance) {
145264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      Base = OldMsg->getInstanceReceiver();
145364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      Base = cast<OpaqueValueExpr>(Base)->getSourceExpr();
145464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      Base = cast<Expr>(RewriteFunctionBodyOrGlobalInitializer(Base));
145564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    }
145688ec6100812d8f551a824d7884e21aaa68138330Fariborz Jahanian
145788ec6100812d8f551a824d7884e21aaa68138330Fariborz Jahanian    unsigned numArgs = OldMsg->getNumArgs();
145888ec6100812d8f551a824d7884e21aaa68138330Fariborz Jahanian    for (unsigned i = 0; i < numArgs; i++) {
145988ec6100812d8f551a824d7884e21aaa68138330Fariborz Jahanian      Expr *Arg = OldMsg->getArg(i);
146088ec6100812d8f551a824d7884e21aaa68138330Fariborz Jahanian      if (isa<OpaqueValueExpr>(Arg))
146188ec6100812d8f551a824d7884e21aaa68138330Fariborz Jahanian        Arg = cast<OpaqueValueExpr>(Arg)->getSourceExpr();
146288ec6100812d8f551a824d7884e21aaa68138330Fariborz Jahanian      Arg = cast<Expr>(RewriteFunctionBodyOrGlobalInitializer(Arg));
146388ec6100812d8f551a824d7884e21aaa68138330Fariborz Jahanian      Args.push_back(Arg);
146488ec6100812d8f551a824d7884e21aaa68138330Fariborz Jahanian    }
146564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  }
146664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
146764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  // TODO: avoid this copy.
146864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  SmallVector<SourceLocation, 1> SelLocs;
146964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  OldMsg->getSelectorLocs(SelLocs);
147064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
14716bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  ObjCMessageExpr *NewMsg = nullptr;
147264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  switch (OldMsg->getReceiverKind()) {
147364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  case ObjCMessageExpr::Class:
147464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    NewMsg = ObjCMessageExpr::Create(*Context, OldMsg->getType(),
147564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                     OldMsg->getValueKind(),
147664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                     OldMsg->getLeftLoc(),
147764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                     OldMsg->getClassReceiverTypeInfo(),
147864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                     OldMsg->getSelector(),
147964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                     SelLocs,
148064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                     OldMsg->getMethodDecl(),
148188ec6100812d8f551a824d7884e21aaa68138330Fariborz Jahanian                                     Args,
148264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                     OldMsg->getRightLoc(),
148364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                     OldMsg->isImplicit());
148464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    break;
148564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
148664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  case ObjCMessageExpr::Instance:
148764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    NewMsg = ObjCMessageExpr::Create(*Context, OldMsg->getType(),
148864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                     OldMsg->getValueKind(),
148964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                     OldMsg->getLeftLoc(),
149064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                     Base,
149164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                     OldMsg->getSelector(),
149264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                     SelLocs,
149364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                     OldMsg->getMethodDecl(),
149488ec6100812d8f551a824d7884e21aaa68138330Fariborz Jahanian                                     Args,
149564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                     OldMsg->getRightLoc(),
149664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                     OldMsg->isImplicit());
149764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    break;
149864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
149964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  case ObjCMessageExpr::SuperClass:
150064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  case ObjCMessageExpr::SuperInstance:
150164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    NewMsg = ObjCMessageExpr::Create(*Context, OldMsg->getType(),
150264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                     OldMsg->getValueKind(),
150364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                     OldMsg->getLeftLoc(),
150464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                     OldMsg->getSuperLoc(),
150564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                 OldMsg->getReceiverKind() == ObjCMessageExpr::SuperInstance,
150664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                     OldMsg->getSuperType(),
150764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                     OldMsg->getSelector(),
150864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                     SelLocs,
150964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                     OldMsg->getMethodDecl(),
151088ec6100812d8f551a824d7884e21aaa68138330Fariborz Jahanian                                     Args,
151164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                     OldMsg->getRightLoc(),
151264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                     OldMsg->isImplicit());
151364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    break;
151464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  }
151564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
151664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  Stmt *Replacement = SynthMessageExpr(NewMsg);
151764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  ReplaceStmtWithRange(PseudoOp, Replacement, OldRange);
151864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  return Replacement;
151964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian}
152064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
152164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz JahanianStmt *RewriteModernObjC::RewritePropertyOrImplicitGetter(PseudoObjectExpr *PseudoOp) {
152264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  SourceRange OldRange = PseudoOp->getSourceRange();
152364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
152464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  // We just magically know some things about the structure of this
152564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  // expression.
152664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  ObjCMessageExpr *OldMsg =
152764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    cast<ObjCMessageExpr>(PseudoOp->getResultExpr()->IgnoreImplicit());
152864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
152964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  // Because the rewriter doesn't allow us to rewrite rewritten code,
153064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  // we need to suppress rewriting the sub-statements.
15316bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  Expr *Base = nullptr;
153288ec6100812d8f551a824d7884e21aaa68138330Fariborz Jahanian  SmallVector<Expr*, 1> Args;
153364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  {
153464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    DisableReplaceStmtScope S(*this);
153564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    // Rebuild the base expression if we have one.
153664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    if (OldMsg->getReceiverKind() == ObjCMessageExpr::Instance) {
153764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      Base = OldMsg->getInstanceReceiver();
153864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      Base = cast<OpaqueValueExpr>(Base)->getSourceExpr();
153964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      Base = cast<Expr>(RewriteFunctionBodyOrGlobalInitializer(Base));
154064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    }
154188ec6100812d8f551a824d7884e21aaa68138330Fariborz Jahanian    unsigned numArgs = OldMsg->getNumArgs();
154288ec6100812d8f551a824d7884e21aaa68138330Fariborz Jahanian    for (unsigned i = 0; i < numArgs; i++) {
154388ec6100812d8f551a824d7884e21aaa68138330Fariborz Jahanian      Expr *Arg = OldMsg->getArg(i);
154488ec6100812d8f551a824d7884e21aaa68138330Fariborz Jahanian      if (isa<OpaqueValueExpr>(Arg))
154588ec6100812d8f551a824d7884e21aaa68138330Fariborz Jahanian        Arg = cast<OpaqueValueExpr>(Arg)->getSourceExpr();
154688ec6100812d8f551a824d7884e21aaa68138330Fariborz Jahanian      Arg = cast<Expr>(RewriteFunctionBodyOrGlobalInitializer(Arg));
154788ec6100812d8f551a824d7884e21aaa68138330Fariborz Jahanian      Args.push_back(Arg);
154888ec6100812d8f551a824d7884e21aaa68138330Fariborz Jahanian    }
154964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  }
155064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
155164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  // Intentionally empty.
155264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  SmallVector<SourceLocation, 1> SelLocs;
155364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
15546bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  ObjCMessageExpr *NewMsg = nullptr;
155564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  switch (OldMsg->getReceiverKind()) {
155664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  case ObjCMessageExpr::Class:
155764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    NewMsg = ObjCMessageExpr::Create(*Context, OldMsg->getType(),
155864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                     OldMsg->getValueKind(),
155964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                     OldMsg->getLeftLoc(),
156064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                     OldMsg->getClassReceiverTypeInfo(),
156164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                     OldMsg->getSelector(),
156264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                     SelLocs,
156364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                     OldMsg->getMethodDecl(),
156464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                     Args,
156564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                     OldMsg->getRightLoc(),
156664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                     OldMsg->isImplicit());
156764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    break;
156864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
156964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  case ObjCMessageExpr::Instance:
157064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    NewMsg = ObjCMessageExpr::Create(*Context, OldMsg->getType(),
157164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                     OldMsg->getValueKind(),
157264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                     OldMsg->getLeftLoc(),
157364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                     Base,
157464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                     OldMsg->getSelector(),
157564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                     SelLocs,
157664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                     OldMsg->getMethodDecl(),
157764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                     Args,
157864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                     OldMsg->getRightLoc(),
157964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                     OldMsg->isImplicit());
158064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    break;
158164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
158264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  case ObjCMessageExpr::SuperClass:
158364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  case ObjCMessageExpr::SuperInstance:
158464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    NewMsg = ObjCMessageExpr::Create(*Context, OldMsg->getType(),
158564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                     OldMsg->getValueKind(),
158664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                     OldMsg->getLeftLoc(),
158764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                     OldMsg->getSuperLoc(),
158864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                 OldMsg->getReceiverKind() == ObjCMessageExpr::SuperInstance,
158964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                     OldMsg->getSuperType(),
159064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                     OldMsg->getSelector(),
159164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                     SelLocs,
159264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                     OldMsg->getMethodDecl(),
159364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                     Args,
159464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                     OldMsg->getRightLoc(),
159564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                     OldMsg->isImplicit());
159664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    break;
159764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  }
159864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
159964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  Stmt *Replacement = SynthMessageExpr(NewMsg);
160064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  ReplaceStmtWithRange(PseudoOp, Replacement, OldRange);
160164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  return Replacement;
160264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian}
160364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
160464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian/// SynthCountByEnumWithState - To print:
1605e38f08aa831617cd0b6dc90d82f98eda674c0fc8Fariborz Jahanian/// ((NSUInteger (*)
1606e38f08aa831617cd0b6dc90d82f98eda674c0fc8Fariborz Jahanian///  (id, SEL, struct __objcFastEnumerationState *, id *, NSUInteger))
160764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian///  (void *)objc_msgSend)((id)l_collection,
160864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian///                        sel_registerName(
160964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian///                          "countByEnumeratingWithState:objects:count:"),
161064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian///                        &enumState,
1611e38f08aa831617cd0b6dc90d82f98eda674c0fc8Fariborz Jahanian///                        (id *)__rw_items, (NSUInteger)16)
161264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian///
161364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanianvoid RewriteModernObjC::SynthCountByEnumWithState(std::string &buf) {
1614e38f08aa831617cd0b6dc90d82f98eda674c0fc8Fariborz Jahanian  buf += "((_WIN_NSUInteger (*) (id, SEL, struct __objcFastEnumerationState *, "
1615e38f08aa831617cd0b6dc90d82f98eda674c0fc8Fariborz Jahanian  "id *, _WIN_NSUInteger))(void *)objc_msgSend)";
161664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  buf += "\n\t\t";
161764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  buf += "((id)l_collection,\n\t\t";
161864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  buf += "sel_registerName(\"countByEnumeratingWithState:objects:count:\"),";
161964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  buf += "\n\t\t";
162064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  buf += "&enumState, "
1621e38f08aa831617cd0b6dc90d82f98eda674c0fc8Fariborz Jahanian         "(id *)__rw_items, (_WIN_NSUInteger)16)";
162264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian}
162364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
162464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian/// RewriteBreakStmt - Rewrite for a break-stmt inside an ObjC2's foreach
162564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian/// statement to exit to its outer synthesized loop.
162664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian///
162764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz JahanianStmt *RewriteModernObjC::RewriteBreakStmt(BreakStmt *S) {
162864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  if (Stmts.empty() || !isa<ObjCForCollectionStmt>(Stmts.back()))
162964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    return S;
163064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  // replace break with goto __break_label
163164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  std::string buf;
163264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
163364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  SourceLocation startLoc = S->getLocStart();
163464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  buf = "goto __break_label_";
163564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  buf += utostr(ObjCBcLabelNo.back());
163664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  ReplaceText(startLoc, strlen("break"), buf);
163764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
16386bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  return nullptr;
163964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian}
164064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
1641f616ae2d1356dadde26ff553eb689e5455d65808Fariborz Jahanianvoid RewriteModernObjC::ConvertSourceLocationToLineDirective(
1642f616ae2d1356dadde26ff553eb689e5455d65808Fariborz Jahanian                                          SourceLocation Loc,
1643f616ae2d1356dadde26ff553eb689e5455d65808Fariborz Jahanian                                          std::string &LineString) {
1644ada7191795dde85a620008094fbe5464abdb916bFariborz Jahanian  if (Loc.isFileID() && GenerateLineInfo) {
1645f616ae2d1356dadde26ff553eb689e5455d65808Fariborz Jahanian    LineString += "\n#line ";
1646f616ae2d1356dadde26ff553eb689e5455d65808Fariborz Jahanian    PresumedLoc PLoc = SM->getPresumedLoc(Loc);
1647f616ae2d1356dadde26ff553eb689e5455d65808Fariborz Jahanian    LineString += utostr(PLoc.getLine());
1648f616ae2d1356dadde26ff553eb689e5455d65808Fariborz Jahanian    LineString += " \"";
1649f616ae2d1356dadde26ff553eb689e5455d65808Fariborz Jahanian    LineString += Lexer::Stringify(PLoc.getFilename());
1650f616ae2d1356dadde26ff553eb689e5455d65808Fariborz Jahanian    LineString += "\"\n";
1651f616ae2d1356dadde26ff553eb689e5455d65808Fariborz Jahanian  }
1652f616ae2d1356dadde26ff553eb689e5455d65808Fariborz Jahanian}
1653f616ae2d1356dadde26ff553eb689e5455d65808Fariborz Jahanian
165464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian/// RewriteContinueStmt - Rewrite for a continue-stmt inside an ObjC2's foreach
165564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian/// statement to continue with its inner synthesized loop.
165664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian///
165764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz JahanianStmt *RewriteModernObjC::RewriteContinueStmt(ContinueStmt *S) {
165864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  if (Stmts.empty() || !isa<ObjCForCollectionStmt>(Stmts.back()))
165964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    return S;
166064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  // replace continue with goto __continue_label
166164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  std::string buf;
166264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
166364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  SourceLocation startLoc = S->getLocStart();
166464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  buf = "goto __continue_label_";
166564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  buf += utostr(ObjCBcLabelNo.back());
166664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  ReplaceText(startLoc, strlen("continue"), buf);
166764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
16686bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  return nullptr;
166964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian}
167064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
167164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian/// RewriteObjCForCollectionStmt - Rewriter for ObjC2's foreach statement.
167264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian///  It rewrites:
167364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian/// for ( type elem in collection) { stmts; }
167464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
167564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian/// Into:
167664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian/// {
167764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian///   type elem;
167864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian///   struct __objcFastEnumerationState enumState = { 0 };
167964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian///   id __rw_items[16];
168064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian///   id l_collection = (id)collection;
1681e38f08aa831617cd0b6dc90d82f98eda674c0fc8Fariborz Jahanian///   NSUInteger limit = [l_collection countByEnumeratingWithState:&enumState
168264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian///                                       objects:__rw_items count:16];
168364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian/// if (limit) {
168464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian///   unsigned long startMutations = *enumState.mutationsPtr;
168564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian///   do {
168664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian///        unsigned long counter = 0;
168764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian///        do {
168864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian///             if (startMutations != *enumState.mutationsPtr)
168964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian///               objc_enumerationMutation(l_collection);
169064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian///             elem = (type)enumState.itemsPtr[counter++];
169164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian///             stmts;
169264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian///             __continue_label: ;
169364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian///        } while (counter < limit);
1694e38f08aa831617cd0b6dc90d82f98eda674c0fc8Fariborz Jahanian///   } while ((limit = [l_collection countByEnumeratingWithState:&enumState
1695e38f08aa831617cd0b6dc90d82f98eda674c0fc8Fariborz Jahanian///                                  objects:__rw_items count:16]));
169664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian///   elem = nil;
169764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian///   __break_label: ;
169864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian///  }
169964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian///  else
170064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian///       elem = nil;
170164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian///  }
170264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian///
170364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz JahanianStmt *RewriteModernObjC::RewriteObjCForCollectionStmt(ObjCForCollectionStmt *S,
170464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                                SourceLocation OrigEnd) {
170564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  assert(!Stmts.empty() && "ObjCForCollectionStmt - Statement stack empty");
170664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  assert(isa<ObjCForCollectionStmt>(Stmts.back()) &&
170764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian         "ObjCForCollectionStmt Statement stack mismatch");
170864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  assert(!ObjCBcLabelNo.empty() &&
170964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian         "ObjCForCollectionStmt - Label No stack empty");
171064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
171164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  SourceLocation startLoc = S->getLocStart();
171264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  const char *startBuf = SM->getCharacterData(startLoc);
171364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  StringRef elementName;
171464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  std::string elementTypeAsString;
171564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  std::string buf;
1716f616ae2d1356dadde26ff553eb689e5455d65808Fariborz Jahanian  // line directive first.
1717f616ae2d1356dadde26ff553eb689e5455d65808Fariborz Jahanian  SourceLocation ForEachLoc = S->getForLoc();
1718f616ae2d1356dadde26ff553eb689e5455d65808Fariborz Jahanian  ConvertSourceLocationToLineDirective(ForEachLoc, buf);
1719f616ae2d1356dadde26ff553eb689e5455d65808Fariborz Jahanian  buf += "{\n\t";
172064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  if (DeclStmt *DS = dyn_cast<DeclStmt>(S->getElement())) {
172164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    // type elem;
172264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    NamedDecl* D = cast<NamedDecl>(DS->getSingleDecl());
172364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    QualType ElementType = cast<ValueDecl>(D)->getType();
172464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    if (ElementType->isObjCQualifiedIdType() ||
172564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        ElementType->isObjCQualifiedInterfaceType())
172664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      // Simply use 'id' for all qualified types.
172764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      elementTypeAsString = "id";
172864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    else
172964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      elementTypeAsString = ElementType.getAsString(Context->getPrintingPolicy());
173064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    buf += elementTypeAsString;
173164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    buf += " ";
173264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    elementName = D->getName();
173364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    buf += elementName;
173464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    buf += ";\n\t";
173564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  }
173664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  else {
173764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    DeclRefExpr *DR = cast<DeclRefExpr>(S->getElement());
173864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    elementName = DR->getDecl()->getName();
173964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    ValueDecl *VD = cast<ValueDecl>(DR->getDecl());
174064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    if (VD->getType()->isObjCQualifiedIdType() ||
174164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        VD->getType()->isObjCQualifiedInterfaceType())
174264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      // Simply use 'id' for all qualified types.
174364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      elementTypeAsString = "id";
174464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    else
174564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      elementTypeAsString = VD->getType().getAsString(Context->getPrintingPolicy());
174664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  }
174764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
174864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  // struct __objcFastEnumerationState enumState = { 0 };
174964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  buf += "struct __objcFastEnumerationState enumState = { 0 };\n\t";
175064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  // id __rw_items[16];
175164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  buf += "id __rw_items[16];\n\t";
175264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  // id l_collection = (id)
175364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  buf += "id l_collection = (id)";
175464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  // Find start location of 'collection' the hard way!
175564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  const char *startCollectionBuf = startBuf;
175664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  startCollectionBuf += 3;  // skip 'for'
175764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  startCollectionBuf = strchr(startCollectionBuf, '(');
175864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  startCollectionBuf++; // skip '('
175964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  // find 'in' and skip it.
176064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  while (*startCollectionBuf != ' ' ||
176164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian         *(startCollectionBuf+1) != 'i' || *(startCollectionBuf+2) != 'n' ||
176264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian         (*(startCollectionBuf+3) != ' ' &&
176364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian          *(startCollectionBuf+3) != '[' && *(startCollectionBuf+3) != '('))
176464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    startCollectionBuf++;
176564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  startCollectionBuf += 3;
176664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
176764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  // Replace: "for (type element in" with string constructed thus far.
176864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  ReplaceText(startLoc, startCollectionBuf - startBuf, buf);
176964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  // Replace ')' in for '(' type elem in collection ')' with ';'
177064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  SourceLocation rightParenLoc = S->getRParenLoc();
177164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  const char *rparenBuf = SM->getCharacterData(rightParenLoc);
177264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  SourceLocation lparenLoc = startLoc.getLocWithOffset(rparenBuf-startBuf);
177364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  buf = ";\n\t";
177464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
177564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  // unsigned long limit = [l_collection countByEnumeratingWithState:&enumState
177664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  //                                   objects:__rw_items count:16];
177764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  // which is synthesized into:
1778e38f08aa831617cd0b6dc90d82f98eda674c0fc8Fariborz Jahanian  // NSUInteger limit =
1779e38f08aa831617cd0b6dc90d82f98eda674c0fc8Fariborz Jahanian  // ((NSUInteger (*)
1780e38f08aa831617cd0b6dc90d82f98eda674c0fc8Fariborz Jahanian  //  (id, SEL, struct __objcFastEnumerationState *, id *, NSUInteger))
178164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  //  (void *)objc_msgSend)((id)l_collection,
178264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  //                        sel_registerName(
178364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  //                          "countByEnumeratingWithState:objects:count:"),
178464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  //                        (struct __objcFastEnumerationState *)&state,
1785e38f08aa831617cd0b6dc90d82f98eda674c0fc8Fariborz Jahanian  //                        (id *)__rw_items, (NSUInteger)16);
1786e38f08aa831617cd0b6dc90d82f98eda674c0fc8Fariborz Jahanian  buf += "_WIN_NSUInteger limit =\n\t\t";
178764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  SynthCountByEnumWithState(buf);
178864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  buf += ";\n\t";
178964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  /// if (limit) {
179064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  ///   unsigned long startMutations = *enumState.mutationsPtr;
179164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  ///   do {
179264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  ///        unsigned long counter = 0;
179364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  ///        do {
179464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  ///             if (startMutations != *enumState.mutationsPtr)
179564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  ///               objc_enumerationMutation(l_collection);
179664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  ///             elem = (type)enumState.itemsPtr[counter++];
179764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  buf += "if (limit) {\n\t";
179864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  buf += "unsigned long startMutations = *enumState.mutationsPtr;\n\t";
179964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  buf += "do {\n\t\t";
180064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  buf += "unsigned long counter = 0;\n\t\t";
180164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  buf += "do {\n\t\t\t";
180264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  buf += "if (startMutations != *enumState.mutationsPtr)\n\t\t\t\t";
180364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  buf += "objc_enumerationMutation(l_collection);\n\t\t\t";
180464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  buf += elementName;
180564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  buf += " = (";
180664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  buf += elementTypeAsString;
180764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  buf += ")enumState.itemsPtr[counter++];";
180864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  // Replace ')' in for '(' type elem in collection ')' with all of these.
180964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  ReplaceText(lparenLoc, 1, buf);
181064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
181164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  ///            __continue_label: ;
181264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  ///        } while (counter < limit);
1813e38f08aa831617cd0b6dc90d82f98eda674c0fc8Fariborz Jahanian  ///   } while ((limit = [l_collection countByEnumeratingWithState:&enumState
1814e38f08aa831617cd0b6dc90d82f98eda674c0fc8Fariborz Jahanian  ///                                  objects:__rw_items count:16]));
181564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  ///   elem = nil;
181664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  ///   __break_label: ;
181764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  ///  }
181864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  ///  else
181964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  ///       elem = nil;
182064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  ///  }
182164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  ///
182264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  buf = ";\n\t";
182364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  buf += "__continue_label_";
182464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  buf += utostr(ObjCBcLabelNo.back());
182564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  buf += ": ;";
182664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  buf += "\n\t\t";
182764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  buf += "} while (counter < limit);\n\t";
1828e38f08aa831617cd0b6dc90d82f98eda674c0fc8Fariborz Jahanian  buf += "} while ((limit = ";
182964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  SynthCountByEnumWithState(buf);
1830e38f08aa831617cd0b6dc90d82f98eda674c0fc8Fariborz Jahanian  buf += "));\n\t";
183164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  buf += elementName;
183264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  buf += " = ((";
183364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  buf += elementTypeAsString;
183464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  buf += ")0);\n\t";
183564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  buf += "__break_label_";
183664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  buf += utostr(ObjCBcLabelNo.back());
183764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  buf += ": ;\n\t";
183864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  buf += "}\n\t";
183964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  buf += "else\n\t\t";
184064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  buf += elementName;
184164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  buf += " = ((";
184264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  buf += elementTypeAsString;
184364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  buf += ")0);\n\t";
184464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  buf += "}\n";
184564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
184664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  // Insert all these *after* the statement body.
184764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  // FIXME: If this should support Obj-C++, support CXXTryStmt
184864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  if (isa<CompoundStmt>(S->getBody())) {
184964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    SourceLocation endBodyLoc = OrigEnd.getLocWithOffset(1);
185064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    InsertText(endBodyLoc, buf);
185164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  } else {
185264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    /* Need to treat single statements specially. For example:
185364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian     *
185464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian     *     for (A *a in b) if (stuff()) break;
185564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian     *     for (A *a in b) xxxyy;
185664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian     *
185764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian     * The following code simply scans ahead to the semi to find the actual end.
185864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian     */
185964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    const char *stmtBuf = SM->getCharacterData(OrigEnd);
186064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    const char *semiBuf = strchr(stmtBuf, ';');
186164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    assert(semiBuf && "Can't find ';'");
186264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    SourceLocation endBodyLoc = OrigEnd.getLocWithOffset(semiBuf-stmtBuf+1);
186364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    InsertText(endBodyLoc, buf);
186464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  }
186564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  Stmts.pop_back();
186664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  ObjCBcLabelNo.pop_back();
18676bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  return nullptr;
186864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian}
186964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
1870542125f84d63864b6f7abbed61576a5dffecd097Fariborz Jahanianstatic void Write_RethrowObject(std::string &buf) {
1871542125f84d63864b6f7abbed61576a5dffecd097Fariborz Jahanian  buf += "{ struct _FIN { _FIN(id reth) : rethrow(reth) {}\n";
1872542125f84d63864b6f7abbed61576a5dffecd097Fariborz Jahanian  buf += "\t~_FIN() { if (rethrow) objc_exception_throw(rethrow); }\n";
1873542125f84d63864b6f7abbed61576a5dffecd097Fariborz Jahanian  buf += "\tid rethrow;\n";
1874542125f84d63864b6f7abbed61576a5dffecd097Fariborz Jahanian  buf += "\t} _fin_force_rethow(_rethrow);";
1875542125f84d63864b6f7abbed61576a5dffecd097Fariborz Jahanian}
1876542125f84d63864b6f7abbed61576a5dffecd097Fariborz Jahanian
187764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian/// RewriteObjCSynchronizedStmt -
187864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian/// This routine rewrites @synchronized(expr) stmt;
187964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian/// into:
188064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian/// objc_sync_enter(expr);
188164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian/// @try stmt @finally { objc_sync_exit(expr); }
188264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian///
188364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz JahanianStmt *RewriteModernObjC::RewriteObjCSynchronizedStmt(ObjCAtSynchronizedStmt *S) {
188464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  // Get the start location and compute the semi location.
188564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  SourceLocation startLoc = S->getLocStart();
188664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  const char *startBuf = SM->getCharacterData(startLoc);
188764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
188864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  assert((*startBuf == '@') && "bogus @synchronized location");
188964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
189064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  std::string buf;
189143f4f1e92bb07a04c30c9781be4d0bb5cc30acddFariborz Jahanian  SourceLocation SynchLoc = S->getAtSynchronizedLoc();
189243f4f1e92bb07a04c30c9781be4d0bb5cc30acddFariborz Jahanian  ConvertSourceLocationToLineDirective(SynchLoc, buf);
1893786e56f5b49fb5f1a4314629a1b80c9308ead28eFariborz Jahanian  buf += "{ id _rethrow = 0; id _sync_obj = (id)";
1894542125f84d63864b6f7abbed61576a5dffecd097Fariborz Jahanian
189564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  const char *lparenBuf = startBuf;
189664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  while (*lparenBuf != '(') lparenBuf++;
189764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  ReplaceText(startLoc, lparenBuf-startBuf+1, buf);
189822e2f854cb7fd53e048fcbdbee1e78108cb8d146Fariborz Jahanian
189922e2f854cb7fd53e048fcbdbee1e78108cb8d146Fariborz Jahanian  buf = "; objc_sync_enter(_sync_obj);\n";
190022e2f854cb7fd53e048fcbdbee1e78108cb8d146Fariborz Jahanian  buf += "try {\n\tstruct _SYNC_EXIT { _SYNC_EXIT(id arg) : sync_exit(arg) {}";
190122e2f854cb7fd53e048fcbdbee1e78108cb8d146Fariborz Jahanian  buf += "\n\t~_SYNC_EXIT() {objc_sync_exit(sync_exit);}";
190222e2f854cb7fd53e048fcbdbee1e78108cb8d146Fariborz Jahanian  buf += "\n\tid sync_exit;";
190322e2f854cb7fd53e048fcbdbee1e78108cb8d146Fariborz Jahanian  buf += "\n\t} _sync_exit(_sync_obj);\n";
190422e2f854cb7fd53e048fcbdbee1e78108cb8d146Fariborz Jahanian
190522e2f854cb7fd53e048fcbdbee1e78108cb8d146Fariborz Jahanian  // We can't use S->getSynchExpr()->getLocEnd() to find the end location, since
190622e2f854cb7fd53e048fcbdbee1e78108cb8d146Fariborz Jahanian  // the sync expression is typically a message expression that's already
190722e2f854cb7fd53e048fcbdbee1e78108cb8d146Fariborz Jahanian  // been rewritten! (which implies the SourceLocation's are invalid).
190822e2f854cb7fd53e048fcbdbee1e78108cb8d146Fariborz Jahanian  SourceLocation RParenExprLoc = S->getSynchBody()->getLocStart();
190922e2f854cb7fd53e048fcbdbee1e78108cb8d146Fariborz Jahanian  const char *RParenExprLocBuf = SM->getCharacterData(RParenExprLoc);
191022e2f854cb7fd53e048fcbdbee1e78108cb8d146Fariborz Jahanian  while (*RParenExprLocBuf != ')') RParenExprLocBuf--;
191122e2f854cb7fd53e048fcbdbee1e78108cb8d146Fariborz Jahanian  RParenExprLoc = startLoc.getLocWithOffset(RParenExprLocBuf-startBuf);
191222e2f854cb7fd53e048fcbdbee1e78108cb8d146Fariborz Jahanian
191322e2f854cb7fd53e048fcbdbee1e78108cb8d146Fariborz Jahanian  SourceLocation LBranceLoc = S->getSynchBody()->getLocStart();
191422e2f854cb7fd53e048fcbdbee1e78108cb8d146Fariborz Jahanian  const char *LBraceLocBuf = SM->getCharacterData(LBranceLoc);
191522e2f854cb7fd53e048fcbdbee1e78108cb8d146Fariborz Jahanian  assert (*LBraceLocBuf == '{');
191622e2f854cb7fd53e048fcbdbee1e78108cb8d146Fariborz Jahanian  ReplaceText(RParenExprLoc, (LBraceLocBuf - SM->getCharacterData(RParenExprLoc) + 1), buf);
1917542125f84d63864b6f7abbed61576a5dffecd097Fariborz Jahanian
1918b655bf06d99bbdb58de5d012642b87cabddabd83Fariborz Jahanian  SourceLocation startRBraceLoc = S->getSynchBody()->getLocEnd();
19199ab511cde246a3a4e47b5b1c4aa2b861fcff08d5Matt Beaumont-Gay  assert((*SM->getCharacterData(startRBraceLoc) == '}') &&
19209ab511cde246a3a4e47b5b1c4aa2b861fcff08d5Matt Beaumont-Gay         "bogus @synchronized block");
1921542125f84d63864b6f7abbed61576a5dffecd097Fariborz Jahanian
1922542125f84d63864b6f7abbed61576a5dffecd097Fariborz Jahanian  buf = "} catch (id e) {_rethrow = e;}\n";
1923542125f84d63864b6f7abbed61576a5dffecd097Fariborz Jahanian  Write_RethrowObject(buf);
192464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  buf += "}\n";
1925542125f84d63864b6f7abbed61576a5dffecd097Fariborz Jahanian  buf += "}\n";
192664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
1927b655bf06d99bbdb58de5d012642b87cabddabd83Fariborz Jahanian  ReplaceText(startRBraceLoc, 1, buf);
192864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
19296bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  return nullptr;
193064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian}
193164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
193264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanianvoid RewriteModernObjC::WarnAboutReturnGotoStmts(Stmt *S)
193364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian{
193464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  // Perform a bottom up traversal of all children.
193564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  for (Stmt::child_range CI = S->children(); CI; ++CI)
193664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    if (*CI)
193764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      WarnAboutReturnGotoStmts(*CI);
193864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
193964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  if (isa<ReturnStmt>(S) || isa<GotoStmt>(S)) {
194064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    Diags.Report(Context->getFullLoc(S->getLocStart()),
194164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                 TryFinallyContainsReturnDiag);
194264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  }
194364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  return;
194464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian}
194564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
1946042b91d53980048619d1e61431387ebe84d384f4Fariborz JahanianStmt *RewriteModernObjC::RewriteObjCAutoreleasePoolStmt(ObjCAutoreleasePoolStmt  *S) {
1947042b91d53980048619d1e61431387ebe84d384f4Fariborz Jahanian  SourceLocation startLoc = S->getAtLoc();
1948042b91d53980048619d1e61431387ebe84d384f4Fariborz Jahanian  ReplaceText(startLoc, strlen("@autoreleasepool"), "/* @autoreleasepool */");
1949c9b72b6d0c21e61c2847dbac2f968306e56dd59cFariborz Jahanian  ReplaceText(S->getSubStmt()->getLocStart(), 1,
1950c9b72b6d0c21e61c2847dbac2f968306e56dd59cFariborz Jahanian              "{ __AtAutoreleasePool __autoreleasepool; ");
19516bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
19526bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  return nullptr;
1953042b91d53980048619d1e61431387ebe84d384f4Fariborz Jahanian}
1954042b91d53980048619d1e61431387ebe84d384f4Fariborz Jahanian
195564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz JahanianStmt *RewriteModernObjC::RewriteObjCTryStmt(ObjCAtTryStmt *S) {
1956b122818a33348a9d1694b10e44eed9746aa492b0Fariborz Jahanian  ObjCAtFinallyStmt *finalStmt = S->getFinallyStmt();
1957220419acf26033d794edef802cbb916a4d2896b4Fariborz Jahanian  bool noCatch = S->getNumCatchStmts() == 0;
1958b122818a33348a9d1694b10e44eed9746aa492b0Fariborz Jahanian  std::string buf;
1959f616ae2d1356dadde26ff553eb689e5455d65808Fariborz Jahanian  SourceLocation TryLocation = S->getAtTryLoc();
1960f616ae2d1356dadde26ff553eb689e5455d65808Fariborz Jahanian  ConvertSourceLocationToLineDirective(TryLocation, buf);
1961b122818a33348a9d1694b10e44eed9746aa492b0Fariborz Jahanian
1962b122818a33348a9d1694b10e44eed9746aa492b0Fariborz Jahanian  if (finalStmt) {
1963220419acf26033d794edef802cbb916a4d2896b4Fariborz Jahanian    if (noCatch)
1964f616ae2d1356dadde26ff553eb689e5455d65808Fariborz Jahanian      buf += "{ id volatile _rethrow = 0;\n";
1965220419acf26033d794edef802cbb916a4d2896b4Fariborz Jahanian    else {
1966f616ae2d1356dadde26ff553eb689e5455d65808Fariborz Jahanian      buf += "{ id volatile _rethrow = 0;\ntry {\n";
1967220419acf26033d794edef802cbb916a4d2896b4Fariborz Jahanian    }
1968b122818a33348a9d1694b10e44eed9746aa492b0Fariborz Jahanian  }
196964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  // Get the start location and compute the semi location.
197064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  SourceLocation startLoc = S->getLocStart();
197164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  const char *startBuf = SM->getCharacterData(startLoc);
197264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
197364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  assert((*startBuf == '@') && "bogus @try location");
1974b122818a33348a9d1694b10e44eed9746aa492b0Fariborz Jahanian  if (finalStmt)
1975b122818a33348a9d1694b10e44eed9746aa492b0Fariborz Jahanian    ReplaceText(startLoc, 1, buf);
1976b122818a33348a9d1694b10e44eed9746aa492b0Fariborz Jahanian  else
1977b122818a33348a9d1694b10e44eed9746aa492b0Fariborz Jahanian    // @try -> try
1978b122818a33348a9d1694b10e44eed9746aa492b0Fariborz Jahanian    ReplaceText(startLoc, 1, "");
1979b122818a33348a9d1694b10e44eed9746aa492b0Fariborz Jahanian
198064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  for (unsigned I = 0, N = S->getNumCatchStmts(); I != N; ++I) {
198164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    ObjCAtCatchStmt *Catch = S->getCatchStmt(I);
19824c14881e86350c8aa12d5182d35ce07860de2325Fariborz Jahanian    VarDecl *catchDecl = Catch->getCatchParamDecl();
1983c38503b4c1cda42154700016d60c6467af438a15Fariborz Jahanian
198464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    startLoc = Catch->getLocStart();
19854c14881e86350c8aa12d5182d35ce07860de2325Fariborz Jahanian    bool AtRemoved = false;
19864c14881e86350c8aa12d5182d35ce07860de2325Fariborz Jahanian    if (catchDecl) {
19874c14881e86350c8aa12d5182d35ce07860de2325Fariborz Jahanian      QualType t = catchDecl->getType();
19884c14881e86350c8aa12d5182d35ce07860de2325Fariborz Jahanian      if (const ObjCObjectPointerType *Ptr = t->getAs<ObjCObjectPointerType>()) {
19894c14881e86350c8aa12d5182d35ce07860de2325Fariborz Jahanian        // Should be a pointer to a class.
19904c14881e86350c8aa12d5182d35ce07860de2325Fariborz Jahanian        ObjCInterfaceDecl *IDecl = Ptr->getObjectType()->getInterface();
19914c14881e86350c8aa12d5182d35ce07860de2325Fariborz Jahanian        if (IDecl) {
19924c14881e86350c8aa12d5182d35ce07860de2325Fariborz Jahanian          std::string Result;
1993f616ae2d1356dadde26ff553eb689e5455d65808Fariborz Jahanian          ConvertSourceLocationToLineDirective(Catch->getLocStart(), Result);
1994f616ae2d1356dadde26ff553eb689e5455d65808Fariborz Jahanian
19954c14881e86350c8aa12d5182d35ce07860de2325Fariborz Jahanian          startBuf = SM->getCharacterData(startLoc);
19964c14881e86350c8aa12d5182d35ce07860de2325Fariborz Jahanian          assert((*startBuf == '@') && "bogus @catch location");
19974c14881e86350c8aa12d5182d35ce07860de2325Fariborz Jahanian          SourceLocation rParenLoc = Catch->getRParenLoc();
19984c14881e86350c8aa12d5182d35ce07860de2325Fariborz Jahanian          const char *rParenBuf = SM->getCharacterData(rParenLoc);
19994c14881e86350c8aa12d5182d35ce07860de2325Fariborz Jahanian
20004c14881e86350c8aa12d5182d35ce07860de2325Fariborz Jahanian          // _objc_exc_Foo *_e as argument to catch.
2001f616ae2d1356dadde26ff553eb689e5455d65808Fariborz Jahanian          Result += "catch (_objc_exc_"; Result += IDecl->getNameAsString();
20024c14881e86350c8aa12d5182d35ce07860de2325Fariborz Jahanian          Result += " *_"; Result += catchDecl->getNameAsString();
20034c14881e86350c8aa12d5182d35ce07860de2325Fariborz Jahanian          Result += ")";
20044c14881e86350c8aa12d5182d35ce07860de2325Fariborz Jahanian          ReplaceText(startLoc, rParenBuf-startBuf+1, Result);
20054c14881e86350c8aa12d5182d35ce07860de2325Fariborz Jahanian          // Foo *e = (Foo *)_e;
20064c14881e86350c8aa12d5182d35ce07860de2325Fariborz Jahanian          Result.clear();
20074c14881e86350c8aa12d5182d35ce07860de2325Fariborz Jahanian          Result = "{ ";
20084c14881e86350c8aa12d5182d35ce07860de2325Fariborz Jahanian          Result += IDecl->getNameAsString();
20094c14881e86350c8aa12d5182d35ce07860de2325Fariborz Jahanian          Result += " *"; Result += catchDecl->getNameAsString();
20104c14881e86350c8aa12d5182d35ce07860de2325Fariborz Jahanian          Result += " = ("; Result += IDecl->getNameAsString(); Result += "*)";
20114c14881e86350c8aa12d5182d35ce07860de2325Fariborz Jahanian          Result += "_"; Result += catchDecl->getNameAsString();
20124c14881e86350c8aa12d5182d35ce07860de2325Fariborz Jahanian
20134c14881e86350c8aa12d5182d35ce07860de2325Fariborz Jahanian          Result += "; ";
20144c14881e86350c8aa12d5182d35ce07860de2325Fariborz Jahanian          SourceLocation lBraceLoc = Catch->getCatchBody()->getLocStart();
20154c14881e86350c8aa12d5182d35ce07860de2325Fariborz Jahanian          ReplaceText(lBraceLoc, 1, Result);
20164c14881e86350c8aa12d5182d35ce07860de2325Fariborz Jahanian          AtRemoved = true;
20174c14881e86350c8aa12d5182d35ce07860de2325Fariborz Jahanian        }
20184c14881e86350c8aa12d5182d35ce07860de2325Fariborz Jahanian      }
20194c14881e86350c8aa12d5182d35ce07860de2325Fariborz Jahanian    }
20204c14881e86350c8aa12d5182d35ce07860de2325Fariborz Jahanian    if (!AtRemoved)
20214c14881e86350c8aa12d5182d35ce07860de2325Fariborz Jahanian      // @catch -> catch
20224c14881e86350c8aa12d5182d35ce07860de2325Fariborz Jahanian      ReplaceText(startLoc, 1, "");
2023c38503b4c1cda42154700016d60c6467af438a15Fariborz Jahanian
202464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  }
2025220419acf26033d794edef802cbb916a4d2896b4Fariborz Jahanian  if (finalStmt) {
2026220419acf26033d794edef802cbb916a4d2896b4Fariborz Jahanian    buf.clear();
2027f616ae2d1356dadde26ff553eb689e5455d65808Fariborz Jahanian    SourceLocation FinallyLoc = finalStmt->getLocStart();
2028f616ae2d1356dadde26ff553eb689e5455d65808Fariborz Jahanian
2029f616ae2d1356dadde26ff553eb689e5455d65808Fariborz Jahanian    if (noCatch) {
2030f616ae2d1356dadde26ff553eb689e5455d65808Fariborz Jahanian      ConvertSourceLocationToLineDirective(FinallyLoc, buf);
2031f616ae2d1356dadde26ff553eb689e5455d65808Fariborz Jahanian      buf += "catch (id e) {_rethrow = e;}\n";
2032f616ae2d1356dadde26ff553eb689e5455d65808Fariborz Jahanian    }
2033f616ae2d1356dadde26ff553eb689e5455d65808Fariborz Jahanian    else {
2034f616ae2d1356dadde26ff553eb689e5455d65808Fariborz Jahanian      buf += "}\n";
2035f616ae2d1356dadde26ff553eb689e5455d65808Fariborz Jahanian      ConvertSourceLocationToLineDirective(FinallyLoc, buf);
2036f616ae2d1356dadde26ff553eb689e5455d65808Fariborz Jahanian      buf += "catch (id e) {_rethrow = e;}\n";
2037f616ae2d1356dadde26ff553eb689e5455d65808Fariborz Jahanian    }
2038f616ae2d1356dadde26ff553eb689e5455d65808Fariborz Jahanian
2039220419acf26033d794edef802cbb916a4d2896b4Fariborz Jahanian    SourceLocation startFinalLoc = finalStmt->getLocStart();
2040220419acf26033d794edef802cbb916a4d2896b4Fariborz Jahanian    ReplaceText(startFinalLoc, 8, buf);
2041220419acf26033d794edef802cbb916a4d2896b4Fariborz Jahanian    Stmt *body = finalStmt->getFinallyBody();
2042220419acf26033d794edef802cbb916a4d2896b4Fariborz Jahanian    SourceLocation startFinalBodyLoc = body->getLocStart();
2043220419acf26033d794edef802cbb916a4d2896b4Fariborz Jahanian    buf.clear();
2044542125f84d63864b6f7abbed61576a5dffecd097Fariborz Jahanian    Write_RethrowObject(buf);
2045220419acf26033d794edef802cbb916a4d2896b4Fariborz Jahanian    ReplaceText(startFinalBodyLoc, 1, buf);
2046220419acf26033d794edef802cbb916a4d2896b4Fariborz Jahanian
2047220419acf26033d794edef802cbb916a4d2896b4Fariborz Jahanian    SourceLocation endFinalBodyLoc = body->getLocEnd();
2048220419acf26033d794edef802cbb916a4d2896b4Fariborz Jahanian    ReplaceText(endFinalBodyLoc, 1, "}\n}");
204922e2f854cb7fd53e048fcbdbee1e78108cb8d146Fariborz Jahanian    // Now check for any return/continue/go statements within the @try.
205022e2f854cb7fd53e048fcbdbee1e78108cb8d146Fariborz Jahanian    WarnAboutReturnGotoStmts(S->getTryBody());
2051220419acf26033d794edef802cbb916a4d2896b4Fariborz Jahanian  }
2052220419acf26033d794edef802cbb916a4d2896b4Fariborz Jahanian
20536bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  return nullptr;
205464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian}
205564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
205664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian// This can't be done with ReplaceStmt(S, ThrowExpr), since
205764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian// the throw expression is typically a message expression that's already
205864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian// been rewritten! (which implies the SourceLocation's are invalid).
205964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz JahanianStmt *RewriteModernObjC::RewriteObjCThrowStmt(ObjCAtThrowStmt *S) {
206064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  // Get the start location and compute the semi location.
206164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  SourceLocation startLoc = S->getLocStart();
206264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  const char *startBuf = SM->getCharacterData(startLoc);
206364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
206464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  assert((*startBuf == '@') && "bogus @throw location");
206564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
206664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  std::string buf;
206764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  /* void objc_exception_throw(id) __attribute__((noreturn)); */
206864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  if (S->getThrowExpr())
206964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    buf = "objc_exception_throw(";
207040539467ec19e6bc53d47ba650f42aa3f414a53fFariborz Jahanian  else
207140539467ec19e6bc53d47ba650f42aa3f414a53fFariborz Jahanian    buf = "throw";
207264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
207364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  // handle "@  throw" correctly.
207464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  const char *wBuf = strchr(startBuf, 'w');
207564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  assert((*wBuf == 'w') && "@throw: can't find 'w'");
207664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  ReplaceText(startLoc, wBuf-startBuf+1, buf);
207764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
2078a09cd8103a6a719cb2628cdf0c91682250a17bd2Fariborz Jahanian  SourceLocation endLoc = S->getLocEnd();
2079a09cd8103a6a719cb2628cdf0c91682250a17bd2Fariborz Jahanian  const char *endBuf = SM->getCharacterData(endLoc);
2080a09cd8103a6a719cb2628cdf0c91682250a17bd2Fariborz Jahanian  const char *semiBuf = strchr(endBuf, ';');
208164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  assert((*semiBuf == ';') && "@throw: can't find ';'");
208264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  SourceLocation semiLoc = startLoc.getLocWithOffset(semiBuf-startBuf);
208340539467ec19e6bc53d47ba650f42aa3f414a53fFariborz Jahanian  if (S->getThrowExpr())
208440539467ec19e6bc53d47ba650f42aa3f414a53fFariborz Jahanian    ReplaceText(semiLoc, 1, ");");
20856bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  return nullptr;
208664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian}
208764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
208864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz JahanianStmt *RewriteModernObjC::RewriteAtEncode(ObjCEncodeExpr *Exp) {
208964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  // Create a new string expression.
209064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  std::string StrEncoding;
209164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  Context->getObjCEncodingForType(Exp->getEncodedType(), StrEncoding);
2092651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  Expr *Replacement = getStringLiteral(StrEncoding);
209364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  ReplaceStmt(Exp, Replacement);
209464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
209564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  // Replace this subexpr in the parent.
209664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  // delete Exp; leak for now, see RewritePropertyOrImplicitSetter() usage for more info.
209764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  return Replacement;
209864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian}
209964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
210064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz JahanianStmt *RewriteModernObjC::RewriteAtSelector(ObjCSelectorExpr *Exp) {
210164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  if (!SelGetUidFunctionDecl)
210264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    SynthSelGetUidFunctionDecl();
210364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  assert(SelGetUidFunctionDecl && "Can't find sel_registerName() decl");
210464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  // Create a call to sel_registerName("selName").
210564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  SmallVector<Expr*, 8> SelExprs;
2106651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  SelExprs.push_back(getStringLiteral(Exp->getSelector().getAsString()));
210764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  CallExpr *SelExp = SynthesizeCallToFunctionDecl(SelGetUidFunctionDecl,
210864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                                 &SelExprs[0], SelExprs.size());
210964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  ReplaceStmt(Exp, SelExp);
211064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  // delete Exp; leak for now, see RewritePropertyOrImplicitSetter() usage for more info.
211164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  return SelExp;
211264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian}
211364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
211464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz JahanianCallExpr *RewriteModernObjC::SynthesizeCallToFunctionDecl(
211564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  FunctionDecl *FD, Expr **args, unsigned nargs, SourceLocation StartLoc,
211664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                                    SourceLocation EndLoc) {
211764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  // Get the type, we will need to reference it in a couple spots.
211864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  QualType msgSendType = FD->getType();
211964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
212064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  // Create a reference to the objc_msgSend() declaration.
212164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  DeclRefExpr *DRE =
2122f4b88a45902af1802a1cb42ba48b1c474474f228John McCall    new (Context) DeclRefExpr(FD, false, msgSendType, VK_LValue, SourceLocation());
212364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
212464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  // Now, we cast the reference to a pointer to the objc_msgSend type.
212564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  QualType pToFunc = Context->getPointerType(msgSendType);
212664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  ImplicitCastExpr *ICE =
212764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    ImplicitCastExpr::Create(*Context, pToFunc, CK_FunctionToPointerDecay,
21286bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines                             DRE, nullptr, VK_RValue);
212964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
213064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  const FunctionType *FT = msgSendType->getAs<FunctionType>();
213164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
213264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  CallExpr *Exp =
21333b6bef9a213249c6ab6d67c07b1ac6380961be3eBenjamin Kramer    new (Context) CallExpr(*Context, ICE, llvm::makeArrayRef(args, nargs),
213464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                           FT->getCallResultType(*Context),
213564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                           VK_RValue, EndLoc);
213664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  return Exp;
213764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian}
213864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
213964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanianstatic bool scanForProtocolRefs(const char *startBuf, const char *endBuf,
214064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                const char *&startRef, const char *&endRef) {
214164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  while (startBuf < endBuf) {
214264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    if (*startBuf == '<')
214364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      startRef = startBuf; // mark the start.
214464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    if (*startBuf == '>') {
214564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      if (startRef && *startRef == '<') {
214664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        endRef = startBuf; // mark the end.
214764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        return true;
214864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      }
214964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      return false;
215064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    }
215164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    startBuf++;
215264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  }
215364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  return false;
215464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian}
215564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
215664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanianstatic void scanToNextArgument(const char *&argRef) {
215764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  int angle = 0;
215864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  while (*argRef != ')' && (*argRef != ',' || angle > 0)) {
215964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    if (*argRef == '<')
216064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      angle++;
216164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    else if (*argRef == '>')
216264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      angle--;
216364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    argRef++;
216464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  }
216564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  assert(angle == 0 && "scanToNextArgument - bad protocol type syntax");
216664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian}
216764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
216864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanianbool RewriteModernObjC::needToScanForQualifiers(QualType T) {
216964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  if (T->isObjCQualifiedIdType())
217064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    return true;
217164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  if (const PointerType *PT = T->getAs<PointerType>()) {
217264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    if (PT->getPointeeType()->isObjCQualifiedIdType())
217364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      return true;
217464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  }
217564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  if (T->isObjCObjectPointerType()) {
217664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    T = T->getPointeeType();
217764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    return T->isObjCQualifiedInterfaceType();
217864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  }
217964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  if (T->isArrayType()) {
218064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    QualType ElemTy = Context->getBaseElementType(T);
218164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    return needToScanForQualifiers(ElemTy);
218264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  }
218364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  return false;
218464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian}
218564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
218664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanianvoid RewriteModernObjC::RewriteObjCQualifiedInterfaceTypes(Expr *E) {
218764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  QualType Type = E->getType();
218864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  if (needToScanForQualifiers(Type)) {
218964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    SourceLocation Loc, EndLoc;
219064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
219164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    if (const CStyleCastExpr *ECE = dyn_cast<CStyleCastExpr>(E)) {
219264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      Loc = ECE->getLParenLoc();
219364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      EndLoc = ECE->getRParenLoc();
219464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    } else {
219564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      Loc = E->getLocStart();
219664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      EndLoc = E->getLocEnd();
219764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    }
219864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    // This will defend against trying to rewrite synthesized expressions.
219964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    if (Loc.isInvalid() || EndLoc.isInvalid())
220064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      return;
220164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
220264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    const char *startBuf = SM->getCharacterData(Loc);
220364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    const char *endBuf = SM->getCharacterData(EndLoc);
22046bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    const char *startRef = nullptr, *endRef = nullptr;
220564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    if (scanForProtocolRefs(startBuf, endBuf, startRef, endRef)) {
220664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      // Get the locations of the startRef, endRef.
220764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      SourceLocation LessLoc = Loc.getLocWithOffset(startRef-startBuf);
220864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      SourceLocation GreaterLoc = Loc.getLocWithOffset(endRef-startBuf+1);
220964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      // Comment out the protocol references.
221064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      InsertText(LessLoc, "/*");
221164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      InsertText(GreaterLoc, "*/");
221264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    }
221364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  }
221464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian}
221564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
221664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanianvoid RewriteModernObjC::RewriteObjCQualifiedInterfaceTypes(Decl *Dcl) {
221764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  SourceLocation Loc;
221864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  QualType Type;
22196bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  const FunctionProtoType *proto = nullptr;
222064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  if (VarDecl *VD = dyn_cast<VarDecl>(Dcl)) {
222164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    Loc = VD->getLocation();
222264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    Type = VD->getType();
222364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  }
222464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  else if (FunctionDecl *FD = dyn_cast<FunctionDecl>(Dcl)) {
222564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    Loc = FD->getLocation();
222664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    // Check for ObjC 'id' and class types that have been adorned with protocol
222764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    // information (id<p>, C<p>*). The protocol references need to be rewritten!
222864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    const FunctionType *funcType = FD->getType()->getAs<FunctionType>();
222964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    assert(funcType && "missing function type");
223064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    proto = dyn_cast<FunctionProtoType>(funcType);
223164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    if (!proto)
223264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      return;
2233651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    Type = proto->getReturnType();
223464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  }
223564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  else if (FieldDecl *FD = dyn_cast<FieldDecl>(Dcl)) {
223664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    Loc = FD->getLocation();
223764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    Type = FD->getType();
223864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  }
2239f9f30791dd20472675de012105219cd975ad1076Fariborz Jahanian  else if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(Dcl)) {
2240f9f30791dd20472675de012105219cd975ad1076Fariborz Jahanian    Loc = TD->getLocation();
2241f9f30791dd20472675de012105219cd975ad1076Fariborz Jahanian    Type = TD->getUnderlyingType();
2242f9f30791dd20472675de012105219cd975ad1076Fariborz Jahanian  }
224364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  else
224464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    return;
224564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
224664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  if (needToScanForQualifiers(Type)) {
224764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    // Since types are unique, we need to scan the buffer.
224864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
224964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    const char *endBuf = SM->getCharacterData(Loc);
225064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    const char *startBuf = endBuf;
225164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    while (*startBuf != ';' && *startBuf != '<' && startBuf != MainFileStart)
225264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      startBuf--; // scan backward (from the decl location) for return type.
22536bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    const char *startRef = nullptr, *endRef = nullptr;
225464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    if (scanForProtocolRefs(startBuf, endBuf, startRef, endRef)) {
225564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      // Get the locations of the startRef, endRef.
225664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      SourceLocation LessLoc = Loc.getLocWithOffset(startRef-endBuf);
225764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      SourceLocation GreaterLoc = Loc.getLocWithOffset(endRef-endBuf+1);
225864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      // Comment out the protocol references.
225964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      InsertText(LessLoc, "/*");
226064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      InsertText(GreaterLoc, "*/");
226164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    }
226264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  }
226364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  if (!proto)
226464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      return; // most likely, was a variable
226564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  // Now check arguments.
226664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  const char *startBuf = SM->getCharacterData(Loc);
226764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  const char *startFuncBuf = startBuf;
2268651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  for (unsigned i = 0; i < proto->getNumParams(); i++) {
2269651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    if (needToScanForQualifiers(proto->getParamType(i))) {
227064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      // Since types are unique, we need to scan the buffer.
227164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
227264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      const char *endBuf = startBuf;
227364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      // scan forward (from the decl location) for argument types.
227464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      scanToNextArgument(endBuf);
22756bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      const char *startRef = nullptr, *endRef = nullptr;
227664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      if (scanForProtocolRefs(startBuf, endBuf, startRef, endRef)) {
227764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        // Get the locations of the startRef, endRef.
227864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        SourceLocation LessLoc =
227964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian          Loc.getLocWithOffset(startRef-startFuncBuf);
228064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        SourceLocation GreaterLoc =
228164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian          Loc.getLocWithOffset(endRef-startFuncBuf+1);
228264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        // Comment out the protocol references.
228364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        InsertText(LessLoc, "/*");
228464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        InsertText(GreaterLoc, "*/");
228564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      }
228664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      startBuf = ++endBuf;
228764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    }
228864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    else {
228964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      // If the function name is derived from a macro expansion, then the
229064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      // argument buffer will not follow the name. Need to speak with Chris.
229164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      while (*startBuf && *startBuf != ')' && *startBuf != ',')
229264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        startBuf++; // scan forward (from the decl location) for argument types.
229364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      startBuf++;
229464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    }
229564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  }
229664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian}
229764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
229864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanianvoid RewriteModernObjC::RewriteTypeOfDecl(VarDecl *ND) {
229964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  QualType QT = ND->getType();
230064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  const Type* TypePtr = QT->getAs<Type>();
230164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  if (!isa<TypeOfExprType>(TypePtr))
230264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    return;
230364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  while (isa<TypeOfExprType>(TypePtr)) {
230464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    const TypeOfExprType *TypeOfExprTypePtr = cast<TypeOfExprType>(TypePtr);
230564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    QT = TypeOfExprTypePtr->getUnderlyingExpr()->getType();
230664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    TypePtr = QT->getAs<Type>();
230764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  }
230864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  // FIXME. This will not work for multiple declarators; as in:
230964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  // __typeof__(a) b,c,d;
231064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  std::string TypeAsString(QT.getAsString(Context->getPrintingPolicy()));
231164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  SourceLocation DeclLoc = ND->getTypeSpecStartLoc();
231264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  const char *startBuf = SM->getCharacterData(DeclLoc);
231364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  if (ND->getInit()) {
231464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    std::string Name(ND->getNameAsString());
231564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    TypeAsString += " " + Name + " = ";
231664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    Expr *E = ND->getInit();
231764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    SourceLocation startLoc;
231864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    if (const CStyleCastExpr *ECE = dyn_cast<CStyleCastExpr>(E))
231964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      startLoc = ECE->getLParenLoc();
232064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    else
232164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      startLoc = E->getLocStart();
232264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    startLoc = SM->getExpansionLoc(startLoc);
232364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    const char *endBuf = SM->getCharacterData(startLoc);
232464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    ReplaceText(DeclLoc, endBuf-startBuf-1, TypeAsString);
232564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  }
232664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  else {
232764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    SourceLocation X = ND->getLocEnd();
232864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    X = SM->getExpansionLoc(X);
232964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    const char *endBuf = SM->getCharacterData(X);
233064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    ReplaceText(DeclLoc, endBuf-startBuf-1, TypeAsString);
233164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  }
233264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian}
233364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
233464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian// SynthSelGetUidFunctionDecl - SEL sel_registerName(const char *str);
233564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanianvoid RewriteModernObjC::SynthSelGetUidFunctionDecl() {
233664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  IdentifierInfo *SelGetUidIdent = &Context->Idents.get("sel_registerName");
233764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  SmallVector<QualType, 16> ArgTys;
233864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  ArgTys.push_back(Context->getPointerType(Context->CharTy.withConst()));
233964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  QualType getFuncType =
2340bea522ff43a3f11c7a2bc7949119dbb9fce19e39Jordan Rose    getSimpleFunctionType(Context->getObjCSelType(), ArgTys);
234164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  SelGetUidFunctionDecl = FunctionDecl::Create(*Context, TUDecl,
2342e3b29886ab053123feeb256e92bf8af23ba136ccChad Rosier                                               SourceLocation(),
2343e3b29886ab053123feeb256e92bf8af23ba136ccChad Rosier                                               SourceLocation(),
23446bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines                                               SelGetUidIdent, getFuncType,
23456bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines                                               nullptr, SC_Extern);
234664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian}
234764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
234864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanianvoid RewriteModernObjC::RewriteFunctionDecl(FunctionDecl *FD) {
234964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  // declared in <objc/objc.h>
235064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  if (FD->getIdentifier() &&
235164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      FD->getName() == "sel_registerName") {
235264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    SelGetUidFunctionDecl = FD;
235364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    return;
235464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  }
235564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  RewriteObjCQualifiedInterfaceTypes(FD);
235664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian}
235764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
235864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanianvoid RewriteModernObjC::RewriteBlockPointerType(std::string& Str, QualType Type) {
235964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  std::string TypeString(Type.getAsString(Context->getPrintingPolicy()));
236064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  const char *argPtr = TypeString.c_str();
236164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  if (!strchr(argPtr, '^')) {
236264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    Str += TypeString;
236364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    return;
236464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  }
236564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  while (*argPtr) {
236664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    Str += (*argPtr == '^' ? '*' : *argPtr);
236764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    argPtr++;
236864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  }
236964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian}
237064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
237164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian// FIXME. Consolidate this routine with RewriteBlockPointerType.
237264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanianvoid RewriteModernObjC::RewriteBlockPointerTypeVariable(std::string& Str,
237364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                                  ValueDecl *VD) {
237464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  QualType Type = VD->getType();
237564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  std::string TypeString(Type.getAsString(Context->getPrintingPolicy()));
237664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  const char *argPtr = TypeString.c_str();
237764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  int paren = 0;
237864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  while (*argPtr) {
237964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    switch (*argPtr) {
238064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      case '(':
238164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        Str += *argPtr;
238264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        paren++;
238364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        break;
238464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      case ')':
238564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        Str += *argPtr;
238664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        paren--;
238764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        break;
238864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      case '^':
238964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        Str += '*';
239064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        if (paren == 1)
239164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian          Str += VD->getNameAsString();
239264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        break;
239364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      default:
239464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        Str += *argPtr;
239564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        break;
239664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    }
239764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    argPtr++;
239864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  }
239964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian}
240064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
2401b75f8de7ddc4f9365dad90ef21a463e94dcdcbdaFariborz Jahanianvoid RewriteModernObjC::RewriteBlockLiteralFunctionDecl(FunctionDecl *FD) {
2402b75f8de7ddc4f9365dad90ef21a463e94dcdcbdaFariborz Jahanian  SourceLocation FunLocStart = FD->getTypeSpecStartLoc();
2403b75f8de7ddc4f9365dad90ef21a463e94dcdcbdaFariborz Jahanian  const FunctionType *funcType = FD->getType()->getAs<FunctionType>();
2404b75f8de7ddc4f9365dad90ef21a463e94dcdcbdaFariborz Jahanian  const FunctionProtoType *proto = dyn_cast<FunctionProtoType>(funcType);
2405b75f8de7ddc4f9365dad90ef21a463e94dcdcbdaFariborz Jahanian  if (!proto)
2406b75f8de7ddc4f9365dad90ef21a463e94dcdcbdaFariborz Jahanian    return;
2407651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  QualType Type = proto->getReturnType();
2408b75f8de7ddc4f9365dad90ef21a463e94dcdcbdaFariborz Jahanian  std::string FdStr = Type.getAsString(Context->getPrintingPolicy());
2409b75f8de7ddc4f9365dad90ef21a463e94dcdcbdaFariborz Jahanian  FdStr += " ";
2410b75f8de7ddc4f9365dad90ef21a463e94dcdcbdaFariborz Jahanian  FdStr += FD->getName();
2411b75f8de7ddc4f9365dad90ef21a463e94dcdcbdaFariborz Jahanian  FdStr +=  "(";
2412651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  unsigned numArgs = proto->getNumParams();
2413b75f8de7ddc4f9365dad90ef21a463e94dcdcbdaFariborz Jahanian  for (unsigned i = 0; i < numArgs; i++) {
2414651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    QualType ArgType = proto->getParamType(i);
2415b75f8de7ddc4f9365dad90ef21a463e94dcdcbdaFariborz Jahanian  RewriteBlockPointerType(FdStr, ArgType);
2416b75f8de7ddc4f9365dad90ef21a463e94dcdcbdaFariborz Jahanian  if (i+1 < numArgs)
2417b75f8de7ddc4f9365dad90ef21a463e94dcdcbdaFariborz Jahanian    FdStr += ", ";
2418b75f8de7ddc4f9365dad90ef21a463e94dcdcbdaFariborz Jahanian  }
2419b5863da6efbf4ad42e26aa56a04366da50b6a3c7Fariborz Jahanian  if (FD->isVariadic()) {
2420b5863da6efbf4ad42e26aa56a04366da50b6a3c7Fariborz Jahanian    FdStr +=  (numArgs > 0) ? ", ...);\n" : "...);\n";
2421b5863da6efbf4ad42e26aa56a04366da50b6a3c7Fariborz Jahanian  }
2422b5863da6efbf4ad42e26aa56a04366da50b6a3c7Fariborz Jahanian  else
2423b5863da6efbf4ad42e26aa56a04366da50b6a3c7Fariborz Jahanian    FdStr +=  ");\n";
2424b75f8de7ddc4f9365dad90ef21a463e94dcdcbdaFariborz Jahanian  InsertText(FunLocStart, FdStr);
2425b75f8de7ddc4f9365dad90ef21a463e94dcdcbdaFariborz Jahanian}
2426b75f8de7ddc4f9365dad90ef21a463e94dcdcbdaFariborz Jahanian
2427e575359c34a9248c55ec0c03a8fc945f1ee4cb01Benjamin Kramer// SynthSuperConstructorFunctionDecl - id __rw_objc_super(id obj, id super);
2428e575359c34a9248c55ec0c03a8fc945f1ee4cb01Benjamin Kramervoid RewriteModernObjC::SynthSuperConstructorFunctionDecl() {
2429e575359c34a9248c55ec0c03a8fc945f1ee4cb01Benjamin Kramer  if (SuperConstructorFunctionDecl)
243064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    return;
243164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  IdentifierInfo *msgSendIdent = &Context->Idents.get("__rw_objc_super");
243264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  SmallVector<QualType, 16> ArgTys;
243364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  QualType argT = Context->getObjCIdType();
243464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  assert(!argT.isNull() && "Can't find 'id' type");
243564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  ArgTys.push_back(argT);
243664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  ArgTys.push_back(argT);
243764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  QualType msgSendType = getSimpleFunctionType(Context->getObjCIdType(),
2438bea522ff43a3f11c7a2bc7949119dbb9fce19e39Jordan Rose                                               ArgTys);
2439e575359c34a9248c55ec0c03a8fc945f1ee4cb01Benjamin Kramer  SuperConstructorFunctionDecl = FunctionDecl::Create(*Context, TUDecl,
2440e3b29886ab053123feeb256e92bf8af23ba136ccChad Rosier                                                     SourceLocation(),
2441e3b29886ab053123feeb256e92bf8af23ba136ccChad Rosier                                                     SourceLocation(),
2442e3b29886ab053123feeb256e92bf8af23ba136ccChad Rosier                                                     msgSendIdent, msgSendType,
24436bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines                                                     nullptr, SC_Extern);
244464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian}
244564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
244664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian// SynthMsgSendFunctionDecl - id objc_msgSend(id self, SEL op, ...);
244764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanianvoid RewriteModernObjC::SynthMsgSendFunctionDecl() {
244864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  IdentifierInfo *msgSendIdent = &Context->Idents.get("objc_msgSend");
244964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  SmallVector<QualType, 16> ArgTys;
245064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  QualType argT = Context->getObjCIdType();
245164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  assert(!argT.isNull() && "Can't find 'id' type");
245264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  ArgTys.push_back(argT);
245364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  argT = Context->getObjCSelType();
245464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  assert(!argT.isNull() && "Can't find 'SEL' type");
245564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  ArgTys.push_back(argT);
245664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  QualType msgSendType = getSimpleFunctionType(Context->getObjCIdType(),
2457bea522ff43a3f11c7a2bc7949119dbb9fce19e39Jordan Rose                                               ArgTys, /*isVariadic=*/true);
245864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  MsgSendFunctionDecl = FunctionDecl::Create(*Context, TUDecl,
2459e3b29886ab053123feeb256e92bf8af23ba136ccChad Rosier                                             SourceLocation(),
2460e3b29886ab053123feeb256e92bf8af23ba136ccChad Rosier                                             SourceLocation(),
24616bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines                                             msgSendIdent, msgSendType, nullptr,
2462d2615cc53b916e8aae45783ca7113b93de515ce3Rafael Espindola                                             SC_Extern);
246364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian}
246464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
2465b20c46ea980b5aed7b480761ea1daf2f26c23b2dFariborz Jahanian// SynthMsgSendSuperFunctionDecl - id objc_msgSendSuper(void);
246664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanianvoid RewriteModernObjC::SynthMsgSendSuperFunctionDecl() {
246764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  IdentifierInfo *msgSendIdent = &Context->Idents.get("objc_msgSendSuper");
2468b20c46ea980b5aed7b480761ea1daf2f26c23b2dFariborz Jahanian  SmallVector<QualType, 2> ArgTys;
2469b20c46ea980b5aed7b480761ea1daf2f26c23b2dFariborz Jahanian  ArgTys.push_back(Context->VoidTy);
247064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  QualType msgSendType = getSimpleFunctionType(Context->getObjCIdType(),
2471bea522ff43a3f11c7a2bc7949119dbb9fce19e39Jordan Rose                                               ArgTys, /*isVariadic=*/true);
247264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  MsgSendSuperFunctionDecl = FunctionDecl::Create(*Context, TUDecl,
2473e3b29886ab053123feeb256e92bf8af23ba136ccChad Rosier                                                  SourceLocation(),
2474e3b29886ab053123feeb256e92bf8af23ba136ccChad Rosier                                                  SourceLocation(),
24756bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines                                                  msgSendIdent, msgSendType,
24766bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines                                                  nullptr, SC_Extern);
247764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian}
247864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
247964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian// SynthMsgSendStretFunctionDecl - id objc_msgSend_stret(id self, SEL op, ...);
248064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanianvoid RewriteModernObjC::SynthMsgSendStretFunctionDecl() {
248164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  IdentifierInfo *msgSendIdent = &Context->Idents.get("objc_msgSend_stret");
248264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  SmallVector<QualType, 16> ArgTys;
248364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  QualType argT = Context->getObjCIdType();
248464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  assert(!argT.isNull() && "Can't find 'id' type");
248564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  ArgTys.push_back(argT);
248664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  argT = Context->getObjCSelType();
248764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  assert(!argT.isNull() && "Can't find 'SEL' type");
248864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  ArgTys.push_back(argT);
248964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  QualType msgSendType = getSimpleFunctionType(Context->getObjCIdType(),
2490bea522ff43a3f11c7a2bc7949119dbb9fce19e39Jordan Rose                                               ArgTys, /*isVariadic=*/true);
249164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  MsgSendStretFunctionDecl = FunctionDecl::Create(*Context, TUDecl,
2492e3b29886ab053123feeb256e92bf8af23ba136ccChad Rosier                                                  SourceLocation(),
2493e3b29886ab053123feeb256e92bf8af23ba136ccChad Rosier                                                  SourceLocation(),
24946bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines                                                  msgSendIdent, msgSendType,
24956bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines                                                  nullptr, SC_Extern);
249664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian}
249764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
249864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian// SynthMsgSendSuperStretFunctionDecl -
2499b20c46ea980b5aed7b480761ea1daf2f26c23b2dFariborz Jahanian// id objc_msgSendSuper_stret(void);
250064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanianvoid RewriteModernObjC::SynthMsgSendSuperStretFunctionDecl() {
250164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  IdentifierInfo *msgSendIdent =
250264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    &Context->Idents.get("objc_msgSendSuper_stret");
2503b20c46ea980b5aed7b480761ea1daf2f26c23b2dFariborz Jahanian  SmallVector<QualType, 2> ArgTys;
2504b20c46ea980b5aed7b480761ea1daf2f26c23b2dFariborz Jahanian  ArgTys.push_back(Context->VoidTy);
250564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  QualType msgSendType = getSimpleFunctionType(Context->getObjCIdType(),
2506bea522ff43a3f11c7a2bc7949119dbb9fce19e39Jordan Rose                                               ArgTys, /*isVariadic=*/true);
250764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  MsgSendSuperStretFunctionDecl = FunctionDecl::Create(*Context, TUDecl,
250864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                                       SourceLocation(),
250964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                                       SourceLocation(),
2510e3b29886ab053123feeb256e92bf8af23ba136ccChad Rosier                                                       msgSendIdent,
25116bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines                                                       msgSendType, nullptr,
2512d2615cc53b916e8aae45783ca7113b93de515ce3Rafael Espindola                                                       SC_Extern);
251364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian}
251464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
251564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian// SynthMsgSendFpretFunctionDecl - double objc_msgSend_fpret(id self, SEL op, ...);
251664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanianvoid RewriteModernObjC::SynthMsgSendFpretFunctionDecl() {
251764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  IdentifierInfo *msgSendIdent = &Context->Idents.get("objc_msgSend_fpret");
251864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  SmallVector<QualType, 16> ArgTys;
251964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  QualType argT = Context->getObjCIdType();
252064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  assert(!argT.isNull() && "Can't find 'id' type");
252164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  ArgTys.push_back(argT);
252264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  argT = Context->getObjCSelType();
252364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  assert(!argT.isNull() && "Can't find 'SEL' type");
252464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  ArgTys.push_back(argT);
252564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  QualType msgSendType = getSimpleFunctionType(Context->DoubleTy,
2526bea522ff43a3f11c7a2bc7949119dbb9fce19e39Jordan Rose                                               ArgTys, /*isVariadic=*/true);
252764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  MsgSendFpretFunctionDecl = FunctionDecl::Create(*Context, TUDecl,
2528e3b29886ab053123feeb256e92bf8af23ba136ccChad Rosier                                                  SourceLocation(),
2529e3b29886ab053123feeb256e92bf8af23ba136ccChad Rosier                                                  SourceLocation(),
25306bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines                                                  msgSendIdent, msgSendType,
25316bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines                                                  nullptr, SC_Extern);
253264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian}
253364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
253420e181a3ece8862dcfcfacf70763074ddec5a68bFariborz Jahanian// SynthGetClassFunctionDecl - Class objc_getClass(const char *name);
253564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanianvoid RewriteModernObjC::SynthGetClassFunctionDecl() {
253664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  IdentifierInfo *getClassIdent = &Context->Idents.get("objc_getClass");
253764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  SmallVector<QualType, 16> ArgTys;
253864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  ArgTys.push_back(Context->getPointerType(Context->CharTy.withConst()));
253920e181a3ece8862dcfcfacf70763074ddec5a68bFariborz Jahanian  QualType getClassType = getSimpleFunctionType(Context->getObjCClassType(),
2540bea522ff43a3f11c7a2bc7949119dbb9fce19e39Jordan Rose                                                ArgTys);
254164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  GetClassFunctionDecl = FunctionDecl::Create(*Context, TUDecl,
2542e3b29886ab053123feeb256e92bf8af23ba136ccChad Rosier                                              SourceLocation(),
2543e3b29886ab053123feeb256e92bf8af23ba136ccChad Rosier                                              SourceLocation(),
25446bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines                                              getClassIdent, getClassType,
25456bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines                                              nullptr, SC_Extern);
254664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian}
254764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
254864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian// SynthGetSuperClassFunctionDecl - Class class_getSuperclass(Class cls);
254964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanianvoid RewriteModernObjC::SynthGetSuperClassFunctionDecl() {
255064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  IdentifierInfo *getSuperClassIdent =
255164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    &Context->Idents.get("class_getSuperclass");
255264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  SmallVector<QualType, 16> ArgTys;
255364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  ArgTys.push_back(Context->getObjCClassType());
255464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  QualType getClassType = getSimpleFunctionType(Context->getObjCClassType(),
2555bea522ff43a3f11c7a2bc7949119dbb9fce19e39Jordan Rose                                                ArgTys);
255664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  GetSuperClassFunctionDecl = FunctionDecl::Create(*Context, TUDecl,
255764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                                   SourceLocation(),
255864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                                   SourceLocation(),
255964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                                   getSuperClassIdent,
25606bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines                                                   getClassType, nullptr,
2561d2615cc53b916e8aae45783ca7113b93de515ce3Rafael Espindola                                                   SC_Extern);
256264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian}
256364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
256420e181a3ece8862dcfcfacf70763074ddec5a68bFariborz Jahanian// SynthGetMetaClassFunctionDecl - Class objc_getMetaClass(const char *name);
256564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanianvoid RewriteModernObjC::SynthGetMetaClassFunctionDecl() {
256664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  IdentifierInfo *getClassIdent = &Context->Idents.get("objc_getMetaClass");
256764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  SmallVector<QualType, 16> ArgTys;
256864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  ArgTys.push_back(Context->getPointerType(Context->CharTy.withConst()));
256920e181a3ece8862dcfcfacf70763074ddec5a68bFariborz Jahanian  QualType getClassType = getSimpleFunctionType(Context->getObjCClassType(),
2570bea522ff43a3f11c7a2bc7949119dbb9fce19e39Jordan Rose                                                ArgTys);
257164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  GetMetaClassFunctionDecl = FunctionDecl::Create(*Context, TUDecl,
2572e3b29886ab053123feeb256e92bf8af23ba136ccChad Rosier                                                  SourceLocation(),
2573e3b29886ab053123feeb256e92bf8af23ba136ccChad Rosier                                                  SourceLocation(),
2574e3b29886ab053123feeb256e92bf8af23ba136ccChad Rosier                                                  getClassIdent, getClassType,
25756bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines                                                  nullptr, SC_Extern);
257664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian}
257764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
257864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz JahanianStmt *RewriteModernObjC::RewriteObjCStringLiteral(ObjCStringLiteral *Exp) {
2579c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  assert (Exp != nullptr && "Expected non-null ObjCStringLiteral");
258064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  QualType strType = getConstantStringStructType();
258164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
258264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  std::string S = "__NSConstantStringImpl_";
258364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
258464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  std::string tmpName = InFileName;
258564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  unsigned i;
258664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  for (i=0; i < tmpName.length(); i++) {
258764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    char c = tmpName.at(i);
2588651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    // replace any non-alphanumeric characters with '_'.
25893f6f51e28231f65de9c2dd150a2d757b2162cfa3Jordan Rose    if (!isAlphanumeric(c))
259064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      tmpName[i] = '_';
259164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  }
259264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  S += tmpName;
259364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  S += "_";
259464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  S += utostr(NumObjCStringLiterals++);
259564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
259664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  Preamble += "static __NSConstantStringImpl " + S;
259764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  Preamble += " __attribute__ ((section (\"__DATA, __cfstring\"))) = {__CFConstantStringClassReference,";
259864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  Preamble += "0x000007c8,"; // utf8_str
259964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  // The pretty printer for StringLiteral handles escape characters properly.
260064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  std::string prettyBufS;
260164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  llvm::raw_string_ostream prettyBuf(prettyBufS);
26026bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  Exp->getString()->printPretty(prettyBuf, nullptr, PrintingPolicy(LangOpts));
260364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  Preamble += prettyBuf.str();
260464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  Preamble += ",";
260564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  Preamble += utostr(Exp->getString()->getByteLength()) + "};\n";
260664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
260764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  VarDecl *NewVD = VarDecl::Create(*Context, TUDecl, SourceLocation(),
260864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                   SourceLocation(), &Context->Idents.get(S),
26096bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines                                   strType, nullptr, SC_Static);
2610f4b88a45902af1802a1cb42ba48b1c474474f228John McCall  DeclRefExpr *DRE = new (Context) DeclRefExpr(NewVD, false, strType, VK_LValue,
261164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                               SourceLocation());
261264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  Expr *Unop = new (Context) UnaryOperator(DRE, UO_AddrOf,
261364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                 Context->getPointerType(DRE->getType()),
261464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                           VK_RValue, OK_Ordinary,
261564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                           SourceLocation());
261664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  // cast to NSConstantString *
261764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  CastExpr *cast = NoTypeInfoCStyleCastExpr(Context, Exp->getType(),
261864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                            CK_CPointerToObjCPointerCast, Unop);
261964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  ReplaceStmt(Exp, cast);
262064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  // delete Exp; leak for now, see RewritePropertyOrImplicitSetter() usage for more info.
262164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  return cast;
262264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian}
262364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
262455947042d86773b7e16aec12070e1ffe62bff4a6Fariborz JahanianStmt *RewriteModernObjC::RewriteObjCBoolLiteralExpr(ObjCBoolLiteralExpr *Exp) {
262555947042d86773b7e16aec12070e1ffe62bff4a6Fariborz Jahanian  unsigned IntSize =
262655947042d86773b7e16aec12070e1ffe62bff4a6Fariborz Jahanian    static_cast<unsigned>(Context->getTypeSize(Context->IntTy));
262755947042d86773b7e16aec12070e1ffe62bff4a6Fariborz Jahanian
262855947042d86773b7e16aec12070e1ffe62bff4a6Fariborz Jahanian  Expr *FlagExp = IntegerLiteral::Create(*Context,
262955947042d86773b7e16aec12070e1ffe62bff4a6Fariborz Jahanian                                         llvm::APInt(IntSize, Exp->getValue()),
263055947042d86773b7e16aec12070e1ffe62bff4a6Fariborz Jahanian                                         Context->IntTy, Exp->getLocation());
263155947042d86773b7e16aec12070e1ffe62bff4a6Fariborz Jahanian  CastExpr *cast = NoTypeInfoCStyleCastExpr(Context, Context->ObjCBuiltinBoolTy,
263255947042d86773b7e16aec12070e1ffe62bff4a6Fariborz Jahanian                                            CK_BitCast, FlagExp);
263355947042d86773b7e16aec12070e1ffe62bff4a6Fariborz Jahanian  ParenExpr *PE = new (Context) ParenExpr(Exp->getLocation(), Exp->getExprLoc(),
263455947042d86773b7e16aec12070e1ffe62bff4a6Fariborz Jahanian                                          cast);
263555947042d86773b7e16aec12070e1ffe62bff4a6Fariborz Jahanian  ReplaceStmt(Exp, PE);
263655947042d86773b7e16aec12070e1ffe62bff4a6Fariborz Jahanian  return PE;
263755947042d86773b7e16aec12070e1ffe62bff4a6Fariborz Jahanian}
263855947042d86773b7e16aec12070e1ffe62bff4a6Fariborz Jahanian
2639eb382ec1507cf2c8c12d7443d0b67c076223aec6Patrick BeardStmt *RewriteModernObjC::RewriteObjCBoxedExpr(ObjCBoxedExpr *Exp) {
26400f9b18ed048cd5c1ebe786d1dee05577e84d0c27Fariborz Jahanian  // synthesize declaration of helper functions needed in this routine.
26410f9b18ed048cd5c1ebe786d1dee05577e84d0c27Fariborz Jahanian  if (!SelGetUidFunctionDecl)
26420f9b18ed048cd5c1ebe786d1dee05577e84d0c27Fariborz Jahanian    SynthSelGetUidFunctionDecl();
26430f9b18ed048cd5c1ebe786d1dee05577e84d0c27Fariborz Jahanian  // use objc_msgSend() for all.
26440f9b18ed048cd5c1ebe786d1dee05577e84d0c27Fariborz Jahanian  if (!MsgSendFunctionDecl)
26450f9b18ed048cd5c1ebe786d1dee05577e84d0c27Fariborz Jahanian    SynthMsgSendFunctionDecl();
26460f9b18ed048cd5c1ebe786d1dee05577e84d0c27Fariborz Jahanian  if (!GetClassFunctionDecl)
26470f9b18ed048cd5c1ebe786d1dee05577e84d0c27Fariborz Jahanian    SynthGetClassFunctionDecl();
26480f9b18ed048cd5c1ebe786d1dee05577e84d0c27Fariborz Jahanian
26490f9b18ed048cd5c1ebe786d1dee05577e84d0c27Fariborz Jahanian  FunctionDecl *MsgSendFlavor = MsgSendFunctionDecl;
26500f9b18ed048cd5c1ebe786d1dee05577e84d0c27Fariborz Jahanian  SourceLocation StartLoc = Exp->getLocStart();
26510f9b18ed048cd5c1ebe786d1dee05577e84d0c27Fariborz Jahanian  SourceLocation EndLoc = Exp->getLocEnd();
26520f9b18ed048cd5c1ebe786d1dee05577e84d0c27Fariborz Jahanian
26530f9b18ed048cd5c1ebe786d1dee05577e84d0c27Fariborz Jahanian  // Synthesize a call to objc_msgSend().
26540f9b18ed048cd5c1ebe786d1dee05577e84d0c27Fariborz Jahanian  SmallVector<Expr*, 4> MsgExprs;
26550f9b18ed048cd5c1ebe786d1dee05577e84d0c27Fariborz Jahanian  SmallVector<Expr*, 4> ClsExprs;
26560f9b18ed048cd5c1ebe786d1dee05577e84d0c27Fariborz Jahanian
2657eb382ec1507cf2c8c12d7443d0b67c076223aec6Patrick Beard  // Create a call to objc_getClass("<BoxingClass>"). It will be the 1st argument.
2658eb382ec1507cf2c8c12d7443d0b67c076223aec6Patrick Beard  ObjCMethodDecl *BoxingMethod = Exp->getBoxingMethod();
2659eb382ec1507cf2c8c12d7443d0b67c076223aec6Patrick Beard  ObjCInterfaceDecl *BoxingClass = BoxingMethod->getClassInterface();
26600f9b18ed048cd5c1ebe786d1dee05577e84d0c27Fariborz Jahanian
2661eb382ec1507cf2c8c12d7443d0b67c076223aec6Patrick Beard  IdentifierInfo *clsName = BoxingClass->getIdentifier();
2662651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  ClsExprs.push_back(getStringLiteral(clsName->getName()));
26630f9b18ed048cd5c1ebe786d1dee05577e84d0c27Fariborz Jahanian  CallExpr *Cls = SynthesizeCallToFunctionDecl(GetClassFunctionDecl,
26640f9b18ed048cd5c1ebe786d1dee05577e84d0c27Fariborz Jahanian                                               &ClsExprs[0],
26650f9b18ed048cd5c1ebe786d1dee05577e84d0c27Fariborz Jahanian                                               ClsExprs.size(),
26660f9b18ed048cd5c1ebe786d1dee05577e84d0c27Fariborz Jahanian                                               StartLoc, EndLoc);
26670f9b18ed048cd5c1ebe786d1dee05577e84d0c27Fariborz Jahanian  MsgExprs.push_back(Cls);
26680f9b18ed048cd5c1ebe786d1dee05577e84d0c27Fariborz Jahanian
2669eb382ec1507cf2c8c12d7443d0b67c076223aec6Patrick Beard  // Create a call to sel_registerName("<BoxingMethod>:"), etc.
26700f9b18ed048cd5c1ebe786d1dee05577e84d0c27Fariborz Jahanian  // it will be the 2nd argument.
26710f9b18ed048cd5c1ebe786d1dee05577e84d0c27Fariborz Jahanian  SmallVector<Expr*, 4> SelExprs;
2672651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  SelExprs.push_back(
2673651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      getStringLiteral(BoxingMethod->getSelector().getAsString()));
26740f9b18ed048cd5c1ebe786d1dee05577e84d0c27Fariborz Jahanian  CallExpr *SelExp = SynthesizeCallToFunctionDecl(SelGetUidFunctionDecl,
26750f9b18ed048cd5c1ebe786d1dee05577e84d0c27Fariborz Jahanian                                                  &SelExprs[0], SelExprs.size(),
26760f9b18ed048cd5c1ebe786d1dee05577e84d0c27Fariborz Jahanian                                                  StartLoc, EndLoc);
26770f9b18ed048cd5c1ebe786d1dee05577e84d0c27Fariborz Jahanian  MsgExprs.push_back(SelExp);
26780f9b18ed048cd5c1ebe786d1dee05577e84d0c27Fariborz Jahanian
2679eb382ec1507cf2c8c12d7443d0b67c076223aec6Patrick Beard  // User provided sub-expression is the 3rd, and last, argument.
2680eb382ec1507cf2c8c12d7443d0b67c076223aec6Patrick Beard  Expr *subExpr  = Exp->getSubExpr();
2681eb382ec1507cf2c8c12d7443d0b67c076223aec6Patrick Beard  if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(subExpr)) {
26820f9b18ed048cd5c1ebe786d1dee05577e84d0c27Fariborz Jahanian    QualType type = ICE->getType();
26830f9b18ed048cd5c1ebe786d1dee05577e84d0c27Fariborz Jahanian    const Expr *SubExpr = ICE->IgnoreParenImpCasts();
26840f9b18ed048cd5c1ebe786d1dee05577e84d0c27Fariborz Jahanian    CastKind CK = CK_BitCast;
26850f9b18ed048cd5c1ebe786d1dee05577e84d0c27Fariborz Jahanian    if (SubExpr->getType()->isIntegralType(*Context) && type->isBooleanType())
26860f9b18ed048cd5c1ebe786d1dee05577e84d0c27Fariborz Jahanian      CK = CK_IntegralToBoolean;
2687eb382ec1507cf2c8c12d7443d0b67c076223aec6Patrick Beard    subExpr = NoTypeInfoCStyleCastExpr(Context, type, CK, subExpr);
26880f9b18ed048cd5c1ebe786d1dee05577e84d0c27Fariborz Jahanian  }
2689eb382ec1507cf2c8c12d7443d0b67c076223aec6Patrick Beard  MsgExprs.push_back(subExpr);
26900f9b18ed048cd5c1ebe786d1dee05577e84d0c27Fariborz Jahanian
26910f9b18ed048cd5c1ebe786d1dee05577e84d0c27Fariborz Jahanian  SmallVector<QualType, 4> ArgTypes;
269233337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  ArgTypes.push_back(Context->getObjCClassType());
26930f9b18ed048cd5c1ebe786d1dee05577e84d0c27Fariborz Jahanian  ArgTypes.push_back(Context->getObjCSelType());
2694651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  for (const auto PI : BoxingMethod->parameters())
2695651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    ArgTypes.push_back(PI->getType());
2696eb382ec1507cf2c8c12d7443d0b67c076223aec6Patrick Beard
26970f9b18ed048cd5c1ebe786d1dee05577e84d0c27Fariborz Jahanian  QualType returnType = Exp->getType();
26980f9b18ed048cd5c1ebe786d1dee05577e84d0c27Fariborz Jahanian  // Get the type, we will need to reference it in a couple spots.
26990f9b18ed048cd5c1ebe786d1dee05577e84d0c27Fariborz Jahanian  QualType msgSendType = MsgSendFlavor->getType();
27000f9b18ed048cd5c1ebe786d1dee05577e84d0c27Fariborz Jahanian
27010f9b18ed048cd5c1ebe786d1dee05577e84d0c27Fariborz Jahanian  // Create a reference to the objc_msgSend() declaration.
27020f9b18ed048cd5c1ebe786d1dee05577e84d0c27Fariborz Jahanian  DeclRefExpr *DRE = new (Context) DeclRefExpr(MsgSendFlavor, false, msgSendType,
27030f9b18ed048cd5c1ebe786d1dee05577e84d0c27Fariborz Jahanian                                               VK_LValue, SourceLocation());
27040f9b18ed048cd5c1ebe786d1dee05577e84d0c27Fariborz Jahanian
27050f9b18ed048cd5c1ebe786d1dee05577e84d0c27Fariborz Jahanian  CastExpr *cast = NoTypeInfoCStyleCastExpr(Context,
2706eb382ec1507cf2c8c12d7443d0b67c076223aec6Patrick Beard                                            Context->getPointerType(Context->VoidTy),
2707eb382ec1507cf2c8c12d7443d0b67c076223aec6Patrick Beard                                            CK_BitCast, DRE);
27080f9b18ed048cd5c1ebe786d1dee05577e84d0c27Fariborz Jahanian
27090f9b18ed048cd5c1ebe786d1dee05577e84d0c27Fariborz Jahanian  // Now do the "normal" pointer to function cast.
27100f9b18ed048cd5c1ebe786d1dee05577e84d0c27Fariborz Jahanian  QualType castType =
2711bea522ff43a3f11c7a2bc7949119dbb9fce19e39Jordan Rose    getSimpleFunctionType(returnType, ArgTypes, BoxingMethod->isVariadic());
27120f9b18ed048cd5c1ebe786d1dee05577e84d0c27Fariborz Jahanian  castType = Context->getPointerType(castType);
27130f9b18ed048cd5c1ebe786d1dee05577e84d0c27Fariborz Jahanian  cast = NoTypeInfoCStyleCastExpr(Context, castType, CK_BitCast,
27140f9b18ed048cd5c1ebe786d1dee05577e84d0c27Fariborz Jahanian                                  cast);
27150f9b18ed048cd5c1ebe786d1dee05577e84d0c27Fariborz Jahanian
27160f9b18ed048cd5c1ebe786d1dee05577e84d0c27Fariborz Jahanian  // Don't forget the parens to enforce the proper binding.
27170f9b18ed048cd5c1ebe786d1dee05577e84d0c27Fariborz Jahanian  ParenExpr *PE = new (Context) ParenExpr(StartLoc, EndLoc, cast);
27180f9b18ed048cd5c1ebe786d1dee05577e84d0c27Fariborz Jahanian
27190f9b18ed048cd5c1ebe786d1dee05577e84d0c27Fariborz Jahanian  const FunctionType *FT = msgSendType->getAs<FunctionType>();
2720651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  CallExpr *CE = new (Context)
2721651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      CallExpr(*Context, PE, MsgExprs, FT->getReturnType(), VK_RValue, EndLoc);
27220f9b18ed048cd5c1ebe786d1dee05577e84d0c27Fariborz Jahanian  ReplaceStmt(Exp, CE);
27230f9b18ed048cd5c1ebe786d1dee05577e84d0c27Fariborz Jahanian  return CE;
27240f9b18ed048cd5c1ebe786d1dee05577e84d0c27Fariborz Jahanian}
27250f9b18ed048cd5c1ebe786d1dee05577e84d0c27Fariborz Jahanian
272686cff6080ba1db907009885adb5c6c64007e8b48Fariborz JahanianStmt *RewriteModernObjC::RewriteObjCArrayLiteralExpr(ObjCArrayLiteral *Exp) {
272786cff6080ba1db907009885adb5c6c64007e8b48Fariborz Jahanian  // synthesize declaration of helper functions needed in this routine.
272886cff6080ba1db907009885adb5c6c64007e8b48Fariborz Jahanian  if (!SelGetUidFunctionDecl)
272986cff6080ba1db907009885adb5c6c64007e8b48Fariborz Jahanian    SynthSelGetUidFunctionDecl();
273086cff6080ba1db907009885adb5c6c64007e8b48Fariborz Jahanian  // use objc_msgSend() for all.
273186cff6080ba1db907009885adb5c6c64007e8b48Fariborz Jahanian  if (!MsgSendFunctionDecl)
273286cff6080ba1db907009885adb5c6c64007e8b48Fariborz Jahanian    SynthMsgSendFunctionDecl();
273386cff6080ba1db907009885adb5c6c64007e8b48Fariborz Jahanian  if (!GetClassFunctionDecl)
273486cff6080ba1db907009885adb5c6c64007e8b48Fariborz Jahanian    SynthGetClassFunctionDecl();
273586cff6080ba1db907009885adb5c6c64007e8b48Fariborz Jahanian
273686cff6080ba1db907009885adb5c6c64007e8b48Fariborz Jahanian  FunctionDecl *MsgSendFlavor = MsgSendFunctionDecl;
273786cff6080ba1db907009885adb5c6c64007e8b48Fariborz Jahanian  SourceLocation StartLoc = Exp->getLocStart();
273886cff6080ba1db907009885adb5c6c64007e8b48Fariborz Jahanian  SourceLocation EndLoc = Exp->getLocEnd();
273986cff6080ba1db907009885adb5c6c64007e8b48Fariborz Jahanian
2740e35abe1fd3f867ae51d5c68d98578d537eb6becaFariborz Jahanian  // Build the expression: __NSContainer_literal(int, ...).arr
2741b0f245ccce94a069c9334e51f3c5d502eb2d0215Fariborz Jahanian  QualType IntQT = Context->IntTy;
2742b0f245ccce94a069c9334e51f3c5d502eb2d0215Fariborz Jahanian  QualType NSArrayFType =
2743bea522ff43a3f11c7a2bc7949119dbb9fce19e39Jordan Rose    getSimpleFunctionType(Context->VoidTy, IntQT, true);
2744e35abe1fd3f867ae51d5c68d98578d537eb6becaFariborz Jahanian  std::string NSArrayFName("__NSContainer_literal");
2745b0f245ccce94a069c9334e51f3c5d502eb2d0215Fariborz Jahanian  FunctionDecl *NSArrayFD = SynthBlockInitFunctionDecl(NSArrayFName);
2746b0f245ccce94a069c9334e51f3c5d502eb2d0215Fariborz Jahanian  DeclRefExpr *NSArrayDRE =
2747b0f245ccce94a069c9334e51f3c5d502eb2d0215Fariborz Jahanian    new (Context) DeclRefExpr(NSArrayFD, false, NSArrayFType, VK_RValue,
2748b0f245ccce94a069c9334e51f3c5d502eb2d0215Fariborz Jahanian                              SourceLocation());
2749b0f245ccce94a069c9334e51f3c5d502eb2d0215Fariborz Jahanian
2750b0f245ccce94a069c9334e51f3c5d502eb2d0215Fariborz Jahanian  SmallVector<Expr*, 16> InitExprs;
2751b0f245ccce94a069c9334e51f3c5d502eb2d0215Fariborz Jahanian  unsigned NumElements = Exp->getNumElements();
2752b0f245ccce94a069c9334e51f3c5d502eb2d0215Fariborz Jahanian  unsigned UnsignedIntSize =
2753b0f245ccce94a069c9334e51f3c5d502eb2d0215Fariborz Jahanian    static_cast<unsigned>(Context->getTypeSize(Context->UnsignedIntTy));
2754b0f245ccce94a069c9334e51f3c5d502eb2d0215Fariborz Jahanian  Expr *count = IntegerLiteral::Create(*Context,
2755b0f245ccce94a069c9334e51f3c5d502eb2d0215Fariborz Jahanian                                       llvm::APInt(UnsignedIntSize, NumElements),
2756b0f245ccce94a069c9334e51f3c5d502eb2d0215Fariborz Jahanian                                       Context->UnsignedIntTy, SourceLocation());
2757b0f245ccce94a069c9334e51f3c5d502eb2d0215Fariborz Jahanian  InitExprs.push_back(count);
2758b0f245ccce94a069c9334e51f3c5d502eb2d0215Fariborz Jahanian  for (unsigned i = 0; i < NumElements; i++)
2759b0f245ccce94a069c9334e51f3c5d502eb2d0215Fariborz Jahanian    InitExprs.push_back(Exp->getElement(i));
2760b0f245ccce94a069c9334e51f3c5d502eb2d0215Fariborz Jahanian  Expr *NSArrayCallExpr =
27613b6bef9a213249c6ab6d67c07b1ac6380961be3eBenjamin Kramer    new (Context) CallExpr(*Context, NSArrayDRE, InitExprs,
2762b0f245ccce94a069c9334e51f3c5d502eb2d0215Fariborz Jahanian                           NSArrayFType, VK_LValue, SourceLocation());
27636bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
27646bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  FieldDecl *ARRFD = FieldDecl::Create(*Context, nullptr, SourceLocation(),
2765b0f245ccce94a069c9334e51f3c5d502eb2d0215Fariborz Jahanian                                    SourceLocation(),
2766b0f245ccce94a069c9334e51f3c5d502eb2d0215Fariborz Jahanian                                    &Context->Idents.get("arr"),
276733337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar                                    Context->getPointerType(Context->VoidPtrTy),
276833337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar                                    nullptr, /*BitWidth=*/nullptr,
276933337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar                                    /*Mutable=*/true, ICIS_NoInit);
277033337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  MemberExpr *ArrayLiteralME = new (Context)
277133337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar      MemberExpr(NSArrayCallExpr, false, SourceLocation(), ARRFD,
277233337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar                 SourceLocation(), ARRFD->getType(), VK_LValue, OK_Ordinary);
277333337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  QualType ConstIdT = Context->getObjCIdType().withConst();
277433337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  CStyleCastExpr * ArrayLiteralObjects =
277533337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar    NoTypeInfoCStyleCastExpr(Context,
2776b0f245ccce94a069c9334e51f3c5d502eb2d0215Fariborz Jahanian                             Context->getPointerType(ConstIdT),
2777b0f245ccce94a069c9334e51f3c5d502eb2d0215Fariborz Jahanian                             CK_BitCast,
2778b0f245ccce94a069c9334e51f3c5d502eb2d0215Fariborz Jahanian                             ArrayLiteralME);
2779b0f245ccce94a069c9334e51f3c5d502eb2d0215Fariborz Jahanian
278086cff6080ba1db907009885adb5c6c64007e8b48Fariborz Jahanian  // Synthesize a call to objc_msgSend().
278186cff6080ba1db907009885adb5c6c64007e8b48Fariborz Jahanian  SmallVector<Expr*, 32> MsgExprs;
278286cff6080ba1db907009885adb5c6c64007e8b48Fariborz Jahanian  SmallVector<Expr*, 4> ClsExprs;
278386cff6080ba1db907009885adb5c6c64007e8b48Fariborz Jahanian  QualType expType = Exp->getType();
278486cff6080ba1db907009885adb5c6c64007e8b48Fariborz Jahanian
278586cff6080ba1db907009885adb5c6c64007e8b48Fariborz Jahanian  // Create a call to objc_getClass("NSArray"). It will be th 1st argument.
278686cff6080ba1db907009885adb5c6c64007e8b48Fariborz Jahanian  ObjCInterfaceDecl *Class =
278786cff6080ba1db907009885adb5c6c64007e8b48Fariborz Jahanian    expType->getPointeeType()->getAs<ObjCObjectType>()->getInterface();
278886cff6080ba1db907009885adb5c6c64007e8b48Fariborz Jahanian
278986cff6080ba1db907009885adb5c6c64007e8b48Fariborz Jahanian  IdentifierInfo *clsName = Class->getIdentifier();
2790651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  ClsExprs.push_back(getStringLiteral(clsName->getName()));
279186cff6080ba1db907009885adb5c6c64007e8b48Fariborz Jahanian  CallExpr *Cls = SynthesizeCallToFunctionDecl(GetClassFunctionDecl,
279286cff6080ba1db907009885adb5c6c64007e8b48Fariborz Jahanian                                               &ClsExprs[0],
279386cff6080ba1db907009885adb5c6c64007e8b48Fariborz Jahanian                                               ClsExprs.size(),
279486cff6080ba1db907009885adb5c6c64007e8b48Fariborz Jahanian                                               StartLoc, EndLoc);
279586cff6080ba1db907009885adb5c6c64007e8b48Fariborz Jahanian  MsgExprs.push_back(Cls);
279686cff6080ba1db907009885adb5c6c64007e8b48Fariborz Jahanian
279786cff6080ba1db907009885adb5c6c64007e8b48Fariborz Jahanian  // Create a call to sel_registerName("arrayWithObjects:count:").
279886cff6080ba1db907009885adb5c6c64007e8b48Fariborz Jahanian  // it will be the 2nd argument.
279986cff6080ba1db907009885adb5c6c64007e8b48Fariborz Jahanian  SmallVector<Expr*, 4> SelExprs;
280086cff6080ba1db907009885adb5c6c64007e8b48Fariborz Jahanian  ObjCMethodDecl *ArrayMethod = Exp->getArrayWithObjectsMethod();
2801651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  SelExprs.push_back(
2802651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      getStringLiteral(ArrayMethod->getSelector().getAsString()));
280386cff6080ba1db907009885adb5c6c64007e8b48Fariborz Jahanian  CallExpr *SelExp = SynthesizeCallToFunctionDecl(SelGetUidFunctionDecl,
280486cff6080ba1db907009885adb5c6c64007e8b48Fariborz Jahanian                                                  &SelExprs[0], SelExprs.size(),
280586cff6080ba1db907009885adb5c6c64007e8b48Fariborz Jahanian                                                  StartLoc, EndLoc);
280686cff6080ba1db907009885adb5c6c64007e8b48Fariborz Jahanian  MsgExprs.push_back(SelExp);
280786cff6080ba1db907009885adb5c6c64007e8b48Fariborz Jahanian
2808b0f245ccce94a069c9334e51f3c5d502eb2d0215Fariborz Jahanian  // (const id [])objects
2809b0f245ccce94a069c9334e51f3c5d502eb2d0215Fariborz Jahanian  MsgExprs.push_back(ArrayLiteralObjects);
281086cff6080ba1db907009885adb5c6c64007e8b48Fariborz Jahanian
2811b0f245ccce94a069c9334e51f3c5d502eb2d0215Fariborz Jahanian  // (NSUInteger)cnt
2812b0f245ccce94a069c9334e51f3c5d502eb2d0215Fariborz Jahanian  Expr *cnt = IntegerLiteral::Create(*Context,
2813b0f245ccce94a069c9334e51f3c5d502eb2d0215Fariborz Jahanian                                     llvm::APInt(UnsignedIntSize, NumElements),
2814b0f245ccce94a069c9334e51f3c5d502eb2d0215Fariborz Jahanian                                     Context->UnsignedIntTy, SourceLocation());
2815b0f245ccce94a069c9334e51f3c5d502eb2d0215Fariborz Jahanian  MsgExprs.push_back(cnt);
281686cff6080ba1db907009885adb5c6c64007e8b48Fariborz Jahanian
281786cff6080ba1db907009885adb5c6c64007e8b48Fariborz Jahanian
281886cff6080ba1db907009885adb5c6c64007e8b48Fariborz Jahanian  SmallVector<QualType, 4> ArgTypes;
281933337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  ArgTypes.push_back(Context->getObjCClassType());
282086cff6080ba1db907009885adb5c6c64007e8b48Fariborz Jahanian  ArgTypes.push_back(Context->getObjCSelType());
2821651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  for (const auto *PI : ArrayMethod->params())
2822651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    ArgTypes.push_back(PI->getType());
282386cff6080ba1db907009885adb5c6c64007e8b48Fariborz Jahanian
282486cff6080ba1db907009885adb5c6c64007e8b48Fariborz Jahanian  QualType returnType = Exp->getType();
282586cff6080ba1db907009885adb5c6c64007e8b48Fariborz Jahanian  // Get the type, we will need to reference it in a couple spots.
282686cff6080ba1db907009885adb5c6c64007e8b48Fariborz Jahanian  QualType msgSendType = MsgSendFlavor->getType();
282786cff6080ba1db907009885adb5c6c64007e8b48Fariborz Jahanian
282886cff6080ba1db907009885adb5c6c64007e8b48Fariborz Jahanian  // Create a reference to the objc_msgSend() declaration.
282986cff6080ba1db907009885adb5c6c64007e8b48Fariborz Jahanian  DeclRefExpr *DRE = new (Context) DeclRefExpr(MsgSendFlavor, false, msgSendType,
283086cff6080ba1db907009885adb5c6c64007e8b48Fariborz Jahanian                                               VK_LValue, SourceLocation());
283186cff6080ba1db907009885adb5c6c64007e8b48Fariborz Jahanian
283286cff6080ba1db907009885adb5c6c64007e8b48Fariborz Jahanian  CastExpr *cast = NoTypeInfoCStyleCastExpr(Context,
283386cff6080ba1db907009885adb5c6c64007e8b48Fariborz Jahanian                                            Context->getPointerType(Context->VoidTy),
283486cff6080ba1db907009885adb5c6c64007e8b48Fariborz Jahanian                                            CK_BitCast, DRE);
283586cff6080ba1db907009885adb5c6c64007e8b48Fariborz Jahanian
283686cff6080ba1db907009885adb5c6c64007e8b48Fariborz Jahanian  // Now do the "normal" pointer to function cast.
283786cff6080ba1db907009885adb5c6c64007e8b48Fariborz Jahanian  QualType castType =
2838bea522ff43a3f11c7a2bc7949119dbb9fce19e39Jordan Rose  getSimpleFunctionType(returnType, ArgTypes, ArrayMethod->isVariadic());
283986cff6080ba1db907009885adb5c6c64007e8b48Fariborz Jahanian  castType = Context->getPointerType(castType);
284086cff6080ba1db907009885adb5c6c64007e8b48Fariborz Jahanian  cast = NoTypeInfoCStyleCastExpr(Context, castType, CK_BitCast,
284186cff6080ba1db907009885adb5c6c64007e8b48Fariborz Jahanian                                  cast);
284286cff6080ba1db907009885adb5c6c64007e8b48Fariborz Jahanian
284386cff6080ba1db907009885adb5c6c64007e8b48Fariborz Jahanian  // Don't forget the parens to enforce the proper binding.
284486cff6080ba1db907009885adb5c6c64007e8b48Fariborz Jahanian  ParenExpr *PE = new (Context) ParenExpr(StartLoc, EndLoc, cast);
284586cff6080ba1db907009885adb5c6c64007e8b48Fariborz Jahanian
284686cff6080ba1db907009885adb5c6c64007e8b48Fariborz Jahanian  const FunctionType *FT = msgSendType->getAs<FunctionType>();
2847651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  CallExpr *CE = new (Context)
2848651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      CallExpr(*Context, PE, MsgExprs, FT->getReturnType(), VK_RValue, EndLoc);
284986cff6080ba1db907009885adb5c6c64007e8b48Fariborz Jahanian  ReplaceStmt(Exp, CE);
285086cff6080ba1db907009885adb5c6c64007e8b48Fariborz Jahanian  return CE;
285186cff6080ba1db907009885adb5c6c64007e8b48Fariborz Jahanian}
285286cff6080ba1db907009885adb5c6c64007e8b48Fariborz Jahanian
2853e35abe1fd3f867ae51d5c68d98578d537eb6becaFariborz JahanianStmt *RewriteModernObjC::RewriteObjCDictionaryLiteralExpr(ObjCDictionaryLiteral *Exp) {
2854e35abe1fd3f867ae51d5c68d98578d537eb6becaFariborz Jahanian  // synthesize declaration of helper functions needed in this routine.
2855e35abe1fd3f867ae51d5c68d98578d537eb6becaFariborz Jahanian  if (!SelGetUidFunctionDecl)
2856e35abe1fd3f867ae51d5c68d98578d537eb6becaFariborz Jahanian    SynthSelGetUidFunctionDecl();
2857e35abe1fd3f867ae51d5c68d98578d537eb6becaFariborz Jahanian  // use objc_msgSend() for all.
2858e35abe1fd3f867ae51d5c68d98578d537eb6becaFariborz Jahanian  if (!MsgSendFunctionDecl)
2859e35abe1fd3f867ae51d5c68d98578d537eb6becaFariborz Jahanian    SynthMsgSendFunctionDecl();
2860e35abe1fd3f867ae51d5c68d98578d537eb6becaFariborz Jahanian  if (!GetClassFunctionDecl)
2861e35abe1fd3f867ae51d5c68d98578d537eb6becaFariborz Jahanian    SynthGetClassFunctionDecl();
2862e35abe1fd3f867ae51d5c68d98578d537eb6becaFariborz Jahanian
2863e35abe1fd3f867ae51d5c68d98578d537eb6becaFariborz Jahanian  FunctionDecl *MsgSendFlavor = MsgSendFunctionDecl;
2864e35abe1fd3f867ae51d5c68d98578d537eb6becaFariborz Jahanian  SourceLocation StartLoc = Exp->getLocStart();
2865e35abe1fd3f867ae51d5c68d98578d537eb6becaFariborz Jahanian  SourceLocation EndLoc = Exp->getLocEnd();
2866e35abe1fd3f867ae51d5c68d98578d537eb6becaFariborz Jahanian
2867e35abe1fd3f867ae51d5c68d98578d537eb6becaFariborz Jahanian  // Build the expression: __NSContainer_literal(int, ...).arr
2868e35abe1fd3f867ae51d5c68d98578d537eb6becaFariborz Jahanian  QualType IntQT = Context->IntTy;
2869e35abe1fd3f867ae51d5c68d98578d537eb6becaFariborz Jahanian  QualType NSDictFType =
2870bea522ff43a3f11c7a2bc7949119dbb9fce19e39Jordan Rose    getSimpleFunctionType(Context->VoidTy, IntQT, true);
2871e35abe1fd3f867ae51d5c68d98578d537eb6becaFariborz Jahanian  std::string NSDictFName("__NSContainer_literal");
2872e35abe1fd3f867ae51d5c68d98578d537eb6becaFariborz Jahanian  FunctionDecl *NSDictFD = SynthBlockInitFunctionDecl(NSDictFName);
2873e35abe1fd3f867ae51d5c68d98578d537eb6becaFariborz Jahanian  DeclRefExpr *NSDictDRE =
2874e35abe1fd3f867ae51d5c68d98578d537eb6becaFariborz Jahanian    new (Context) DeclRefExpr(NSDictFD, false, NSDictFType, VK_RValue,
2875e35abe1fd3f867ae51d5c68d98578d537eb6becaFariborz Jahanian                              SourceLocation());
2876e35abe1fd3f867ae51d5c68d98578d537eb6becaFariborz Jahanian
2877e35abe1fd3f867ae51d5c68d98578d537eb6becaFariborz Jahanian  SmallVector<Expr*, 16> KeyExprs;
2878e35abe1fd3f867ae51d5c68d98578d537eb6becaFariborz Jahanian  SmallVector<Expr*, 16> ValueExprs;
2879e35abe1fd3f867ae51d5c68d98578d537eb6becaFariborz Jahanian
2880e35abe1fd3f867ae51d5c68d98578d537eb6becaFariborz Jahanian  unsigned NumElements = Exp->getNumElements();
2881e35abe1fd3f867ae51d5c68d98578d537eb6becaFariborz Jahanian  unsigned UnsignedIntSize =
2882e35abe1fd3f867ae51d5c68d98578d537eb6becaFariborz Jahanian    static_cast<unsigned>(Context->getTypeSize(Context->UnsignedIntTy));
2883e35abe1fd3f867ae51d5c68d98578d537eb6becaFariborz Jahanian  Expr *count = IntegerLiteral::Create(*Context,
2884e35abe1fd3f867ae51d5c68d98578d537eb6becaFariborz Jahanian                                       llvm::APInt(UnsignedIntSize, NumElements),
2885e35abe1fd3f867ae51d5c68d98578d537eb6becaFariborz Jahanian                                       Context->UnsignedIntTy, SourceLocation());
2886e35abe1fd3f867ae51d5c68d98578d537eb6becaFariborz Jahanian  KeyExprs.push_back(count);
2887e35abe1fd3f867ae51d5c68d98578d537eb6becaFariborz Jahanian  ValueExprs.push_back(count);
2888e35abe1fd3f867ae51d5c68d98578d537eb6becaFariborz Jahanian  for (unsigned i = 0; i < NumElements; i++) {
2889e35abe1fd3f867ae51d5c68d98578d537eb6becaFariborz Jahanian    ObjCDictionaryElement Element = Exp->getKeyValueElement(i);
2890e35abe1fd3f867ae51d5c68d98578d537eb6becaFariborz Jahanian    KeyExprs.push_back(Element.Key);
2891e35abe1fd3f867ae51d5c68d98578d537eb6becaFariborz Jahanian    ValueExprs.push_back(Element.Value);
2892e35abe1fd3f867ae51d5c68d98578d537eb6becaFariborz Jahanian  }
2893e35abe1fd3f867ae51d5c68d98578d537eb6becaFariborz Jahanian
2894e35abe1fd3f867ae51d5c68d98578d537eb6becaFariborz Jahanian  // (const id [])objects
2895e35abe1fd3f867ae51d5c68d98578d537eb6becaFariborz Jahanian  Expr *NSValueCallExpr =
28963b6bef9a213249c6ab6d67c07b1ac6380961be3eBenjamin Kramer    new (Context) CallExpr(*Context, NSDictDRE, ValueExprs,
2897e35abe1fd3f867ae51d5c68d98578d537eb6becaFariborz Jahanian                           NSDictFType, VK_LValue, SourceLocation());
28986bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
28996bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  FieldDecl *ARRFD = FieldDecl::Create(*Context, nullptr, SourceLocation(),
2900e35abe1fd3f867ae51d5c68d98578d537eb6becaFariborz Jahanian                                       SourceLocation(),
2901e35abe1fd3f867ae51d5c68d98578d537eb6becaFariborz Jahanian                                       &Context->Idents.get("arr"),
290233337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar                                       Context->getPointerType(Context->VoidPtrTy),
290333337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar                                       nullptr, /*BitWidth=*/nullptr,
290433337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar                                       /*Mutable=*/true, ICIS_NoInit);
290533337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  MemberExpr *DictLiteralValueME = new (Context)
290633337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar      MemberExpr(NSValueCallExpr, false, SourceLocation(), ARRFD,
290733337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar                 SourceLocation(), ARRFD->getType(), VK_LValue, OK_Ordinary);
290833337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  QualType ConstIdT = Context->getObjCIdType().withConst();
290933337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  CStyleCastExpr * DictValueObjects =
291033337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar    NoTypeInfoCStyleCastExpr(Context,
2911e35abe1fd3f867ae51d5c68d98578d537eb6becaFariborz Jahanian                             Context->getPointerType(ConstIdT),
2912e35abe1fd3f867ae51d5c68d98578d537eb6becaFariborz Jahanian                             CK_BitCast,
2913e35abe1fd3f867ae51d5c68d98578d537eb6becaFariborz Jahanian                             DictLiteralValueME);
2914e35abe1fd3f867ae51d5c68d98578d537eb6becaFariborz Jahanian  // (const id <NSCopying> [])keys
291533337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  Expr *NSKeyCallExpr =
291633337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar    new (Context) CallExpr(*Context, NSDictDRE, KeyExprs,
291733337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar                           NSDictFType, VK_LValue, SourceLocation());
291833337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar
291933337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  MemberExpr *DictLiteralKeyME = new (Context)
292033337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar      MemberExpr(NSKeyCallExpr, false, SourceLocation(), ARRFD,
292133337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar                 SourceLocation(), ARRFD->getType(), VK_LValue, OK_Ordinary);
292233337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar
292333337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  CStyleCastExpr * DictKeyObjects =
292433337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar    NoTypeInfoCStyleCastExpr(Context,
292533337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar                             Context->getPointerType(ConstIdT),
2926e35abe1fd3f867ae51d5c68d98578d537eb6becaFariborz Jahanian                             CK_BitCast,
2927e35abe1fd3f867ae51d5c68d98578d537eb6becaFariborz Jahanian                             DictLiteralKeyME);
2928e35abe1fd3f867ae51d5c68d98578d537eb6becaFariborz Jahanian
2929e35abe1fd3f867ae51d5c68d98578d537eb6becaFariborz Jahanian
2930e35abe1fd3f867ae51d5c68d98578d537eb6becaFariborz Jahanian
2931e35abe1fd3f867ae51d5c68d98578d537eb6becaFariborz Jahanian  // Synthesize a call to objc_msgSend().
2932e35abe1fd3f867ae51d5c68d98578d537eb6becaFariborz Jahanian  SmallVector<Expr*, 32> MsgExprs;
2933e35abe1fd3f867ae51d5c68d98578d537eb6becaFariborz Jahanian  SmallVector<Expr*, 4> ClsExprs;
2934e35abe1fd3f867ae51d5c68d98578d537eb6becaFariborz Jahanian  QualType expType = Exp->getType();
2935e35abe1fd3f867ae51d5c68d98578d537eb6becaFariborz Jahanian
2936e35abe1fd3f867ae51d5c68d98578d537eb6becaFariborz Jahanian  // Create a call to objc_getClass("NSArray"). It will be th 1st argument.
2937e35abe1fd3f867ae51d5c68d98578d537eb6becaFariborz Jahanian  ObjCInterfaceDecl *Class =
2938e35abe1fd3f867ae51d5c68d98578d537eb6becaFariborz Jahanian  expType->getPointeeType()->getAs<ObjCObjectType>()->getInterface();
2939e35abe1fd3f867ae51d5c68d98578d537eb6becaFariborz Jahanian
2940e35abe1fd3f867ae51d5c68d98578d537eb6becaFariborz Jahanian  IdentifierInfo *clsName = Class->getIdentifier();
2941651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  ClsExprs.push_back(getStringLiteral(clsName->getName()));
2942e35abe1fd3f867ae51d5c68d98578d537eb6becaFariborz Jahanian  CallExpr *Cls = SynthesizeCallToFunctionDecl(GetClassFunctionDecl,
2943e35abe1fd3f867ae51d5c68d98578d537eb6becaFariborz Jahanian                                               &ClsExprs[0],
2944e35abe1fd3f867ae51d5c68d98578d537eb6becaFariborz Jahanian                                               ClsExprs.size(),
2945e35abe1fd3f867ae51d5c68d98578d537eb6becaFariborz Jahanian                                               StartLoc, EndLoc);
2946e35abe1fd3f867ae51d5c68d98578d537eb6becaFariborz Jahanian  MsgExprs.push_back(Cls);
2947e35abe1fd3f867ae51d5c68d98578d537eb6becaFariborz Jahanian
2948e35abe1fd3f867ae51d5c68d98578d537eb6becaFariborz Jahanian  // Create a call to sel_registerName("arrayWithObjects:count:").
2949e35abe1fd3f867ae51d5c68d98578d537eb6becaFariborz Jahanian  // it will be the 2nd argument.
2950e35abe1fd3f867ae51d5c68d98578d537eb6becaFariborz Jahanian  SmallVector<Expr*, 4> SelExprs;
2951e35abe1fd3f867ae51d5c68d98578d537eb6becaFariborz Jahanian  ObjCMethodDecl *DictMethod = Exp->getDictWithObjectsMethod();
2952651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  SelExprs.push_back(getStringLiteral(DictMethod->getSelector().getAsString()));
2953e35abe1fd3f867ae51d5c68d98578d537eb6becaFariborz Jahanian  CallExpr *SelExp = SynthesizeCallToFunctionDecl(SelGetUidFunctionDecl,
2954e35abe1fd3f867ae51d5c68d98578d537eb6becaFariborz Jahanian                                                  &SelExprs[0], SelExprs.size(),
2955e35abe1fd3f867ae51d5c68d98578d537eb6becaFariborz Jahanian                                                  StartLoc, EndLoc);
2956e35abe1fd3f867ae51d5c68d98578d537eb6becaFariborz Jahanian  MsgExprs.push_back(SelExp);
2957e35abe1fd3f867ae51d5c68d98578d537eb6becaFariborz Jahanian
2958e35abe1fd3f867ae51d5c68d98578d537eb6becaFariborz Jahanian  // (const id [])objects
2959e35abe1fd3f867ae51d5c68d98578d537eb6becaFariborz Jahanian  MsgExprs.push_back(DictValueObjects);
2960e35abe1fd3f867ae51d5c68d98578d537eb6becaFariborz Jahanian
2961e35abe1fd3f867ae51d5c68d98578d537eb6becaFariborz Jahanian  // (const id <NSCopying> [])keys
2962e35abe1fd3f867ae51d5c68d98578d537eb6becaFariborz Jahanian  MsgExprs.push_back(DictKeyObjects);
2963e35abe1fd3f867ae51d5c68d98578d537eb6becaFariborz Jahanian
2964e35abe1fd3f867ae51d5c68d98578d537eb6becaFariborz Jahanian  // (NSUInteger)cnt
2965e35abe1fd3f867ae51d5c68d98578d537eb6becaFariborz Jahanian  Expr *cnt = IntegerLiteral::Create(*Context,
2966e35abe1fd3f867ae51d5c68d98578d537eb6becaFariborz Jahanian                                     llvm::APInt(UnsignedIntSize, NumElements),
2967e35abe1fd3f867ae51d5c68d98578d537eb6becaFariborz Jahanian                                     Context->UnsignedIntTy, SourceLocation());
2968e35abe1fd3f867ae51d5c68d98578d537eb6becaFariborz Jahanian  MsgExprs.push_back(cnt);
2969e35abe1fd3f867ae51d5c68d98578d537eb6becaFariborz Jahanian
2970e35abe1fd3f867ae51d5c68d98578d537eb6becaFariborz Jahanian
2971e35abe1fd3f867ae51d5c68d98578d537eb6becaFariborz Jahanian  SmallVector<QualType, 8> ArgTypes;
297233337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  ArgTypes.push_back(Context->getObjCClassType());
2973e35abe1fd3f867ae51d5c68d98578d537eb6becaFariborz Jahanian  ArgTypes.push_back(Context->getObjCSelType());
2974651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  for (const auto *PI : DictMethod->params()) {
2975651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    QualType T = PI->getType();
2976e35abe1fd3f867ae51d5c68d98578d537eb6becaFariborz Jahanian    if (const PointerType* PT = T->getAs<PointerType>()) {
2977e35abe1fd3f867ae51d5c68d98578d537eb6becaFariborz Jahanian      QualType PointeeTy = PT->getPointeeType();
2978e35abe1fd3f867ae51d5c68d98578d537eb6becaFariborz Jahanian      convertToUnqualifiedObjCType(PointeeTy);
2979e35abe1fd3f867ae51d5c68d98578d537eb6becaFariborz Jahanian      T = Context->getPointerType(PointeeTy);
2980e35abe1fd3f867ae51d5c68d98578d537eb6becaFariborz Jahanian    }
2981e35abe1fd3f867ae51d5c68d98578d537eb6becaFariborz Jahanian    ArgTypes.push_back(T);
2982e35abe1fd3f867ae51d5c68d98578d537eb6becaFariborz Jahanian  }
2983e35abe1fd3f867ae51d5c68d98578d537eb6becaFariborz Jahanian
2984e35abe1fd3f867ae51d5c68d98578d537eb6becaFariborz Jahanian  QualType returnType = Exp->getType();
2985e35abe1fd3f867ae51d5c68d98578d537eb6becaFariborz Jahanian  // Get the type, we will need to reference it in a couple spots.
2986e35abe1fd3f867ae51d5c68d98578d537eb6becaFariborz Jahanian  QualType msgSendType = MsgSendFlavor->getType();
2987e35abe1fd3f867ae51d5c68d98578d537eb6becaFariborz Jahanian
2988e35abe1fd3f867ae51d5c68d98578d537eb6becaFariborz Jahanian  // Create a reference to the objc_msgSend() declaration.
2989e35abe1fd3f867ae51d5c68d98578d537eb6becaFariborz Jahanian  DeclRefExpr *DRE = new (Context) DeclRefExpr(MsgSendFlavor, false, msgSendType,
2990e35abe1fd3f867ae51d5c68d98578d537eb6becaFariborz Jahanian                                               VK_LValue, SourceLocation());
2991e35abe1fd3f867ae51d5c68d98578d537eb6becaFariborz Jahanian
2992e35abe1fd3f867ae51d5c68d98578d537eb6becaFariborz Jahanian  CastExpr *cast = NoTypeInfoCStyleCastExpr(Context,
2993e35abe1fd3f867ae51d5c68d98578d537eb6becaFariborz Jahanian                                            Context->getPointerType(Context->VoidTy),
2994e35abe1fd3f867ae51d5c68d98578d537eb6becaFariborz Jahanian                                            CK_BitCast, DRE);
2995e35abe1fd3f867ae51d5c68d98578d537eb6becaFariborz Jahanian
2996e35abe1fd3f867ae51d5c68d98578d537eb6becaFariborz Jahanian  // Now do the "normal" pointer to function cast.
2997e35abe1fd3f867ae51d5c68d98578d537eb6becaFariborz Jahanian  QualType castType =
2998bea522ff43a3f11c7a2bc7949119dbb9fce19e39Jordan Rose  getSimpleFunctionType(returnType, ArgTypes, DictMethod->isVariadic());
2999e35abe1fd3f867ae51d5c68d98578d537eb6becaFariborz Jahanian  castType = Context->getPointerType(castType);
3000e35abe1fd3f867ae51d5c68d98578d537eb6becaFariborz Jahanian  cast = NoTypeInfoCStyleCastExpr(Context, castType, CK_BitCast,
3001e35abe1fd3f867ae51d5c68d98578d537eb6becaFariborz Jahanian                                  cast);
3002e35abe1fd3f867ae51d5c68d98578d537eb6becaFariborz Jahanian
3003e35abe1fd3f867ae51d5c68d98578d537eb6becaFariborz Jahanian  // Don't forget the parens to enforce the proper binding.
3004e35abe1fd3f867ae51d5c68d98578d537eb6becaFariborz Jahanian  ParenExpr *PE = new (Context) ParenExpr(StartLoc, EndLoc, cast);
3005e35abe1fd3f867ae51d5c68d98578d537eb6becaFariborz Jahanian
3006e35abe1fd3f867ae51d5c68d98578d537eb6becaFariborz Jahanian  const FunctionType *FT = msgSendType->getAs<FunctionType>();
3007651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  CallExpr *CE = new (Context)
3008651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      CallExpr(*Context, PE, MsgExprs, FT->getReturnType(), VK_RValue, EndLoc);
3009e35abe1fd3f867ae51d5c68d98578d537eb6becaFariborz Jahanian  ReplaceStmt(Exp, CE);
3010e35abe1fd3f867ae51d5c68d98578d537eb6becaFariborz Jahanian  return CE;
3011e35abe1fd3f867ae51d5c68d98578d537eb6becaFariborz Jahanian}
3012e35abe1fd3f867ae51d5c68d98578d537eb6becaFariborz Jahanian
3013b20c46ea980b5aed7b480761ea1daf2f26c23b2dFariborz Jahanian// struct __rw_objc_super {
3014b20c46ea980b5aed7b480761ea1daf2f26c23b2dFariborz Jahanian//   struct objc_object *object; struct objc_object *superClass;
3015b20c46ea980b5aed7b480761ea1daf2f26c23b2dFariborz Jahanian// };
301664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz JahanianQualType RewriteModernObjC::getSuperStructType() {
301764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  if (!SuperStructDecl) {
301864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    SuperStructDecl = RecordDecl::Create(*Context, TTK_Struct, TUDecl,
301964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                         SourceLocation(), SourceLocation(),
3020b20c46ea980b5aed7b480761ea1daf2f26c23b2dFariborz Jahanian                                         &Context->Idents.get("__rw_objc_super"));
302164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    QualType FieldTypes[2];
302264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
3023b20c46ea980b5aed7b480761ea1daf2f26c23b2dFariborz Jahanian    // struct objc_object *object;
302464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    FieldTypes[0] = Context->getObjCIdType();
3025b20c46ea980b5aed7b480761ea1daf2f26c23b2dFariborz Jahanian    // struct objc_object *superClass;
3026b20c46ea980b5aed7b480761ea1daf2f26c23b2dFariborz Jahanian    FieldTypes[1] = Context->getObjCIdType();
302764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
302864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    // Create fields
302964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    for (unsigned i = 0; i < 2; ++i) {
303064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      SuperStructDecl->addDecl(FieldDecl::Create(*Context, SuperStructDecl,
303164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                                 SourceLocation(),
30326bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines                                                 SourceLocation(), nullptr,
30336bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines                                                 FieldTypes[i], nullptr,
30346bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines                                                 /*BitWidth=*/nullptr,
303564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                                 /*Mutable=*/false,
3036ca5233044ef679840d1ad1c46a36b16e2ee8a6e1Richard Smith                                                 ICIS_NoInit));
303764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    }
303864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
303964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    SuperStructDecl->completeDefinition();
304064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  }
304164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  return Context->getTagDeclType(SuperStructDecl);
304264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian}
304364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
304464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz JahanianQualType RewriteModernObjC::getConstantStringStructType() {
304564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  if (!ConstantStringDecl) {
304664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    ConstantStringDecl = RecordDecl::Create(*Context, TTK_Struct, TUDecl,
304764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                            SourceLocation(), SourceLocation(),
304864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                         &Context->Idents.get("__NSConstantStringImpl"));
304964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    QualType FieldTypes[4];
305064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
305164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    // struct objc_object *receiver;
305264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    FieldTypes[0] = Context->getObjCIdType();
305364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    // int flags;
305464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    FieldTypes[1] = Context->IntTy;
305564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    // char *str;
305664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    FieldTypes[2] = Context->getPointerType(Context->CharTy);
305764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    // long length;
305864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    FieldTypes[3] = Context->LongTy;
305964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
306064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    // Create fields
306164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    for (unsigned i = 0; i < 4; ++i) {
306264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      ConstantStringDecl->addDecl(FieldDecl::Create(*Context,
306364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                                    ConstantStringDecl,
306464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                                    SourceLocation(),
30656bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines                                                    SourceLocation(), nullptr,
30666bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines                                                    FieldTypes[i], nullptr,
30676bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines                                                    /*BitWidth=*/nullptr,
306864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                                    /*Mutable=*/true,
3069ca5233044ef679840d1ad1c46a36b16e2ee8a6e1Richard Smith                                                    ICIS_NoInit));
307064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    }
307164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
307264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    ConstantStringDecl->completeDefinition();
307364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  }
307464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  return Context->getTagDeclType(ConstantStringDecl);
307564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian}
307664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
3077be8d55ce4a20b86d9337dcb28759e068cb3510f3Fariborz Jahanian/// getFunctionSourceLocation - returns start location of a function
3078be8d55ce4a20b86d9337dcb28759e068cb3510f3Fariborz Jahanian/// definition. Complication arises when function has declared as
3079be8d55ce4a20b86d9337dcb28759e068cb3510f3Fariborz Jahanian/// extern "C" or extern "C" {...}
3080be8d55ce4a20b86d9337dcb28759e068cb3510f3Fariborz Jahanianstatic SourceLocation getFunctionSourceLocation (RewriteModernObjC &R,
3081be8d55ce4a20b86d9337dcb28759e068cb3510f3Fariborz Jahanian                                                 FunctionDecl *FD) {
3082be8d55ce4a20b86d9337dcb28759e068cb3510f3Fariborz Jahanian  if (FD->isExternC()  && !FD->isMain()) {
3083be8d55ce4a20b86d9337dcb28759e068cb3510f3Fariborz Jahanian    const DeclContext *DC = FD->getDeclContext();
3084be8d55ce4a20b86d9337dcb28759e068cb3510f3Fariborz Jahanian    if (const LinkageSpecDecl *LSD = dyn_cast<LinkageSpecDecl>(DC))
3085be8d55ce4a20b86d9337dcb28759e068cb3510f3Fariborz Jahanian      // if it is extern "C" {...}, return function decl's own location.
3086be8d55ce4a20b86d9337dcb28759e068cb3510f3Fariborz Jahanian      if (!LSD->getRBraceLoc().isValid())
3087be8d55ce4a20b86d9337dcb28759e068cb3510f3Fariborz Jahanian        return LSD->getExternLoc();
3088be8d55ce4a20b86d9337dcb28759e068cb3510f3Fariborz Jahanian  }
3089d2615cc53b916e8aae45783ca7113b93de515ce3Rafael Espindola  if (FD->getStorageClass() != SC_None)
3090be8d55ce4a20b86d9337dcb28759e068cb3510f3Fariborz Jahanian    R.RewriteBlockLiteralFunctionDecl(FD);
3091be8d55ce4a20b86d9337dcb28759e068cb3510f3Fariborz Jahanian  return FD->getTypeSpecStartLoc();
3092be8d55ce4a20b86d9337dcb28759e068cb3510f3Fariborz Jahanian}
3093be8d55ce4a20b86d9337dcb28759e068cb3510f3Fariborz Jahanian
30949620596ca2ca19e365af4e4d4968cb4d9228c4fcFariborz Jahanianvoid RewriteModernObjC::RewriteLineDirective(const Decl *D) {
30959620596ca2ca19e365af4e4d4968cb4d9228c4fcFariborz Jahanian
30969620596ca2ca19e365af4e4d4968cb4d9228c4fcFariborz Jahanian  SourceLocation Location = D->getLocation();
30979620596ca2ca19e365af4e4d4968cb4d9228c4fcFariborz Jahanian
3098ada7191795dde85a620008094fbe5464abdb916bFariborz Jahanian  if (Location.isFileID() && GenerateLineInfo) {
30993b45ca9e6292b45ab39d8c44d15a617017f26198Fariborz Jahanian    std::string LineString("\n#line ");
31009620596ca2ca19e365af4e4d4968cb4d9228c4fcFariborz Jahanian    PresumedLoc PLoc = SM->getPresumedLoc(Location);
31019620596ca2ca19e365af4e4d4968cb4d9228c4fcFariborz Jahanian    LineString += utostr(PLoc.getLine());
31029620596ca2ca19e365af4e4d4968cb4d9228c4fcFariborz Jahanian    LineString += " \"";
3103ba529a9bf9acbfc718970a030017b73715108b8eNAKAMURA Takumi    LineString += Lexer::Stringify(PLoc.getFilename());
31049620596ca2ca19e365af4e4d4968cb4d9228c4fcFariborz Jahanian    if (isa<ObjCMethodDecl>(D))
31059620596ca2ca19e365af4e4d4968cb4d9228c4fcFariborz Jahanian      LineString += "\"";
31069620596ca2ca19e365af4e4d4968cb4d9228c4fcFariborz Jahanian    else LineString += "\"\n";
31079620596ca2ca19e365af4e4d4968cb4d9228c4fcFariborz Jahanian
31089620596ca2ca19e365af4e4d4968cb4d9228c4fcFariborz Jahanian    Location = D->getLocStart();
31099620596ca2ca19e365af4e4d4968cb4d9228c4fcFariborz Jahanian    if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
31109620596ca2ca19e365af4e4d4968cb4d9228c4fcFariborz Jahanian      if (FD->isExternC()  && !FD->isMain()) {
31119620596ca2ca19e365af4e4d4968cb4d9228c4fcFariborz Jahanian        const DeclContext *DC = FD->getDeclContext();
31129620596ca2ca19e365af4e4d4968cb4d9228c4fcFariborz Jahanian        if (const LinkageSpecDecl *LSD = dyn_cast<LinkageSpecDecl>(DC))
31139620596ca2ca19e365af4e4d4968cb4d9228c4fcFariborz Jahanian          // if it is extern "C" {...}, return function decl's own location.
31149620596ca2ca19e365af4e4d4968cb4d9228c4fcFariborz Jahanian          if (!LSD->getRBraceLoc().isValid())
31159620596ca2ca19e365af4e4d4968cb4d9228c4fcFariborz Jahanian            Location = LSD->getExternLoc();
31169620596ca2ca19e365af4e4d4968cb4d9228c4fcFariborz Jahanian      }
31179620596ca2ca19e365af4e4d4968cb4d9228c4fcFariborz Jahanian    }
31189620596ca2ca19e365af4e4d4968cb4d9228c4fcFariborz Jahanian    InsertText(Location, LineString);
31199620596ca2ca19e365af4e4d4968cb4d9228c4fcFariborz Jahanian  }
31209620596ca2ca19e365af4e4d4968cb4d9228c4fcFariborz Jahanian}
31219620596ca2ca19e365af4e4d4968cb4d9228c4fcFariborz Jahanian
3122be8d55ce4a20b86d9337dcb28759e068cb3510f3Fariborz Jahanian/// SynthMsgSendStretCallExpr - This routine translates message expression
3123be8d55ce4a20b86d9337dcb28759e068cb3510f3Fariborz Jahanian/// into a call to objc_msgSend_stret() entry point. Tricky part is that
3124be8d55ce4a20b86d9337dcb28759e068cb3510f3Fariborz Jahanian/// nil check on receiver must be performed before calling objc_msgSend_stret.
3125be8d55ce4a20b86d9337dcb28759e068cb3510f3Fariborz Jahanian/// MsgSendStretFlavor - function declaration objc_msgSend_stret(...)
3126be8d55ce4a20b86d9337dcb28759e068cb3510f3Fariborz Jahanian/// msgSendType - function type of objc_msgSend_stret(...)
3127be8d55ce4a20b86d9337dcb28759e068cb3510f3Fariborz Jahanian/// returnType - Result type of the method being synthesized.
3128be8d55ce4a20b86d9337dcb28759e068cb3510f3Fariborz Jahanian/// ArgTypes - type of the arguments passed to objc_msgSend_stret, starting with receiver type.
3129be8d55ce4a20b86d9337dcb28759e068cb3510f3Fariborz Jahanian/// MsgExprs - list of argument expressions being passed to objc_msgSend_stret,
3130be8d55ce4a20b86d9337dcb28759e068cb3510f3Fariborz Jahanian/// starting with receiver.
3131be8d55ce4a20b86d9337dcb28759e068cb3510f3Fariborz Jahanian/// Method - Method being rewritten.
3132be8d55ce4a20b86d9337dcb28759e068cb3510f3Fariborz JahanianExpr *RewriteModernObjC::SynthMsgSendStretCallExpr(FunctionDecl *MsgSendStretFlavor,
3133be8d55ce4a20b86d9337dcb28759e068cb3510f3Fariborz Jahanian                                                 QualType returnType,
3134be8d55ce4a20b86d9337dcb28759e068cb3510f3Fariborz Jahanian                                                 SmallVectorImpl<QualType> &ArgTypes,
3135be8d55ce4a20b86d9337dcb28759e068cb3510f3Fariborz Jahanian                                                 SmallVectorImpl<Expr*> &MsgExprs,
3136be8d55ce4a20b86d9337dcb28759e068cb3510f3Fariborz Jahanian                                                 ObjCMethodDecl *Method) {
3137be8d55ce4a20b86d9337dcb28759e068cb3510f3Fariborz Jahanian  // Now do the "normal" pointer to function cast.
3138bea522ff43a3f11c7a2bc7949119dbb9fce19e39Jordan Rose  QualType castType = getSimpleFunctionType(returnType, ArgTypes,
3139bea522ff43a3f11c7a2bc7949119dbb9fce19e39Jordan Rose                                            Method ? Method->isVariadic()
3140bea522ff43a3f11c7a2bc7949119dbb9fce19e39Jordan Rose                                                   : false);
3141be8d55ce4a20b86d9337dcb28759e068cb3510f3Fariborz Jahanian  castType = Context->getPointerType(castType);
3142be8d55ce4a20b86d9337dcb28759e068cb3510f3Fariborz Jahanian
3143be8d55ce4a20b86d9337dcb28759e068cb3510f3Fariborz Jahanian  // build type for containing the objc_msgSend_stret object.
3144be8d55ce4a20b86d9337dcb28759e068cb3510f3Fariborz Jahanian  static unsigned stretCount=0;
3145be8d55ce4a20b86d9337dcb28759e068cb3510f3Fariborz Jahanian  std::string name = "__Stret"; name += utostr(stretCount);
31462ca5af239af48ed5c6af62ae03cd39c246af06dbFariborz Jahanian  std::string str =
31472ca5af239af48ed5c6af62ae03cd39c246af06dbFariborz Jahanian    "extern \"C\" void * __cdecl memset(void *_Dst, int _Val, size_t _Size);\n";
3148426bb9c9008b9f042e8b882352a2070e5b39d08cFariborz Jahanian  str += "namespace {\n";
31492ca5af239af48ed5c6af62ae03cd39c246af06dbFariborz Jahanian  str += "struct "; str += name;
3150be8d55ce4a20b86d9337dcb28759e068cb3510f3Fariborz Jahanian  str += " {\n\t";
3151be8d55ce4a20b86d9337dcb28759e068cb3510f3Fariborz Jahanian  str += name;
3152be8d55ce4a20b86d9337dcb28759e068cb3510f3Fariborz Jahanian  str += "(id receiver, SEL sel";
3153be8d55ce4a20b86d9337dcb28759e068cb3510f3Fariborz Jahanian  for (unsigned i = 2; i < ArgTypes.size(); i++) {
31546734ec41ab596088fd157b127f98aeae59ce8e6dFariborz Jahanian    std::string ArgName = "arg"; ArgName += utostr(i);
31556734ec41ab596088fd157b127f98aeae59ce8e6dFariborz Jahanian    ArgTypes[i].getAsStringInternal(ArgName, Context->getPrintingPolicy());
31566734ec41ab596088fd157b127f98aeae59ce8e6dFariborz Jahanian    str += ", "; str += ArgName;
3157be8d55ce4a20b86d9337dcb28759e068cb3510f3Fariborz Jahanian  }
3158be8d55ce4a20b86d9337dcb28759e068cb3510f3Fariborz Jahanian  // could be vararg.
3159be8d55ce4a20b86d9337dcb28759e068cb3510f3Fariborz Jahanian  for (unsigned i = ArgTypes.size(); i < MsgExprs.size(); i++) {
31606734ec41ab596088fd157b127f98aeae59ce8e6dFariborz Jahanian    std::string ArgName = "arg"; ArgName += utostr(i);
31616734ec41ab596088fd157b127f98aeae59ce8e6dFariborz Jahanian    MsgExprs[i]->getType().getAsStringInternal(ArgName,
31626734ec41ab596088fd157b127f98aeae59ce8e6dFariborz Jahanian                                               Context->getPrintingPolicy());
31636734ec41ab596088fd157b127f98aeae59ce8e6dFariborz Jahanian    str += ", "; str += ArgName;
3164be8d55ce4a20b86d9337dcb28759e068cb3510f3Fariborz Jahanian  }
3165be8d55ce4a20b86d9337dcb28759e068cb3510f3Fariborz Jahanian
3166be8d55ce4a20b86d9337dcb28759e068cb3510f3Fariborz Jahanian  str += ") {\n";
3167426bb9c9008b9f042e8b882352a2070e5b39d08cFariborz Jahanian  str += "\t  unsigned size = sizeof(";
3168426bb9c9008b9f042e8b882352a2070e5b39d08cFariborz Jahanian  str += returnType.getAsString(Context->getPrintingPolicy()); str += ");\n";
3169426bb9c9008b9f042e8b882352a2070e5b39d08cFariborz Jahanian
3170426bb9c9008b9f042e8b882352a2070e5b39d08cFariborz Jahanian  str += "\t  if (size == 1 || size == 2 || size == 4 || size == 8)\n";
3171426bb9c9008b9f042e8b882352a2070e5b39d08cFariborz Jahanian
3172426bb9c9008b9f042e8b882352a2070e5b39d08cFariborz Jahanian  str += "\t    s = (("; str += castType.getAsString(Context->getPrintingPolicy());
3173426bb9c9008b9f042e8b882352a2070e5b39d08cFariborz Jahanian  str += ")(void *)objc_msgSend)(receiver, sel";
3174426bb9c9008b9f042e8b882352a2070e5b39d08cFariborz Jahanian  for (unsigned i = 2; i < ArgTypes.size(); i++) {
3175426bb9c9008b9f042e8b882352a2070e5b39d08cFariborz Jahanian    str += ", arg"; str += utostr(i);
3176426bb9c9008b9f042e8b882352a2070e5b39d08cFariborz Jahanian  }
3177426bb9c9008b9f042e8b882352a2070e5b39d08cFariborz Jahanian  // could be vararg.
3178426bb9c9008b9f042e8b882352a2070e5b39d08cFariborz Jahanian  for (unsigned i = ArgTypes.size(); i < MsgExprs.size(); i++) {
3179426bb9c9008b9f042e8b882352a2070e5b39d08cFariborz Jahanian    str += ", arg"; str += utostr(i);
3180426bb9c9008b9f042e8b882352a2070e5b39d08cFariborz Jahanian  }
3181426bb9c9008b9f042e8b882352a2070e5b39d08cFariborz Jahanian  str+= ");\n";
3182426bb9c9008b9f042e8b882352a2070e5b39d08cFariborz Jahanian
3183426bb9c9008b9f042e8b882352a2070e5b39d08cFariborz Jahanian  str += "\t  else if (receiver == 0)\n";
3184be8d55ce4a20b86d9337dcb28759e068cb3510f3Fariborz Jahanian  str += "\t    memset((void*)&s, 0, sizeof(s));\n";
3185be8d55ce4a20b86d9337dcb28759e068cb3510f3Fariborz Jahanian  str += "\t  else\n";
3186426bb9c9008b9f042e8b882352a2070e5b39d08cFariborz Jahanian
3187426bb9c9008b9f042e8b882352a2070e5b39d08cFariborz Jahanian
3188be8d55ce4a20b86d9337dcb28759e068cb3510f3Fariborz Jahanian  str += "\t    s = (("; str += castType.getAsString(Context->getPrintingPolicy());
3189be8d55ce4a20b86d9337dcb28759e068cb3510f3Fariborz Jahanian  str += ")(void *)objc_msgSend_stret)(receiver, sel";
3190be8d55ce4a20b86d9337dcb28759e068cb3510f3Fariborz Jahanian  for (unsigned i = 2; i < ArgTypes.size(); i++) {
3191be8d55ce4a20b86d9337dcb28759e068cb3510f3Fariborz Jahanian    str += ", arg"; str += utostr(i);
3192be8d55ce4a20b86d9337dcb28759e068cb3510f3Fariborz Jahanian  }
3193be8d55ce4a20b86d9337dcb28759e068cb3510f3Fariborz Jahanian  // could be vararg.
3194be8d55ce4a20b86d9337dcb28759e068cb3510f3Fariborz Jahanian  for (unsigned i = ArgTypes.size(); i < MsgExprs.size(); i++) {
3195be8d55ce4a20b86d9337dcb28759e068cb3510f3Fariborz Jahanian    str += ", arg"; str += utostr(i);
3196be8d55ce4a20b86d9337dcb28759e068cb3510f3Fariborz Jahanian  }
3197be8d55ce4a20b86d9337dcb28759e068cb3510f3Fariborz Jahanian  str += ");\n";
3198426bb9c9008b9f042e8b882352a2070e5b39d08cFariborz Jahanian
3199426bb9c9008b9f042e8b882352a2070e5b39d08cFariborz Jahanian
3200be8d55ce4a20b86d9337dcb28759e068cb3510f3Fariborz Jahanian  str += "\t}\n";
3201be8d55ce4a20b86d9337dcb28759e068cb3510f3Fariborz Jahanian  str += "\t"; str += returnType.getAsString(Context->getPrintingPolicy());
3202be8d55ce4a20b86d9337dcb28759e068cb3510f3Fariborz Jahanian  str += " s;\n";
3203426bb9c9008b9f042e8b882352a2070e5b39d08cFariborz Jahanian  str += "};\n};\n\n";
3204a6e5a6e60ba744463819c1ee2595539c6055382bFariborz Jahanian  SourceLocation FunLocStart;
3205a6e5a6e60ba744463819c1ee2595539c6055382bFariborz Jahanian  if (CurFunctionDef)
3206a6e5a6e60ba744463819c1ee2595539c6055382bFariborz Jahanian    FunLocStart = getFunctionSourceLocation(*this, CurFunctionDef);
3207a6e5a6e60ba744463819c1ee2595539c6055382bFariborz Jahanian  else {
3208a6e5a6e60ba744463819c1ee2595539c6055382bFariborz Jahanian    assert(CurMethodDef && "SynthMsgSendStretCallExpr - CurMethodDef is null");
3209a6e5a6e60ba744463819c1ee2595539c6055382bFariborz Jahanian    FunLocStart = CurMethodDef->getLocStart();
3210a6e5a6e60ba744463819c1ee2595539c6055382bFariborz Jahanian  }
3211a6e5a6e60ba744463819c1ee2595539c6055382bFariborz Jahanian
3212be8d55ce4a20b86d9337dcb28759e068cb3510f3Fariborz Jahanian  InsertText(FunLocStart, str);
3213be8d55ce4a20b86d9337dcb28759e068cb3510f3Fariborz Jahanian  ++stretCount;
3214be8d55ce4a20b86d9337dcb28759e068cb3510f3Fariborz Jahanian
3215be8d55ce4a20b86d9337dcb28759e068cb3510f3Fariborz Jahanian  // AST for __Stretn(receiver, args).s;
3216be8d55ce4a20b86d9337dcb28759e068cb3510f3Fariborz Jahanian  IdentifierInfo *ID = &Context->Idents.get(name);
3217be8d55ce4a20b86d9337dcb28759e068cb3510f3Fariborz Jahanian  FunctionDecl *FD = FunctionDecl::Create(*Context, TUDecl, SourceLocation(),
32186bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines                                          SourceLocation(), ID, castType,
32196bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines                                          nullptr, SC_Extern, false, false);
3220be8d55ce4a20b86d9337dcb28759e068cb3510f3Fariborz Jahanian  DeclRefExpr *DRE = new (Context) DeclRefExpr(FD, false, castType, VK_RValue,
3221be8d55ce4a20b86d9337dcb28759e068cb3510f3Fariborz Jahanian                                               SourceLocation());
32223b6bef9a213249c6ab6d67c07b1ac6380961be3eBenjamin Kramer  CallExpr *STCE = new (Context) CallExpr(*Context, DRE, MsgExprs,
3223be8d55ce4a20b86d9337dcb28759e068cb3510f3Fariborz Jahanian                                          castType, VK_LValue, SourceLocation());
32246bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
32256bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  FieldDecl *FieldD = FieldDecl::Create(*Context, nullptr, SourceLocation(),
3226be8d55ce4a20b86d9337dcb28759e068cb3510f3Fariborz Jahanian                                    SourceLocation(),
3227be8d55ce4a20b86d9337dcb28759e068cb3510f3Fariborz Jahanian                                    &Context->Idents.get("s"),
322833337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar                                    returnType, nullptr,
322933337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar                                    /*BitWidth=*/nullptr,
323033337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar                                    /*Mutable=*/true, ICIS_NoInit);
323133337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  MemberExpr *ME = new (Context)
323233337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar      MemberExpr(STCE, false, SourceLocation(), FieldD, SourceLocation(),
323333337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar                 FieldD->getType(), VK_LValue, OK_Ordinary);
323433337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar
323533337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  return ME;
323633337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar}
3237be8d55ce4a20b86d9337dcb28759e068cb3510f3Fariborz Jahanian
323864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz JahanianStmt *RewriteModernObjC::SynthMessageExpr(ObjCMessageExpr *Exp,
323964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                    SourceLocation StartLoc,
324064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                    SourceLocation EndLoc) {
324164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  if (!SelGetUidFunctionDecl)
324264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    SynthSelGetUidFunctionDecl();
324364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  if (!MsgSendFunctionDecl)
324464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    SynthMsgSendFunctionDecl();
324564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  if (!MsgSendSuperFunctionDecl)
324664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    SynthMsgSendSuperFunctionDecl();
324764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  if (!MsgSendStretFunctionDecl)
324864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    SynthMsgSendStretFunctionDecl();
324964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  if (!MsgSendSuperStretFunctionDecl)
325064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    SynthMsgSendSuperStretFunctionDecl();
325164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  if (!MsgSendFpretFunctionDecl)
325264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    SynthMsgSendFpretFunctionDecl();
325364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  if (!GetClassFunctionDecl)
325464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    SynthGetClassFunctionDecl();
325564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  if (!GetSuperClassFunctionDecl)
325664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    SynthGetSuperClassFunctionDecl();
325764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  if (!GetMetaClassFunctionDecl)
325864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    SynthGetMetaClassFunctionDecl();
325964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
326064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  // default to objc_msgSend().
326164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  FunctionDecl *MsgSendFlavor = MsgSendFunctionDecl;
326264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  // May need to use objc_msgSend_stret() as well.
32636bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  FunctionDecl *MsgSendStretFlavor = nullptr;
326464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  if (ObjCMethodDecl *mDecl = Exp->getMethodDecl()) {
3265651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    QualType resultType = mDecl->getReturnType();
326664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    if (resultType->isRecordType())
326764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      MsgSendStretFlavor = MsgSendStretFunctionDecl;
326864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    else if (resultType->isRealFloatingType())
326964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      MsgSendFlavor = MsgSendFpretFunctionDecl;
327064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  }
327164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
327264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  // Synthesize a call to objc_msgSend().
327364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  SmallVector<Expr*, 8> MsgExprs;
327464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  switch (Exp->getReceiverKind()) {
327564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  case ObjCMessageExpr::SuperClass: {
327664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    MsgSendFlavor = MsgSendSuperFunctionDecl;
327764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    if (MsgSendStretFlavor)
327864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      MsgSendStretFlavor = MsgSendSuperStretFunctionDecl;
327964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    assert(MsgSendFlavor && "MsgSendFlavor is NULL!");
328064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
328164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    ObjCInterfaceDecl *ClassDecl = CurMethodDef->getClassInterface();
328264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
328364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    SmallVector<Expr*, 4> InitExprs;
328464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
328564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    // set the receiver to self, the first argument to all methods.
328664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    InitExprs.push_back(
328764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      NoTypeInfoCStyleCastExpr(Context, Context->getObjCIdType(),
328864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                               CK_BitCast,
328964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                   new (Context) DeclRefExpr(CurMethodDef->getSelfDecl(),
3290f4b88a45902af1802a1cb42ba48b1c474474f228John McCall                                             false,
329164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                             Context->getObjCIdType(),
329264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                             VK_RValue,
329364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                             SourceLocation()))
329464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                        ); // set the 'receiver'.
329564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
329664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    // (id)class_getSuperclass((Class)objc_getClass("CurrentClass"))
329764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    SmallVector<Expr*, 8> ClsExprs;
3298651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    ClsExprs.push_back(getStringLiteral(ClassDecl->getIdentifier()->getName()));
329920e181a3ece8862dcfcfacf70763074ddec5a68bFariborz Jahanian    // (Class)objc_getClass("CurrentClass")
330064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    CallExpr *Cls = SynthesizeCallToFunctionDecl(GetMetaClassFunctionDecl,
330164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                                 &ClsExprs[0],
330264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                                 ClsExprs.size(),
330364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                                 StartLoc,
330464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                                 EndLoc);
330564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    ClsExprs.clear();
330620e181a3ece8862dcfcfacf70763074ddec5a68bFariborz Jahanian    ClsExprs.push_back(Cls);
330764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    Cls = SynthesizeCallToFunctionDecl(GetSuperClassFunctionDecl,
330864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                       &ClsExprs[0], ClsExprs.size(),
330964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                       StartLoc, EndLoc);
331064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
331164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    // (id)class_getSuperclass((Class)objc_getClass("CurrentClass"))
331264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    // To turn off a warning, type-cast to 'id'
331364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    InitExprs.push_back( // set 'super class', using class_getSuperclass().
331464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                        NoTypeInfoCStyleCastExpr(Context,
331564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                                 Context->getObjCIdType(),
331664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                                 CK_BitCast, Cls));
3317b20c46ea980b5aed7b480761ea1daf2f26c23b2dFariborz Jahanian    // struct __rw_objc_super
331864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    QualType superType = getSuperStructType();
331964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    Expr *SuperRep;
332064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
332164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    if (LangOpts.MicrosoftExt) {
3322e575359c34a9248c55ec0c03a8fc945f1ee4cb01Benjamin Kramer      SynthSuperConstructorFunctionDecl();
3323e575359c34a9248c55ec0c03a8fc945f1ee4cb01Benjamin Kramer      // Simulate a constructor call...
3324e575359c34a9248c55ec0c03a8fc945f1ee4cb01Benjamin Kramer      DeclRefExpr *DRE = new (Context) DeclRefExpr(SuperConstructorFunctionDecl,
3325f4b88a45902af1802a1cb42ba48b1c474474f228John McCall                                                   false, superType, VK_LValue,
332664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                                   SourceLocation());
33273b6bef9a213249c6ab6d67c07b1ac6380961be3eBenjamin Kramer      SuperRep = new (Context) CallExpr(*Context, DRE, InitExprs,
332864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                        superType, VK_LValue,
332964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                        SourceLocation());
333064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      // The code for super is a little tricky to prevent collision with
333164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      // the structure definition in the header. The rewriter has it's own
333264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      // internal definition (__rw_objc_super) that is uses. This is why
333364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      // we need the cast below. For example:
3334b20c46ea980b5aed7b480761ea1daf2f26c23b2dFariborz Jahanian      // (struct __rw_objc_super *)&__rw_objc_super((id)self, (id)objc_getClass("SUPER"))
333564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      //
333664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      SuperRep = new (Context) UnaryOperator(SuperRep, UO_AddrOf,
333764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                               Context->getPointerType(SuperRep->getType()),
333864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                             VK_RValue, OK_Ordinary,
333964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                             SourceLocation());
334064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      SuperRep = NoTypeInfoCStyleCastExpr(Context,
334164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                          Context->getPointerType(superType),
334264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                          CK_BitCast, SuperRep);
334364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    } else {
3344b20c46ea980b5aed7b480761ea1daf2f26c23b2dFariborz Jahanian      // (struct __rw_objc_super) { <exprs from above> }
334564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      InitListExpr *ILE =
33463b6bef9a213249c6ab6d67c07b1ac6380961be3eBenjamin Kramer        new (Context) InitListExpr(*Context, SourceLocation(), InitExprs,
334764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                   SourceLocation());
334864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      TypeSourceInfo *superTInfo
334964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        = Context->getTrivialTypeSourceInfo(superType);
335064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      SuperRep = new (Context) CompoundLiteralExpr(SourceLocation(), superTInfo,
335164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                                   superType, VK_LValue,
335264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                                   ILE, false);
3353b20c46ea980b5aed7b480761ea1daf2f26c23b2dFariborz Jahanian      // struct __rw_objc_super *
335464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      SuperRep = new (Context) UnaryOperator(SuperRep, UO_AddrOf,
335564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                               Context->getPointerType(SuperRep->getType()),
335664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                             VK_RValue, OK_Ordinary,
335764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                             SourceLocation());
335864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    }
335964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    MsgExprs.push_back(SuperRep);
336064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    break;
336164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  }
336264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
336364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  case ObjCMessageExpr::Class: {
336464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    SmallVector<Expr*, 8> ClsExprs;
336564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    ObjCInterfaceDecl *Class
336664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      = Exp->getClassReceiver()->getAs<ObjCObjectType>()->getInterface();
336764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    IdentifierInfo *clsName = Class->getIdentifier();
3368651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    ClsExprs.push_back(getStringLiteral(clsName->getName()));
336964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    CallExpr *Cls = SynthesizeCallToFunctionDecl(GetClassFunctionDecl,
337064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                                 &ClsExprs[0],
337164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                                 ClsExprs.size(),
337264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                                 StartLoc, EndLoc);
337320e181a3ece8862dcfcfacf70763074ddec5a68bFariborz Jahanian    CastExpr *ArgExpr = NoTypeInfoCStyleCastExpr(Context,
337420e181a3ece8862dcfcfacf70763074ddec5a68bFariborz Jahanian                                                 Context->getObjCIdType(),
337520e181a3ece8862dcfcfacf70763074ddec5a68bFariborz Jahanian                                                 CK_BitCast, Cls);
337620e181a3ece8862dcfcfacf70763074ddec5a68bFariborz Jahanian    MsgExprs.push_back(ArgExpr);
337764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    break;
337864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  }
337964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
338064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  case ObjCMessageExpr::SuperInstance:{
338164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    MsgSendFlavor = MsgSendSuperFunctionDecl;
338264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    if (MsgSendStretFlavor)
338364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      MsgSendStretFlavor = MsgSendSuperStretFunctionDecl;
338464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    assert(MsgSendFlavor && "MsgSendFlavor is NULL!");
338564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    ObjCInterfaceDecl *ClassDecl = CurMethodDef->getClassInterface();
338664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    SmallVector<Expr*, 4> InitExprs;
338764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
338864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    InitExprs.push_back(
338964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      NoTypeInfoCStyleCastExpr(Context, Context->getObjCIdType(),
339064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                               CK_BitCast,
339164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                   new (Context) DeclRefExpr(CurMethodDef->getSelfDecl(),
3392f4b88a45902af1802a1cb42ba48b1c474474f228John McCall                                             false,
339364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                             Context->getObjCIdType(),
339464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                             VK_RValue, SourceLocation()))
339564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                        ); // set the 'receiver'.
339664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
339764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    // (id)class_getSuperclass((Class)objc_getClass("CurrentClass"))
339864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    SmallVector<Expr*, 8> ClsExprs;
3399651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    ClsExprs.push_back(getStringLiteral(ClassDecl->getIdentifier()->getName()));
340020e181a3ece8862dcfcfacf70763074ddec5a68bFariborz Jahanian    // (Class)objc_getClass("CurrentClass")
340164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    CallExpr *Cls = SynthesizeCallToFunctionDecl(GetClassFunctionDecl,
340264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                                 &ClsExprs[0],
340364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                                 ClsExprs.size(),
340464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                                 StartLoc, EndLoc);
340564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    ClsExprs.clear();
340620e181a3ece8862dcfcfacf70763074ddec5a68bFariborz Jahanian    ClsExprs.push_back(Cls);
340764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    Cls = SynthesizeCallToFunctionDecl(GetSuperClassFunctionDecl,
340864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                       &ClsExprs[0], ClsExprs.size(),
340964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                       StartLoc, EndLoc);
341064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
341164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    // (id)class_getSuperclass((Class)objc_getClass("CurrentClass"))
341264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    // To turn off a warning, type-cast to 'id'
341364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    InitExprs.push_back(
341464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      // set 'super class', using class_getSuperclass().
341564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      NoTypeInfoCStyleCastExpr(Context, Context->getObjCIdType(),
341664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                               CK_BitCast, Cls));
3417b20c46ea980b5aed7b480761ea1daf2f26c23b2dFariborz Jahanian    // struct __rw_objc_super
341864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    QualType superType = getSuperStructType();
341964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    Expr *SuperRep;
342064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
342164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    if (LangOpts.MicrosoftExt) {
3422e575359c34a9248c55ec0c03a8fc945f1ee4cb01Benjamin Kramer      SynthSuperConstructorFunctionDecl();
3423e575359c34a9248c55ec0c03a8fc945f1ee4cb01Benjamin Kramer      // Simulate a constructor call...
3424e575359c34a9248c55ec0c03a8fc945f1ee4cb01Benjamin Kramer      DeclRefExpr *DRE = new (Context) DeclRefExpr(SuperConstructorFunctionDecl,
3425f4b88a45902af1802a1cb42ba48b1c474474f228John McCall                                                   false, superType, VK_LValue,
342664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                                   SourceLocation());
34273b6bef9a213249c6ab6d67c07b1ac6380961be3eBenjamin Kramer      SuperRep = new (Context) CallExpr(*Context, DRE, InitExprs,
342864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                        superType, VK_LValue, SourceLocation());
342964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      // The code for super is a little tricky to prevent collision with
343064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      // the structure definition in the header. The rewriter has it's own
343164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      // internal definition (__rw_objc_super) that is uses. This is why
343264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      // we need the cast below. For example:
3433b20c46ea980b5aed7b480761ea1daf2f26c23b2dFariborz Jahanian      // (struct __rw_objc_super *)&__rw_objc_super((id)self, (id)objc_getClass("SUPER"))
343464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      //
343564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      SuperRep = new (Context) UnaryOperator(SuperRep, UO_AddrOf,
343664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                               Context->getPointerType(SuperRep->getType()),
343764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                               VK_RValue, OK_Ordinary,
343864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                               SourceLocation());
343964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      SuperRep = NoTypeInfoCStyleCastExpr(Context,
344064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                               Context->getPointerType(superType),
344164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                               CK_BitCast, SuperRep);
344264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    } else {
3443b20c46ea980b5aed7b480761ea1daf2f26c23b2dFariborz Jahanian      // (struct __rw_objc_super) { <exprs from above> }
344464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      InitListExpr *ILE =
34453b6bef9a213249c6ab6d67c07b1ac6380961be3eBenjamin Kramer        new (Context) InitListExpr(*Context, SourceLocation(), InitExprs,
344664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                   SourceLocation());
344764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      TypeSourceInfo *superTInfo
344864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        = Context->getTrivialTypeSourceInfo(superType);
344964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      SuperRep = new (Context) CompoundLiteralExpr(SourceLocation(), superTInfo,
345064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                                   superType, VK_RValue, ILE,
345164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                                   false);
345264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    }
345364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    MsgExprs.push_back(SuperRep);
345464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    break;
345564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  }
345664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
345764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  case ObjCMessageExpr::Instance: {
345864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    // Remove all type-casts because it may contain objc-style types; e.g.
345964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    // Foo<Proto> *.
346064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    Expr *recExpr = Exp->getInstanceReceiver();
346164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    while (CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(recExpr))
346264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      recExpr = CE->getSubExpr();
346364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    CastKind CK = recExpr->getType()->isObjCObjectPointerType()
346464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                    ? CK_BitCast : recExpr->getType()->isBlockPointerType()
346564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                     ? CK_BlockPointerToObjCPointerCast
346664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                     : CK_CPointerToObjCPointerCast;
346764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
346864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    recExpr = NoTypeInfoCStyleCastExpr(Context, Context->getObjCIdType(),
346964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                       CK, recExpr);
347064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    MsgExprs.push_back(recExpr);
347164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    break;
347264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  }
347364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  }
347464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
347564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  // Create a call to sel_registerName("selName"), it will be the 2nd argument.
347664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  SmallVector<Expr*, 8> SelExprs;
3477651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  SelExprs.push_back(getStringLiteral(Exp->getSelector().getAsString()));
347864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  CallExpr *SelExp = SynthesizeCallToFunctionDecl(SelGetUidFunctionDecl,
347964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                                 &SelExprs[0], SelExprs.size(),
348064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                                  StartLoc,
348164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                                  EndLoc);
348264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  MsgExprs.push_back(SelExp);
348364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
348464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  // Now push any user supplied arguments.
348564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  for (unsigned i = 0; i < Exp->getNumArgs(); i++) {
348664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    Expr *userExpr = Exp->getArg(i);
348764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    // Make all implicit casts explicit...ICE comes in handy:-)
348864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(userExpr)) {
348964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      // Reuse the ICE type, it is exactly what the doctor ordered.
349064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      QualType type = ICE->getType();
349164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      if (needToScanForQualifiers(type))
349264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        type = Context->getObjCIdType();
349364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      // Make sure we convert "type (^)(...)" to "type (*)(...)".
349464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      (void)convertBlockPointerToFunctionPointer(type);
349564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      const Expr *SubExpr = ICE->IgnoreParenImpCasts();
349664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      CastKind CK;
349764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      if (SubExpr->getType()->isIntegralType(*Context) &&
349864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian          type->isBooleanType()) {
349964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        CK = CK_IntegralToBoolean;
350064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      } else if (type->isObjCObjectPointerType()) {
350164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        if (SubExpr->getType()->isBlockPointerType()) {
350264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian          CK = CK_BlockPointerToObjCPointerCast;
350364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        } else if (SubExpr->getType()->isPointerType()) {
350464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian          CK = CK_CPointerToObjCPointerCast;
350564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        } else {
350664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian          CK = CK_BitCast;
350764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        }
350864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      } else {
350964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        CK = CK_BitCast;
351064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      }
351164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
351264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      userExpr = NoTypeInfoCStyleCastExpr(Context, type, CK, userExpr);
351364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    }
351464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    // Make id<P...> cast into an 'id' cast.
351564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    else if (CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(userExpr)) {
351664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      if (CE->getType()->isObjCQualifiedIdType()) {
351764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        while ((CE = dyn_cast<CStyleCastExpr>(userExpr)))
351864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian          userExpr = CE->getSubExpr();
351964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        CastKind CK;
352064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        if (userExpr->getType()->isIntegralType(*Context)) {
352164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian          CK = CK_IntegralToPointer;
352264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        } else if (userExpr->getType()->isBlockPointerType()) {
352364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian          CK = CK_BlockPointerToObjCPointerCast;
352464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        } else if (userExpr->getType()->isPointerType()) {
352564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian          CK = CK_CPointerToObjCPointerCast;
352664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        } else {
352764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian          CK = CK_BitCast;
352864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        }
352964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        userExpr = NoTypeInfoCStyleCastExpr(Context, Context->getObjCIdType(),
353064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                            CK, userExpr);
353164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      }
353264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    }
353364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    MsgExprs.push_back(userExpr);
353464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    // We've transferred the ownership to MsgExprs. For now, we *don't* null
353564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    // out the argument in the original expression (since we aren't deleting
353664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    // the ObjCMessageExpr). See RewritePropertyOrImplicitSetter() usage for more info.
353764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    //Exp->setArg(i, 0);
353864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  }
353964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  // Generate the funky cast.
354064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  CastExpr *cast;
354164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  SmallVector<QualType, 8> ArgTypes;
354264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  QualType returnType;
354364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
354464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  // Push 'id' and 'SEL', the 2 implicit arguments.
354564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  if (MsgSendFlavor == MsgSendSuperFunctionDecl)
354664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    ArgTypes.push_back(Context->getPointerType(getSuperStructType()));
354764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  else
354864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    ArgTypes.push_back(Context->getObjCIdType());
354964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  ArgTypes.push_back(Context->getObjCSelType());
355064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  if (ObjCMethodDecl *OMD = Exp->getMethodDecl()) {
355164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    // Push any user argument types.
3552651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    for (const auto *PI : OMD->params()) {
3553651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      QualType t = PI->getType()->isObjCQualifiedIdType()
355464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                     ? Context->getObjCIdType()
3555651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                     : PI->getType();
355664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      // Make sure we convert "t (^)(...)" to "t (*)(...)".
355764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      (void)convertBlockPointerToFunctionPointer(t);
355864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      ArgTypes.push_back(t);
355964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    }
356064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    returnType = Exp->getType();
356164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    convertToUnqualifiedObjCType(returnType);
356264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    (void)convertBlockPointerToFunctionPointer(returnType);
356364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  } else {
356464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    returnType = Context->getObjCIdType();
356564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  }
356664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  // Get the type, we will need to reference it in a couple spots.
356764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  QualType msgSendType = MsgSendFlavor->getType();
356864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
356964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  // Create a reference to the objc_msgSend() declaration.
3570f4b88a45902af1802a1cb42ba48b1c474474f228John McCall  DeclRefExpr *DRE = new (Context) DeclRefExpr(MsgSendFlavor, false, msgSendType,
357164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                               VK_LValue, SourceLocation());
357264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
357364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  // Need to cast objc_msgSend to "void *" (to workaround a GCC bandaid).
357464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  // If we don't do this cast, we get the following bizarre warning/note:
357564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  // xx.m:13: warning: function called through a non-compatible type
357664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  // xx.m:13: note: if this code is reached, the program will abort
357764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  cast = NoTypeInfoCStyleCastExpr(Context,
357864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                  Context->getPointerType(Context->VoidTy),
357964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                  CK_BitCast, DRE);
358064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
358164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  // Now do the "normal" pointer to function cast.
3582bea522ff43a3f11c7a2bc7949119dbb9fce19e39Jordan Rose  // If we don't have a method decl, force a variadic cast.
3583bea522ff43a3f11c7a2bc7949119dbb9fce19e39Jordan Rose  const ObjCMethodDecl *MD = Exp->getMethodDecl();
358464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  QualType castType =
3585bea522ff43a3f11c7a2bc7949119dbb9fce19e39Jordan Rose    getSimpleFunctionType(returnType, ArgTypes, MD ? MD->isVariadic() : true);
358664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  castType = Context->getPointerType(castType);
358764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  cast = NoTypeInfoCStyleCastExpr(Context, castType, CK_BitCast,
358864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                  cast);
358964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
359064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  // Don't forget the parens to enforce the proper binding.
359164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  ParenExpr *PE = new (Context) ParenExpr(StartLoc, EndLoc, cast);
359264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
359364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  const FunctionType *FT = msgSendType->getAs<FunctionType>();
3594651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  CallExpr *CE = new (Context)
3595651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      CallExpr(*Context, PE, MsgExprs, FT->getReturnType(), VK_RValue, EndLoc);
359664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  Stmt *ReplacingStmt = CE;
359764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  if (MsgSendStretFlavor) {
359864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    // We have the method which returns a struct/union. Must also generate
359964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    // call to objc_msgSend_stret and hang both varieties on a conditional
360064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    // expression which dictate which one to envoke depending on size of
360164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    // method's return type.
360264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
3603426bb9c9008b9f042e8b882352a2070e5b39d08cFariborz Jahanian    Expr *STCE = SynthMsgSendStretCallExpr(MsgSendStretFlavor,
3604426bb9c9008b9f042e8b882352a2070e5b39d08cFariborz Jahanian                                           returnType,
3605be8d55ce4a20b86d9337dcb28759e068cb3510f3Fariborz Jahanian                                           ArgTypes, MsgExprs,
3606be8d55ce4a20b86d9337dcb28759e068cb3510f3Fariborz Jahanian                                           Exp->getMethodDecl());
3607426bb9c9008b9f042e8b882352a2070e5b39d08cFariborz Jahanian    ReplacingStmt = STCE;
360864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  }
360964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  // delete Exp; leak for now, see RewritePropertyOrImplicitSetter() usage for more info.
361064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  return ReplacingStmt;
361164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian}
361264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
361364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz JahanianStmt *RewriteModernObjC::RewriteMessageExpr(ObjCMessageExpr *Exp) {
361464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  Stmt *ReplacingStmt = SynthMessageExpr(Exp, Exp->getLocStart(),
361564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                         Exp->getLocEnd());
361664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
361764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  // Now do the actual rewrite.
361864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  ReplaceStmt(Exp, ReplacingStmt);
361964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
362064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  // delete Exp; leak for now, see RewritePropertyOrImplicitSetter() usage for more info.
362164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  return ReplacingStmt;
362264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian}
362364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
362464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian// typedef struct objc_object Protocol;
362564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz JahanianQualType RewriteModernObjC::getProtocolType() {
362664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  if (!ProtocolTypeDecl) {
362764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    TypeSourceInfo *TInfo
362864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      = Context->getTrivialTypeSourceInfo(Context->getObjCIdType());
362964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    ProtocolTypeDecl = TypedefDecl::Create(*Context, TUDecl,
363064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                           SourceLocation(), SourceLocation(),
363164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                           &Context->Idents.get("Protocol"),
363264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                           TInfo);
363364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  }
363464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  return Context->getTypeDeclType(ProtocolTypeDecl);
363564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian}
363664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
363764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian/// RewriteObjCProtocolExpr - Rewrite a protocol expression into
363864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian/// a synthesized/forward data reference (to the protocol's metadata).
363964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian/// The forward references (and metadata) are generated in
364064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian/// RewriteModernObjC::HandleTranslationUnit().
364164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz JahanianStmt *RewriteModernObjC::RewriteObjCProtocolExpr(ObjCProtocolExpr *Exp) {
364230650ebe652854d8bdce832cbdae1cf3c43e54aaFariborz Jahanian  std::string Name = "_OBJC_PROTOCOL_REFERENCE_$_" +
364330650ebe652854d8bdce832cbdae1cf3c43e54aaFariborz Jahanian                      Exp->getProtocol()->getNameAsString();
364464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  IdentifierInfo *ID = &Context->Idents.get(Name);
364564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  VarDecl *VD = VarDecl::Create(*Context, TUDecl, SourceLocation(),
36466bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines                                SourceLocation(), ID, getProtocolType(),
36476bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines                                nullptr, SC_Extern);
3648f4b88a45902af1802a1cb42ba48b1c474474f228John McCall  DeclRefExpr *DRE = new (Context) DeclRefExpr(VD, false, getProtocolType(),
3649f4b88a45902af1802a1cb42ba48b1c474474f228John McCall                                               VK_LValue, SourceLocation());
3650651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  CastExpr *castExpr =
3651651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    NoTypeInfoCStyleCastExpr(
3652651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      Context, Context->getPointerType(DRE->getType()), CK_BitCast, DRE);
365364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  ReplaceStmt(Exp, castExpr);
365464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  ProtocolExprDecls.insert(Exp->getProtocol()->getCanonicalDecl());
365564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  // delete Exp; leak for now, see RewritePropertyOrImplicitSetter() usage for more info.
365664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  return castExpr;
365764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
365864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian}
365964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
366064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanianbool RewriteModernObjC::BufferContainsPPDirectives(const char *startBuf,
366164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                             const char *endBuf) {
366264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  while (startBuf < endBuf) {
366364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    if (*startBuf == '#') {
366464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      // Skip whitespace.
366564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      for (++startBuf; startBuf[0] == ' ' || startBuf[0] == '\t'; ++startBuf)
366664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        ;
366764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      if (!strncmp(startBuf, "if", strlen("if")) ||
366864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian          !strncmp(startBuf, "ifdef", strlen("ifdef")) ||
366964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian          !strncmp(startBuf, "ifndef", strlen("ifndef")) ||
367064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian          !strncmp(startBuf, "define", strlen("define")) ||
367164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian          !strncmp(startBuf, "undef", strlen("undef")) ||
367264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian          !strncmp(startBuf, "else", strlen("else")) ||
367364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian          !strncmp(startBuf, "elif", strlen("elif")) ||
367464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian          !strncmp(startBuf, "endif", strlen("endif")) ||
367564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian          !strncmp(startBuf, "pragma", strlen("pragma")) ||
367664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian          !strncmp(startBuf, "include", strlen("include")) ||
367764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian          !strncmp(startBuf, "import", strlen("import")) ||
367864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian          !strncmp(startBuf, "include_next", strlen("include_next")))
367964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        return true;
368064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    }
368164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    startBuf++;
368264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  }
368364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  return false;
368464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian}
368564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
36868fba894335b979e6d213c685bca959168c1f2182Fariborz Jahanian/// IsTagDefinedInsideClass - This routine checks that a named tagged type
36878fba894335b979e6d213c685bca959168c1f2182Fariborz Jahanian/// is defined inside an objective-c class. If so, it returns true.
3688b68258fba663cd6a75bf44114e4eb2849551a45fFariborz Jahanianbool RewriteModernObjC::IsTagDefinedInsideClass(ObjCContainerDecl *IDecl,
36898fba894335b979e6d213c685bca959168c1f2182Fariborz Jahanian                                                TagDecl *Tag,
36908fba894335b979e6d213c685bca959168c1f2182Fariborz Jahanian                                                bool &IsNamedDefinition) {
369189585e800122de7ee4ca74dfca1c86a11685528fFariborz Jahanian  if (!IDecl)
369289585e800122de7ee4ca74dfca1c86a11685528fFariborz Jahanian    return false;
369389585e800122de7ee4ca74dfca1c86a11685528fFariborz Jahanian  SourceLocation TagLocation;
369489585e800122de7ee4ca74dfca1c86a11685528fFariborz Jahanian  if (RecordDecl *RD = dyn_cast<RecordDecl>(Tag)) {
369589585e800122de7ee4ca74dfca1c86a11685528fFariborz Jahanian    RD = RD->getDefinition();
36968fba894335b979e6d213c685bca959168c1f2182Fariborz Jahanian    if (!RD || !RD->getDeclName().getAsIdentifierInfo())
369789585e800122de7ee4ca74dfca1c86a11685528fFariborz Jahanian      return false;
36988fba894335b979e6d213c685bca959168c1f2182Fariborz Jahanian    IsNamedDefinition = true;
369989585e800122de7ee4ca74dfca1c86a11685528fFariborz Jahanian    TagLocation = RD->getLocation();
370089585e800122de7ee4ca74dfca1c86a11685528fFariborz Jahanian    return Context->getSourceManager().isBeforeInTranslationUnit(
37018fba894335b979e6d213c685bca959168c1f2182Fariborz Jahanian                                          IDecl->getLocation(), TagLocation);
37028fba894335b979e6d213c685bca959168c1f2182Fariborz Jahanian  }
37038fba894335b979e6d213c685bca959168c1f2182Fariborz Jahanian  if (EnumDecl *ED = dyn_cast<EnumDecl>(Tag)) {
37048fba894335b979e6d213c685bca959168c1f2182Fariborz Jahanian    if (!ED || !ED->getDeclName().getAsIdentifierInfo())
37058fba894335b979e6d213c685bca959168c1f2182Fariborz Jahanian      return false;
37068fba894335b979e6d213c685bca959168c1f2182Fariborz Jahanian    IsNamedDefinition = true;
37078fba894335b979e6d213c685bca959168c1f2182Fariborz Jahanian    TagLocation = ED->getLocation();
37088fba894335b979e6d213c685bca959168c1f2182Fariborz Jahanian    return Context->getSourceManager().isBeforeInTranslationUnit(
37098fba894335b979e6d213c685bca959168c1f2182Fariborz Jahanian                                          IDecl->getLocation(), TagLocation);
37108fba894335b979e6d213c685bca959168c1f2182Fariborz Jahanian
371189585e800122de7ee4ca74dfca1c86a11685528fFariborz Jahanian  }
371289585e800122de7ee4ca74dfca1c86a11685528fFariborz Jahanian  return false;
371389585e800122de7ee4ca74dfca1c86a11685528fFariborz Jahanian}
371489585e800122de7ee4ca74dfca1c86a11685528fFariborz Jahanian
371597c1fd651c24638a4989b4e1f8eb2e629c2073d1Fariborz Jahanian/// RewriteObjCFieldDeclType - This routine rewrites a type into the buffer.
371615f87771cae0c31da45c05b34841d0a2ca70bc87Fariborz Jahanian/// It handles elaborated types, as well as enum types in the process.
371797c1fd651c24638a4989b4e1f8eb2e629c2073d1Fariborz Jahanianbool RewriteModernObjC::RewriteObjCFieldDeclType(QualType &Type,
371897c1fd651c24638a4989b4e1f8eb2e629c2073d1Fariborz Jahanian                                                 std::string &Result) {
3719f5eac481ab6da79f05ca13fd859b67abfd2ed246Fariborz Jahanian  if (isa<TypedefType>(Type)) {
3720f5eac481ab6da79f05ca13fd859b67abfd2ed246Fariborz Jahanian    Result += "\t";
3721f5eac481ab6da79f05ca13fd859b67abfd2ed246Fariborz Jahanian    return false;
3722f5eac481ab6da79f05ca13fd859b67abfd2ed246Fariborz Jahanian  }
3723f5eac481ab6da79f05ca13fd859b67abfd2ed246Fariborz Jahanian
372497c1fd651c24638a4989b4e1f8eb2e629c2073d1Fariborz Jahanian  if (Type->isArrayType()) {
372597c1fd651c24638a4989b4e1f8eb2e629c2073d1Fariborz Jahanian    QualType ElemTy = Context->getBaseElementType(Type);
372697c1fd651c24638a4989b4e1f8eb2e629c2073d1Fariborz Jahanian    return RewriteObjCFieldDeclType(ElemTy, Result);
372797c1fd651c24638a4989b4e1f8eb2e629c2073d1Fariborz Jahanian  }
372897c1fd651c24638a4989b4e1f8eb2e629c2073d1Fariborz Jahanian  else if (Type->isRecordType()) {
372915f87771cae0c31da45c05b34841d0a2ca70bc87Fariborz Jahanian    RecordDecl *RD = Type->getAs<RecordType>()->getDecl();
373015f87771cae0c31da45c05b34841d0a2ca70bc87Fariborz Jahanian    if (RD->isCompleteDefinition()) {
373115f87771cae0c31da45c05b34841d0a2ca70bc87Fariborz Jahanian      if (RD->isStruct())
373215f87771cae0c31da45c05b34841d0a2ca70bc87Fariborz Jahanian        Result += "\n\tstruct ";
373315f87771cae0c31da45c05b34841d0a2ca70bc87Fariborz Jahanian      else if (RD->isUnion())
373415f87771cae0c31da45c05b34841d0a2ca70bc87Fariborz Jahanian        Result += "\n\tunion ";
373515f87771cae0c31da45c05b34841d0a2ca70bc87Fariborz Jahanian      else
373615f87771cae0c31da45c05b34841d0a2ca70bc87Fariborz Jahanian        assert(false && "class not allowed as an ivar type");
373797c1fd651c24638a4989b4e1f8eb2e629c2073d1Fariborz Jahanian
373815f87771cae0c31da45c05b34841d0a2ca70bc87Fariborz Jahanian      Result += RD->getName();
37398fba894335b979e6d213c685bca959168c1f2182Fariborz Jahanian      if (GlobalDefinedTags.count(RD)) {
37408fba894335b979e6d213c685bca959168c1f2182Fariborz Jahanian        // struct/union is defined globally, use it.
374197c1fd651c24638a4989b4e1f8eb2e629c2073d1Fariborz Jahanian        Result += " ";
374297c1fd651c24638a4989b4e1f8eb2e629c2073d1Fariborz Jahanian        return true;
374315f87771cae0c31da45c05b34841d0a2ca70bc87Fariborz Jahanian      }
374415f87771cae0c31da45c05b34841d0a2ca70bc87Fariborz Jahanian      Result += " {\n";
3745651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      for (auto *FD : RD->fields())
374615f87771cae0c31da45c05b34841d0a2ca70bc87Fariborz Jahanian        RewriteObjCFieldDecl(FD, Result);
374715f87771cae0c31da45c05b34841d0a2ca70bc87Fariborz Jahanian      Result += "\t} ";
374897c1fd651c24638a4989b4e1f8eb2e629c2073d1Fariborz Jahanian      return true;
374915f87771cae0c31da45c05b34841d0a2ca70bc87Fariborz Jahanian    }
375015f87771cae0c31da45c05b34841d0a2ca70bc87Fariborz Jahanian  }
375115f87771cae0c31da45c05b34841d0a2ca70bc87Fariborz Jahanian  else if (Type->isEnumeralType()) {
375215f87771cae0c31da45c05b34841d0a2ca70bc87Fariborz Jahanian    EnumDecl *ED = Type->getAs<EnumType>()->getDecl();
375315f87771cae0c31da45c05b34841d0a2ca70bc87Fariborz Jahanian    if (ED->isCompleteDefinition()) {
375415f87771cae0c31da45c05b34841d0a2ca70bc87Fariborz Jahanian      Result += "\n\tenum ";
375515f87771cae0c31da45c05b34841d0a2ca70bc87Fariborz Jahanian      Result += ED->getName();
37568fba894335b979e6d213c685bca959168c1f2182Fariborz Jahanian      if (GlobalDefinedTags.count(ED)) {
37578fba894335b979e6d213c685bca959168c1f2182Fariborz Jahanian        // Enum is globall defined, use it.
375897c1fd651c24638a4989b4e1f8eb2e629c2073d1Fariborz Jahanian        Result += " ";
375997c1fd651c24638a4989b4e1f8eb2e629c2073d1Fariborz Jahanian        return true;
376015f87771cae0c31da45c05b34841d0a2ca70bc87Fariborz Jahanian      }
376115f87771cae0c31da45c05b34841d0a2ca70bc87Fariborz Jahanian
376215f87771cae0c31da45c05b34841d0a2ca70bc87Fariborz Jahanian      Result += " {\n";
3763651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      for (const auto *EC : ED->enumerators()) {
376415f87771cae0c31da45c05b34841d0a2ca70bc87Fariborz Jahanian        Result += "\t"; Result += EC->getName(); Result += " = ";
376515f87771cae0c31da45c05b34841d0a2ca70bc87Fariborz Jahanian        llvm::APSInt Val = EC->getInitVal();
376615f87771cae0c31da45c05b34841d0a2ca70bc87Fariborz Jahanian        Result += Val.toString(10);
376715f87771cae0c31da45c05b34841d0a2ca70bc87Fariborz Jahanian        Result += ",\n";
376815f87771cae0c31da45c05b34841d0a2ca70bc87Fariborz Jahanian      }
376915f87771cae0c31da45c05b34841d0a2ca70bc87Fariborz Jahanian      Result += "\t} ";
377097c1fd651c24638a4989b4e1f8eb2e629c2073d1Fariborz Jahanian      return true;
377115f87771cae0c31da45c05b34841d0a2ca70bc87Fariborz Jahanian    }
377215f87771cae0c31da45c05b34841d0a2ca70bc87Fariborz Jahanian  }
377315f87771cae0c31da45c05b34841d0a2ca70bc87Fariborz Jahanian
377415f87771cae0c31da45c05b34841d0a2ca70bc87Fariborz Jahanian  Result += "\t";
377515f87771cae0c31da45c05b34841d0a2ca70bc87Fariborz Jahanian  convertObjCTypeToCStyleType(Type);
377697c1fd651c24638a4989b4e1f8eb2e629c2073d1Fariborz Jahanian  return false;
377797c1fd651c24638a4989b4e1f8eb2e629c2073d1Fariborz Jahanian}
377897c1fd651c24638a4989b4e1f8eb2e629c2073d1Fariborz Jahanian
377997c1fd651c24638a4989b4e1f8eb2e629c2073d1Fariborz Jahanian
378097c1fd651c24638a4989b4e1f8eb2e629c2073d1Fariborz Jahanian/// RewriteObjCFieldDecl - This routine rewrites a field into the buffer.
378197c1fd651c24638a4989b4e1f8eb2e629c2073d1Fariborz Jahanian/// It handles elaborated types, as well as enum types in the process.
378297c1fd651c24638a4989b4e1f8eb2e629c2073d1Fariborz Jahanianvoid RewriteModernObjC::RewriteObjCFieldDecl(FieldDecl *fieldDecl,
378397c1fd651c24638a4989b4e1f8eb2e629c2073d1Fariborz Jahanian                                             std::string &Result) {
378497c1fd651c24638a4989b4e1f8eb2e629c2073d1Fariborz Jahanian  QualType Type = fieldDecl->getType();
378597c1fd651c24638a4989b4e1f8eb2e629c2073d1Fariborz Jahanian  std::string Name = fieldDecl->getNameAsString();
378615f87771cae0c31da45c05b34841d0a2ca70bc87Fariborz Jahanian
378797c1fd651c24638a4989b4e1f8eb2e629c2073d1Fariborz Jahanian  bool EleboratedType = RewriteObjCFieldDeclType(Type, Result);
378897c1fd651c24638a4989b4e1f8eb2e629c2073d1Fariborz Jahanian  if (!EleboratedType)
378997c1fd651c24638a4989b4e1f8eb2e629c2073d1Fariborz Jahanian    Type.getAsStringInternal(Name, Context->getPrintingPolicy());
379015f87771cae0c31da45c05b34841d0a2ca70bc87Fariborz Jahanian  Result += Name;
379115f87771cae0c31da45c05b34841d0a2ca70bc87Fariborz Jahanian  if (fieldDecl->isBitField()) {
379215f87771cae0c31da45c05b34841d0a2ca70bc87Fariborz Jahanian    Result += " : "; Result += utostr(fieldDecl->getBitWidthValue(*Context));
379315f87771cae0c31da45c05b34841d0a2ca70bc87Fariborz Jahanian  }
379497c1fd651c24638a4989b4e1f8eb2e629c2073d1Fariborz Jahanian  else if (EleboratedType && Type->isArrayType()) {
37956febf1265b5a5c3025752193caa9714ed523b12dEli Friedman    const ArrayType *AT = Context->getAsArrayType(Type);
37966febf1265b5a5c3025752193caa9714ed523b12dEli Friedman    do {
37976febf1265b5a5c3025752193caa9714ed523b12dEli Friedman      if (const ConstantArrayType *CAT = dyn_cast<ConstantArrayType>(AT)) {
379897c1fd651c24638a4989b4e1f8eb2e629c2073d1Fariborz Jahanian        Result += "[";
379997c1fd651c24638a4989b4e1f8eb2e629c2073d1Fariborz Jahanian        llvm::APInt Dim = CAT->getSize();
380097c1fd651c24638a4989b4e1f8eb2e629c2073d1Fariborz Jahanian        Result += utostr(Dim.getZExtValue());
380197c1fd651c24638a4989b4e1f8eb2e629c2073d1Fariborz Jahanian        Result += "]";
380297c1fd651c24638a4989b4e1f8eb2e629c2073d1Fariborz Jahanian      }
38036febf1265b5a5c3025752193caa9714ed523b12dEli Friedman      AT = Context->getAsArrayType(AT->getElementType());
38046febf1265b5a5c3025752193caa9714ed523b12dEli Friedman    } while (AT);
380597c1fd651c24638a4989b4e1f8eb2e629c2073d1Fariborz Jahanian  }
380697c1fd651c24638a4989b4e1f8eb2e629c2073d1Fariborz Jahanian
380715f87771cae0c31da45c05b34841d0a2ca70bc87Fariborz Jahanian  Result += ";\n";
380815f87771cae0c31da45c05b34841d0a2ca70bc87Fariborz Jahanian}
380915f87771cae0c31da45c05b34841d0a2ca70bc87Fariborz Jahanian
38108fba894335b979e6d213c685bca959168c1f2182Fariborz Jahanian/// RewriteLocallyDefinedNamedAggregates - This routine rewrites locally defined
38118fba894335b979e6d213c685bca959168c1f2182Fariborz Jahanian/// named aggregate types into the input buffer.
38128fba894335b979e6d213c685bca959168c1f2182Fariborz Jahanianvoid RewriteModernObjC::RewriteLocallyDefinedNamedAggregates(FieldDecl *fieldDecl,
38138fba894335b979e6d213c685bca959168c1f2182Fariborz Jahanian                                             std::string &Result) {
38148fba894335b979e6d213c685bca959168c1f2182Fariborz Jahanian  QualType Type = fieldDecl->getType();
3815f5eac481ab6da79f05ca13fd859b67abfd2ed246Fariborz Jahanian  if (isa<TypedefType>(Type))
3816f5eac481ab6da79f05ca13fd859b67abfd2ed246Fariborz Jahanian    return;
38178fba894335b979e6d213c685bca959168c1f2182Fariborz Jahanian  if (Type->isArrayType())
38188fba894335b979e6d213c685bca959168c1f2182Fariborz Jahanian    Type = Context->getBaseElementType(Type);
3819b68258fba663cd6a75bf44114e4eb2849551a45fFariborz Jahanian  ObjCContainerDecl *IDecl =
3820b68258fba663cd6a75bf44114e4eb2849551a45fFariborz Jahanian    dyn_cast<ObjCContainerDecl>(fieldDecl->getDeclContext());
38216bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
38226bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  TagDecl *TD = nullptr;
38238fba894335b979e6d213c685bca959168c1f2182Fariborz Jahanian  if (Type->isRecordType()) {
38248fba894335b979e6d213c685bca959168c1f2182Fariborz Jahanian    TD = Type->getAs<RecordType>()->getDecl();
38258fba894335b979e6d213c685bca959168c1f2182Fariborz Jahanian  }
38268fba894335b979e6d213c685bca959168c1f2182Fariborz Jahanian  else if (Type->isEnumeralType()) {
38278fba894335b979e6d213c685bca959168c1f2182Fariborz Jahanian    TD = Type->getAs<EnumType>()->getDecl();
38288fba894335b979e6d213c685bca959168c1f2182Fariborz Jahanian  }
38298fba894335b979e6d213c685bca959168c1f2182Fariborz Jahanian
38308fba894335b979e6d213c685bca959168c1f2182Fariborz Jahanian  if (TD) {
38318fba894335b979e6d213c685bca959168c1f2182Fariborz Jahanian    if (GlobalDefinedTags.count(TD))
38328fba894335b979e6d213c685bca959168c1f2182Fariborz Jahanian      return;
38338fba894335b979e6d213c685bca959168c1f2182Fariborz Jahanian
38348fba894335b979e6d213c685bca959168c1f2182Fariborz Jahanian    bool IsNamedDefinition = false;
38358fba894335b979e6d213c685bca959168c1f2182Fariborz Jahanian    if (IsTagDefinedInsideClass(IDecl, TD, IsNamedDefinition)) {
38368fba894335b979e6d213c685bca959168c1f2182Fariborz Jahanian      RewriteObjCFieldDeclType(Type, Result);
38378fba894335b979e6d213c685bca959168c1f2182Fariborz Jahanian      Result += ";";
38388fba894335b979e6d213c685bca959168c1f2182Fariborz Jahanian    }
38398fba894335b979e6d213c685bca959168c1f2182Fariborz Jahanian    if (IsNamedDefinition)
38408fba894335b979e6d213c685bca959168c1f2182Fariborz Jahanian      GlobalDefinedTags.insert(TD);
38418fba894335b979e6d213c685bca959168c1f2182Fariborz Jahanian  }
38428fba894335b979e6d213c685bca959168c1f2182Fariborz Jahanian
38438fba894335b979e6d213c685bca959168c1f2182Fariborz Jahanian}
38448fba894335b979e6d213c685bca959168c1f2182Fariborz Jahanian
3845cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanianunsigned RewriteModernObjC::ObjCIvarBitfieldGroupNo(ObjCIvarDecl *IV) {
3846cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian  const ObjCInterfaceDecl *CDecl = IV->getContainingInterface();
3847cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian  if (ObjCInterefaceHasBitfieldGroups.count(CDecl)) {
3848cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian    return IvarGroupNumber[IV];
3849cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian  }
3850cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian  unsigned GroupNo = 0;
3851cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian  SmallVector<const ObjCIvarDecl *, 8> IVars;
3852cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian  for (const ObjCIvarDecl *IVD = CDecl->all_declared_ivar_begin();
3853cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian       IVD; IVD = IVD->getNextIvar())
3854cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian    IVars.push_back(IVD);
3855cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian
3856cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian  for (unsigned i = 0, e = IVars.size(); i < e; i++)
3857cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian    if (IVars[i]->isBitField()) {
3858cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian      IvarGroupNumber[IVars[i++]] = ++GroupNo;
3859cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian      while (i < e && IVars[i]->isBitField())
3860cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian        IvarGroupNumber[IVars[i++]] = GroupNo;
3861cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian      if (i < e)
3862cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian        --i;
3863cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian    }
3864cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian
3865cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian  ObjCInterefaceHasBitfieldGroups.insert(CDecl);
3866cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian  return IvarGroupNumber[IV];
3867cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian}
3868cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian
3869cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz JahanianQualType RewriteModernObjC::SynthesizeBitfieldGroupStructType(
3870cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian                              ObjCIvarDecl *IV,
3871cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian                              SmallVectorImpl<ObjCIvarDecl *> &IVars) {
3872cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian  std::string StructTagName;
3873cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian  ObjCIvarBitfieldGroupType(IV, StructTagName);
3874cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian  RecordDecl *RD = RecordDecl::Create(*Context, TTK_Struct,
3875cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian                                      Context->getTranslationUnitDecl(),
3876cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian                                      SourceLocation(), SourceLocation(),
3877cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian                                      &Context->Idents.get(StructTagName));
3878cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian  for (unsigned i=0, e = IVars.size(); i < e; i++) {
3879cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian    ObjCIvarDecl *Ivar = IVars[i];
3880cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian    RD->addDecl(FieldDecl::Create(*Context, RD, SourceLocation(), SourceLocation(),
3881cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian                                  &Context->Idents.get(Ivar->getName()),
3882cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian                                  Ivar->getType(),
38836bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines                                  nullptr, /*Expr *BW */Ivar->getBitWidth(),
38846bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines                                  false, ICIS_NoInit));
3885cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian  }
3886cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian  RD->completeDefinition();
3887cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian  return Context->getTagDeclType(RD);
3888cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian}
3889cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian
3890cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz JahanianQualType RewriteModernObjC::GetGroupRecordTypeForObjCIvarBitfield(ObjCIvarDecl *IV) {
3891cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian  const ObjCInterfaceDecl *CDecl = IV->getContainingInterface();
3892cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian  unsigned GroupNo = ObjCIvarBitfieldGroupNo(IV);
3893cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian  std::pair<const ObjCInterfaceDecl*, unsigned> tuple = std::make_pair(CDecl, GroupNo);
3894cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian  if (GroupRecordType.count(tuple))
3895cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian    return GroupRecordType[tuple];
3896cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian
3897cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian  SmallVector<ObjCIvarDecl *, 8> IVars;
3898cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian  for (const ObjCIvarDecl *IVD = CDecl->all_declared_ivar_begin();
3899cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian       IVD; IVD = IVD->getNextIvar()) {
3900cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian    if (IVD->isBitField())
3901cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian      IVars.push_back(const_cast<ObjCIvarDecl *>(IVD));
3902cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian    else {
3903cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian      if (!IVars.empty()) {
3904cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian        unsigned GroupNo = ObjCIvarBitfieldGroupNo(IVars[0]);
3905cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian        // Generate the struct type for this group of bitfield ivars.
3906cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian        GroupRecordType[std::make_pair(CDecl, GroupNo)] =
3907cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian          SynthesizeBitfieldGroupStructType(IVars[0], IVars);
3908cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian        IVars.clear();
3909cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian      }
3910cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian    }
3911cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian  }
3912cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian  if (!IVars.empty()) {
3913cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian    // Do the last one.
3914cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian    unsigned GroupNo = ObjCIvarBitfieldGroupNo(IVars[0]);
3915cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian    GroupRecordType[std::make_pair(CDecl, GroupNo)] =
3916cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian      SynthesizeBitfieldGroupStructType(IVars[0], IVars);
3917cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian  }
3918cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian  QualType RetQT = GroupRecordType[tuple];
3919cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian  assert(!RetQT.isNull() && "GetGroupRecordTypeForObjCIvarBitfield struct type is NULL");
3920cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian
3921cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian  return RetQT;
3922cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian}
3923cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian
3924cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian/// ObjCIvarBitfieldGroupDecl - Names field decl. for ivar bitfield group.
3925cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian/// Name would be: classname__GRBF_n where n is the group number for this ivar.
3926cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanianvoid RewriteModernObjC::ObjCIvarBitfieldGroupDecl(ObjCIvarDecl *IV,
3927cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian                                                  std::string &Result) {
3928cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian  const ObjCInterfaceDecl *CDecl = IV->getContainingInterface();
3929cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian  Result += CDecl->getName();
3930cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian  Result += "__GRBF_";
3931cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian  unsigned GroupNo = ObjCIvarBitfieldGroupNo(IV);
3932cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian  Result += utostr(GroupNo);
3933cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian  return;
3934cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian}
3935cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian
3936cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian/// ObjCIvarBitfieldGroupType - Names struct type for ivar bitfield group.
3937cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian/// Name of the struct would be: classname__T_n where n is the group number for
3938cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian/// this ivar.
3939cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanianvoid RewriteModernObjC::ObjCIvarBitfieldGroupType(ObjCIvarDecl *IV,
3940cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian                                                  std::string &Result) {
3941cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian  const ObjCInterfaceDecl *CDecl = IV->getContainingInterface();
3942cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian  Result += CDecl->getName();
3943cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian  Result += "__T_";
3944cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian  unsigned GroupNo = ObjCIvarBitfieldGroupNo(IV);
3945cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian  Result += utostr(GroupNo);
3946cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian  return;
3947cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian}
3948cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian
3949cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian/// ObjCIvarBitfieldGroupOffset - Names symbol for ivar bitfield group field offset.
3950cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian/// Name would be: OBJC_IVAR_$_classname__GRBF_n where n is the group number for
3951cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian/// this ivar.
3952cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanianvoid RewriteModernObjC::ObjCIvarBitfieldGroupOffset(ObjCIvarDecl *IV,
3953cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian                                                    std::string &Result) {
3954cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian  Result += "OBJC_IVAR_$_";
3955cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian  ObjCIvarBitfieldGroupDecl(IV, Result);
3956cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian}
3957cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian
3958cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian#define SKIP_BITFIELDS(IX, ENDIX, VEC) { \
3959cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian      while ((IX < ENDIX) && VEC[IX]->isBitField()) \
3960cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian        ++IX; \
3961cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian      if (IX < ENDIX) \
3962cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian        --IX; \
3963cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian}
3964cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian
396564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian/// RewriteObjCInternalStruct - Rewrite one internal struct corresponding to
396664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian/// an objective-c class with ivars.
396764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanianvoid RewriteModernObjC::RewriteObjCInternalStruct(ObjCInterfaceDecl *CDecl,
396864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                               std::string &Result) {
396964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  assert(CDecl && "Class missing in SynthesizeObjCInternalStruct");
397064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  assert(CDecl->getName() != "" &&
397164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian         "Name missing in SynthesizeObjCInternalStruct");
397264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  ObjCInterfaceDecl *RCDecl = CDecl->getSuperClass();
3973a63b422eda86b9ff5a08395dcfc288a31419038eFariborz Jahanian  SmallVector<ObjCIvarDecl *, 8> IVars;
3974a63b422eda86b9ff5a08395dcfc288a31419038eFariborz Jahanian  for (ObjCIvarDecl *IVD = CDecl->all_declared_ivar_begin();
39759a2105bc790b3d0d4d5edb77c617aeccc4187c0eFariborz Jahanian       IVD; IVD = IVD->getNextIvar())
3976a63b422eda86b9ff5a08395dcfc288a31419038eFariborz Jahanian    IVars.push_back(IVD);
39779a2105bc790b3d0d4d5edb77c617aeccc4187c0eFariborz Jahanian
397864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  SourceLocation LocStart = CDecl->getLocStart();
397964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  SourceLocation LocEnd = CDecl->getEndOfDefinitionLoc();
3980a63b422eda86b9ff5a08395dcfc288a31419038eFariborz Jahanian
398164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  const char *startBuf = SM->getCharacterData(LocStart);
398264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  const char *endBuf = SM->getCharacterData(LocEnd);
3983a63b422eda86b9ff5a08395dcfc288a31419038eFariborz Jahanian
398464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  // If no ivars and no root or if its root, directly or indirectly,
398564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  // have no ivars (thus not synthesized) then no need to synthesize this class.
3986a63b422eda86b9ff5a08395dcfc288a31419038eFariborz Jahanian  if ((!CDecl->isThisDeclarationADefinition() || IVars.size() == 0) &&
398764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      (!RCDecl || !ObjCSynthesizedStructs.count(RCDecl))) {
398864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    endBuf += Lexer::MeasureTokenLength(LocEnd, *SM, LangOpts);
398964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    ReplaceText(LocStart, endBuf-startBuf, Result);
399064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    return;
399164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  }
3992a63b422eda86b9ff5a08395dcfc288a31419038eFariborz Jahanian
39938fba894335b979e6d213c685bca959168c1f2182Fariborz Jahanian  // Insert named struct/union definitions inside class to
39948fba894335b979e6d213c685bca959168c1f2182Fariborz Jahanian  // outer scope. This follows semantics of locally defined
39958fba894335b979e6d213c685bca959168c1f2182Fariborz Jahanian  // struct/unions in objective-c classes.
39968fba894335b979e6d213c685bca959168c1f2182Fariborz Jahanian  for (unsigned i = 0, e = IVars.size(); i < e; i++)
39978fba894335b979e6d213c685bca959168c1f2182Fariborz Jahanian    RewriteLocallyDefinedNamedAggregates(IVars[i], Result);
3998cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian
3999cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian  // Insert named structs which are syntheized to group ivar bitfields
4000cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian  // to outer scope as well.
4001cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian  for (unsigned i = 0, e = IVars.size(); i < e; i++)
4002cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian    if (IVars[i]->isBitField()) {
4003cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian      ObjCIvarDecl *IV = IVars[i];
4004cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian      QualType QT = GetGroupRecordTypeForObjCIvarBitfield(IV);
4005cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian      RewriteObjCFieldDeclType(QT, Result);
4006cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian      Result += ";";
4007cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian      // skip over ivar bitfields in this group.
4008cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian      SKIP_BITFIELDS(i , e, IVars);
4009cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian    }
4010cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian
401164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  Result += "\nstruct ";
401264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  Result += CDecl->getNameAsString();
4013a63b422eda86b9ff5a08395dcfc288a31419038eFariborz Jahanian  Result += "_IMPL {\n";
4014a63b422eda86b9ff5a08395dcfc288a31419038eFariborz Jahanian
4015f1c1d9a99dd02b2cd9c4052ec2ec759783175e5eFariborz Jahanian  if (RCDecl && ObjCSynthesizedStructs.count(RCDecl)) {
4016a63b422eda86b9ff5a08395dcfc288a31419038eFariborz Jahanian    Result += "\tstruct "; Result += RCDecl->getNameAsString();
4017a63b422eda86b9ff5a08395dcfc288a31419038eFariborz Jahanian    Result += "_IMPL "; Result += RCDecl->getNameAsString();
4018a63b422eda86b9ff5a08395dcfc288a31419038eFariborz Jahanian    Result += "_IVARS;\n";
4019a63b422eda86b9ff5a08395dcfc288a31419038eFariborz Jahanian  }
40208fba894335b979e6d213c685bca959168c1f2182Fariborz Jahanian
4021cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian  for (unsigned i = 0, e = IVars.size(); i < e; i++) {
4022cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian    if (IVars[i]->isBitField()) {
4023cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian      ObjCIvarDecl *IV = IVars[i];
4024cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian      Result += "\tstruct ";
4025cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian      ObjCIvarBitfieldGroupType(IV, Result); Result += " ";
4026cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian      ObjCIvarBitfieldGroupDecl(IV, Result); Result += ";\n";
4027cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian      // skip over ivar bitfields in this group.
4028cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian      SKIP_BITFIELDS(i , e, IVars);
4029cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian    }
4030cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian    else
4031cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian      RewriteObjCFieldDecl(IVars[i], Result);
4032cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian  }
40330b17b9a1b6ec0522dda5ddd8244844eb9ab1cc1cFariborz Jahanian
4034a63b422eda86b9ff5a08395dcfc288a31419038eFariborz Jahanian  Result += "};\n";
4035a63b422eda86b9ff5a08395dcfc288a31419038eFariborz Jahanian  endBuf += Lexer::MeasureTokenLength(LocEnd, *SM, LangOpts);
4036a63b422eda86b9ff5a08395dcfc288a31419038eFariborz Jahanian  ReplaceText(LocStart, endBuf-startBuf, Result);
4037f1c1d9a99dd02b2cd9c4052ec2ec759783175e5eFariborz Jahanian  // Mark this struct as having been generated.
4038176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  if (!ObjCSynthesizedStructs.insert(CDecl).second)
4039f1c1d9a99dd02b2cd9c4052ec2ec759783175e5eFariborz Jahanian    llvm_unreachable("struct already synthesize- RewriteObjCInternalStruct");
404064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian}
404164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
404272c88f13f79e2012b8a5f84cf48c6af779dfd1baFariborz Jahanian/// RewriteIvarOffsetSymbols - Rewrite ivar offset symbols of those ivars which
404372c88f13f79e2012b8a5f84cf48c6af779dfd1baFariborz Jahanian/// have been referenced in an ivar access expression.
404472c88f13f79e2012b8a5f84cf48c6af779dfd1baFariborz Jahanianvoid RewriteModernObjC::RewriteIvarOffsetSymbols(ObjCInterfaceDecl *CDecl,
404572c88f13f79e2012b8a5f84cf48c6af779dfd1baFariborz Jahanian                                                  std::string &Result) {
404672c88f13f79e2012b8a5f84cf48c6af779dfd1baFariborz Jahanian  // write out ivar offset symbols which have been referenced in an ivar
404772c88f13f79e2012b8a5f84cf48c6af779dfd1baFariborz Jahanian  // access expression.
404872c88f13f79e2012b8a5f84cf48c6af779dfd1baFariborz Jahanian  llvm::SmallPtrSet<ObjCIvarDecl *, 8> Ivars = ReferencedIvars[CDecl];
404972c88f13f79e2012b8a5f84cf48c6af779dfd1baFariborz Jahanian  if (Ivars.empty())
405072c88f13f79e2012b8a5f84cf48c6af779dfd1baFariborz Jahanian    return;
4051cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian
4052cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian  llvm::DenseSet<std::pair<const ObjCInterfaceDecl*, unsigned> > GroupSymbolOutput;
4053176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  for (ObjCIvarDecl *IvarDecl : Ivars) {
4054cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian    const ObjCInterfaceDecl *IDecl = IvarDecl->getContainingInterface();
4055cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian    unsigned GroupNo = 0;
4056cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian    if (IvarDecl->isBitField()) {
4057cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian      GroupNo = ObjCIvarBitfieldGroupNo(IvarDecl);
4058cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian      if (GroupSymbolOutput.count(std::make_pair(IDecl, GroupNo)))
4059cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian        continue;
4060cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian    }
406140a777a157c00cc7e9c9db7197017d83311c76c6Fariborz Jahanian    Result += "\n";
406240a777a157c00cc7e9c9db7197017d83311c76c6Fariborz Jahanian    if (LangOpts.MicrosoftExt)
406340a777a157c00cc7e9c9db7197017d83311c76c6Fariborz Jahanian      Result += "__declspec(allocate(\".objc_ivar$B\")) ";
4064297976d3dc9a5c402b52c734dc06d69f2f987e1cFariborz Jahanian    Result += "extern \"C\" ";
406540a777a157c00cc7e9c9db7197017d83311c76c6Fariborz Jahanian    if (LangOpts.MicrosoftExt &&
406640a777a157c00cc7e9c9db7197017d83311c76c6Fariborz Jahanian        IvarDecl->getAccessControl() != ObjCIvarDecl::Private &&
4067297976d3dc9a5c402b52c734dc06d69f2f987e1cFariborz Jahanian        IvarDecl->getAccessControl() != ObjCIvarDecl::Package)
4068297976d3dc9a5c402b52c734dc06d69f2f987e1cFariborz Jahanian        Result += "__declspec(dllimport) ";
4069297976d3dc9a5c402b52c734dc06d69f2f987e1cFariborz Jahanian
40703f162c398be7fd02167e7382b3a6728c7b2b672dFariborz Jahanian    Result += "unsigned long ";
4071cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian    if (IvarDecl->isBitField()) {
4072cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian      ObjCIvarBitfieldGroupOffset(IvarDecl, Result);
4073cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian      GroupSymbolOutput.insert(std::make_pair(IDecl, GroupNo));
4074cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian    }
4075cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian    else
4076cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian      WriteInternalIvarName(CDecl, IvarDecl, Result);
40777cb2a1b4b6ef60aa57a5f2e5e820a57adef3ea77Fariborz Jahanian    Result += ";";
407872c88f13f79e2012b8a5f84cf48c6af779dfd1baFariborz Jahanian  }
407972c88f13f79e2012b8a5f84cf48c6af779dfd1baFariborz Jahanian}
408072c88f13f79e2012b8a5f84cf48c6af779dfd1baFariborz Jahanian
408164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian//===----------------------------------------------------------------------===//
408264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian// Meta Data Emission
408364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian//===----------------------------------------------------------------------===//
408464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
408564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
408664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian/// RewriteImplementations - This routine rewrites all method implementations
408764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian/// and emits meta-data.
408864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
408964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanianvoid RewriteModernObjC::RewriteImplementations() {
409064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  int ClsDefCount = ClassImplementation.size();
409164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  int CatDefCount = CategoryImplementation.size();
409264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
409364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  // Rewrite implemented methods
40948f1fed036eb78b747725560c10ad29d370d6ef62Fariborz Jahanian  for (int i = 0; i < ClsDefCount; i++) {
40958f1fed036eb78b747725560c10ad29d370d6ef62Fariborz Jahanian    ObjCImplementationDecl *OIMP = ClassImplementation[i];
40968f1fed036eb78b747725560c10ad29d370d6ef62Fariborz Jahanian    ObjCInterfaceDecl *CDecl = OIMP->getClassInterface();
40978f1fed036eb78b747725560c10ad29d370d6ef62Fariborz Jahanian    if (CDecl->isImplicitInterfaceDecl())
4098cf4c60feae11b2f6a135d7cd8ecf97a5040951c3Fariborz Jahanian      assert(false &&
4099cf4c60feae11b2f6a135d7cd8ecf97a5040951c3Fariborz Jahanian             "Legacy implicit interface rewriting not supported in moder abi");
41008f1fed036eb78b747725560c10ad29d370d6ef62Fariborz Jahanian    RewriteImplementationDecl(OIMP);
41018f1fed036eb78b747725560c10ad29d370d6ef62Fariborz Jahanian  }
410264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
41038c00a1b66a1110d8354c3c48f0cbd037d5b04c38Fariborz Jahanian  for (int i = 0; i < CatDefCount; i++) {
41048c00a1b66a1110d8354c3c48f0cbd037d5b04c38Fariborz Jahanian    ObjCCategoryImplDecl *CIMP = CategoryImplementation[i];
41058c00a1b66a1110d8354c3c48f0cbd037d5b04c38Fariborz Jahanian    ObjCInterfaceDecl *CDecl = CIMP->getClassInterface();
41068c00a1b66a1110d8354c3c48f0cbd037d5b04c38Fariborz Jahanian    if (CDecl->isImplicitInterfaceDecl())
41078c00a1b66a1110d8354c3c48f0cbd037d5b04c38Fariborz Jahanian      assert(false &&
41088c00a1b66a1110d8354c3c48f0cbd037d5b04c38Fariborz Jahanian             "Legacy implicit interface rewriting not supported in moder abi");
41098c00a1b66a1110d8354c3c48f0cbd037d5b04c38Fariborz Jahanian    RewriteImplementationDecl(CIMP);
41108c00a1b66a1110d8354c3c48f0cbd037d5b04c38Fariborz Jahanian  }
411164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian}
411264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
411364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanianvoid RewriteModernObjC::RewriteByRefString(std::string &ResultStr,
411464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                     const std::string &Name,
411564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                     ValueDecl *VD, bool def) {
411664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  assert(BlockByRefDeclNo.count(VD) &&
411764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian         "RewriteByRefString: ByRef decl missing");
411864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  if (def)
411964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    ResultStr += "struct ";
412064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  ResultStr += "__Block_byref_" + Name +
412164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    "_" + utostr(BlockByRefDeclNo[VD]) ;
412264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian}
412364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
412464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanianstatic bool HasLocalVariableExternalStorage(ValueDecl *VD) {
412564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  if (VarDecl *Var = dyn_cast<VarDecl>(VD))
412664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    return (Var->isFunctionOrMethodVarDecl() && !Var->hasLocalStorage());
412764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  return false;
412864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian}
412964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
413064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanianstd::string RewriteModernObjC::SynthesizeBlockFunc(BlockExpr *CE, int i,
413164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                                   StringRef funcName,
413264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                                   std::string Tag) {
413364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  const FunctionType *AFT = CE->getFunctionType();
4134651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  QualType RT = AFT->getReturnType();
413564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  std::string StructRef = "struct " + Tag;
4136f616ae2d1356dadde26ff553eb689e5455d65808Fariborz Jahanian  SourceLocation BlockLoc = CE->getExprLoc();
4137f616ae2d1356dadde26ff553eb689e5455d65808Fariborz Jahanian  std::string S;
4138f616ae2d1356dadde26ff553eb689e5455d65808Fariborz Jahanian  ConvertSourceLocationToLineDirective(BlockLoc, S);
4139f616ae2d1356dadde26ff553eb689e5455d65808Fariborz Jahanian
4140f616ae2d1356dadde26ff553eb689e5455d65808Fariborz Jahanian  S += "static " + RT.getAsString(Context->getPrintingPolicy()) + " __" +
4141f616ae2d1356dadde26ff553eb689e5455d65808Fariborz Jahanian         funcName.str() + "_block_func_" + utostr(i);
414264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
414364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  BlockDecl *BD = CE->getBlockDecl();
414464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
414564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  if (isa<FunctionNoProtoType>(AFT)) {
414664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    // No user-supplied arguments. Still need to pass in a pointer to the
414764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    // block (to reference imported block decl refs).
414864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    S += "(" + StructRef + " *__cself)";
414964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  } else if (BD->param_empty()) {
415064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    S += "(" + StructRef + " *__cself)";
415164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  } else {
415264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    const FunctionProtoType *FT = cast<FunctionProtoType>(AFT);
415364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    assert(FT && "SynthesizeBlockFunc: No function proto");
415464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    S += '(';
415564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    // first add the implicit argument.
415664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    S += StructRef + " *__cself, ";
415764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    std::string ParamStr;
415864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    for (BlockDecl::param_iterator AI = BD->param_begin(),
415964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian         E = BD->param_end(); AI != E; ++AI) {
416064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      if (AI != BD->param_begin()) S += ", ";
416164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      ParamStr = (*AI)->getNameAsString();
416264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      QualType QT = (*AI)->getType();
41632610f90135571be7bf983c80a1cf7bfa0844dc57Fariborz Jahanian      (void)convertBlockPointerToFunctionPointer(QT);
41642610f90135571be7bf983c80a1cf7bfa0844dc57Fariborz Jahanian      QT.getAsStringInternal(ParamStr, Context->getPrintingPolicy());
416564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      S += ParamStr;
416664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    }
416764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    if (FT->isVariadic()) {
416864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      if (!BD->param_empty()) S += ", ";
416964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      S += "...";
417064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    }
417164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    S += ')';
417264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  }
417364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  S += " {\n";
417464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
417564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  // Create local declarations to avoid rewriting all closure decl ref exprs.
417664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  // First, emit a declaration for all "by ref" decls.
417709d19efaa147762f84aed55efa7930bb3616a4e5Craig Topper  for (SmallVectorImpl<ValueDecl *>::iterator I = BlockByRefDecls.begin(),
417864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian       E = BlockByRefDecls.end(); I != E; ++I) {
417964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    S += "  ";
418064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    std::string Name = (*I)->getNameAsString();
418164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    std::string TypeString;
418264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    RewriteByRefString(TypeString, Name, (*I));
418364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    TypeString += " *";
418464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    Name = TypeString + Name;
418564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    S += Name + " = __cself->" + (*I)->getNameAsString() + "; // bound by ref\n";
418664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  }
418764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  // Next, emit a declaration for all "by copy" declarations.
418809d19efaa147762f84aed55efa7930bb3616a4e5Craig Topper  for (SmallVectorImpl<ValueDecl *>::iterator I = BlockByCopyDecls.begin(),
418964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian       E = BlockByCopyDecls.end(); I != E; ++I) {
419064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    S += "  ";
419164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    // Handle nested closure invocation. For example:
419264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    //
419364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    //   void (^myImportedClosure)(void);
419464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    //   myImportedClosure  = ^(void) { setGlobalInt(x + y); };
419564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    //
419664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    //   void (^anotherClosure)(void);
419764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    //   anotherClosure = ^(void) {
419864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    //     myImportedClosure(); // import and invoke the closure
419964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    //   };
420064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    //
420164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    if (isTopLevelBlockPointerType((*I)->getType())) {
420264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      RewriteBlockPointerTypeVariable(S, (*I));
420364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      S += " = (";
420464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      RewriteBlockPointerType(S, (*I)->getType());
420564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      S += ")";
420664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      S += "__cself->" + (*I)->getNameAsString() + "; // bound by copy\n";
420764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    }
420864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    else {
420964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      std::string Name = (*I)->getNameAsString();
421064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      QualType QT = (*I)->getType();
421164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      if (HasLocalVariableExternalStorage(*I))
421264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        QT = Context->getPointerType(QT);
421364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      QT.getAsStringInternal(Name, Context->getPrintingPolicy());
421464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      S += Name + " = __cself->" +
421564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                              (*I)->getNameAsString() + "; // bound by copy\n";
421664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    }
421764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  }
421864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  std::string RewrittenStr = RewrittenBlockExprs[CE];
421964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  const char *cstr = RewrittenStr.c_str();
422064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  while (*cstr++ != '{') ;
422164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  S += cstr;
422264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  S += "\n";
422364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  return S;
422464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian}
422564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
422664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanianstd::string RewriteModernObjC::SynthesizeBlockHelperFuncs(BlockExpr *CE, int i,
422764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                                   StringRef funcName,
422864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                                   std::string Tag) {
422964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  std::string StructRef = "struct " + Tag;
423064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  std::string S = "static void __";
423164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
423264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  S += funcName;
423364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  S += "_block_copy_" + utostr(i);
423464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  S += "(" + StructRef;
423564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  S += "*dst, " + StructRef;
423664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  S += "*src) {";
4237176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  for (ValueDecl *VD : ImportedBlockDecls) {
423864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    S += "_Block_object_assign((void*)&dst->";
4239176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    S += VD->getNameAsString();
424064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    S += ", (void*)src->";
4241176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    S += VD->getNameAsString();
4242176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    if (BlockByRefDeclsPtrSet.count(VD))
424364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      S += ", " + utostr(BLOCK_FIELD_IS_BYREF) + "/*BLOCK_FIELD_IS_BYREF*/);";
424464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    else if (VD->getType()->isBlockPointerType())
424564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      S += ", " + utostr(BLOCK_FIELD_IS_BLOCK) + "/*BLOCK_FIELD_IS_BLOCK*/);";
424664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    else
424764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      S += ", " + utostr(BLOCK_FIELD_IS_OBJECT) + "/*BLOCK_FIELD_IS_OBJECT*/);";
424864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  }
424964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  S += "}\n";
425064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
425164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  S += "\nstatic void __";
425264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  S += funcName;
425364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  S += "_block_dispose_" + utostr(i);
425464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  S += "(" + StructRef;
425564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  S += "*src) {";
4256176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  for (ValueDecl *VD : ImportedBlockDecls) {
425764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    S += "_Block_object_dispose((void*)src->";
4258176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    S += VD->getNameAsString();
4259176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    if (BlockByRefDeclsPtrSet.count(VD))
426064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      S += ", " + utostr(BLOCK_FIELD_IS_BYREF) + "/*BLOCK_FIELD_IS_BYREF*/);";
426164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    else if (VD->getType()->isBlockPointerType())
426264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      S += ", " + utostr(BLOCK_FIELD_IS_BLOCK) + "/*BLOCK_FIELD_IS_BLOCK*/);";
426364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    else
426464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      S += ", " + utostr(BLOCK_FIELD_IS_OBJECT) + "/*BLOCK_FIELD_IS_OBJECT*/);";
426564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  }
426664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  S += "}\n";
426764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  return S;
426864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian}
426964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
427064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanianstd::string RewriteModernObjC::SynthesizeBlockImpl(BlockExpr *CE, std::string Tag,
427164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                             std::string Desc) {
427264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  std::string S = "\nstruct " + Tag;
427364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  std::string Constructor = "  " + Tag;
427464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
427564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  S += " {\n  struct __block_impl impl;\n";
427664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  S += "  struct " + Desc;
427764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  S += "* Desc;\n";
427864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
427964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  Constructor += "(void *fp, "; // Invoke function pointer.
428064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  Constructor += "struct " + Desc; // Descriptor pointer.
428164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  Constructor += " *desc";
428264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
428364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  if (BlockDeclRefs.size()) {
428464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    // Output all "by copy" declarations.
428509d19efaa147762f84aed55efa7930bb3616a4e5Craig Topper    for (SmallVectorImpl<ValueDecl *>::iterator I = BlockByCopyDecls.begin(),
428664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian         E = BlockByCopyDecls.end(); I != E; ++I) {
428764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      S += "  ";
428864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      std::string FieldName = (*I)->getNameAsString();
428964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      std::string ArgName = "_" + FieldName;
429064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      // Handle nested closure invocation. For example:
429164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      //
429264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      //   void (^myImportedBlock)(void);
429364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      //   myImportedBlock  = ^(void) { setGlobalInt(x + y); };
429464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      //
429564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      //   void (^anotherBlock)(void);
429664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      //   anotherBlock = ^(void) {
429764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      //     myImportedBlock(); // import and invoke the closure
429864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      //   };
429964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      //
430064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      if (isTopLevelBlockPointerType((*I)->getType())) {
430164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        S += "struct __block_impl *";
430264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        Constructor += ", void *" + ArgName;
430364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      } else {
430464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        QualType QT = (*I)->getType();
430564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        if (HasLocalVariableExternalStorage(*I))
430664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian          QT = Context->getPointerType(QT);
430764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        QT.getAsStringInternal(FieldName, Context->getPrintingPolicy());
430864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        QT.getAsStringInternal(ArgName, Context->getPrintingPolicy());
430964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        Constructor += ", " + ArgName;
431064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      }
431164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      S += FieldName + ";\n";
431264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    }
431364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    // Output all "by ref" declarations.
431409d19efaa147762f84aed55efa7930bb3616a4e5Craig Topper    for (SmallVectorImpl<ValueDecl *>::iterator I = BlockByRefDecls.begin(),
431564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian         E = BlockByRefDecls.end(); I != E; ++I) {
431664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      S += "  ";
431764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      std::string FieldName = (*I)->getNameAsString();
431864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      std::string ArgName = "_" + FieldName;
431964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      {
432064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        std::string TypeString;
432164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        RewriteByRefString(TypeString, FieldName, (*I));
432264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        TypeString += " *";
432364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        FieldName = TypeString + FieldName;
432464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        ArgName = TypeString + ArgName;
432564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        Constructor += ", " + ArgName;
432664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      }
432764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      S += FieldName + "; // by ref\n";
432864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    }
432964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    // Finish writing the constructor.
433064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    Constructor += ", int flags=0)";
433164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    // Initialize all "by copy" arguments.
433264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    bool firsTime = true;
433309d19efaa147762f84aed55efa7930bb3616a4e5Craig Topper    for (SmallVectorImpl<ValueDecl *>::iterator I = BlockByCopyDecls.begin(),
433464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian         E = BlockByCopyDecls.end(); I != E; ++I) {
433564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      std::string Name = (*I)->getNameAsString();
433664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        if (firsTime) {
433764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian          Constructor += " : ";
433864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian          firsTime = false;
433964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        }
434064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        else
434164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian          Constructor += ", ";
434264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        if (isTopLevelBlockPointerType((*I)->getType()))
434364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian          Constructor += Name + "((struct __block_impl *)_" + Name + ")";
434464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        else
434564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian          Constructor += Name + "(_" + Name + ")";
434664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    }
434764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    // Initialize all "by ref" arguments.
434809d19efaa147762f84aed55efa7930bb3616a4e5Craig Topper    for (SmallVectorImpl<ValueDecl *>::iterator I = BlockByRefDecls.begin(),
434964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian         E = BlockByRefDecls.end(); I != E; ++I) {
435064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      std::string Name = (*I)->getNameAsString();
435164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      if (firsTime) {
435264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        Constructor += " : ";
435364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        firsTime = false;
435464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      }
435564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      else
435664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        Constructor += ", ";
435764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      Constructor += Name + "(_" + Name + "->__forwarding)";
435864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    }
435964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
436064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    Constructor += " {\n";
436164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    if (GlobalVarDecl)
436264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      Constructor += "    impl.isa = &_NSConcreteGlobalBlock;\n";
436364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    else
436464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      Constructor += "    impl.isa = &_NSConcreteStackBlock;\n";
436564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    Constructor += "    impl.Flags = flags;\n    impl.FuncPtr = fp;\n";
436664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
436764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    Constructor += "    Desc = desc;\n";
436864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  } else {
436964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    // Finish writing the constructor.
437064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    Constructor += ", int flags=0) {\n";
437164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    if (GlobalVarDecl)
437264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      Constructor += "    impl.isa = &_NSConcreteGlobalBlock;\n";
437364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    else
437464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      Constructor += "    impl.isa = &_NSConcreteStackBlock;\n";
437564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    Constructor += "    impl.Flags = flags;\n    impl.FuncPtr = fp;\n";
437664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    Constructor += "    Desc = desc;\n";
437764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  }
437864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  Constructor += "  ";
437964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  Constructor += "}\n";
438064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  S += Constructor;
438164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  S += "};\n";
438264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  return S;
438364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian}
438464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
438564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanianstd::string RewriteModernObjC::SynthesizeBlockDescriptor(std::string DescTag,
438664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                                   std::string ImplTag, int i,
438764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                                   StringRef FunName,
438864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                                   unsigned hasCopy) {
438964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  std::string S = "\nstatic struct " + DescTag;
439064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
43918b08adb279e7db69c65461f7c0029344dc3e4e5fFariborz Jahanian  S += " {\n  size_t reserved;\n";
43928b08adb279e7db69c65461f7c0029344dc3e4e5fFariborz Jahanian  S += "  size_t Block_size;\n";
439364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  if (hasCopy) {
439464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    S += "  void (*copy)(struct ";
439564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    S += ImplTag; S += "*, struct ";
439664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    S += ImplTag; S += "*);\n";
439764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
439864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    S += "  void (*dispose)(struct ";
439964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    S += ImplTag; S += "*);\n";
440064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  }
440164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  S += "} ";
440264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
440364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  S += DescTag + "_DATA = { 0, sizeof(struct ";
440464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  S += ImplTag + ")";
440564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  if (hasCopy) {
440664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    S += ", __" + FunName.str() + "_block_copy_" + utostr(i);
440764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    S += ", __" + FunName.str() + "_block_dispose_" + utostr(i);
440864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  }
440964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  S += "};\n";
441064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  return S;
441164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian}
441264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
441364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanianvoid RewriteModernObjC::SynthesizeBlockLiterals(SourceLocation FunLocStart,
441464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                          StringRef FunName) {
441564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  bool RewriteSC = (GlobalVarDecl &&
441664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                    !Blocks.empty() &&
441764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                    GlobalVarDecl->getStorageClass() == SC_Static &&
441864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                    GlobalVarDecl->getType().getCVRQualifiers());
441964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  if (RewriteSC) {
442064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    std::string SC(" void __");
442164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    SC += GlobalVarDecl->getNameAsString();
442264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    SC += "() {}";
442364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    InsertText(FunLocStart, SC);
442464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  }
442564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
442664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  // Insert closures that were part of the function.
442764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  for (unsigned i = 0, count=0; i < Blocks.size(); i++) {
442864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    CollectBlockDeclRefInfo(Blocks[i]);
442964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    // Need to copy-in the inner copied-in variables not actually used in this
443064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    // block.
443164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    for (int j = 0; j < InnerDeclRefsCount[i]; j++) {
4432f4b88a45902af1802a1cb42ba48b1c474474f228John McCall      DeclRefExpr *Exp = InnerDeclRefs[count++];
443364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      ValueDecl *VD = Exp->getDecl();
443464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      BlockDeclRefs.push_back(Exp);
4435f4b88a45902af1802a1cb42ba48b1c474474f228John McCall      if (!VD->hasAttr<BlocksAttr>()) {
4436f4b88a45902af1802a1cb42ba48b1c474474f228John McCall        if (!BlockByCopyDeclsPtrSet.count(VD)) {
4437f4b88a45902af1802a1cb42ba48b1c474474f228John McCall          BlockByCopyDeclsPtrSet.insert(VD);
4438f4b88a45902af1802a1cb42ba48b1c474474f228John McCall          BlockByCopyDecls.push_back(VD);
4439f4b88a45902af1802a1cb42ba48b1c474474f228John McCall        }
4440f4b88a45902af1802a1cb42ba48b1c474474f228John McCall        continue;
444164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      }
4442f4b88a45902af1802a1cb42ba48b1c474474f228John McCall
4443f4b88a45902af1802a1cb42ba48b1c474474f228John McCall      if (!BlockByRefDeclsPtrSet.count(VD)) {
444464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        BlockByRefDeclsPtrSet.insert(VD);
444564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        BlockByRefDecls.push_back(VD);
444664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      }
4447f4b88a45902af1802a1cb42ba48b1c474474f228John McCall
444864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      // imported objects in the inner blocks not used in the outer
444964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      // blocks must be copied/disposed in the outer block as well.
4450f4b88a45902af1802a1cb42ba48b1c474474f228John McCall      if (VD->getType()->isObjCObjectPointerType() ||
445164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian          VD->getType()->isBlockPointerType())
445264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        ImportedBlockDecls.insert(VD);
445364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    }
445464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
445564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    std::string ImplTag = "__" + FunName.str() + "_block_impl_" + utostr(i);
445664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    std::string DescTag = "__" + FunName.str() + "_block_desc_" + utostr(i);
445764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
445864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    std::string CI = SynthesizeBlockImpl(Blocks[i], ImplTag, DescTag);
445964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
446064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    InsertText(FunLocStart, CI);
446164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
446264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    std::string CF = SynthesizeBlockFunc(Blocks[i], i, FunName, ImplTag);
446364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
446464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    InsertText(FunLocStart, CF);
446564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
446664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    if (ImportedBlockDecls.size()) {
446764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      std::string HF = SynthesizeBlockHelperFuncs(Blocks[i], i, FunName, ImplTag);
446864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      InsertText(FunLocStart, HF);
446964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    }
447064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    std::string BD = SynthesizeBlockDescriptor(DescTag, ImplTag, i, FunName,
447164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                               ImportedBlockDecls.size() > 0);
447264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    InsertText(FunLocStart, BD);
447364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
447464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    BlockDeclRefs.clear();
447564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    BlockByRefDecls.clear();
447664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    BlockByRefDeclsPtrSet.clear();
447764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    BlockByCopyDecls.clear();
447864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    BlockByCopyDeclsPtrSet.clear();
447964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    ImportedBlockDecls.clear();
448064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  }
448164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  if (RewriteSC) {
448264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    // Must insert any 'const/volatile/static here. Since it has been
448364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    // removed as result of rewriting of block literals.
448464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    std::string SC;
448564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    if (GlobalVarDecl->getStorageClass() == SC_Static)
448664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      SC = "static ";
448764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    if (GlobalVarDecl->getType().isConstQualified())
448864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      SC += "const ";
448964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    if (GlobalVarDecl->getType().isVolatileQualified())
449064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      SC += "volatile ";
449164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    if (GlobalVarDecl->getType().isRestrictQualified())
449264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      SC += "restrict ";
449364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    InsertText(FunLocStart, SC);
449464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  }
4495df474ec64a86bb88c7543875634d3fc628105bb5Fariborz Jahanian  if (GlobalConstructionExp) {
4496df474ec64a86bb88c7543875634d3fc628105bb5Fariborz Jahanian    // extra fancy dance for global literal expression.
4497df474ec64a86bb88c7543875634d3fc628105bb5Fariborz Jahanian
4498df474ec64a86bb88c7543875634d3fc628105bb5Fariborz Jahanian    // Always the latest block expression on the block stack.
4499df474ec64a86bb88c7543875634d3fc628105bb5Fariborz Jahanian    std::string Tag = "__";
4500df474ec64a86bb88c7543875634d3fc628105bb5Fariborz Jahanian    Tag += FunName;
4501df474ec64a86bb88c7543875634d3fc628105bb5Fariborz Jahanian    Tag += "_block_impl_";
4502df474ec64a86bb88c7543875634d3fc628105bb5Fariborz Jahanian    Tag += utostr(Blocks.size()-1);
4503df474ec64a86bb88c7543875634d3fc628105bb5Fariborz Jahanian    std::string globalBuf = "static ";
4504df474ec64a86bb88c7543875634d3fc628105bb5Fariborz Jahanian    globalBuf += Tag; globalBuf += " ";
4505df474ec64a86bb88c7543875634d3fc628105bb5Fariborz Jahanian    std::string SStr;
450664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
4507df474ec64a86bb88c7543875634d3fc628105bb5Fariborz Jahanian    llvm::raw_string_ostream constructorExprBuf(SStr);
45086bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    GlobalConstructionExp->printPretty(constructorExprBuf, nullptr,
45096bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines                                       PrintingPolicy(LangOpts));
4510df474ec64a86bb88c7543875634d3fc628105bb5Fariborz Jahanian    globalBuf += constructorExprBuf.str();
4511df474ec64a86bb88c7543875634d3fc628105bb5Fariborz Jahanian    globalBuf += ";\n";
4512df474ec64a86bb88c7543875634d3fc628105bb5Fariborz Jahanian    InsertText(FunLocStart, globalBuf);
45136bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    GlobalConstructionExp = nullptr;
4514df474ec64a86bb88c7543875634d3fc628105bb5Fariborz Jahanian  }
4515df474ec64a86bb88c7543875634d3fc628105bb5Fariborz Jahanian
451664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  Blocks.clear();
451764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  InnerDeclRefsCount.clear();
451864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  InnerDeclRefs.clear();
451964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  RewrittenBlockExprs.clear();
452064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian}
452164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
452264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanianvoid RewriteModernObjC::InsertBlockLiteralsWithinFunction(FunctionDecl *FD) {
4523041895354a5c4280f00a86082e4218312dd44467Fariborz Jahanian  SourceLocation FunLocStart =
4524041895354a5c4280f00a86082e4218312dd44467Fariborz Jahanian    (!Blocks.empty()) ? getFunctionSourceLocation(*this, FD)
4525041895354a5c4280f00a86082e4218312dd44467Fariborz Jahanian                      : FD->getTypeSpecStartLoc();
452664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  StringRef FuncName = FD->getName();
452764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
452864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  SynthesizeBlockLiterals(FunLocStart, FuncName);
452964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian}
453064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
453164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanianstatic void BuildUniqueMethodName(std::string &Name,
453264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                  ObjCMethodDecl *MD) {
453364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  ObjCInterfaceDecl *IFace = MD->getClassInterface();
453464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  Name = IFace->getName();
453564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  Name += "__" + MD->getSelector().getAsString();
453664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  // Convert colons to underscores.
453764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  std::string::size_type loc = 0;
453864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  while ((loc = Name.find(":", loc)) != std::string::npos)
453964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    Name.replace(loc, 1, "_");
454064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian}
454164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
454264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanianvoid RewriteModernObjC::InsertBlockLiteralsWithinMethod(ObjCMethodDecl *MD) {
454364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  //fprintf(stderr,"In InsertBlockLiteralsWitinMethod\n");
454464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  //SourceLocation FunLocStart = MD->getLocStart();
454564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  SourceLocation FunLocStart = MD->getLocStart();
454664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  std::string FuncName;
454764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  BuildUniqueMethodName(FuncName, MD);
454864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  SynthesizeBlockLiterals(FunLocStart, FuncName);
454964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian}
455064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
455164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanianvoid RewriteModernObjC::GetBlockDeclRefExprs(Stmt *S) {
455264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  for (Stmt::child_range CI = S->children(); CI; ++CI)
455364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    if (*CI) {
455464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      if (BlockExpr *CBE = dyn_cast<BlockExpr>(*CI))
455564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        GetBlockDeclRefExprs(CBE->getBody());
455664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      else
455764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        GetBlockDeclRefExprs(*CI);
455864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    }
455964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  // Handle specific things.
45600e2c34f92f00628d48968dfea096d36381f494cbStephen Hines  if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(S))
45610e2c34f92f00628d48968dfea096d36381f494cbStephen Hines    if (DRE->refersToEnclosingVariableOrCapture() ||
45620e2c34f92f00628d48968dfea096d36381f494cbStephen Hines        HasLocalVariableExternalStorage(DRE->getDecl()))
45630e976818ea1c7624b7dc250e7e2f9d251845874fFariborz Jahanian      // FIXME: Handle enums.
45640e2c34f92f00628d48968dfea096d36381f494cbStephen Hines      BlockDeclRefs.push_back(DRE);
45650e2c34f92f00628d48968dfea096d36381f494cbStephen Hines
456664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  return;
456764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian}
456864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
45696b9240e058bf3451685df73fc8ce181b3046e92bCraig Toppervoid RewriteModernObjC::GetInnerBlockDeclRefExprs(Stmt *S,
45706b9240e058bf3451685df73fc8ce181b3046e92bCraig Topper                SmallVectorImpl<DeclRefExpr *> &InnerBlockDeclRefs,
4571176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines                llvm::SmallPtrSetImpl<const DeclContext *> &InnerContexts) {
457264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  for (Stmt::child_range CI = S->children(); CI; ++CI)
457364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    if (*CI) {
457464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      if (BlockExpr *CBE = dyn_cast<BlockExpr>(*CI)) {
457564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        InnerContexts.insert(cast<DeclContext>(CBE->getBlockDecl()));
457664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        GetInnerBlockDeclRefExprs(CBE->getBody(),
457764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                  InnerBlockDeclRefs,
457864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                  InnerContexts);
457964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      }
458064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      else
458164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        GetInnerBlockDeclRefExprs(*CI,
458264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                  InnerBlockDeclRefs,
458364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                  InnerContexts);
458464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
458564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    }
458664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  // Handle specific things.
4587f4b88a45902af1802a1cb42ba48b1c474474f228John McCall  if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(S)) {
45880e2c34f92f00628d48968dfea096d36381f494cbStephen Hines    if (DRE->refersToEnclosingVariableOrCapture() ||
45890e2c34f92f00628d48968dfea096d36381f494cbStephen Hines        HasLocalVariableExternalStorage(DRE->getDecl())) {
45900e2c34f92f00628d48968dfea096d36381f494cbStephen Hines      if (!InnerContexts.count(DRE->getDecl()->getDeclContext()))
4591f4b88a45902af1802a1cb42ba48b1c474474f228John McCall        InnerBlockDeclRefs.push_back(DRE);
45920e2c34f92f00628d48968dfea096d36381f494cbStephen Hines      if (VarDecl *Var = cast<VarDecl>(DRE->getDecl()))
4593f4b88a45902af1802a1cb42ba48b1c474474f228John McCall        if (Var->isFunctionOrMethodVarDecl())
4594f4b88a45902af1802a1cb42ba48b1c474474f228John McCall          ImportedLocalExternalDecls.insert(Var);
4595f4b88a45902af1802a1cb42ba48b1c474474f228John McCall    }
459664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  }
459764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
459864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  return;
459964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian}
460064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
4601164d6f8c7e040cb766b071ce92320a18dafbece1Fariborz Jahanian/// convertObjCTypeToCStyleType - This routine converts such objc types
4602164d6f8c7e040cb766b071ce92320a18dafbece1Fariborz Jahanian/// as qualified objects, and blocks to their closest c/c++ types that
4603164d6f8c7e040cb766b071ce92320a18dafbece1Fariborz Jahanian/// it can. It returns true if input type was modified.
4604164d6f8c7e040cb766b071ce92320a18dafbece1Fariborz Jahanianbool RewriteModernObjC::convertObjCTypeToCStyleType(QualType &T) {
4605164d6f8c7e040cb766b071ce92320a18dafbece1Fariborz Jahanian  QualType oldT = T;
4606164d6f8c7e040cb766b071ce92320a18dafbece1Fariborz Jahanian  convertBlockPointerToFunctionPointer(T);
4607164d6f8c7e040cb766b071ce92320a18dafbece1Fariborz Jahanian  if (T->isFunctionPointerType()) {
4608164d6f8c7e040cb766b071ce92320a18dafbece1Fariborz Jahanian    QualType PointeeTy;
4609164d6f8c7e040cb766b071ce92320a18dafbece1Fariborz Jahanian    if (const PointerType* PT = T->getAs<PointerType>()) {
4610164d6f8c7e040cb766b071ce92320a18dafbece1Fariborz Jahanian      PointeeTy = PT->getPointeeType();
4611164d6f8c7e040cb766b071ce92320a18dafbece1Fariborz Jahanian      if (const FunctionType *FT = PointeeTy->getAs<FunctionType>()) {
4612164d6f8c7e040cb766b071ce92320a18dafbece1Fariborz Jahanian        T = convertFunctionTypeOfBlocks(FT);
4613164d6f8c7e040cb766b071ce92320a18dafbece1Fariborz Jahanian        T = Context->getPointerType(T);
4614164d6f8c7e040cb766b071ce92320a18dafbece1Fariborz Jahanian      }
4615164d6f8c7e040cb766b071ce92320a18dafbece1Fariborz Jahanian    }
4616164d6f8c7e040cb766b071ce92320a18dafbece1Fariborz Jahanian  }
4617164d6f8c7e040cb766b071ce92320a18dafbece1Fariborz Jahanian
4618164d6f8c7e040cb766b071ce92320a18dafbece1Fariborz Jahanian  convertToUnqualifiedObjCType(T);
4619164d6f8c7e040cb766b071ce92320a18dafbece1Fariborz Jahanian  return T != oldT;
4620164d6f8c7e040cb766b071ce92320a18dafbece1Fariborz Jahanian}
4621164d6f8c7e040cb766b071ce92320a18dafbece1Fariborz Jahanian
462264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian/// convertFunctionTypeOfBlocks - This routine converts a function type
462364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian/// whose result type may be a block pointer or whose argument type(s)
462464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian/// might be block pointers to an equivalent function type replacing
462564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian/// all block pointers to function pointers.
462664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz JahanianQualType RewriteModernObjC::convertFunctionTypeOfBlocks(const FunctionType *FT) {
462764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  const FunctionProtoType *FTP = dyn_cast<FunctionProtoType>(FT);
462864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  // FTP will be null for closures that don't take arguments.
462964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  // Generate a funky cast.
463064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  SmallVector<QualType, 8> ArgTypes;
4631651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  QualType Res = FT->getReturnType();
4632164d6f8c7e040cb766b071ce92320a18dafbece1Fariborz Jahanian  bool modified = convertObjCTypeToCStyleType(Res);
463364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
463464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  if (FTP) {
4635651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    for (auto &I : FTP->param_types()) {
4636651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      QualType t = I;
463764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      // Make sure we convert "t (^)(...)" to "t (*)(...)".
4638164d6f8c7e040cb766b071ce92320a18dafbece1Fariborz Jahanian      if (convertObjCTypeToCStyleType(t))
4639164d6f8c7e040cb766b071ce92320a18dafbece1Fariborz Jahanian        modified = true;
464064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      ArgTypes.push_back(t);
464164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    }
464264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  }
464364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  QualType FuncType;
4644164d6f8c7e040cb766b071ce92320a18dafbece1Fariborz Jahanian  if (modified)
4645bea522ff43a3f11c7a2bc7949119dbb9fce19e39Jordan Rose    FuncType = getSimpleFunctionType(Res, ArgTypes);
464664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  else FuncType = QualType(FT, 0);
464764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  return FuncType;
464864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian}
464964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
465064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz JahanianStmt *RewriteModernObjC::SynthesizeBlockCall(CallExpr *Exp, const Expr *BlockExp) {
465164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  // Navigate to relevant type information.
46526bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  const BlockPointerType *CPT = nullptr;
465364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
465464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(BlockExp)) {
465564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    CPT = DRE->getType()->getAs<BlockPointerType>();
465664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  } else if (const MemberExpr *MExpr = dyn_cast<MemberExpr>(BlockExp)) {
465764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    CPT = MExpr->getType()->getAs<BlockPointerType>();
465864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  }
465964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  else if (const ParenExpr *PRE = dyn_cast<ParenExpr>(BlockExp)) {
466064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    return SynthesizeBlockCall(Exp, PRE->getSubExpr());
466164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  }
466264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  else if (const ImplicitCastExpr *IEXPR = dyn_cast<ImplicitCastExpr>(BlockExp))
466364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    CPT = IEXPR->getType()->getAs<BlockPointerType>();
466464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  else if (const ConditionalOperator *CEXPR =
466564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian            dyn_cast<ConditionalOperator>(BlockExp)) {
466664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    Expr *LHSExp = CEXPR->getLHS();
466764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    Stmt *LHSStmt = SynthesizeBlockCall(Exp, LHSExp);
466864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    Expr *RHSExp = CEXPR->getRHS();
466964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    Stmt *RHSStmt = SynthesizeBlockCall(Exp, RHSExp);
467064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    Expr *CONDExp = CEXPR->getCond();
467164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    ConditionalOperator *CondExpr =
467264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      new (Context) ConditionalOperator(CONDExp,
467364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                      SourceLocation(), cast<Expr>(LHSStmt),
467464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                      SourceLocation(), cast<Expr>(RHSStmt),
467564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                      Exp->getType(), VK_RValue, OK_Ordinary);
467664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    return CondExpr;
467764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  } else if (const ObjCIvarRefExpr *IRE = dyn_cast<ObjCIvarRefExpr>(BlockExp)) {
467864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    CPT = IRE->getType()->getAs<BlockPointerType>();
467964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  } else if (const PseudoObjectExpr *POE
468064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian               = dyn_cast<PseudoObjectExpr>(BlockExp)) {
468164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    CPT = POE->getType()->castAs<BlockPointerType>();
468264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  } else {
468364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    assert(1 && "RewriteBlockClass: Bad type");
468464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  }
468564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  assert(CPT && "RewriteBlockClass: Bad type");
468664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  const FunctionType *FT = CPT->getPointeeType()->getAs<FunctionType>();
468764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  assert(FT && "RewriteBlockClass: Bad type");
468864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  const FunctionProtoType *FTP = dyn_cast<FunctionProtoType>(FT);
468964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  // FTP will be null for closures that don't take arguments.
469064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
469164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  RecordDecl *RD = RecordDecl::Create(*Context, TTK_Struct, TUDecl,
469264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                      SourceLocation(), SourceLocation(),
469364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                      &Context->Idents.get("__block_impl"));
469464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  QualType PtrBlock = Context->getPointerType(Context->getTagDeclType(RD));
469564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
469664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  // Generate a funky cast.
469764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  SmallVector<QualType, 8> ArgTypes;
469864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
469964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  // Push the block argument type.
470064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  ArgTypes.push_back(PtrBlock);
470164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  if (FTP) {
4702651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    for (auto &I : FTP->param_types()) {
4703651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      QualType t = I;
470464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      // Make sure we convert "t (^)(...)" to "t (*)(...)".
470564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      if (!convertBlockPointerToFunctionPointer(t))
470664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        convertToUnqualifiedObjCType(t);
470764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      ArgTypes.push_back(t);
470864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    }
470964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  }
471064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  // Now do the pointer to function cast.
4711bea522ff43a3f11c7a2bc7949119dbb9fce19e39Jordan Rose  QualType PtrToFuncCastType = getSimpleFunctionType(Exp->getType(), ArgTypes);
471264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
471364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  PtrToFuncCastType = Context->getPointerType(PtrToFuncCastType);
471464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
471564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  CastExpr *BlkCast = NoTypeInfoCStyleCastExpr(Context, PtrBlock,
471664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                               CK_BitCast,
471764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                               const_cast<Expr*>(BlockExp));
471864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  // Don't forget the parens to enforce the proper binding.
471964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  ParenExpr *PE = new (Context) ParenExpr(SourceLocation(), SourceLocation(),
472064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                          BlkCast);
472164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  //PE->dump();
472264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
47236bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  FieldDecl *FD = FieldDecl::Create(*Context, nullptr, SourceLocation(),
472464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                    SourceLocation(),
472564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                    &Context->Idents.get("FuncPtr"),
472633337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar                                    Context->VoidPtrTy, nullptr,
472733337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar                                    /*BitWidth=*/nullptr, /*Mutable=*/true,
472833337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar                                    ICIS_NoInit);
472933337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  MemberExpr *ME =
473033337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar      new (Context) MemberExpr(PE, true, SourceLocation(), FD, SourceLocation(),
473133337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar                               FD->getType(), VK_LValue, OK_Ordinary);
473233337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar
473333337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  CastExpr *FunkCast = NoTypeInfoCStyleCastExpr(Context, PtrToFuncCastType,
473433337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar                                                CK_BitCast, ME);
473533337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  PE = new (Context) ParenExpr(SourceLocation(), SourceLocation(), FunkCast);
473664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
473764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  SmallVector<Expr*, 8> BlkExprs;
473864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  // Add the implicit argument.
473964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  BlkExprs.push_back(BlkCast);
474064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  // Add the user arguments.
474164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  for (CallExpr::arg_iterator I = Exp->arg_begin(),
474264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian       E = Exp->arg_end(); I != E; ++I) {
474364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    BlkExprs.push_back(*I);
474464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  }
47453b6bef9a213249c6ab6d67c07b1ac6380961be3eBenjamin Kramer  CallExpr *CE = new (Context) CallExpr(*Context, PE, BlkExprs,
474664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                        Exp->getType(), VK_RValue,
474764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                        SourceLocation());
474864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  return CE;
474964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian}
475064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
475164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian// We need to return the rewritten expression to handle cases where the
4752f4b88a45902af1802a1cb42ba48b1c474474f228John McCall// DeclRefExpr is embedded in another expression being rewritten.
475364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian// For example:
475464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian//
475564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian// int main() {
475664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian//    __block Foo *f;
475764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian//    __block int i;
475864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian//
475964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian//    void (^myblock)() = ^() {
4760f4b88a45902af1802a1cb42ba48b1c474474f228John McCall//        [f test]; // f is a DeclRefExpr embedded in a message (which is being rewritten).
476164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian//        i = 77;
476264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian//    };
476364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian//}
4764f4b88a45902af1802a1cb42ba48b1c474474f228John McCallStmt *RewriteModernObjC::RewriteBlockDeclRefExpr(DeclRefExpr *DeclRefExp) {
476564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  // Rewrite the byref variable into BYREFVAR->__forwarding->BYREFVAR
476664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  // for each DeclRefExp where BYREFVAR is name of the variable.
4767f4b88a45902af1802a1cb42ba48b1c474474f228John McCall  ValueDecl *VD = DeclRefExp->getDecl();
47680e2c34f92f00628d48968dfea096d36381f494cbStephen Hines  bool isArrow = DeclRefExp->refersToEnclosingVariableOrCapture() ||
47690e2c34f92f00628d48968dfea096d36381f494cbStephen Hines                 HasLocalVariableExternalStorage(DeclRefExp->getDecl());
47706bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
47716bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  FieldDecl *FD = FieldDecl::Create(*Context, nullptr, SourceLocation(),
477264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                    SourceLocation(),
477364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                    &Context->Idents.get("__forwarding"),
477433337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar                                    Context->VoidPtrTy, nullptr,
477533337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar                                    /*BitWidth=*/nullptr, /*Mutable=*/true,
477633337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar                                    ICIS_NoInit);
477733337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  MemberExpr *ME = new (Context)
477833337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar      MemberExpr(DeclRefExp, isArrow, SourceLocation(), FD, SourceLocation(),
477933337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar                 FD->getType(), VK_LValue, OK_Ordinary);
478033337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar
478133337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  StringRef Name = VD->getName();
478233337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  FD = FieldDecl::Create(*Context, nullptr, SourceLocation(), SourceLocation(),
478364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                         &Context->Idents.get(Name),
478433337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar                         Context->VoidPtrTy, nullptr,
478533337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar                         /*BitWidth=*/nullptr, /*Mutable=*/true,
478633337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar                         ICIS_NoInit);
478733337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  ME =
478833337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar      new (Context) MemberExpr(ME, true, SourceLocation(), FD, SourceLocation(),
478933337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar                               DeclRefExp->getType(), VK_LValue, OK_Ordinary);
479033337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar
479133337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  // Need parens to enforce precedence.
479233337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  ParenExpr *PE = new (Context) ParenExpr(DeclRefExp->getExprLoc(),
479333337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar                                          DeclRefExp->getExprLoc(),
479464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                          ME);
479564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  ReplaceStmt(DeclRefExp, PE);
479664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  return PE;
479764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian}
479864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
479964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian// Rewrites the imported local variable V with external storage
480064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian// (static, extern, etc.) as *V
480164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian//
480264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz JahanianStmt *RewriteModernObjC::RewriteLocalVariableExternalStorage(DeclRefExpr *DRE) {
480364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  ValueDecl *VD = DRE->getDecl();
480464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  if (VarDecl *Var = dyn_cast<VarDecl>(VD))
480564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    if (!ImportedLocalExternalDecls.count(Var))
480664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      return DRE;
480764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  Expr *Exp = new (Context) UnaryOperator(DRE, UO_Deref, DRE->getType(),
480864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                          VK_LValue, OK_Ordinary,
480964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                          DRE->getLocation());
481064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  // Need parens to enforce precedence.
481164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  ParenExpr *PE = new (Context) ParenExpr(SourceLocation(), SourceLocation(),
481264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                          Exp);
481364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  ReplaceStmt(DRE, PE);
481464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  return PE;
481564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian}
481664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
481764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanianvoid RewriteModernObjC::RewriteCastExpr(CStyleCastExpr *CE) {
481864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  SourceLocation LocStart = CE->getLParenLoc();
481964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  SourceLocation LocEnd = CE->getRParenLoc();
482064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
482164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  // Need to avoid trying to rewrite synthesized casts.
482264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  if (LocStart.isInvalid())
482364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    return;
482464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  // Need to avoid trying to rewrite casts contained in macros.
482564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  if (!Rewriter::isRewritable(LocStart) || !Rewriter::isRewritable(LocEnd))
482664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    return;
482764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
482864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  const char *startBuf = SM->getCharacterData(LocStart);
482964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  const char *endBuf = SM->getCharacterData(LocEnd);
483064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  QualType QT = CE->getType();
483164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  const Type* TypePtr = QT->getAs<Type>();
483264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  if (isa<TypeOfExprType>(TypePtr)) {
483364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    const TypeOfExprType *TypeOfExprTypePtr = cast<TypeOfExprType>(TypePtr);
483464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    QT = TypeOfExprTypePtr->getUnderlyingExpr()->getType();
483564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    std::string TypeAsString = "(";
483664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    RewriteBlockPointerType(TypeAsString, QT);
483764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    TypeAsString += ")";
483864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    ReplaceText(LocStart, endBuf-startBuf+1, TypeAsString);
483964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    return;
484064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  }
484164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  // advance the location to startArgList.
484264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  const char *argPtr = startBuf;
484364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
484464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  while (*argPtr++ && (argPtr < endBuf)) {
484564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    switch (*argPtr) {
484664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    case '^':
484764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      // Replace the '^' with '*'.
484864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      LocStart = LocStart.getLocWithOffset(argPtr-startBuf);
484964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      ReplaceText(LocStart, 1, "*");
485064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      break;
485164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    }
485264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  }
485364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  return;
485464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian}
485564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
4856f1ee68710ae8ca93a35ab11995ed5df321ade9ecFariborz Jahanianvoid RewriteModernObjC::RewriteImplicitCastObjCExpr(CastExpr *IC) {
4857f1ee68710ae8ca93a35ab11995ed5df321ade9ecFariborz Jahanian  CastKind CastKind = IC->getCastKind();
485843aa1c302b31492ab0abfbf656b06ca446d93b3aFariborz Jahanian  if (CastKind != CK_BlockPointerToObjCPointerCast &&
485943aa1c302b31492ab0abfbf656b06ca446d93b3aFariborz Jahanian      CastKind != CK_AnyPointerToBlockPointerCast)
486043aa1c302b31492ab0abfbf656b06ca446d93b3aFariborz Jahanian    return;
4861f1ee68710ae8ca93a35ab11995ed5df321ade9ecFariborz Jahanian
486243aa1c302b31492ab0abfbf656b06ca446d93b3aFariborz Jahanian  QualType QT = IC->getType();
486343aa1c302b31492ab0abfbf656b06ca446d93b3aFariborz Jahanian  (void)convertBlockPointerToFunctionPointer(QT);
486443aa1c302b31492ab0abfbf656b06ca446d93b3aFariborz Jahanian  std::string TypeString(QT.getAsString(Context->getPrintingPolicy()));
486543aa1c302b31492ab0abfbf656b06ca446d93b3aFariborz Jahanian  std::string Str = "(";
486643aa1c302b31492ab0abfbf656b06ca446d93b3aFariborz Jahanian  Str += TypeString;
486743aa1c302b31492ab0abfbf656b06ca446d93b3aFariborz Jahanian  Str += ")";
486843aa1c302b31492ab0abfbf656b06ca446d93b3aFariborz Jahanian  InsertText(IC->getSubExpr()->getLocStart(), &Str[0], Str.size());
486943aa1c302b31492ab0abfbf656b06ca446d93b3aFariborz Jahanian
4870f1ee68710ae8ca93a35ab11995ed5df321ade9ecFariborz Jahanian  return;
4871f1ee68710ae8ca93a35ab11995ed5df321ade9ecFariborz Jahanian}
4872f1ee68710ae8ca93a35ab11995ed5df321ade9ecFariborz Jahanian
487364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanianvoid RewriteModernObjC::RewriteBlockPointerFunctionArgs(FunctionDecl *FD) {
487464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  SourceLocation DeclLoc = FD->getLocation();
487564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  unsigned parenCount = 0;
487664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
487764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  // We have 1 or more arguments that have closure pointers.
487864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  const char *startBuf = SM->getCharacterData(DeclLoc);
487964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  const char *startArgList = strchr(startBuf, '(');
488064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
488164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  assert((*startArgList == '(') && "Rewriter fuzzy parser confused");
488264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
488364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  parenCount++;
488464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  // advance the location to startArgList.
488564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  DeclLoc = DeclLoc.getLocWithOffset(startArgList-startBuf);
488664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  assert((DeclLoc.isValid()) && "Invalid DeclLoc");
488764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
488864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  const char *argPtr = startArgList;
488964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
489064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  while (*argPtr++ && parenCount) {
489164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    switch (*argPtr) {
489264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    case '^':
489364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      // Replace the '^' with '*'.
489464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      DeclLoc = DeclLoc.getLocWithOffset(argPtr-startArgList);
489564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      ReplaceText(DeclLoc, 1, "*");
489664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      break;
489764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    case '(':
489864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      parenCount++;
489964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      break;
490064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    case ')':
490164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      parenCount--;
490264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      break;
490364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    }
490464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  }
490564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  return;
490664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian}
490764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
490864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanianbool RewriteModernObjC::PointerTypeTakesAnyBlockArguments(QualType QT) {
490964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  const FunctionProtoType *FTP;
491064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  const PointerType *PT = QT->getAs<PointerType>();
491164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  if (PT) {
491264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    FTP = PT->getPointeeType()->getAs<FunctionProtoType>();
491364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  } else {
491464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    const BlockPointerType *BPT = QT->getAs<BlockPointerType>();
491564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    assert(BPT && "BlockPointerTypeTakeAnyBlockArguments(): not a block pointer type");
491664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    FTP = BPT->getPointeeType()->getAs<FunctionProtoType>();
491764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  }
491864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  if (FTP) {
4919651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    for (const auto &I : FTP->param_types())
4920651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      if (isTopLevelBlockPointerType(I))
492164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        return true;
492264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  }
492364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  return false;
492464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian}
492564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
492664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanianbool RewriteModernObjC::PointerTypeTakesAnyObjCQualifiedType(QualType QT) {
492764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  const FunctionProtoType *FTP;
492864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  const PointerType *PT = QT->getAs<PointerType>();
492964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  if (PT) {
493064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    FTP = PT->getPointeeType()->getAs<FunctionProtoType>();
493164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  } else {
493264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    const BlockPointerType *BPT = QT->getAs<BlockPointerType>();
493364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    assert(BPT && "BlockPointerTypeTakeAnyBlockArguments(): not a block pointer type");
493464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    FTP = BPT->getPointeeType()->getAs<FunctionProtoType>();
493564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  }
493664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  if (FTP) {
4937651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    for (const auto &I : FTP->param_types()) {
4938651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      if (I->isObjCQualifiedIdType())
493964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        return true;
4940651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      if (I->isObjCObjectPointerType() &&
4941651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines          I->getPointeeType()->isObjCQualifiedInterfaceType())
494264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        return true;
494364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    }
494464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
494564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  }
494664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  return false;
494764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian}
494864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
494964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanianvoid RewriteModernObjC::GetExtentOfArgList(const char *Name, const char *&LParen,
495064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                     const char *&RParen) {
495164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  const char *argPtr = strchr(Name, '(');
495264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  assert((*argPtr == '(') && "Rewriter fuzzy parser confused");
495364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
495464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  LParen = argPtr; // output the start.
495564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  argPtr++; // skip past the left paren.
495664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  unsigned parenCount = 1;
495764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
495864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  while (*argPtr && parenCount) {
495964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    switch (*argPtr) {
496064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    case '(': parenCount++; break;
496164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    case ')': parenCount--; break;
496264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    default: break;
496364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    }
496464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    if (parenCount) argPtr++;
496564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  }
496664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  assert((*argPtr == ')') && "Rewriter fuzzy parser confused");
496764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  RParen = argPtr; // output the end
496864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian}
496964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
497064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanianvoid RewriteModernObjC::RewriteBlockPointerDecl(NamedDecl *ND) {
497164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  if (FunctionDecl *FD = dyn_cast<FunctionDecl>(ND)) {
497264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    RewriteBlockPointerFunctionArgs(FD);
497364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    return;
497464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  }
497564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  // Handle Variables and Typedefs.
497664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  SourceLocation DeclLoc = ND->getLocation();
497764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  QualType DeclT;
497864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  if (VarDecl *VD = dyn_cast<VarDecl>(ND))
497964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    DeclT = VD->getType();
498064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  else if (TypedefNameDecl *TDD = dyn_cast<TypedefNameDecl>(ND))
498164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    DeclT = TDD->getUnderlyingType();
498264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  else if (FieldDecl *FD = dyn_cast<FieldDecl>(ND))
498364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    DeclT = FD->getType();
498464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  else
498564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    llvm_unreachable("RewriteBlockPointerDecl(): Decl type not yet handled");
498664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
498764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  const char *startBuf = SM->getCharacterData(DeclLoc);
498864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  const char *endBuf = startBuf;
498964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  // scan backward (from the decl location) for the end of the previous decl.
499064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  while (*startBuf != '^' && *startBuf != ';' && startBuf != MainFileStart)
499164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    startBuf--;
499264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  SourceLocation Start = DeclLoc.getLocWithOffset(startBuf-endBuf);
499364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  std::string buf;
499464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  unsigned OrigLength=0;
499564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  // *startBuf != '^' if we are dealing with a pointer to function that
499664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  // may take block argument types (which will be handled below).
499764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  if (*startBuf == '^') {
499864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    // Replace the '^' with '*', computing a negative offset.
499964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    buf = '*';
500064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    startBuf++;
500164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    OrigLength++;
500264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  }
500364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  while (*startBuf != ')') {
500464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    buf += *startBuf;
500564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    startBuf++;
500664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    OrigLength++;
500764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  }
500864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  buf += ')';
500964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  OrigLength++;
501064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
501164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  if (PointerTypeTakesAnyBlockArguments(DeclT) ||
501264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      PointerTypeTakesAnyObjCQualifiedType(DeclT)) {
501364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    // Replace the '^' with '*' for arguments.
501464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    // Replace id<P> with id/*<>*/
501564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    DeclLoc = ND->getLocation();
501664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    startBuf = SM->getCharacterData(DeclLoc);
501764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    const char *argListBegin, *argListEnd;
501864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    GetExtentOfArgList(startBuf, argListBegin, argListEnd);
501964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    while (argListBegin < argListEnd) {
502064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      if (*argListBegin == '^')
502164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        buf += '*';
502264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      else if (*argListBegin ==  '<') {
502364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        buf += "/*";
502464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        buf += *argListBegin++;
50251ad23d62007162df82b58bca31b4aa277a5f6586Dmitri Gribenko        OrigLength++;
502664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        while (*argListBegin != '>') {
502764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian          buf += *argListBegin++;
502864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian          OrigLength++;
502964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        }
503064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        buf += *argListBegin;
503164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        buf += "*/";
503264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      }
503364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      else
503464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        buf += *argListBegin;
503564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      argListBegin++;
503664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      OrigLength++;
503764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    }
503864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    buf += ')';
503964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    OrigLength++;
504064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  }
504164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  ReplaceText(Start, OrigLength, buf);
504264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
504364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  return;
504464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian}
504564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
504664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
504764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian/// SynthesizeByrefCopyDestroyHelper - This routine synthesizes:
504864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian/// void __Block_byref_id_object_copy(struct Block_byref_id_object *dst,
504964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian///                    struct Block_byref_id_object *src) {
505064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian///  _Block_object_assign (&_dest->object, _src->object,
505164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian///                        BLOCK_BYREF_CALLER | BLOCK_FIELD_IS_OBJECT
505264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian///                        [|BLOCK_FIELD_IS_WEAK]) // object
505364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian///  _Block_object_assign(&_dest->object, _src->object,
505464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian///                       BLOCK_BYREF_CALLER | BLOCK_FIELD_IS_BLOCK
505564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian///                       [|BLOCK_FIELD_IS_WEAK]) // block
505664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian/// }
505764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian/// And:
505864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian/// void __Block_byref_id_object_dispose(struct Block_byref_id_object *_src) {
505964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian///  _Block_object_dispose(_src->object,
506064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian///                        BLOCK_BYREF_CALLER | BLOCK_FIELD_IS_OBJECT
506164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian///                        [|BLOCK_FIELD_IS_WEAK]) // object
506264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian///  _Block_object_dispose(_src->object,
506364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian///                         BLOCK_BYREF_CALLER | BLOCK_FIELD_IS_BLOCK
506464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian///                         [|BLOCK_FIELD_IS_WEAK]) // block
506564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian/// }
506664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
506764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanianstd::string RewriteModernObjC::SynthesizeByrefCopyDestroyHelper(VarDecl *VD,
506864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                                          int flag) {
506964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  std::string S;
507064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  if (CopyDestroyCache.count(flag))
507164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    return S;
507264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  CopyDestroyCache.insert(flag);
507364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  S = "static void __Block_byref_id_object_copy_";
507464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  S += utostr(flag);
507564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  S += "(void *dst, void *src) {\n";
507664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
507764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  // offset into the object pointer is computed as:
507864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  // void * + void* + int + int + void* + void *
507964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  unsigned IntSize =
508064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  static_cast<unsigned>(Context->getTypeSize(Context->IntTy));
508164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  unsigned VoidPtrSize =
508264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  static_cast<unsigned>(Context->getTypeSize(Context->VoidPtrTy));
508364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
508464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  unsigned offset = (VoidPtrSize*4 + IntSize + IntSize)/Context->getCharWidth();
508564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  S += " _Block_object_assign((char*)dst + ";
508664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  S += utostr(offset);
508764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  S += ", *(void * *) ((char*)src + ";
508864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  S += utostr(offset);
508964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  S += "), ";
509064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  S += utostr(flag);
509164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  S += ");\n}\n";
509264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
509364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  S += "static void __Block_byref_id_object_dispose_";
509464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  S += utostr(flag);
509564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  S += "(void *src) {\n";
509664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  S += " _Block_object_dispose(*(void * *) ((char*)src + ";
509764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  S += utostr(offset);
509864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  S += "), ";
509964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  S += utostr(flag);
510064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  S += ");\n}\n";
510164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  return S;
510264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian}
510364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
510464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian/// RewriteByRefVar - For each __block typex ND variable this routine transforms
510564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian/// the declaration into:
510664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian/// struct __Block_byref_ND {
510764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian/// void *__isa;                  // NULL for everything except __weak pointers
510864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian/// struct __Block_byref_ND *__forwarding;
510964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian/// int32_t __flags;
511064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian/// int32_t __size;
511164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian/// void *__Block_byref_id_object_copy; // If variable is __block ObjC object
511264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian/// void *__Block_byref_id_object_dispose; // If variable is __block ObjC object
511364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian/// typex ND;
511464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian/// };
511564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian///
511664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian/// It then replaces declaration of ND variable with:
511764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian/// struct __Block_byref_ND ND = {__isa=0B, __forwarding=&ND, __flags=some_flag,
511864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian///                               __size=sizeof(struct __Block_byref_ND),
511964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian///                               ND=initializer-if-any};
512064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian///
512164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian///
51224fe261cb0a6420b103335acc1f6bcb7b72188184Fariborz Jahanianvoid RewriteModernObjC::RewriteByRefVar(VarDecl *ND, bool firstDecl,
51234fe261cb0a6420b103335acc1f6bcb7b72188184Fariborz Jahanian                                        bool lastDecl) {
512464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  int flag = 0;
512564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  int isa = 0;
512664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  SourceLocation DeclLoc = ND->getTypeSpecStartLoc();
512764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  if (DeclLoc.isInvalid())
512864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    // If type location is missing, it is because of missing type (a warning).
512964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    // Use variable's location which is good for this case.
513064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    DeclLoc = ND->getLocation();
513164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  const char *startBuf = SM->getCharacterData(DeclLoc);
513264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  SourceLocation X = ND->getLocEnd();
513364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  X = SM->getExpansionLoc(X);
513464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  const char *endBuf = SM->getCharacterData(X);
513564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  std::string Name(ND->getNameAsString());
513664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  std::string ByrefType;
513764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  RewriteByRefString(ByrefType, Name, ND, true);
513864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  ByrefType += " {\n";
513964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  ByrefType += "  void *__isa;\n";
514064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  RewriteByRefString(ByrefType, Name, ND);
514164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  ByrefType += " *__forwarding;\n";
514264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  ByrefType += " int __flags;\n";
514364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  ByrefType += " int __size;\n";
514464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  // Add void *__Block_byref_id_object_copy;
514564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  // void *__Block_byref_id_object_dispose; if needed.
514664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  QualType Ty = ND->getType();
5147b15c8984ea300624fbbde385d3907667ce1043faFariborz Jahanian  bool HasCopyAndDispose = Context->BlockRequiresCopying(Ty, ND);
514864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  if (HasCopyAndDispose) {
514964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    ByrefType += " void (*__Block_byref_id_object_copy)(void*, void*);\n";
515064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    ByrefType += " void (*__Block_byref_id_object_dispose)(void*);\n";
515164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  }
515264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
515364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  QualType T = Ty;
515464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  (void)convertBlockPointerToFunctionPointer(T);
515564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  T.getAsStringInternal(Name, Context->getPrintingPolicy());
515664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
515764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  ByrefType += " " + Name + ";\n";
515864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  ByrefType += "};\n";
515964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  // Insert this type in global scope. It is needed by helper function.
516064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  SourceLocation FunLocStart;
516164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  if (CurFunctionDef)
5162b75f8de7ddc4f9365dad90ef21a463e94dcdcbdaFariborz Jahanian     FunLocStart = getFunctionSourceLocation(*this, CurFunctionDef);
516364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  else {
516464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    assert(CurMethodDef && "RewriteByRefVar - CurMethodDef is null");
516564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    FunLocStart = CurMethodDef->getLocStart();
516664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  }
516764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  InsertText(FunLocStart, ByrefType);
51688247c4ed71c126b274d3123f7a97d0770deb9f4eFariborz Jahanian
516964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  if (Ty.isObjCGCWeak()) {
517064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    flag |= BLOCK_FIELD_IS_WEAK;
517164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    isa = 1;
517264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  }
517364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  if (HasCopyAndDispose) {
517464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    flag = BLOCK_BYREF_CALLER;
517564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    QualType Ty = ND->getType();
517664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    // FIXME. Handle __weak variable (BLOCK_FIELD_IS_WEAK) as well.
517764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    if (Ty->isBlockPointerType())
517864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      flag |= BLOCK_FIELD_IS_BLOCK;
517964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    else
518064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      flag |= BLOCK_FIELD_IS_OBJECT;
518164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    std::string HF = SynthesizeByrefCopyDestroyHelper(ND, flag);
518264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    if (!HF.empty())
518331c4a4b0171aac01d2a6aedb4960ade7ee7d998aFariborz Jahanian      Preamble += HF;
518464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  }
518564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
518664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  // struct __Block_byref_ND ND =
518764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  // {0, &ND, some_flag, __size=sizeof(struct __Block_byref_ND),
518864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  //  initializer-if-any};
51896bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  bool hasInit = (ND->getInit() != nullptr);
5190104dbf982582f16888fb15f9342fce9748af48c5Fariborz Jahanian  // FIXME. rewriter does not support __block c++ objects which
5191104dbf982582f16888fb15f9342fce9748af48c5Fariborz Jahanian  // require construction.
519265a7c685b78c18dc158399d2cc688a611d5e2553Fariborz Jahanian  if (hasInit)
519365a7c685b78c18dc158399d2cc688a611d5e2553Fariborz Jahanian    if (CXXConstructExpr *CExp = dyn_cast<CXXConstructExpr>(ND->getInit())) {
519465a7c685b78c18dc158399d2cc688a611d5e2553Fariborz Jahanian      CXXConstructorDecl *CXXDecl = CExp->getConstructor();
519565a7c685b78c18dc158399d2cc688a611d5e2553Fariborz Jahanian      if (CXXDecl && CXXDecl->isDefaultConstructor())
519665a7c685b78c18dc158399d2cc688a611d5e2553Fariborz Jahanian        hasInit = false;
519765a7c685b78c18dc158399d2cc688a611d5e2553Fariborz Jahanian    }
519865a7c685b78c18dc158399d2cc688a611d5e2553Fariborz Jahanian
519964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  unsigned flags = 0;
520064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  if (HasCopyAndDispose)
520164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    flags |= BLOCK_HAS_COPY_DISPOSE;
520264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  Name = ND->getNameAsString();
520364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  ByrefType.clear();
520464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  RewriteByRefString(ByrefType, Name, ND);
520564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  std::string ForwardingCastType("(");
520664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  ForwardingCastType += ByrefType + " *)";
52078247c4ed71c126b274d3123f7a97d0770deb9f4eFariborz Jahanian  ByrefType += " " + Name + " = {(void*)";
52088247c4ed71c126b274d3123f7a97d0770deb9f4eFariborz Jahanian  ByrefType += utostr(isa);
52098247c4ed71c126b274d3123f7a97d0770deb9f4eFariborz Jahanian  ByrefType += "," +  ForwardingCastType + "&" + Name + ", ";
52108247c4ed71c126b274d3123f7a97d0770deb9f4eFariborz Jahanian  ByrefType += utostr(flags);
52118247c4ed71c126b274d3123f7a97d0770deb9f4eFariborz Jahanian  ByrefType += ", ";
52128247c4ed71c126b274d3123f7a97d0770deb9f4eFariborz Jahanian  ByrefType += "sizeof(";
52138247c4ed71c126b274d3123f7a97d0770deb9f4eFariborz Jahanian  RewriteByRefString(ByrefType, Name, ND);
52148247c4ed71c126b274d3123f7a97d0770deb9f4eFariborz Jahanian  ByrefType += ")";
52158247c4ed71c126b274d3123f7a97d0770deb9f4eFariborz Jahanian  if (HasCopyAndDispose) {
52168247c4ed71c126b274d3123f7a97d0770deb9f4eFariborz Jahanian    ByrefType += ", __Block_byref_id_object_copy_";
52178247c4ed71c126b274d3123f7a97d0770deb9f4eFariborz Jahanian    ByrefType += utostr(flag);
52188247c4ed71c126b274d3123f7a97d0770deb9f4eFariborz Jahanian    ByrefType += ", __Block_byref_id_object_dispose_";
52198247c4ed71c126b274d3123f7a97d0770deb9f4eFariborz Jahanian    ByrefType += utostr(flag);
52208247c4ed71c126b274d3123f7a97d0770deb9f4eFariborz Jahanian  }
52218247c4ed71c126b274d3123f7a97d0770deb9f4eFariborz Jahanian
52224fe261cb0a6420b103335acc1f6bcb7b72188184Fariborz Jahanian  if (!firstDecl) {
52234fe261cb0a6420b103335acc1f6bcb7b72188184Fariborz Jahanian    // In multiple __block declarations, and for all but 1st declaration,
52244fe261cb0a6420b103335acc1f6bcb7b72188184Fariborz Jahanian    // find location of the separating comma. This would be start location
52254fe261cb0a6420b103335acc1f6bcb7b72188184Fariborz Jahanian    // where new text is to be inserted.
52264fe261cb0a6420b103335acc1f6bcb7b72188184Fariborz Jahanian    DeclLoc = ND->getLocation();
52274fe261cb0a6420b103335acc1f6bcb7b72188184Fariborz Jahanian    const char *startDeclBuf = SM->getCharacterData(DeclLoc);
52284fe261cb0a6420b103335acc1f6bcb7b72188184Fariborz Jahanian    const char *commaBuf = startDeclBuf;
52294fe261cb0a6420b103335acc1f6bcb7b72188184Fariborz Jahanian    while (*commaBuf != ',')
52304fe261cb0a6420b103335acc1f6bcb7b72188184Fariborz Jahanian      commaBuf--;
52314fe261cb0a6420b103335acc1f6bcb7b72188184Fariborz Jahanian    assert((*commaBuf == ',') && "RewriteByRefVar: can't find ','");
52324fe261cb0a6420b103335acc1f6bcb7b72188184Fariborz Jahanian    DeclLoc = DeclLoc.getLocWithOffset(commaBuf - startDeclBuf);
52334fe261cb0a6420b103335acc1f6bcb7b72188184Fariborz Jahanian    startBuf = commaBuf;
52344fe261cb0a6420b103335acc1f6bcb7b72188184Fariborz Jahanian  }
52354fe261cb0a6420b103335acc1f6bcb7b72188184Fariborz Jahanian
523664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  if (!hasInit) {
523764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    ByrefType += "};\n";
523864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    unsigned nameSize = Name.size();
523964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    // for block or function pointer declaration. Name is aleady
524064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    // part of the declaration.
524164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    if (Ty->isBlockPointerType() || Ty->isFunctionPointerType())
524264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      nameSize = 1;
524364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    ReplaceText(DeclLoc, endBuf-startBuf+nameSize, ByrefType);
524464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  }
524564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  else {
52468247c4ed71c126b274d3123f7a97d0770deb9f4eFariborz Jahanian    ByrefType += ", ";
524764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    SourceLocation startLoc;
524864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    Expr *E = ND->getInit();
524964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    if (const CStyleCastExpr *ECE = dyn_cast<CStyleCastExpr>(E))
525064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      startLoc = ECE->getLParenLoc();
525164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    else
525264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      startLoc = E->getLocStart();
525364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    startLoc = SM->getExpansionLoc(startLoc);
525464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    endBuf = SM->getCharacterData(startLoc);
525564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    ReplaceText(DeclLoc, endBuf-startBuf, ByrefType);
525664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
52574fe261cb0a6420b103335acc1f6bcb7b72188184Fariborz Jahanian    const char separator = lastDecl ? ';' : ',';
52584fe261cb0a6420b103335acc1f6bcb7b72188184Fariborz Jahanian    const char *startInitializerBuf = SM->getCharacterData(startLoc);
52594fe261cb0a6420b103335acc1f6bcb7b72188184Fariborz Jahanian    const char *separatorBuf = strchr(startInitializerBuf, separator);
52604fe261cb0a6420b103335acc1f6bcb7b72188184Fariborz Jahanian    assert((*separatorBuf == separator) &&
52614fe261cb0a6420b103335acc1f6bcb7b72188184Fariborz Jahanian           "RewriteByRefVar: can't find ';' or ','");
52624fe261cb0a6420b103335acc1f6bcb7b72188184Fariborz Jahanian    SourceLocation separatorLoc =
52634fe261cb0a6420b103335acc1f6bcb7b72188184Fariborz Jahanian      startLoc.getLocWithOffset(separatorBuf-startInitializerBuf);
52644fe261cb0a6420b103335acc1f6bcb7b72188184Fariborz Jahanian
52654fe261cb0a6420b103335acc1f6bcb7b72188184Fariborz Jahanian    InsertText(separatorLoc, lastDecl ? "}" : "};\n");
526664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  }
526764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  return;
526864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian}
526964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
527064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanianvoid RewriteModernObjC::CollectBlockDeclRefInfo(BlockExpr *Exp) {
527164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  // Add initializers for any closure decl refs.
527264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  GetBlockDeclRefExprs(Exp->getBody());
527364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  if (BlockDeclRefs.size()) {
527464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    // Unique all "by copy" declarations.
527564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    for (unsigned i = 0; i < BlockDeclRefs.size(); i++)
5276f4b88a45902af1802a1cb42ba48b1c474474f228John McCall      if (!BlockDeclRefs[i]->getDecl()->hasAttr<BlocksAttr>()) {
527764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        if (!BlockByCopyDeclsPtrSet.count(BlockDeclRefs[i]->getDecl())) {
527864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian          BlockByCopyDeclsPtrSet.insert(BlockDeclRefs[i]->getDecl());
527964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian          BlockByCopyDecls.push_back(BlockDeclRefs[i]->getDecl());
528064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        }
528164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      }
528264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    // Unique all "by ref" declarations.
528364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    for (unsigned i = 0; i < BlockDeclRefs.size(); i++)
5284f4b88a45902af1802a1cb42ba48b1c474474f228John McCall      if (BlockDeclRefs[i]->getDecl()->hasAttr<BlocksAttr>()) {
528564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        if (!BlockByRefDeclsPtrSet.count(BlockDeclRefs[i]->getDecl())) {
528664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian          BlockByRefDeclsPtrSet.insert(BlockDeclRefs[i]->getDecl());
528764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian          BlockByRefDecls.push_back(BlockDeclRefs[i]->getDecl());
528864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        }
528964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      }
529064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    // Find any imported blocks...they will need special attention.
529164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    for (unsigned i = 0; i < BlockDeclRefs.size(); i++)
5292f4b88a45902af1802a1cb42ba48b1c474474f228John McCall      if (BlockDeclRefs[i]->getDecl()->hasAttr<BlocksAttr>() ||
529364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian          BlockDeclRefs[i]->getType()->isObjCObjectPointerType() ||
529464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian          BlockDeclRefs[i]->getType()->isBlockPointerType())
529564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        ImportedBlockDecls.insert(BlockDeclRefs[i]->getDecl());
529664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  }
529764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian}
529864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
529964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz JahanianFunctionDecl *RewriteModernObjC::SynthBlockInitFunctionDecl(StringRef name) {
530064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  IdentifierInfo *ID = &Context->Idents.get(name);
530164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  QualType FType = Context->getFunctionNoProtoType(Context->VoidPtrTy);
530264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  return FunctionDecl::Create(*Context, TUDecl, SourceLocation(),
53036bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines                              SourceLocation(), ID, FType, nullptr, SC_Extern,
5304d2615cc53b916e8aae45783ca7113b93de515ce3Rafael Espindola                              false, false);
530564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian}
530664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
530764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz JahanianStmt *RewriteModernObjC::SynthBlockInitExpr(BlockExpr *Exp,
53086b9240e058bf3451685df73fc8ce181b3046e92bCraig Topper                     const SmallVectorImpl<DeclRefExpr *> &InnerBlockDeclRefs) {
5309d13c2c291f9fec2ed0e12a65f1638710ca979bb0Fariborz Jahanian
531064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  const BlockDecl *block = Exp->getBlockDecl();
5311d13c2c291f9fec2ed0e12a65f1638710ca979bb0Fariborz Jahanian
531264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  Blocks.push_back(Exp);
531364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
531464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  CollectBlockDeclRefInfo(Exp);
531564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
531664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  // Add inner imported variables now used in current block.
531764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian int countOfInnerDecls = 0;
531864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  if (!InnerBlockDeclRefs.empty()) {
531964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    for (unsigned i = 0; i < InnerBlockDeclRefs.size(); i++) {
5320f4b88a45902af1802a1cb42ba48b1c474474f228John McCall      DeclRefExpr *Exp = InnerBlockDeclRefs[i];
532164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      ValueDecl *VD = Exp->getDecl();
5322f4b88a45902af1802a1cb42ba48b1c474474f228John McCall      if (!VD->hasAttr<BlocksAttr>() && !BlockByCopyDeclsPtrSet.count(VD)) {
532364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      // We need to save the copied-in variables in nested
532464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      // blocks because it is needed at the end for some of the API generations.
532564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      // See SynthesizeBlockLiterals routine.
532664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        InnerDeclRefs.push_back(Exp); countOfInnerDecls++;
532764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        BlockDeclRefs.push_back(Exp);
532864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        BlockByCopyDeclsPtrSet.insert(VD);
532964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        BlockByCopyDecls.push_back(VD);
533064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      }
5331f4b88a45902af1802a1cb42ba48b1c474474f228John McCall      if (VD->hasAttr<BlocksAttr>() && !BlockByRefDeclsPtrSet.count(VD)) {
533264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        InnerDeclRefs.push_back(Exp); countOfInnerDecls++;
533364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        BlockDeclRefs.push_back(Exp);
533464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        BlockByRefDeclsPtrSet.insert(VD);
533564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        BlockByRefDecls.push_back(VD);
533664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      }
533764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    }
533864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    // Find any imported blocks...they will need special attention.
533964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    for (unsigned i = 0; i < InnerBlockDeclRefs.size(); i++)
5340f4b88a45902af1802a1cb42ba48b1c474474f228John McCall      if (InnerBlockDeclRefs[i]->getDecl()->hasAttr<BlocksAttr>() ||
534164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian          InnerBlockDeclRefs[i]->getType()->isObjCObjectPointerType() ||
534264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian          InnerBlockDeclRefs[i]->getType()->isBlockPointerType())
534364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        ImportedBlockDecls.insert(InnerBlockDeclRefs[i]->getDecl());
534464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  }
534564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  InnerDeclRefsCount.push_back(countOfInnerDecls);
534664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
534764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  std::string FuncName;
534864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
534964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  if (CurFunctionDef)
535064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    FuncName = CurFunctionDef->getNameAsString();
535164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  else if (CurMethodDef)
535264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    BuildUniqueMethodName(FuncName, CurMethodDef);
535364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  else if (GlobalVarDecl)
535464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    FuncName = std::string(GlobalVarDecl->getNameAsString());
535564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
5356df474ec64a86bb88c7543875634d3fc628105bb5Fariborz Jahanian  bool GlobalBlockExpr =
5357df474ec64a86bb88c7543875634d3fc628105bb5Fariborz Jahanian    block->getDeclContext()->getRedeclContext()->isFileContext();
5358df474ec64a86bb88c7543875634d3fc628105bb5Fariborz Jahanian
5359df474ec64a86bb88c7543875634d3fc628105bb5Fariborz Jahanian  if (GlobalBlockExpr && !GlobalVarDecl) {
5360df474ec64a86bb88c7543875634d3fc628105bb5Fariborz Jahanian    Diags.Report(block->getLocation(), GlobalBlockRewriteFailedDiag);
5361df474ec64a86bb88c7543875634d3fc628105bb5Fariborz Jahanian    GlobalBlockExpr = false;
5362df474ec64a86bb88c7543875634d3fc628105bb5Fariborz Jahanian  }
5363df474ec64a86bb88c7543875634d3fc628105bb5Fariborz Jahanian
536464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  std::string BlockNumber = utostr(Blocks.size()-1);
536564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
536664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  std::string Func = "__" + FuncName + "_block_func_" + BlockNumber;
536764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
536864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  // Get a pointer to the function type so we can cast appropriately.
536964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  QualType BFT = convertFunctionTypeOfBlocks(Exp->getFunctionType());
537064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  QualType FType = Context->getPointerType(BFT);
537164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
537264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  FunctionDecl *FD;
537364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  Expr *NewRep;
537464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
5375e575359c34a9248c55ec0c03a8fc945f1ee4cb01Benjamin Kramer  // Simulate a constructor call...
5376df474ec64a86bb88c7543875634d3fc628105bb5Fariborz Jahanian  std::string Tag;
5377df474ec64a86bb88c7543875634d3fc628105bb5Fariborz Jahanian
5378df474ec64a86bb88c7543875634d3fc628105bb5Fariborz Jahanian  if (GlobalBlockExpr)
5379df474ec64a86bb88c7543875634d3fc628105bb5Fariborz Jahanian    Tag = "__global_";
5380df474ec64a86bb88c7543875634d3fc628105bb5Fariborz Jahanian  else
5381df474ec64a86bb88c7543875634d3fc628105bb5Fariborz Jahanian    Tag = "__";
5382df474ec64a86bb88c7543875634d3fc628105bb5Fariborz Jahanian  Tag += FuncName + "_block_impl_" + BlockNumber;
5383df474ec64a86bb88c7543875634d3fc628105bb5Fariborz Jahanian
538464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  FD = SynthBlockInitFunctionDecl(Tag);
5385f4b88a45902af1802a1cb42ba48b1c474474f228John McCall  DeclRefExpr *DRE = new (Context) DeclRefExpr(FD, false, FType, VK_RValue,
538664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                               SourceLocation());
538764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
538864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  SmallVector<Expr*, 4> InitExprs;
538964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
539064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  // Initialize the block function.
539164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  FD = SynthBlockInitFunctionDecl(Func);
5392f4b88a45902af1802a1cb42ba48b1c474474f228John McCall  DeclRefExpr *Arg = new (Context) DeclRefExpr(FD, false, FD->getType(),
5393f4b88a45902af1802a1cb42ba48b1c474474f228John McCall                                               VK_LValue, SourceLocation());
539464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  CastExpr *castExpr = NoTypeInfoCStyleCastExpr(Context, Context->VoidPtrTy,
539564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                                CK_BitCast, Arg);
539664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  InitExprs.push_back(castExpr);
539764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
539864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  // Initialize the block descriptor.
539964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  std::string DescData = "__" + FuncName + "_block_desc_" + BlockNumber + "_DATA";
540064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
540164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  VarDecl *NewVD = VarDecl::Create(*Context, TUDecl,
540264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                   SourceLocation(), SourceLocation(),
540364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                   &Context->Idents.get(DescData.c_str()),
54046bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines                                   Context->VoidPtrTy, nullptr,
5405d2615cc53b916e8aae45783ca7113b93de515ce3Rafael Espindola                                   SC_Static);
540664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  UnaryOperator *DescRefExpr =
5407f4b88a45902af1802a1cb42ba48b1c474474f228John McCall    new (Context) UnaryOperator(new (Context) DeclRefExpr(NewVD, false,
540864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                                          Context->VoidPtrTy,
540964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                                          VK_LValue,
541064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                                          SourceLocation()),
541164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                UO_AddrOf,
541264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                Context->getPointerType(Context->VoidPtrTy),
541364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                VK_RValue, OK_Ordinary,
541464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                SourceLocation());
541564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  InitExprs.push_back(DescRefExpr);
541664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
541764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  // Add initializers for any closure decl refs.
541864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  if (BlockDeclRefs.size()) {
541964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    Expr *Exp;
542064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    // Output all "by copy" declarations.
542109d19efaa147762f84aed55efa7930bb3616a4e5Craig Topper    for (SmallVectorImpl<ValueDecl *>::iterator I = BlockByCopyDecls.begin(),
542264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian         E = BlockByCopyDecls.end(); I != E; ++I) {
542364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      if (isObjCType((*I)->getType())) {
542464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        // FIXME: Conform to ABI ([[obj retain] autorelease]).
542564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        FD = SynthBlockInitFunctionDecl((*I)->getName());
5426f4b88a45902af1802a1cb42ba48b1c474474f228John McCall        Exp = new (Context) DeclRefExpr(FD, false, FD->getType(),
5427f4b88a45902af1802a1cb42ba48b1c474474f228John McCall                                        VK_LValue, SourceLocation());
542864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        if (HasLocalVariableExternalStorage(*I)) {
542964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian          QualType QT = (*I)->getType();
543064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian          QT = Context->getPointerType(QT);
543164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian          Exp = new (Context) UnaryOperator(Exp, UO_AddrOf, QT, VK_RValue,
543264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                            OK_Ordinary, SourceLocation());
543364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        }
543464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      } else if (isTopLevelBlockPointerType((*I)->getType())) {
543564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        FD = SynthBlockInitFunctionDecl((*I)->getName());
5436f4b88a45902af1802a1cb42ba48b1c474474f228John McCall        Arg = new (Context) DeclRefExpr(FD, false, FD->getType(),
5437f4b88a45902af1802a1cb42ba48b1c474474f228John McCall                                        VK_LValue, SourceLocation());
543864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        Exp = NoTypeInfoCStyleCastExpr(Context, Context->VoidPtrTy,
543964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                       CK_BitCast, Arg);
544064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      } else {
544164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        FD = SynthBlockInitFunctionDecl((*I)->getName());
5442f4b88a45902af1802a1cb42ba48b1c474474f228John McCall        Exp = new (Context) DeclRefExpr(FD, false, FD->getType(),
5443f4b88a45902af1802a1cb42ba48b1c474474f228John McCall                                        VK_LValue, SourceLocation());
544464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        if (HasLocalVariableExternalStorage(*I)) {
544564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian          QualType QT = (*I)->getType();
544664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian          QT = Context->getPointerType(QT);
544764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian          Exp = new (Context) UnaryOperator(Exp, UO_AddrOf, QT, VK_RValue,
544864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                            OK_Ordinary, SourceLocation());
544964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        }
545064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
545164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      }
545264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      InitExprs.push_back(Exp);
545364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    }
545464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    // Output all "by ref" declarations.
545509d19efaa147762f84aed55efa7930bb3616a4e5Craig Topper    for (SmallVectorImpl<ValueDecl *>::iterator I = BlockByRefDecls.begin(),
545664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian         E = BlockByRefDecls.end(); I != E; ++I) {
545764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      ValueDecl *ND = (*I);
545864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      std::string Name(ND->getNameAsString());
545964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      std::string RecName;
546064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      RewriteByRefString(RecName, Name, ND, true);
546164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      IdentifierInfo *II = &Context->Idents.get(RecName.c_str()
546264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                                + sizeof("struct"));
546364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      RecordDecl *RD = RecordDecl::Create(*Context, TTK_Struct, TUDecl,
546464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                          SourceLocation(), SourceLocation(),
546564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                          II);
546664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      assert(RD && "SynthBlockInitExpr(): Can't find RecordDecl");
546764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      QualType castT = Context->getPointerType(Context->getTagDeclType(RD));
546864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
546964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      FD = SynthBlockInitFunctionDecl((*I)->getName());
5470f4b88a45902af1802a1cb42ba48b1c474474f228John McCall      Exp = new (Context) DeclRefExpr(FD, false, FD->getType(), VK_LValue,
547164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                      SourceLocation());
547264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      bool isNestedCapturedVar = false;
547364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      if (block)
5474651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines        for (const auto &CI : block->captures()) {
5475651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines          const VarDecl *variable = CI.getVariable();
5476651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines          if (variable == ND && CI.isNested()) {
5477651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines            assert (CI.isByRef() &&
547864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                    "SynthBlockInitExpr - captured block variable is not byref");
547964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian            isNestedCapturedVar = true;
548064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian            break;
548164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian          }
548264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        }
548364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      // captured nested byref variable has its address passed. Do not take
548464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      // its address again.
548564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      if (!isNestedCapturedVar)
548664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian          Exp = new (Context) UnaryOperator(Exp, UO_AddrOf,
548764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                     Context->getPointerType(Exp->getType()),
548864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                     VK_RValue, OK_Ordinary, SourceLocation());
548964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      Exp = NoTypeInfoCStyleCastExpr(Context, castT, CK_BitCast, Exp);
549064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      InitExprs.push_back(Exp);
549164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    }
549264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  }
549364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  if (ImportedBlockDecls.size()) {
549464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    // generate BLOCK_HAS_COPY_DISPOSE(have helper funcs) | BLOCK_HAS_DESCRIPTOR
549564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    int flag = (BLOCK_HAS_COPY_DISPOSE | BLOCK_HAS_DESCRIPTOR);
549664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    unsigned IntSize =
549764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      static_cast<unsigned>(Context->getTypeSize(Context->IntTy));
549864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    Expr *FlagExp = IntegerLiteral::Create(*Context, llvm::APInt(IntSize, flag),
549964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                           Context->IntTy, SourceLocation());
550064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    InitExprs.push_back(FlagExp);
550164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  }
55023b6bef9a213249c6ab6d67c07b1ac6380961be3eBenjamin Kramer  NewRep = new (Context) CallExpr(*Context, DRE, InitExprs,
550364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                  FType, VK_LValue, SourceLocation());
5504df474ec64a86bb88c7543875634d3fc628105bb5Fariborz Jahanian
5505df474ec64a86bb88c7543875634d3fc628105bb5Fariborz Jahanian  if (GlobalBlockExpr) {
55066bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    assert (!GlobalConstructionExp &&
5507df474ec64a86bb88c7543875634d3fc628105bb5Fariborz Jahanian            "SynthBlockInitExpr - GlobalConstructionExp must be null");
5508df474ec64a86bb88c7543875634d3fc628105bb5Fariborz Jahanian    GlobalConstructionExp = NewRep;
5509df474ec64a86bb88c7543875634d3fc628105bb5Fariborz Jahanian    NewRep = DRE;
5510df474ec64a86bb88c7543875634d3fc628105bb5Fariborz Jahanian  }
5511df474ec64a86bb88c7543875634d3fc628105bb5Fariborz Jahanian
551264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  NewRep = new (Context) UnaryOperator(NewRep, UO_AddrOf,
551364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                             Context->getPointerType(NewRep->getType()),
551464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                             VK_RValue, OK_Ordinary, SourceLocation());
551564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  NewRep = NoTypeInfoCStyleCastExpr(Context, FType, CK_BitCast,
551664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                    NewRep);
5517176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  // Put Paren around the call.
5518176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  NewRep = new (Context) ParenExpr(SourceLocation(), SourceLocation(),
5519176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines                                   NewRep);
5520176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines
552164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  BlockDeclRefs.clear();
552264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  BlockByRefDecls.clear();
552364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  BlockByRefDeclsPtrSet.clear();
552464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  BlockByCopyDecls.clear();
552564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  BlockByCopyDeclsPtrSet.clear();
552664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  ImportedBlockDecls.clear();
552764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  return NewRep;
552864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian}
552964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
553064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanianbool RewriteModernObjC::IsDeclStmtInForeachHeader(DeclStmt *DS) {
553164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  if (const ObjCForCollectionStmt * CS =
553264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      dyn_cast<ObjCForCollectionStmt>(Stmts.back()))
553364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        return CS->getElement() == DS;
553464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  return false;
553564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian}
553664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
553764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian//===----------------------------------------------------------------------===//
553864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian// Function Body / Expression rewriting
553964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian//===----------------------------------------------------------------------===//
554064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
554164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz JahanianStmt *RewriteModernObjC::RewriteFunctionBodyOrGlobalInitializer(Stmt *S) {
554264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  if (isa<SwitchStmt>(S) || isa<WhileStmt>(S) ||
554364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      isa<DoStmt>(S) || isa<ForStmt>(S))
554464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    Stmts.push_back(S);
554564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  else if (isa<ObjCForCollectionStmt>(S)) {
554664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    Stmts.push_back(S);
554764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    ObjCBcLabelNo.push_back(++BcLabelCount);
554864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  }
554964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
555064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  // Pseudo-object operations and ivar references need special
555164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  // treatment because we're going to recursively rewrite them.
555264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  if (PseudoObjectExpr *PseudoOp = dyn_cast<PseudoObjectExpr>(S)) {
555364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    if (isa<BinaryOperator>(PseudoOp->getSyntacticForm())) {
555464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      return RewritePropertyOrImplicitSetter(PseudoOp);
555564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    } else {
555664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      return RewritePropertyOrImplicitGetter(PseudoOp);
555764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    }
555864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  } else if (ObjCIvarRefExpr *IvarRefExpr = dyn_cast<ObjCIvarRefExpr>(S)) {
555964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    return RewriteObjCIvarRefExpr(IvarRefExpr);
556064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  }
55619ffd1aea980a0bb1f577f3069c63f741b72d8f80Fariborz Jahanian  else if (isa<OpaqueValueExpr>(S))
55629ffd1aea980a0bb1f577f3069c63f741b72d8f80Fariborz Jahanian    S = cast<OpaqueValueExpr>(S)->getSourceExpr();
556364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
556464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  SourceRange OrigStmtRange = S->getSourceRange();
556564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
556664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  // Perform a bottom up rewrite of all children.
556764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  for (Stmt::child_range CI = S->children(); CI; ++CI)
556864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    if (*CI) {
556964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      Stmt *childStmt = (*CI);
557064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      Stmt *newStmt = RewriteFunctionBodyOrGlobalInitializer(childStmt);
557164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      if (newStmt) {
557264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        *CI = newStmt;
557364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      }
557464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    }
557564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
557664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  if (BlockExpr *BE = dyn_cast<BlockExpr>(S)) {
5577f4b88a45902af1802a1cb42ba48b1c474474f228John McCall    SmallVector<DeclRefExpr *, 8> InnerBlockDeclRefs;
557864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    llvm::SmallPtrSet<const DeclContext *, 8> InnerContexts;
557964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    InnerContexts.insert(BE->getBlockDecl());
558064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    ImportedLocalExternalDecls.clear();
558164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    GetInnerBlockDeclRefExprs(BE->getBody(),
558264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                              InnerBlockDeclRefs, InnerContexts);
558364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    // Rewrite the block body in place.
558464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    Stmt *SaveCurrentBody = CurrentBody;
558564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    CurrentBody = BE->getBody();
55866bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    PropParentMap = nullptr;
558764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    // block literal on rhs of a property-dot-sytax assignment
558864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    // must be replaced by its synthesize ast so getRewrittenText
558964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    // works as expected. In this case, what actually ends up on RHS
559064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    // is the blockTranscribed which is the helper function for the
559164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    // block literal; as in: self.c = ^() {[ace ARR];};
559264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    bool saveDisableReplaceStmt = DisableReplaceStmt;
559364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    DisableReplaceStmt = false;
559464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    RewriteFunctionBodyOrGlobalInitializer(BE->getBody());
559564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    DisableReplaceStmt = saveDisableReplaceStmt;
559664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    CurrentBody = SaveCurrentBody;
55976bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    PropParentMap = nullptr;
559864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    ImportedLocalExternalDecls.clear();
559964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    // Now we snarf the rewritten text and stash it away for later use.
560064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    std::string Str = Rewrite.getRewrittenText(BE->getSourceRange());
560164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    RewrittenBlockExprs[BE] = Str;
560264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
560364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    Stmt *blockTranscribed = SynthBlockInitExpr(BE, InnerBlockDeclRefs);
560464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
560564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    //blockTranscribed->dump();
560664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    ReplaceStmt(S, blockTranscribed);
560764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    return blockTranscribed;
560864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  }
560964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  // Handle specific things.
561064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  if (ObjCEncodeExpr *AtEncode = dyn_cast<ObjCEncodeExpr>(S))
561164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    return RewriteAtEncode(AtEncode);
561264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
561364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  if (ObjCSelectorExpr *AtSelector = dyn_cast<ObjCSelectorExpr>(S))
561464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    return RewriteAtSelector(AtSelector);
561564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
561664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  if (ObjCStringLiteral *AtString = dyn_cast<ObjCStringLiteral>(S))
561764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    return RewriteObjCStringLiteral(AtString);
561855947042d86773b7e16aec12070e1ffe62bff4a6Fariborz Jahanian
561955947042d86773b7e16aec12070e1ffe62bff4a6Fariborz Jahanian  if (ObjCBoolLiteralExpr *BoolLitExpr = dyn_cast<ObjCBoolLiteralExpr>(S))
562055947042d86773b7e16aec12070e1ffe62bff4a6Fariborz Jahanian    return RewriteObjCBoolLiteralExpr(BoolLitExpr);
56210f9b18ed048cd5c1ebe786d1dee05577e84d0c27Fariborz Jahanian
5622eb382ec1507cf2c8c12d7443d0b67c076223aec6Patrick Beard  if (ObjCBoxedExpr *BoxedExpr = dyn_cast<ObjCBoxedExpr>(S))
5623eb382ec1507cf2c8c12d7443d0b67c076223aec6Patrick Beard    return RewriteObjCBoxedExpr(BoxedExpr);
562486cff6080ba1db907009885adb5c6c64007e8b48Fariborz Jahanian
562586cff6080ba1db907009885adb5c6c64007e8b48Fariborz Jahanian  if (ObjCArrayLiteral *ArrayLitExpr = dyn_cast<ObjCArrayLiteral>(S))
562686cff6080ba1db907009885adb5c6c64007e8b48Fariborz Jahanian    return RewriteObjCArrayLiteralExpr(ArrayLitExpr);
5627e35abe1fd3f867ae51d5c68d98578d537eb6becaFariborz Jahanian
5628e35abe1fd3f867ae51d5c68d98578d537eb6becaFariborz Jahanian  if (ObjCDictionaryLiteral *DictionaryLitExpr =
5629e35abe1fd3f867ae51d5c68d98578d537eb6becaFariborz Jahanian        dyn_cast<ObjCDictionaryLiteral>(S))
5630e35abe1fd3f867ae51d5c68d98578d537eb6becaFariborz Jahanian    return RewriteObjCDictionaryLiteralExpr(DictionaryLitExpr);
563164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
563264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  if (ObjCMessageExpr *MessExpr = dyn_cast<ObjCMessageExpr>(S)) {
563364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian#if 0
563464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    // Before we rewrite it, put the original message expression in a comment.
563564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    SourceLocation startLoc = MessExpr->getLocStart();
563664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    SourceLocation endLoc = MessExpr->getLocEnd();
563764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
563864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    const char *startBuf = SM->getCharacterData(startLoc);
563964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    const char *endBuf = SM->getCharacterData(endLoc);
564064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
564164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    std::string messString;
564264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    messString += "// ";
564364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    messString.append(startBuf, endBuf-startBuf+1);
564464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    messString += "\n";
564564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
564664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    // FIXME: Missing definition of
564764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    // InsertText(clang::SourceLocation, char const*, unsigned int).
564864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    // InsertText(startLoc, messString.c_str(), messString.size());
564964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    // Tried this, but it didn't work either...
565064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    // ReplaceText(startLoc, 0, messString.c_str(), messString.size());
565164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian#endif
565264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    return RewriteMessageExpr(MessExpr);
565364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  }
565464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
5655042b91d53980048619d1e61431387ebe84d384f4Fariborz Jahanian  if (ObjCAutoreleasePoolStmt *StmtAutoRelease =
5656042b91d53980048619d1e61431387ebe84d384f4Fariborz Jahanian        dyn_cast<ObjCAutoreleasePoolStmt>(S)) {
5657042b91d53980048619d1e61431387ebe84d384f4Fariborz Jahanian    return RewriteObjCAutoreleasePoolStmt(StmtAutoRelease);
5658042b91d53980048619d1e61431387ebe84d384f4Fariborz Jahanian  }
5659042b91d53980048619d1e61431387ebe84d384f4Fariborz Jahanian
566064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  if (ObjCAtTryStmt *StmtTry = dyn_cast<ObjCAtTryStmt>(S))
566164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    return RewriteObjCTryStmt(StmtTry);
566264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
566364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  if (ObjCAtSynchronizedStmt *StmtTry = dyn_cast<ObjCAtSynchronizedStmt>(S))
566464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    return RewriteObjCSynchronizedStmt(StmtTry);
566564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
566664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  if (ObjCAtThrowStmt *StmtThrow = dyn_cast<ObjCAtThrowStmt>(S))
566764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    return RewriteObjCThrowStmt(StmtThrow);
566864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
566964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  if (ObjCProtocolExpr *ProtocolExp = dyn_cast<ObjCProtocolExpr>(S))
567064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    return RewriteObjCProtocolExpr(ProtocolExp);
567164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
567264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  if (ObjCForCollectionStmt *StmtForCollection =
567364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        dyn_cast<ObjCForCollectionStmt>(S))
567464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    return RewriteObjCForCollectionStmt(StmtForCollection,
567564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                        OrigStmtRange.getEnd());
567664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  if (BreakStmt *StmtBreakStmt =
567764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      dyn_cast<BreakStmt>(S))
567864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    return RewriteBreakStmt(StmtBreakStmt);
567964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  if (ContinueStmt *StmtContinueStmt =
568064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      dyn_cast<ContinueStmt>(S))
568164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    return RewriteContinueStmt(StmtContinueStmt);
568264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
568364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  // Need to check for protocol refs (id <P>, Foo <P> *) in variable decls
568464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  // and cast exprs.
568564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  if (DeclStmt *DS = dyn_cast<DeclStmt>(S)) {
568664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    // FIXME: What we're doing here is modifying the type-specifier that
568764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    // precedes the first Decl.  In the future the DeclGroup should have
568864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    // a separate type-specifier that we can rewrite.
568964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    // NOTE: We need to avoid rewriting the DeclStmt if it is within
569064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    // the context of an ObjCForCollectionStmt. For example:
569164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    //   NSArray *someArray;
569264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    //   for (id <FooProtocol> index in someArray) ;
569364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    // This is because RewriteObjCForCollectionStmt() does textual rewriting
569464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    // and it depends on the original text locations/positions.
569564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    if (Stmts.empty() || !IsDeclStmtInForeachHeader(DS))
569664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      RewriteObjCQualifiedInterfaceTypes(*DS->decl_begin());
569764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
569864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    // Blocks rewrite rules.
569964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    for (DeclStmt::decl_iterator DI = DS->decl_begin(), DE = DS->decl_end();
570064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian         DI != DE; ++DI) {
570164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      Decl *SD = *DI;
570264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      if (ValueDecl *ND = dyn_cast<ValueDecl>(SD)) {
570364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        if (isTopLevelBlockPointerType(ND->getType()))
570464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian          RewriteBlockPointerDecl(ND);
570564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        else if (ND->getType()->isFunctionPointerType())
570664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian          CheckFunctionPointerDecl(ND->getType(), ND);
570764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        if (VarDecl *VD = dyn_cast<VarDecl>(SD)) {
570864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian          if (VD->hasAttr<BlocksAttr>()) {
570964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian            static unsigned uniqueByrefDeclCount = 0;
571064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian            assert(!BlockByRefDeclNo.count(ND) &&
571164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian              "RewriteFunctionBodyOrGlobalInitializer: Duplicate byref decl");
571264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian            BlockByRefDeclNo[ND] = uniqueByrefDeclCount++;
57134fe261cb0a6420b103335acc1f6bcb7b72188184Fariborz Jahanian            RewriteByRefVar(VD, (DI == DS->decl_begin()), ((DI+1) == DE));
571464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian          }
571564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian          else
571664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian            RewriteTypeOfDecl(VD);
571764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        }
571864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      }
571964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(SD)) {
572064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        if (isTopLevelBlockPointerType(TD->getUnderlyingType()))
572164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian          RewriteBlockPointerDecl(TD);
572264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        else if (TD->getUnderlyingType()->isFunctionPointerType())
572364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian          CheckFunctionPointerDecl(TD->getUnderlyingType(), TD);
572464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      }
572564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    }
572664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  }
572764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
572864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  if (CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(S))
572964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    RewriteObjCQualifiedInterfaceTypes(CE);
573064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
573164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  if (isa<SwitchStmt>(S) || isa<WhileStmt>(S) ||
573264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      isa<DoStmt>(S) || isa<ForStmt>(S)) {
573364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    assert(!Stmts.empty() && "Statement stack is empty");
573464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    assert ((isa<SwitchStmt>(Stmts.back()) || isa<WhileStmt>(Stmts.back()) ||
573564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian             isa<DoStmt>(Stmts.back()) || isa<ForStmt>(Stmts.back()))
573664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian            && "Statement stack mismatch");
573764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    Stmts.pop_back();
573864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  }
573964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  // Handle blocks rewriting.
574064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(S)) {
574164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    ValueDecl *VD = DRE->getDecl();
574264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    if (VD->hasAttr<BlocksAttr>())
574364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      return RewriteBlockDeclRefExpr(DRE);
574464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    if (HasLocalVariableExternalStorage(VD))
574564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      return RewriteLocalVariableExternalStorage(DRE);
574664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  }
574764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
574864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  if (CallExpr *CE = dyn_cast<CallExpr>(S)) {
574964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    if (CE->getCallee()->getType()->isBlockPointerType()) {
575064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      Stmt *BlockCall = SynthesizeBlockCall(CE, CE->getCallee());
575164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      ReplaceStmt(S, BlockCall);
575264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      return BlockCall;
575364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    }
575464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  }
575564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  if (CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(S)) {
575664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    RewriteCastExpr(CE);
575764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  }
5758f1ee68710ae8ca93a35ab11995ed5df321ade9ecFariborz Jahanian  if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(S)) {
5759f1ee68710ae8ca93a35ab11995ed5df321ade9ecFariborz Jahanian    RewriteImplicitCastObjCExpr(ICE);
5760f1ee68710ae8ca93a35ab11995ed5df321ade9ecFariborz Jahanian  }
576143aa1c302b31492ab0abfbf656b06ca446d93b3aFariborz Jahanian#if 0
5762653b7cff0efe0d32ab12535846196e3465445fefFariborz Jahanian
576364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(S)) {
576464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    CastExpr *Replacement = new (Context) CastExpr(ICE->getType(),
576564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                                   ICE->getSubExpr(),
576664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                                   SourceLocation());
576764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    // Get the new text.
576864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    std::string SStr;
576964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    llvm::raw_string_ostream Buf(SStr);
5770d1420c6fa788669e49f21e184927c7833881e399Richard Smith    Replacement->printPretty(Buf);
577164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    const std::string &Str = Buf.str();
577264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
577364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    printf("CAST = %s\n", &Str[0]);
577464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    InsertText(ICE->getSubExpr()->getLocStart(), &Str[0], Str.size());
577564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    delete S;
577664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    return Replacement;
577764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  }
577864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian#endif
577964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  // Return this stmt unmodified.
578064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  return S;
578164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian}
578264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
578364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanianvoid RewriteModernObjC::RewriteRecordBody(RecordDecl *RD) {
5784651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  for (auto *FD : RD->fields()) {
578564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    if (isTopLevelBlockPointerType(FD->getType()))
578664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      RewriteBlockPointerDecl(FD);
578764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    if (FD->getType()->isObjCQualifiedIdType() ||
578864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        FD->getType()->isObjCQualifiedInterfaceType())
578964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      RewriteObjCQualifiedInterfaceTypes(FD);
579064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  }
579164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian}
579264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
579364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian/// HandleDeclInMainFile - This is called for each top-level decl defined in the
579464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian/// main file of the input.
579564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanianvoid RewriteModernObjC::HandleDeclInMainFile(Decl *D) {
579664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  switch (D->getKind()) {
579764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    case Decl::Function: {
579864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      FunctionDecl *FD = cast<FunctionDecl>(D);
579964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      if (FD->isOverloadedOperator())
580064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        return;
580164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
580264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      // Since function prototypes don't have ParmDecl's, we check the function
580364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      // prototype. This enables us to rewrite function declarations and
580464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      // definitions using the same code.
580564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      RewriteBlocksInFunctionProtoType(FD->getType(), FD);
580664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
58079335df324951c022bc696e64b5fe9f66a8ad5222Argyrios Kyrtzidis      if (!FD->isThisDeclarationADefinition())
58089335df324951c022bc696e64b5fe9f66a8ad5222Argyrios Kyrtzidis        break;
58099335df324951c022bc696e64b5fe9f66a8ad5222Argyrios Kyrtzidis
581064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      // FIXME: If this should support Obj-C++, support CXXTryStmt
581164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      if (CompoundStmt *Body = dyn_cast_or_null<CompoundStmt>(FD->getBody())) {
581264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        CurFunctionDef = FD;
581364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        CurrentBody = Body;
581464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        Body =
581564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        cast_or_null<CompoundStmt>(RewriteFunctionBodyOrGlobalInitializer(Body));
581664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        FD->setBody(Body);
58176bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines        CurrentBody = nullptr;
581864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        if (PropParentMap) {
581964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian          delete PropParentMap;
58206bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines          PropParentMap = nullptr;
582164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        }
582264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        // This synthesizes and inserts the block "impl" struct, invoke function,
582364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        // and any copy/dispose helper functions.
582464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        InsertBlockLiteralsWithinFunction(FD);
58259620596ca2ca19e365af4e4d4968cb4d9228c4fcFariborz Jahanian        RewriteLineDirective(D);
58266bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines        CurFunctionDef = nullptr;
582764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      }
582864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      break;
582964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    }
583064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    case Decl::ObjCMethod: {
583164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      ObjCMethodDecl *MD = cast<ObjCMethodDecl>(D);
583264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      if (CompoundStmt *Body = MD->getCompoundBody()) {
583364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        CurMethodDef = MD;
583464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        CurrentBody = Body;
583564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        Body =
583664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian          cast_or_null<CompoundStmt>(RewriteFunctionBodyOrGlobalInitializer(Body));
583764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        MD->setBody(Body);
58386bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines        CurrentBody = nullptr;
583964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        if (PropParentMap) {
584064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian          delete PropParentMap;
58416bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines          PropParentMap = nullptr;
584264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        }
584364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        InsertBlockLiteralsWithinMethod(MD);
58449620596ca2ca19e365af4e4d4968cb4d9228c4fcFariborz Jahanian        RewriteLineDirective(D);
58456bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines        CurMethodDef = nullptr;
584664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      }
584764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      break;
584864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    }
584964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    case Decl::ObjCImplementation: {
585064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      ObjCImplementationDecl *CI = cast<ObjCImplementationDecl>(D);
585164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      ClassImplementation.push_back(CI);
585264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      break;
585364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    }
585464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    case Decl::ObjCCategoryImpl: {
585564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      ObjCCategoryImplDecl *CI = cast<ObjCCategoryImplDecl>(D);
585664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      CategoryImplementation.push_back(CI);
585764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      break;
585864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    }
585964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    case Decl::Var: {
586064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      VarDecl *VD = cast<VarDecl>(D);
586164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      RewriteObjCQualifiedInterfaceTypes(VD);
586264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      if (isTopLevelBlockPointerType(VD->getType()))
586364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        RewriteBlockPointerDecl(VD);
586464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      else if (VD->getType()->isFunctionPointerType()) {
586564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        CheckFunctionPointerDecl(VD->getType(), VD);
586664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        if (VD->getInit()) {
586764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian          if (CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(VD->getInit())) {
586864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian            RewriteCastExpr(CE);
586964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian          }
587064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        }
587164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      } else if (VD->getType()->isRecordType()) {
587264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        RecordDecl *RD = VD->getType()->getAs<RecordType>()->getDecl();
587364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        if (RD->isCompleteDefinition())
587464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian          RewriteRecordBody(RD);
587564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      }
587664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      if (VD->getInit()) {
587764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        GlobalVarDecl = VD;
587864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        CurrentBody = VD->getInit();
587964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        RewriteFunctionBodyOrGlobalInitializer(VD->getInit());
58806bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines        CurrentBody = nullptr;
588164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        if (PropParentMap) {
588264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian          delete PropParentMap;
58836bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines          PropParentMap = nullptr;
588464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        }
588564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        SynthesizeBlockLiterals(VD->getTypeSpecStartLoc(), VD->getName());
58866bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines        GlobalVarDecl = nullptr;
58876bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
588864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        // This is needed for blocks.
588964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        if (CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(VD->getInit())) {
589064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian            RewriteCastExpr(CE);
589164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        }
589264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      }
589364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      break;
589464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    }
589564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    case Decl::TypeAlias:
589664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    case Decl::Typedef: {
589764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(D)) {
589864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        if (isTopLevelBlockPointerType(TD->getUnderlyingType()))
589964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian          RewriteBlockPointerDecl(TD);
590064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        else if (TD->getUnderlyingType()->isFunctionPointerType())
590164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian          CheckFunctionPointerDecl(TD->getUnderlyingType(), TD);
5902f9f30791dd20472675de012105219cd975ad1076Fariborz Jahanian        else
5903f9f30791dd20472675de012105219cd975ad1076Fariborz Jahanian          RewriteObjCQualifiedInterfaceTypes(TD);
590464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      }
590564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      break;
590664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    }
590764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    case Decl::CXXRecord:
590864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    case Decl::Record: {
590964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      RecordDecl *RD = cast<RecordDecl>(D);
591064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      if (RD->isCompleteDefinition())
591164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian        RewriteRecordBody(RD);
591264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      break;
591364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    }
591464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    default:
591564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      break;
591664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  }
591764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  // Nothing yet.
591864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian}
591964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
592030650ebe652854d8bdce832cbdae1cf3c43e54aaFariborz Jahanian/// Write_ProtocolExprReferencedMetadata - This routine writer out the
592130650ebe652854d8bdce832cbdae1cf3c43e54aaFariborz Jahanian/// protocol reference symbols in the for of:
592230650ebe652854d8bdce832cbdae1cf3c43e54aaFariborz Jahanian/// struct _protocol_t *PROTOCOL_REF = &PROTOCOL_METADATA.
592330650ebe652854d8bdce832cbdae1cf3c43e54aaFariborz Jahanianstatic void Write_ProtocolExprReferencedMetadata(ASTContext *Context,
592430650ebe652854d8bdce832cbdae1cf3c43e54aaFariborz Jahanian                                                 ObjCProtocolDecl *PDecl,
592530650ebe652854d8bdce832cbdae1cf3c43e54aaFariborz Jahanian                                                 std::string &Result) {
592630650ebe652854d8bdce832cbdae1cf3c43e54aaFariborz Jahanian  // Also output .objc_protorefs$B section and its meta-data.
592730650ebe652854d8bdce832cbdae1cf3c43e54aaFariborz Jahanian  if (Context->getLangOpts().MicrosoftExt)
5928bd78cfa0480df14a627b536b628532070b6632c9Fariborz Jahanian    Result += "static ";
592930650ebe652854d8bdce832cbdae1cf3c43e54aaFariborz Jahanian  Result += "struct _protocol_t *";
593030650ebe652854d8bdce832cbdae1cf3c43e54aaFariborz Jahanian  Result += "_OBJC_PROTOCOL_REFERENCE_$_";
593130650ebe652854d8bdce832cbdae1cf3c43e54aaFariborz Jahanian  Result += PDecl->getNameAsString();
593230650ebe652854d8bdce832cbdae1cf3c43e54aaFariborz Jahanian  Result += " = &";
593330650ebe652854d8bdce832cbdae1cf3c43e54aaFariborz Jahanian  Result += "_OBJC_PROTOCOL_"; Result += PDecl->getNameAsString();
593430650ebe652854d8bdce832cbdae1cf3c43e54aaFariborz Jahanian  Result += ";\n";
593530650ebe652854d8bdce832cbdae1cf3c43e54aaFariborz Jahanian}
593630650ebe652854d8bdce832cbdae1cf3c43e54aaFariborz Jahanian
593764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanianvoid RewriteModernObjC::HandleTranslationUnit(ASTContext &C) {
593864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  if (Diags.hasErrorOccurred())
593964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    return;
594064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
594164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  RewriteInclude();
594264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
594331c4a4b0171aac01d2a6aedb4960ade7ee7d998aFariborz Jahanian  for (unsigned i = 0, e = FunctionDefinitionsSeen.size(); i < e; i++) {
5944651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    // translation of function bodies were postponed until all class and
594531c4a4b0171aac01d2a6aedb4960ade7ee7d998aFariborz Jahanian    // their extensions and implementations are seen. This is because, we
5946651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    // cannot build grouping structs for bitfields until they are all seen.
594731c4a4b0171aac01d2a6aedb4960ade7ee7d998aFariborz Jahanian    FunctionDecl *FDecl = FunctionDefinitionsSeen[i];
594831c4a4b0171aac01d2a6aedb4960ade7ee7d998aFariborz Jahanian    HandleTopLevelSingleDecl(FDecl);
594931c4a4b0171aac01d2a6aedb4960ade7ee7d998aFariborz Jahanian  }
595031c4a4b0171aac01d2a6aedb4960ade7ee7d998aFariborz Jahanian
595164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  // Here's a great place to add any extra declarations that may be needed.
595264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  // Write out meta data for each @protocol(<expr>).
5953176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  for (ObjCProtocolDecl *ProtDecl : ProtocolExprDecls) {
5954176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    RewriteObjCProtocolMetaData(ProtDecl, Preamble);
5955176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    Write_ProtocolExprReferencedMetadata(Context, ProtDecl, Preamble);
595630650ebe652854d8bdce832cbdae1cf3c43e54aaFariborz Jahanian  }
595764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
595864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  InsertText(SM->getLocForStartOfFile(MainFileID), Preamble, false);
5959163d3cef334169e41225d94a4c353e0d7159570bFariborz Jahanian
5960163d3cef334169e41225d94a4c353e0d7159570bFariborz Jahanian  if (ClassImplementation.size() || CategoryImplementation.size())
5961163d3cef334169e41225d94a4c353e0d7159570bFariborz Jahanian    RewriteImplementations();
5962163d3cef334169e41225d94a4c353e0d7159570bFariborz Jahanian
596357317788289549d61ada868d07792b637a32d52eFariborz Jahanian  for (unsigned i = 0, e = ObjCInterfacesSeen.size(); i < e; i++) {
596457317788289549d61ada868d07792b637a32d52eFariborz Jahanian    ObjCInterfaceDecl *CDecl = ObjCInterfacesSeen[i];
596557317788289549d61ada868d07792b637a32d52eFariborz Jahanian    // Write struct declaration for the class matching its ivar declarations.
596657317788289549d61ada868d07792b637a32d52eFariborz Jahanian    // Note that for modern abi, this is postponed until the end of TU
596757317788289549d61ada868d07792b637a32d52eFariborz Jahanian    // because class extensions and the implementation might declare their own
596857317788289549d61ada868d07792b637a32d52eFariborz Jahanian    // private ivars.
596957317788289549d61ada868d07792b637a32d52eFariborz Jahanian    RewriteInterfaceDecl(CDecl);
597057317788289549d61ada868d07792b637a32d52eFariborz Jahanian  }
597131c4a4b0171aac01d2a6aedb4960ade7ee7d998aFariborz Jahanian
597264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  // Get the buffer corresponding to MainFileID.  If we haven't changed it, then
597364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  // we are done.
597464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  if (const RewriteBuffer *RewriteBuf =
597564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      Rewrite.getRewriteBufferFor(MainFileID)) {
597664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    //printf("Changed:\n");
597764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    *OutFile << std::string(RewriteBuf->begin(), RewriteBuf->end());
597864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  } else {
597964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    llvm::errs() << "No changes\n";
598064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  }
598164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
598264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  if (ClassImplementation.size() || CategoryImplementation.size() ||
598364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      ProtocolExprDecls.size()) {
598464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    // Rewrite Objective-c meta data*
598564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    std::string ResultStr;
598664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    RewriteMetaDataIntoBuffer(ResultStr);
598764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    // Emit metadata.
598864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    *OutFile << ResultStr;
598964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  }
599010cde2fc0c1804427dd3e0c050c149ac6d415f51Fariborz Jahanian  // Emit ImageInfo;
599110cde2fc0c1804427dd3e0c050c149ac6d415f51Fariborz Jahanian  {
599210cde2fc0c1804427dd3e0c050c149ac6d415f51Fariborz Jahanian    std::string ResultStr;
599310cde2fc0c1804427dd3e0c050c149ac6d415f51Fariborz Jahanian    WriteImageInfo(ResultStr);
599410cde2fc0c1804427dd3e0c050c149ac6d415f51Fariborz Jahanian    *OutFile << ResultStr;
599510cde2fc0c1804427dd3e0c050c149ac6d415f51Fariborz Jahanian  }
599664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  OutFile->flush();
599764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian}
599864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
599964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanianvoid RewriteModernObjC::Initialize(ASTContext &context) {
600064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  InitializeCommon(context);
600164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
60026991bc5a45b6d334a19e1ba995c8aea16553973bFariborz Jahanian  Preamble += "#ifndef __OBJC2__\n";
60036991bc5a45b6d334a19e1ba995c8aea16553973bFariborz Jahanian  Preamble += "#define __OBJC2__\n";
60046991bc5a45b6d334a19e1ba995c8aea16553973bFariborz Jahanian  Preamble += "#endif\n";
60056991bc5a45b6d334a19e1ba995c8aea16553973bFariborz Jahanian
600664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  // declaring objc_selector outside the parameter list removes a silly
600764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  // scope related warning...
600864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  if (IsHeader)
600964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    Preamble = "#pragma once\n";
601064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  Preamble += "struct objc_selector; struct objc_class;\n";
6011e2d87bc0be8e5a5b2e45118675ff878d89daee44Fariborz Jahanian  Preamble += "struct __rw_objc_super { \n\tstruct objc_object *object; ";
6012e2d87bc0be8e5a5b2e45118675ff878d89daee44Fariborz Jahanian  Preamble += "\n\tstruct objc_object *superClass; ";
6013e2d87bc0be8e5a5b2e45118675ff878d89daee44Fariborz Jahanian  // Add a constructor for creating temporary objects.
6014e2d87bc0be8e5a5b2e45118675ff878d89daee44Fariborz Jahanian  Preamble += "\n\t__rw_objc_super(struct objc_object *o, struct objc_object *s) ";
6015e2d87bc0be8e5a5b2e45118675ff878d89daee44Fariborz Jahanian  Preamble += ": object(o), superClass(s) {} ";
6016e2d87bc0be8e5a5b2e45118675ff878d89daee44Fariborz Jahanian  Preamble += "\n};\n";
6017e2d87bc0be8e5a5b2e45118675ff878d89daee44Fariborz Jahanian
601864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  if (LangOpts.MicrosoftExt) {
60191ca052c09868169d4de4da5d1d45f07f2fe8511aFariborz Jahanian    // Define all sections using syntax that makes sense.
602010cde2fc0c1804427dd3e0c050c149ac6d415f51Fariborz Jahanian    // These are currently generated.
602110cde2fc0c1804427dd3e0c050c149ac6d415f51Fariborz Jahanian    Preamble += "\n#pragma section(\".objc_classlist$B\", long, read, write)\n";
60221ca052c09868169d4de4da5d1d45f07f2fe8511aFariborz Jahanian    Preamble += "#pragma section(\".objc_catlist$B\", long, read, write)\n";
602310cde2fc0c1804427dd3e0c050c149ac6d415f51Fariborz Jahanian    Preamble += "#pragma section(\".objc_imageinfo$B\", long, read, write)\n";
602488f7f75e35425f3f228473c4c84a2445793a39c1Fariborz Jahanian    Preamble += "#pragma section(\".objc_nlclslist$B\", long, read, write)\n";
602588f7f75e35425f3f228473c4c84a2445793a39c1Fariborz Jahanian    Preamble += "#pragma section(\".objc_nlcatlist$B\", long, read, write)\n";
602610cde2fc0c1804427dd3e0c050c149ac6d415f51Fariborz Jahanian    // These are generated but not necessary for functionality.
602710cde2fc0c1804427dd3e0c050c149ac6d415f51Fariborz Jahanian    Preamble += "#pragma section(\".cat_cls_meth$B\", long, read, write)\n";
60281ca052c09868169d4de4da5d1d45f07f2fe8511aFariborz Jahanian    Preamble += "#pragma section(\".inst_meth$B\", long, read, write)\n";
60291ca052c09868169d4de4da5d1d45f07f2fe8511aFariborz Jahanian    Preamble += "#pragma section(\".cls_meth$B\", long, read, write)\n";
603040a777a157c00cc7e9c9db7197017d83311c76c6Fariborz Jahanian    Preamble += "#pragma section(\".objc_ivar$B\", long, read, write)\n";
6031de5d946288bb3d68576c95974beb8cfd21d7043aFariborz Jahanian
603230650ebe652854d8bdce832cbdae1cf3c43e54aaFariborz Jahanian    // These need be generated for performance. Currently they are not,
603330650ebe652854d8bdce832cbdae1cf3c43e54aaFariborz Jahanian    // using API calls instead.
603430650ebe652854d8bdce832cbdae1cf3c43e54aaFariborz Jahanian    Preamble += "#pragma section(\".objc_selrefs$B\", long, read, write)\n";
603530650ebe652854d8bdce832cbdae1cf3c43e54aaFariborz Jahanian    Preamble += "#pragma section(\".objc_classrefs$B\", long, read, write)\n";
603630650ebe652854d8bdce832cbdae1cf3c43e54aaFariborz Jahanian    Preamble += "#pragma section(\".objc_superrefs$B\", long, read, write)\n";
603730650ebe652854d8bdce832cbdae1cf3c43e54aaFariborz Jahanian
603864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  }
603964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  Preamble += "#ifndef _REWRITER_typedef_Protocol\n";
604064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  Preamble += "typedef struct objc_object Protocol;\n";
604164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  Preamble += "#define _REWRITER_typedef_Protocol\n";
604264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  Preamble += "#endif\n";
604364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  if (LangOpts.MicrosoftExt) {
604464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    Preamble += "#define __OBJC_RW_DLLIMPORT extern \"C\" __declspec(dllimport)\n";
604564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    Preamble += "#define __OBJC_RW_STATICIMPORT extern \"C\"\n";
60465cf6b6ca7c08d3bed3fd899e7a18fc5f58c736b5Fariborz Jahanian  }
60475cf6b6ca7c08d3bed3fd899e7a18fc5f58c736b5Fariborz Jahanian  else
604864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    Preamble += "#define __OBJC_RW_DLLIMPORT extern\n";
60495cf6b6ca7c08d3bed3fd899e7a18fc5f58c736b5Fariborz Jahanian
60505cf6b6ca7c08d3bed3fd899e7a18fc5f58c736b5Fariborz Jahanian  Preamble += "__OBJC_RW_DLLIMPORT void objc_msgSend(void);\n";
60515cf6b6ca7c08d3bed3fd899e7a18fc5f58c736b5Fariborz Jahanian  Preamble += "__OBJC_RW_DLLIMPORT void objc_msgSendSuper(void);\n";
60525cf6b6ca7c08d3bed3fd899e7a18fc5f58c736b5Fariborz Jahanian  Preamble += "__OBJC_RW_DLLIMPORT void objc_msgSend_stret(void);\n";
60535cf6b6ca7c08d3bed3fd899e7a18fc5f58c736b5Fariborz Jahanian  Preamble += "__OBJC_RW_DLLIMPORT void objc_msgSendSuper_stret(void);\n";
60545cf6b6ca7c08d3bed3fd899e7a18fc5f58c736b5Fariborz Jahanian  Preamble += "__OBJC_RW_DLLIMPORT void objc_msgSend_fpret(void);\n";
60555cf6b6ca7c08d3bed3fd899e7a18fc5f58c736b5Fariborz Jahanian
605620e181a3ece8862dcfcfacf70763074ddec5a68bFariborz Jahanian  Preamble += "__OBJC_RW_DLLIMPORT struct objc_class *objc_getClass";
605764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  Preamble += "(const char *);\n";
605864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  Preamble += "__OBJC_RW_DLLIMPORT struct objc_class *class_getSuperclass";
605964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  Preamble += "(struct objc_class *);\n";
606020e181a3ece8862dcfcfacf70763074ddec5a68bFariborz Jahanian  Preamble += "__OBJC_RW_DLLIMPORT struct objc_class *objc_getMetaClass";
606164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  Preamble += "(const char *);\n";
606255261afb725b8af330addddd2e452f9f28ddd96bFariborz Jahanian  Preamble += "__OBJC_RW_DLLIMPORT void objc_exception_throw( struct objc_object *);\n";
606364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  // @synchronized hooks.
60642d234d73f687428c89f8a99af94f123012f05551Aaron Ballman  Preamble += "__OBJC_RW_DLLIMPORT int objc_sync_enter( struct objc_object *);\n";
60652d234d73f687428c89f8a99af94f123012f05551Aaron Ballman  Preamble += "__OBJC_RW_DLLIMPORT int objc_sync_exit( struct objc_object *);\n";
606664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  Preamble += "__OBJC_RW_DLLIMPORT Protocol *objc_getProtocol(const char *);\n";
6067e38f08aa831617cd0b6dc90d82f98eda674c0fc8Fariborz Jahanian  Preamble += "#ifdef _WIN64\n";
6068e38f08aa831617cd0b6dc90d82f98eda674c0fc8Fariborz Jahanian  Preamble += "typedef unsigned long long  _WIN_NSUInteger;\n";
6069e38f08aa831617cd0b6dc90d82f98eda674c0fc8Fariborz Jahanian  Preamble += "#else\n";
6070e38f08aa831617cd0b6dc90d82f98eda674c0fc8Fariborz Jahanian  Preamble += "typedef unsigned int _WIN_NSUInteger;\n";
6071e38f08aa831617cd0b6dc90d82f98eda674c0fc8Fariborz Jahanian  Preamble += "#endif\n";
607264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  Preamble += "#ifndef __FASTENUMERATIONSTATE\n";
607364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  Preamble += "struct __objcFastEnumerationState {\n\t";
607464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  Preamble += "unsigned long state;\n\t";
607564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  Preamble += "void **itemsPtr;\n\t";
607664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  Preamble += "unsigned long *mutationsPtr;\n\t";
607764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  Preamble += "unsigned long extra[5];\n};\n";
607864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  Preamble += "__OBJC_RW_DLLIMPORT void objc_enumerationMutation(struct objc_object *);\n";
607964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  Preamble += "#define __FASTENUMERATIONSTATE\n";
608064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  Preamble += "#endif\n";
608164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  Preamble += "#ifndef __NSCONSTANTSTRINGIMPL\n";
608264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  Preamble += "struct __NSConstantStringImpl {\n";
608364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  Preamble += "  int *isa;\n";
608464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  Preamble += "  int flags;\n";
608564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  Preamble += "  char *str;\n";
60866bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  Preamble += "#if _WIN64\n";
6087651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  Preamble += "  long long length;\n";
6088651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  Preamble += "#else\n";
608964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  Preamble += "  long length;\n";
6090651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  Preamble += "#endif\n";
609164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  Preamble += "};\n";
609264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  Preamble += "#ifdef CF_EXPORT_CONSTANT_STRING\n";
609364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  Preamble += "extern \"C\" __declspec(dllexport) int __CFConstantStringClassReference[];\n";
609464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  Preamble += "#else\n";
609564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  Preamble += "__OBJC_RW_DLLIMPORT int __CFConstantStringClassReference[];\n";
609664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  Preamble += "#endif\n";
609764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  Preamble += "#define __NSCONSTANTSTRINGIMPL\n";
609864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  Preamble += "#endif\n";
609964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  // Blocks preamble.
610064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  Preamble += "#ifndef BLOCK_IMPL\n";
610164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  Preamble += "#define BLOCK_IMPL\n";
610264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  Preamble += "struct __block_impl {\n";
610364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  Preamble += "  void *isa;\n";
610464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  Preamble += "  int Flags;\n";
610564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  Preamble += "  int Reserved;\n";
610664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  Preamble += "  void *FuncPtr;\n";
610764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  Preamble += "};\n";
610864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  Preamble += "// Runtime copy/destroy helper functions (from Block_private.h)\n";
610964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  Preamble += "#ifdef __OBJC_EXPORT_BLOCKS\n";
611064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  Preamble += "extern \"C\" __declspec(dllexport) "
611164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  "void _Block_object_assign(void *, const void *, const int);\n";
611264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  Preamble += "extern \"C\" __declspec(dllexport) void _Block_object_dispose(const void *, const int);\n";
611364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  Preamble += "extern \"C\" __declspec(dllexport) void *_NSConcreteGlobalBlock[32];\n";
611464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  Preamble += "extern \"C\" __declspec(dllexport) void *_NSConcreteStackBlock[32];\n";
611564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  Preamble += "#else\n";
611664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  Preamble += "__OBJC_RW_DLLIMPORT void _Block_object_assign(void *, const void *, const int);\n";
611764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  Preamble += "__OBJC_RW_DLLIMPORT void _Block_object_dispose(const void *, const int);\n";
611864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  Preamble += "__OBJC_RW_DLLIMPORT void *_NSConcreteGlobalBlock[32];\n";
611964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  Preamble += "__OBJC_RW_DLLIMPORT void *_NSConcreteStackBlock[32];\n";
612064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  Preamble += "#endif\n";
612164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  Preamble += "#endif\n";
612264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  if (LangOpts.MicrosoftExt) {
612364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    Preamble += "#undef __OBJC_RW_DLLIMPORT\n";
612464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    Preamble += "#undef __OBJC_RW_STATICIMPORT\n";
612564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    Preamble += "#ifndef KEEP_ATTRIBUTES\n";  // We use this for clang tests.
612664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    Preamble += "#define __attribute__(X)\n";
612764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    Preamble += "#endif\n";
61285ce2827de3aa069a4796dea404c0679620581dbeFariborz Jahanian    Preamble += "#ifndef __weak\n";
612964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    Preamble += "#define __weak\n";
61305ce2827de3aa069a4796dea404c0679620581dbeFariborz Jahanian    Preamble += "#endif\n";
61315ce2827de3aa069a4796dea404c0679620581dbeFariborz Jahanian    Preamble += "#ifndef __block\n";
61325ce2827de3aa069a4796dea404c0679620581dbeFariborz Jahanian    Preamble += "#define __block\n";
61335ce2827de3aa069a4796dea404c0679620581dbeFariborz Jahanian    Preamble += "#endif\n";
613464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  }
613564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  else {
613664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    Preamble += "#define __block\n";
613764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    Preamble += "#define __weak\n";
613864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  }
6139be8d55ce4a20b86d9337dcb28759e068cb3510f3Fariborz Jahanian
6140b0f245ccce94a069c9334e51f3c5d502eb2d0215Fariborz Jahanian  // Declarations required for modern objective-c array and dictionary literals.
6141b0f245ccce94a069c9334e51f3c5d502eb2d0215Fariborz Jahanian  Preamble += "\n#include <stdarg.h>\n";
6142e35abe1fd3f867ae51d5c68d98578d537eb6becaFariborz Jahanian  Preamble += "struct __NSContainer_literal {\n";
6143b0f245ccce94a069c9334e51f3c5d502eb2d0215Fariborz Jahanian  Preamble += "  void * *arr;\n";
6144e35abe1fd3f867ae51d5c68d98578d537eb6becaFariborz Jahanian  Preamble += "  __NSContainer_literal (unsigned int count, ...) {\n";
6145b0f245ccce94a069c9334e51f3c5d502eb2d0215Fariborz Jahanian  Preamble += "\tva_list marker;\n";
6146b0f245ccce94a069c9334e51f3c5d502eb2d0215Fariborz Jahanian  Preamble += "\tva_start(marker, count);\n";
6147b0f245ccce94a069c9334e51f3c5d502eb2d0215Fariborz Jahanian  Preamble += "\tarr = new void *[count];\n";
6148b0f245ccce94a069c9334e51f3c5d502eb2d0215Fariborz Jahanian  Preamble += "\tfor (unsigned i = 0; i < count; i++)\n";
6149b0f245ccce94a069c9334e51f3c5d502eb2d0215Fariborz Jahanian  Preamble += "\t  arr[i] = va_arg(marker, void *);\n";
6150b0f245ccce94a069c9334e51f3c5d502eb2d0215Fariborz Jahanian  Preamble += "\tva_end( marker );\n";
6151b0f245ccce94a069c9334e51f3c5d502eb2d0215Fariborz Jahanian  Preamble += "  };\n";
615213a9c02b54f185da611d9b0443017e22d4d46eb4Fariborz Jahanian  Preamble += "  ~__NSContainer_literal() {\n";
6153b0f245ccce94a069c9334e51f3c5d502eb2d0215Fariborz Jahanian  Preamble += "\tdelete[] arr;\n";
6154b0f245ccce94a069c9334e51f3c5d502eb2d0215Fariborz Jahanian  Preamble += "  }\n";
6155b0f245ccce94a069c9334e51f3c5d502eb2d0215Fariborz Jahanian  Preamble += "};\n";
6156b0f245ccce94a069c9334e51f3c5d502eb2d0215Fariborz Jahanian
6157042b91d53980048619d1e61431387ebe84d384f4Fariborz Jahanian  // Declaration required for implementation of @autoreleasepool statement.
6158042b91d53980048619d1e61431387ebe84d384f4Fariborz Jahanian  Preamble += "extern \"C\" __declspec(dllimport) void * objc_autoreleasePoolPush(void);\n";
6159042b91d53980048619d1e61431387ebe84d384f4Fariborz Jahanian  Preamble += "extern \"C\" __declspec(dllimport) void objc_autoreleasePoolPop(void *);\n\n";
6160042b91d53980048619d1e61431387ebe84d384f4Fariborz Jahanian  Preamble += "struct __AtAutoreleasePool {\n";
6161042b91d53980048619d1e61431387ebe84d384f4Fariborz Jahanian  Preamble += "  __AtAutoreleasePool() {atautoreleasepoolobj = objc_autoreleasePoolPush();}\n";
6162042b91d53980048619d1e61431387ebe84d384f4Fariborz Jahanian  Preamble += "  ~__AtAutoreleasePool() {objc_autoreleasePoolPop(atautoreleasepoolobj);}\n";
6163042b91d53980048619d1e61431387ebe84d384f4Fariborz Jahanian  Preamble += "  void * atautoreleasepoolobj;\n";
6164042b91d53980048619d1e61431387ebe84d384f4Fariborz Jahanian  Preamble += "};\n";
6165042b91d53980048619d1e61431387ebe84d384f4Fariborz Jahanian
616664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  // NOTE! Windows uses LLP64 for 64bit mode. So, cast pointer to long long
616764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  // as this avoids warning in any 64bit/32bit compilation model.
616864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  Preamble += "\n#define __OFFSETOFIVAR__(TYPE, MEMBER) ((long long) &((TYPE *)0)->MEMBER)\n";
616964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian}
617064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
617164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian/// RewriteIvarOffsetComputation - This rutine synthesizes computation of
617264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian/// ivar offset.
617364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanianvoid RewriteModernObjC::RewriteIvarOffsetComputation(ObjCIvarDecl *ivar,
617464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                                         std::string &Result) {
6175cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian  Result += "__OFFSETOFIVAR__(struct ";
6176cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian  Result += ivar->getContainingInterface()->getNameAsString();
6177cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian  if (LangOpts.MicrosoftExt)
6178cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian    Result += "_IMPL";
6179cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian  Result += ", ";
6180cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian  if (ivar->isBitField())
6181cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian    ObjCIvarBitfieldGroupDecl(ivar, Result);
6182cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian  else
618364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    Result += ivar->getNameAsString();
6184cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian  Result += ")";
618564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian}
618664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
618764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian/// WriteModernMetadataDeclarations - Writes out metadata declarations for modern ABI.
618864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian/// struct _prop_t {
6189da35eacc6e05a99ab30f7290f1d42df32d06b22eFariborz Jahanian///   const char *name;
619064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian///   char *attributes;
619164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian/// }
619264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
619364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian/// struct _prop_list_t {
619464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian///   uint32_t entsize;      // sizeof(struct _prop_t)
619564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian///   uint32_t count_of_properties;
619664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian///   struct _prop_t prop_list[count_of_properties];
619764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian/// }
619864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
619964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian/// struct _protocol_t;
620064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
620164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian/// struct _protocol_list_t {
620264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian///   long protocol_count;   // Note, this is 32/64 bit
620364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian///   struct _protocol_t * protocol_list[protocol_count];
620464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian/// }
620564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
620664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian/// struct _objc_method {
620764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian///   SEL _cmd;
620877e4bcacd5c80d8bffe19a4489b5f059b618d4bcFariborz Jahanian///   const char *method_type;
620964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian///   char *_imp;
621064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian/// }
621164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
621264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian/// struct _method_list_t {
621364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian///   uint32_t entsize;  // sizeof(struct _objc_method)
621464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian///   uint32_t method_count;
621564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian///   struct _objc_method method_list[method_count];
621664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian/// }
621764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
621864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian/// struct _protocol_t {
621964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian///   id isa;  // NULL
62204e825dfc1260163564ae0f072089c4411b39e2e5Fariborz Jahanian///   const char *protocol_name;
622164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian///   const struct _protocol_list_t * protocol_list; // super protocols
62224e825dfc1260163564ae0f072089c4411b39e2e5Fariborz Jahanian///   const struct method_list_t *instance_methods;
62234e825dfc1260163564ae0f072089c4411b39e2e5Fariborz Jahanian///   const struct method_list_t *class_methods;
622464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian///   const struct method_list_t *optionalInstanceMethods;
622564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian///   const struct method_list_t *optionalClassMethods;
622664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian///   const struct _prop_list_t * properties;
622764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian///   const uint32_t size;  // sizeof(struct _protocol_t)
622864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian///   const uint32_t flags;  // = 0
622964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian///   const char ** extendedMethodTypes;
623064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian/// }
623164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
623242e9a35ce0676f1ad2adf83ee1f1f4f503596353Fariborz Jahanian/// struct _ivar_t {
623342e9a35ce0676f1ad2adf83ee1f1f4f503596353Fariborz Jahanian///   unsigned long int *offset;  // pointer to ivar offset location
6234ae9329570ba16e48ffdfe3d55349b53fd893a711Fariborz Jahanian///   const char *name;
6235ae9329570ba16e48ffdfe3d55349b53fd893a711Fariborz Jahanian///   const char *type;
623642e9a35ce0676f1ad2adf83ee1f1f4f503596353Fariborz Jahanian///   uint32_t alignment;
623742e9a35ce0676f1ad2adf83ee1f1f4f503596353Fariborz Jahanian///   uint32_t size;
623842e9a35ce0676f1ad2adf83ee1f1f4f503596353Fariborz Jahanian/// }
623942e9a35ce0676f1ad2adf83ee1f1f4f503596353Fariborz Jahanian
624042e9a35ce0676f1ad2adf83ee1f1f4f503596353Fariborz Jahanian/// struct _ivar_list_t {
624142e9a35ce0676f1ad2adf83ee1f1f4f503596353Fariborz Jahanian///   uint32 entsize;  // sizeof(struct _ivar_t)
624242e9a35ce0676f1ad2adf83ee1f1f4f503596353Fariborz Jahanian///   uint32 count;
6243ae9329570ba16e48ffdfe3d55349b53fd893a711Fariborz Jahanian///   struct _ivar_t list[count];
624442e9a35ce0676f1ad2adf83ee1f1f4f503596353Fariborz Jahanian/// }
624542e9a35ce0676f1ad2adf83ee1f1f4f503596353Fariborz Jahanian
624642e9a35ce0676f1ad2adf83ee1f1f4f503596353Fariborz Jahanian/// struct _class_ro_t {
6247249cd102cbea7410ed5cd4ab93dabf7804d79c7bFariborz Jahanian///   uint32_t flags;
6248249cd102cbea7410ed5cd4ab93dabf7804d79c7bFariborz Jahanian///   uint32_t instanceStart;
6249249cd102cbea7410ed5cd4ab93dabf7804d79c7bFariborz Jahanian///   uint32_t instanceSize;
6250249cd102cbea7410ed5cd4ab93dabf7804d79c7bFariborz Jahanian///   uint32_t reserved;  // only when building for 64bit targets
62514e825dfc1260163564ae0f072089c4411b39e2e5Fariborz Jahanian///   const uint8_t *ivarLayout;
62524e825dfc1260163564ae0f072089c4411b39e2e5Fariborz Jahanian///   const char *name;
62534e825dfc1260163564ae0f072089c4411b39e2e5Fariborz Jahanian///   const struct _method_list_t *baseMethods;
62544e825dfc1260163564ae0f072089c4411b39e2e5Fariborz Jahanian///   const struct _protocol_list_t *baseProtocols;
62554e825dfc1260163564ae0f072089c4411b39e2e5Fariborz Jahanian///   const struct _ivar_list_t *ivars;
62564e825dfc1260163564ae0f072089c4411b39e2e5Fariborz Jahanian///   const uint8_t *weakIvarLayout;
62574e825dfc1260163564ae0f072089c4411b39e2e5Fariborz Jahanian///   const struct _prop_list_t *properties;
625842e9a35ce0676f1ad2adf83ee1f1f4f503596353Fariborz Jahanian/// }
625942e9a35ce0676f1ad2adf83ee1f1f4f503596353Fariborz Jahanian
626042e9a35ce0676f1ad2adf83ee1f1f4f503596353Fariborz Jahanian/// struct _class_t {
626142e9a35ce0676f1ad2adf83ee1f1f4f503596353Fariborz Jahanian///   struct _class_t *isa;
6262fd4ce2c9d64032b42c037b2af3bf4ebeac5bbac8Fariborz Jahanian///   struct _class_t *superclass;
626342e9a35ce0676f1ad2adf83ee1f1f4f503596353Fariborz Jahanian///   void *cache;
626442e9a35ce0676f1ad2adf83ee1f1f4f503596353Fariborz Jahanian///   IMP *vtable;
62653f77c7b56d515a6756dba63a3dfa0a332711a779Fariborz Jahanian///   struct _class_ro_t *ro;
626642e9a35ce0676f1ad2adf83ee1f1f4f503596353Fariborz Jahanian/// }
626742e9a35ce0676f1ad2adf83ee1f1f4f503596353Fariborz Jahanian
626842e9a35ce0676f1ad2adf83ee1f1f4f503596353Fariborz Jahanian/// struct _category_t {
62694e825dfc1260163564ae0f072089c4411b39e2e5Fariborz Jahanian///   const char *name;
62704b2fe6e48fe72122fc749a79953755c6fa055900Fariborz Jahanian///   struct _class_t *cls;
62714e825dfc1260163564ae0f072089c4411b39e2e5Fariborz Jahanian///   const struct _method_list_t *instance_methods;
62724e825dfc1260163564ae0f072089c4411b39e2e5Fariborz Jahanian///   const struct _method_list_t *class_methods;
62734e825dfc1260163564ae0f072089c4411b39e2e5Fariborz Jahanian///   const struct _protocol_list_t *protocols;
62744e825dfc1260163564ae0f072089c4411b39e2e5Fariborz Jahanian///   const struct _prop_list_t *properties;
627542e9a35ce0676f1ad2adf83ee1f1f4f503596353Fariborz Jahanian/// }
627642e9a35ce0676f1ad2adf83ee1f1f4f503596353Fariborz Jahanian
627742e9a35ce0676f1ad2adf83ee1f1f4f503596353Fariborz Jahanian/// MessageRefTy - LLVM for:
627842e9a35ce0676f1ad2adf83ee1f1f4f503596353Fariborz Jahanian/// struct _message_ref_t {
627942e9a35ce0676f1ad2adf83ee1f1f4f503596353Fariborz Jahanian///   IMP messenger;
628042e9a35ce0676f1ad2adf83ee1f1f4f503596353Fariborz Jahanian///   SEL name;
628142e9a35ce0676f1ad2adf83ee1f1f4f503596353Fariborz Jahanian/// };
628242e9a35ce0676f1ad2adf83ee1f1f4f503596353Fariborz Jahanian
628342e9a35ce0676f1ad2adf83ee1f1f4f503596353Fariborz Jahanian/// SuperMessageRefTy - LLVM for:
628442e9a35ce0676f1ad2adf83ee1f1f4f503596353Fariborz Jahanian/// struct _super_message_ref_t {
628542e9a35ce0676f1ad2adf83ee1f1f4f503596353Fariborz Jahanian///   SUPER_IMP messenger;
628642e9a35ce0676f1ad2adf83ee1f1f4f503596353Fariborz Jahanian///   SEL name;
628742e9a35ce0676f1ad2adf83ee1f1f4f503596353Fariborz Jahanian/// };
628842e9a35ce0676f1ad2adf83ee1f1f4f503596353Fariborz Jahanian
6289de5d946288bb3d68576c95974beb8cfd21d7043aFariborz Jahanianstatic void WriteModernMetadataDeclarations(ASTContext *Context, std::string &Result) {
629064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  static bool meta_data_declared = false;
629164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  if (meta_data_declared)
629264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    return;
629364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
629464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  Result += "\nstruct _prop_t {\n";
6295da35eacc6e05a99ab30f7290f1d42df32d06b22eFariborz Jahanian  Result += "\tconst char *name;\n";
6296da35eacc6e05a99ab30f7290f1d42df32d06b22eFariborz Jahanian  Result += "\tconst char *attributes;\n";
629764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  Result += "};\n";
629864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
629964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  Result += "\nstruct _protocol_t;\n";
630064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
630164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  Result += "\nstruct _objc_method {\n";
630264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  Result += "\tstruct objc_selector * _cmd;\n";
630377e4bcacd5c80d8bffe19a4489b5f059b618d4bcFariborz Jahanian  Result += "\tconst char *method_type;\n";
630490af4e22a8fb83f159b512bfd48fb77699337b3dFariborz Jahanian  Result += "\tvoid  *_imp;\n";
630564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  Result += "};\n";
630664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
630764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  Result += "\nstruct _protocol_t {\n";
630864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  Result += "\tvoid * isa;  // NULL\n";
63094e825dfc1260163564ae0f072089c4411b39e2e5Fariborz Jahanian  Result += "\tconst char *protocol_name;\n";
631064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  Result += "\tconst struct _protocol_list_t * protocol_list; // super protocols\n";
63114e825dfc1260163564ae0f072089c4411b39e2e5Fariborz Jahanian  Result += "\tconst struct method_list_t *instance_methods;\n";
63124e825dfc1260163564ae0f072089c4411b39e2e5Fariborz Jahanian  Result += "\tconst struct method_list_t *class_methods;\n";
631364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  Result += "\tconst struct method_list_t *optionalInstanceMethods;\n";
631464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  Result += "\tconst struct method_list_t *optionalClassMethods;\n";
631564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  Result += "\tconst struct _prop_list_t * properties;\n";
631664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  Result += "\tconst unsigned int size;  // sizeof(struct _protocol_t)\n";
631764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  Result += "\tconst unsigned int flags;  // = 0\n";
631864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  Result += "\tconst char ** extendedMethodTypes;\n";
631964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  Result += "};\n";
632064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
632142e9a35ce0676f1ad2adf83ee1f1f4f503596353Fariborz Jahanian  Result += "\nstruct _ivar_t {\n";
632242e9a35ce0676f1ad2adf83ee1f1f4f503596353Fariborz Jahanian  Result += "\tunsigned long int *offset;  // pointer to ivar offset location\n";
6323ae9329570ba16e48ffdfe3d55349b53fd893a711Fariborz Jahanian  Result += "\tconst char *name;\n";
6324ae9329570ba16e48ffdfe3d55349b53fd893a711Fariborz Jahanian  Result += "\tconst char *type;\n";
632542e9a35ce0676f1ad2adf83ee1f1f4f503596353Fariborz Jahanian  Result += "\tunsigned int alignment;\n";
632642e9a35ce0676f1ad2adf83ee1f1f4f503596353Fariborz Jahanian  Result += "\tunsigned int  size;\n";
632742e9a35ce0676f1ad2adf83ee1f1f4f503596353Fariborz Jahanian  Result += "};\n";
632842e9a35ce0676f1ad2adf83ee1f1f4f503596353Fariborz Jahanian
632942e9a35ce0676f1ad2adf83ee1f1f4f503596353Fariborz Jahanian  Result += "\nstruct _class_ro_t {\n";
6330249cd102cbea7410ed5cd4ab93dabf7804d79c7bFariborz Jahanian  Result += "\tunsigned int flags;\n";
633142e9a35ce0676f1ad2adf83ee1f1f4f503596353Fariborz Jahanian  Result += "\tunsigned int instanceStart;\n";
6332249cd102cbea7410ed5cd4ab93dabf7804d79c7bFariborz Jahanian  Result += "\tunsigned int instanceSize;\n";
6333de5d946288bb3d68576c95974beb8cfd21d7043aFariborz Jahanian  const llvm::Triple &Triple(Context->getTargetInfo().getTriple());
6334de5d946288bb3d68576c95974beb8cfd21d7043aFariborz Jahanian  if (Triple.getArch() == llvm::Triple::x86_64)
6335249cd102cbea7410ed5cd4ab93dabf7804d79c7bFariborz Jahanian    Result += "\tunsigned int reserved;\n";
63364e825dfc1260163564ae0f072089c4411b39e2e5Fariborz Jahanian  Result += "\tconst unsigned char *ivarLayout;\n";
63374e825dfc1260163564ae0f072089c4411b39e2e5Fariborz Jahanian  Result += "\tconst char *name;\n";
63384e825dfc1260163564ae0f072089c4411b39e2e5Fariborz Jahanian  Result += "\tconst struct _method_list_t *baseMethods;\n";
63394e825dfc1260163564ae0f072089c4411b39e2e5Fariborz Jahanian  Result += "\tconst struct _objc_protocol_list *baseProtocols;\n";
63404e825dfc1260163564ae0f072089c4411b39e2e5Fariborz Jahanian  Result += "\tconst struct _ivar_list_t *ivars;\n";
63414e825dfc1260163564ae0f072089c4411b39e2e5Fariborz Jahanian  Result += "\tconst unsigned char *weakIvarLayout;\n";
63424e825dfc1260163564ae0f072089c4411b39e2e5Fariborz Jahanian  Result += "\tconst struct _prop_list_t *properties;\n";
634342e9a35ce0676f1ad2adf83ee1f1f4f503596353Fariborz Jahanian  Result += "};\n";
634442e9a35ce0676f1ad2adf83ee1f1f4f503596353Fariborz Jahanian
634542e9a35ce0676f1ad2adf83ee1f1f4f503596353Fariborz Jahanian  Result += "\nstruct _class_t {\n";
634642e9a35ce0676f1ad2adf83ee1f1f4f503596353Fariborz Jahanian  Result += "\tstruct _class_t *isa;\n";
6347fd4ce2c9d64032b42c037b2af3bf4ebeac5bbac8Fariborz Jahanian  Result += "\tstruct _class_t *superclass;\n";
634842e9a35ce0676f1ad2adf83ee1f1f4f503596353Fariborz Jahanian  Result += "\tvoid *cache;\n";
634942e9a35ce0676f1ad2adf83ee1f1f4f503596353Fariborz Jahanian  Result += "\tvoid *vtable;\n";
63503f77c7b56d515a6756dba63a3dfa0a332711a779Fariborz Jahanian  Result += "\tstruct _class_ro_t *ro;\n";
635142e9a35ce0676f1ad2adf83ee1f1f4f503596353Fariborz Jahanian  Result += "};\n";
635242e9a35ce0676f1ad2adf83ee1f1f4f503596353Fariborz Jahanian
635342e9a35ce0676f1ad2adf83ee1f1f4f503596353Fariborz Jahanian  Result += "\nstruct _category_t {\n";
63544e825dfc1260163564ae0f072089c4411b39e2e5Fariborz Jahanian  Result += "\tconst char *name;\n";
63554b2fe6e48fe72122fc749a79953755c6fa055900Fariborz Jahanian  Result += "\tstruct _class_t *cls;\n";
63564e825dfc1260163564ae0f072089c4411b39e2e5Fariborz Jahanian  Result += "\tconst struct _method_list_t *instance_methods;\n";
63574e825dfc1260163564ae0f072089c4411b39e2e5Fariborz Jahanian  Result += "\tconst struct _method_list_t *class_methods;\n";
63584e825dfc1260163564ae0f072089c4411b39e2e5Fariborz Jahanian  Result += "\tconst struct _protocol_list_t *protocols;\n";
63594e825dfc1260163564ae0f072089c4411b39e2e5Fariborz Jahanian  Result += "\tconst struct _prop_list_t *properties;\n";
636042e9a35ce0676f1ad2adf83ee1f1f4f503596353Fariborz Jahanian  Result += "};\n";
636142e9a35ce0676f1ad2adf83ee1f1f4f503596353Fariborz Jahanian
63623f162c398be7fd02167e7382b3a6728c7b2b672dFariborz Jahanian  Result += "extern \"C\" __declspec(dllimport) struct objc_cache _objc_empty_cache;\n";
6363297976d3dc9a5c402b52c734dc06d69f2f987e1cFariborz Jahanian  Result += "#pragma warning(disable:4273)\n";
636464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  meta_data_declared = true;
636564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian}
636664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
6367da9624a77352bc61b9713c31edd671c02a3ff260Fariborz Jahanianstatic void Write_protocol_list_t_TypeDecl(std::string &Result,
6368da9624a77352bc61b9713c31edd671c02a3ff260Fariborz Jahanian                                           long super_protocol_count) {
6369da9624a77352bc61b9713c31edd671c02a3ff260Fariborz Jahanian  Result += "struct /*_protocol_list_t*/"; Result += " {\n";
6370da9624a77352bc61b9713c31edd671c02a3ff260Fariborz Jahanian  Result += "\tlong protocol_count;  // Note, this is 32/64 bit\n";
6371da9624a77352bc61b9713c31edd671c02a3ff260Fariborz Jahanian  Result += "\tstruct _protocol_t *super_protocols[";
6372da9624a77352bc61b9713c31edd671c02a3ff260Fariborz Jahanian  Result += utostr(super_protocol_count); Result += "];\n";
6373da9624a77352bc61b9713c31edd671c02a3ff260Fariborz Jahanian  Result += "}";
6374da9624a77352bc61b9713c31edd671c02a3ff260Fariborz Jahanian}
6375da9624a77352bc61b9713c31edd671c02a3ff260Fariborz Jahanian
637677e4bcacd5c80d8bffe19a4489b5f059b618d4bcFariborz Jahanianstatic void Write_method_list_t_TypeDecl(std::string &Result,
637777e4bcacd5c80d8bffe19a4489b5f059b618d4bcFariborz Jahanian                                         unsigned int method_count) {
637877e4bcacd5c80d8bffe19a4489b5f059b618d4bcFariborz Jahanian  Result += "struct /*_method_list_t*/"; Result += " {\n";
637977e4bcacd5c80d8bffe19a4489b5f059b618d4bcFariborz Jahanian  Result += "\tunsigned int entsize;  // sizeof(struct _objc_method)\n";
638077e4bcacd5c80d8bffe19a4489b5f059b618d4bcFariborz Jahanian  Result += "\tunsigned int method_count;\n";
638177e4bcacd5c80d8bffe19a4489b5f059b618d4bcFariborz Jahanian  Result += "\tstruct _objc_method method_list[";
638277e4bcacd5c80d8bffe19a4489b5f059b618d4bcFariborz Jahanian  Result += utostr(method_count); Result += "];\n";
638377e4bcacd5c80d8bffe19a4489b5f059b618d4bcFariborz Jahanian  Result += "}";
638477e4bcacd5c80d8bffe19a4489b5f059b618d4bcFariborz Jahanian}
638577e4bcacd5c80d8bffe19a4489b5f059b618d4bcFariborz Jahanian
6386da35eacc6e05a99ab30f7290f1d42df32d06b22eFariborz Jahanianstatic void Write__prop_list_t_TypeDecl(std::string &Result,
6387da35eacc6e05a99ab30f7290f1d42df32d06b22eFariborz Jahanian                                        unsigned int property_count) {
6388da35eacc6e05a99ab30f7290f1d42df32d06b22eFariborz Jahanian  Result += "struct /*_prop_list_t*/"; Result += " {\n";
6389da35eacc6e05a99ab30f7290f1d42df32d06b22eFariborz Jahanian  Result += "\tunsigned int entsize;  // sizeof(struct _prop_t)\n";
6390da35eacc6e05a99ab30f7290f1d42df32d06b22eFariborz Jahanian  Result += "\tunsigned int count_of_properties;\n";
6391da35eacc6e05a99ab30f7290f1d42df32d06b22eFariborz Jahanian  Result += "\tstruct _prop_t prop_list[";
6392da35eacc6e05a99ab30f7290f1d42df32d06b22eFariborz Jahanian  Result += utostr(property_count); Result += "];\n";
6393da35eacc6e05a99ab30f7290f1d42df32d06b22eFariborz Jahanian  Result += "}";
6394da35eacc6e05a99ab30f7290f1d42df32d06b22eFariborz Jahanian}
6395da35eacc6e05a99ab30f7290f1d42df32d06b22eFariborz Jahanian
6396ae9329570ba16e48ffdfe3d55349b53fd893a711Fariborz Jahanianstatic void Write__ivar_list_t_TypeDecl(std::string &Result,
6397ae9329570ba16e48ffdfe3d55349b53fd893a711Fariborz Jahanian                                        unsigned int ivar_count) {
6398ae9329570ba16e48ffdfe3d55349b53fd893a711Fariborz Jahanian  Result += "struct /*_ivar_list_t*/"; Result += " {\n";
6399ae9329570ba16e48ffdfe3d55349b53fd893a711Fariborz Jahanian  Result += "\tunsigned int entsize;  // sizeof(struct _prop_t)\n";
6400ae9329570ba16e48ffdfe3d55349b53fd893a711Fariborz Jahanian  Result += "\tunsigned int count;\n";
6401ae9329570ba16e48ffdfe3d55349b53fd893a711Fariborz Jahanian  Result += "\tstruct _ivar_t ivar_list[";
6402ae9329570ba16e48ffdfe3d55349b53fd893a711Fariborz Jahanian  Result += utostr(ivar_count); Result += "];\n";
6403ae9329570ba16e48ffdfe3d55349b53fd893a711Fariborz Jahanian  Result += "}";
6404ae9329570ba16e48ffdfe3d55349b53fd893a711Fariborz Jahanian}
6405ae9329570ba16e48ffdfe3d55349b53fd893a711Fariborz Jahanian
6406da9624a77352bc61b9713c31edd671c02a3ff260Fariborz Jahanianstatic void Write_protocol_list_initializer(ASTContext *Context, std::string &Result,
6407da9624a77352bc61b9713c31edd671c02a3ff260Fariborz Jahanian                                            ArrayRef<ObjCProtocolDecl *> SuperProtocols,
6408da9624a77352bc61b9713c31edd671c02a3ff260Fariborz Jahanian                                            StringRef VarName,
6409da9624a77352bc61b9713c31edd671c02a3ff260Fariborz Jahanian                                            StringRef ProtocolName) {
6410da9624a77352bc61b9713c31edd671c02a3ff260Fariborz Jahanian  if (SuperProtocols.size() > 0) {
6411da9624a77352bc61b9713c31edd671c02a3ff260Fariborz Jahanian    Result += "\nstatic ";
6412da9624a77352bc61b9713c31edd671c02a3ff260Fariborz Jahanian    Write_protocol_list_t_TypeDecl(Result, SuperProtocols.size());
6413da9624a77352bc61b9713c31edd671c02a3ff260Fariborz Jahanian    Result += " "; Result += VarName;
6414da9624a77352bc61b9713c31edd671c02a3ff260Fariborz Jahanian    Result += ProtocolName;
6415da9624a77352bc61b9713c31edd671c02a3ff260Fariborz Jahanian    Result += " __attribute__ ((used, section (\"__DATA,__objc_const\"))) = {\n";
6416da9624a77352bc61b9713c31edd671c02a3ff260Fariborz Jahanian    Result += "\t"; Result += utostr(SuperProtocols.size()); Result += ",\n";
6417da9624a77352bc61b9713c31edd671c02a3ff260Fariborz Jahanian    for (unsigned i = 0, e = SuperProtocols.size(); i < e; i++) {
6418da9624a77352bc61b9713c31edd671c02a3ff260Fariborz Jahanian      ObjCProtocolDecl *SuperPD = SuperProtocols[i];
6419da9624a77352bc61b9713c31edd671c02a3ff260Fariborz Jahanian      Result += "\t&"; Result += "_OBJC_PROTOCOL_";
6420da9624a77352bc61b9713c31edd671c02a3ff260Fariborz Jahanian      Result += SuperPD->getNameAsString();
6421da9624a77352bc61b9713c31edd671c02a3ff260Fariborz Jahanian      if (i == e-1)
6422da9624a77352bc61b9713c31edd671c02a3ff260Fariborz Jahanian        Result += "\n};\n";
6423da9624a77352bc61b9713c31edd671c02a3ff260Fariborz Jahanian      else
6424da9624a77352bc61b9713c31edd671c02a3ff260Fariborz Jahanian        Result += ",\n";
6425da9624a77352bc61b9713c31edd671c02a3ff260Fariborz Jahanian    }
6426da9624a77352bc61b9713c31edd671c02a3ff260Fariborz Jahanian  }
6427da9624a77352bc61b9713c31edd671c02a3ff260Fariborz Jahanian}
6428da9624a77352bc61b9713c31edd671c02a3ff260Fariborz Jahanian
642990af4e22a8fb83f159b512bfd48fb77699337b3dFariborz Jahanianstatic void Write_method_list_t_initializer(RewriteModernObjC &RewriteObj,
643090af4e22a8fb83f159b512bfd48fb77699337b3dFariborz Jahanian                                            ASTContext *Context, std::string &Result,
643177e4bcacd5c80d8bffe19a4489b5f059b618d4bcFariborz Jahanian                                            ArrayRef<ObjCMethodDecl *> Methods,
643277e4bcacd5c80d8bffe19a4489b5f059b618d4bcFariborz Jahanian                                            StringRef VarName,
643390af4e22a8fb83f159b512bfd48fb77699337b3dFariborz Jahanian                                            StringRef TopLevelDeclName,
643490af4e22a8fb83f159b512bfd48fb77699337b3dFariborz Jahanian                                            bool MethodImpl) {
643577e4bcacd5c80d8bffe19a4489b5f059b618d4bcFariborz Jahanian  if (Methods.size() > 0) {
643677e4bcacd5c80d8bffe19a4489b5f059b618d4bcFariborz Jahanian    Result += "\nstatic ";
643777e4bcacd5c80d8bffe19a4489b5f059b618d4bcFariborz Jahanian    Write_method_list_t_TypeDecl(Result, Methods.size());
643877e4bcacd5c80d8bffe19a4489b5f059b618d4bcFariborz Jahanian    Result += " "; Result += VarName;
643990af4e22a8fb83f159b512bfd48fb77699337b3dFariborz Jahanian    Result += TopLevelDeclName;
644077e4bcacd5c80d8bffe19a4489b5f059b618d4bcFariborz Jahanian    Result += " __attribute__ ((used, section (\"__DATA,__objc_const\"))) = {\n";
644177e4bcacd5c80d8bffe19a4489b5f059b618d4bcFariborz Jahanian    Result += "\t"; Result += "sizeof(_objc_method)"; Result += ",\n";
644277e4bcacd5c80d8bffe19a4489b5f059b618d4bcFariborz Jahanian    Result += "\t"; Result += utostr(Methods.size()); Result += ",\n";
644377e4bcacd5c80d8bffe19a4489b5f059b618d4bcFariborz Jahanian    for (unsigned i = 0, e = Methods.size(); i < e; i++) {
644477e4bcacd5c80d8bffe19a4489b5f059b618d4bcFariborz Jahanian      ObjCMethodDecl *MD = Methods[i];
644577e4bcacd5c80d8bffe19a4489b5f059b618d4bcFariborz Jahanian      if (i == 0)
644677e4bcacd5c80d8bffe19a4489b5f059b618d4bcFariborz Jahanian        Result += "\t{{(struct objc_selector *)\"";
644777e4bcacd5c80d8bffe19a4489b5f059b618d4bcFariborz Jahanian      else
644877e4bcacd5c80d8bffe19a4489b5f059b618d4bcFariborz Jahanian        Result += "\t{(struct objc_selector *)\"";
644977e4bcacd5c80d8bffe19a4489b5f059b618d4bcFariborz Jahanian      Result += (MD)->getSelector().getAsString(); Result += "\"";
645077e4bcacd5c80d8bffe19a4489b5f059b618d4bcFariborz Jahanian      Result += ", ";
645177e4bcacd5c80d8bffe19a4489b5f059b618d4bcFariborz Jahanian      std::string MethodTypeString;
645277e4bcacd5c80d8bffe19a4489b5f059b618d4bcFariborz Jahanian      Context->getObjCEncodingForMethodDecl(MD, MethodTypeString);
645377e4bcacd5c80d8bffe19a4489b5f059b618d4bcFariborz Jahanian      Result += "\""; Result += MethodTypeString; Result += "\"";
645477e4bcacd5c80d8bffe19a4489b5f059b618d4bcFariborz Jahanian      Result += ", ";
645590af4e22a8fb83f159b512bfd48fb77699337b3dFariborz Jahanian      if (!MethodImpl)
645690af4e22a8fb83f159b512bfd48fb77699337b3dFariborz Jahanian        Result += "0";
645790af4e22a8fb83f159b512bfd48fb77699337b3dFariborz Jahanian      else {
645890af4e22a8fb83f159b512bfd48fb77699337b3dFariborz Jahanian        Result += "(void *)";
645990af4e22a8fb83f159b512bfd48fb77699337b3dFariborz Jahanian        Result += RewriteObj.MethodInternalNames[MD];
646090af4e22a8fb83f159b512bfd48fb77699337b3dFariborz Jahanian      }
646177e4bcacd5c80d8bffe19a4489b5f059b618d4bcFariborz Jahanian      if (i  == e-1)
646290af4e22a8fb83f159b512bfd48fb77699337b3dFariborz Jahanian        Result += "}}\n";
646377e4bcacd5c80d8bffe19a4489b5f059b618d4bcFariborz Jahanian      else
646490af4e22a8fb83f159b512bfd48fb77699337b3dFariborz Jahanian        Result += "},\n";
646577e4bcacd5c80d8bffe19a4489b5f059b618d4bcFariborz Jahanian    }
646677e4bcacd5c80d8bffe19a4489b5f059b618d4bcFariborz Jahanian    Result += "};\n";
646777e4bcacd5c80d8bffe19a4489b5f059b618d4bcFariborz Jahanian  }
646877e4bcacd5c80d8bffe19a4489b5f059b618d4bcFariborz Jahanian}
646977e4bcacd5c80d8bffe19a4489b5f059b618d4bcFariborz Jahanian
6470f1c1d9a99dd02b2cd9c4052ec2ec759783175e5eFariborz Jahanianstatic void Write_prop_list_t_initializer(RewriteModernObjC &RewriteObj,
6471da35eacc6e05a99ab30f7290f1d42df32d06b22eFariborz Jahanian                                           ASTContext *Context, std::string &Result,
6472da35eacc6e05a99ab30f7290f1d42df32d06b22eFariborz Jahanian                                           ArrayRef<ObjCPropertyDecl *> Properties,
6473da35eacc6e05a99ab30f7290f1d42df32d06b22eFariborz Jahanian                                           const Decl *Container,
6474da35eacc6e05a99ab30f7290f1d42df32d06b22eFariborz Jahanian                                           StringRef VarName,
6475da35eacc6e05a99ab30f7290f1d42df32d06b22eFariborz Jahanian                                           StringRef ProtocolName) {
6476da35eacc6e05a99ab30f7290f1d42df32d06b22eFariborz Jahanian  if (Properties.size() > 0) {
6477da35eacc6e05a99ab30f7290f1d42df32d06b22eFariborz Jahanian    Result += "\nstatic ";
6478da35eacc6e05a99ab30f7290f1d42df32d06b22eFariborz Jahanian    Write__prop_list_t_TypeDecl(Result, Properties.size());
6479da35eacc6e05a99ab30f7290f1d42df32d06b22eFariborz Jahanian    Result += " "; Result += VarName;
6480da35eacc6e05a99ab30f7290f1d42df32d06b22eFariborz Jahanian    Result += ProtocolName;
6481da35eacc6e05a99ab30f7290f1d42df32d06b22eFariborz Jahanian    Result += " __attribute__ ((used, section (\"__DATA,__objc_const\"))) = {\n";
6482da35eacc6e05a99ab30f7290f1d42df32d06b22eFariborz Jahanian    Result += "\t"; Result += "sizeof(_prop_t)"; Result += ",\n";
6483da35eacc6e05a99ab30f7290f1d42df32d06b22eFariborz Jahanian    Result += "\t"; Result += utostr(Properties.size()); Result += ",\n";
6484da35eacc6e05a99ab30f7290f1d42df32d06b22eFariborz Jahanian    for (unsigned i = 0, e = Properties.size(); i < e; i++) {
6485da35eacc6e05a99ab30f7290f1d42df32d06b22eFariborz Jahanian      ObjCPropertyDecl *PropDecl = Properties[i];
6486da35eacc6e05a99ab30f7290f1d42df32d06b22eFariborz Jahanian      if (i == 0)
6487da35eacc6e05a99ab30f7290f1d42df32d06b22eFariborz Jahanian        Result += "\t{{\"";
6488da35eacc6e05a99ab30f7290f1d42df32d06b22eFariborz Jahanian      else
6489da35eacc6e05a99ab30f7290f1d42df32d06b22eFariborz Jahanian        Result += "\t{\"";
6490da35eacc6e05a99ab30f7290f1d42df32d06b22eFariborz Jahanian      Result += PropDecl->getName(); Result += "\",";
6491da35eacc6e05a99ab30f7290f1d42df32d06b22eFariborz Jahanian      std::string PropertyTypeString, QuotePropertyTypeString;
6492da35eacc6e05a99ab30f7290f1d42df32d06b22eFariborz Jahanian      Context->getObjCEncodingForPropertyDecl(PropDecl, Container, PropertyTypeString);
6493da35eacc6e05a99ab30f7290f1d42df32d06b22eFariborz Jahanian      RewriteObj.QuoteDoublequotes(PropertyTypeString, QuotePropertyTypeString);
6494da35eacc6e05a99ab30f7290f1d42df32d06b22eFariborz Jahanian      Result += "\""; Result += QuotePropertyTypeString; Result += "\"";
6495da35eacc6e05a99ab30f7290f1d42df32d06b22eFariborz Jahanian      if (i  == e-1)
6496da35eacc6e05a99ab30f7290f1d42df32d06b22eFariborz Jahanian        Result += "}}\n";
6497da35eacc6e05a99ab30f7290f1d42df32d06b22eFariborz Jahanian      else
6498da35eacc6e05a99ab30f7290f1d42df32d06b22eFariborz Jahanian        Result += "},\n";
6499da35eacc6e05a99ab30f7290f1d42df32d06b22eFariborz Jahanian    }
6500da35eacc6e05a99ab30f7290f1d42df32d06b22eFariborz Jahanian    Result += "};\n";
6501da35eacc6e05a99ab30f7290f1d42df32d06b22eFariborz Jahanian  }
6502da35eacc6e05a99ab30f7290f1d42df32d06b22eFariborz Jahanian}
6503da35eacc6e05a99ab30f7290f1d42df32d06b22eFariborz Jahanian
65046ade343d180d029fc61b17377553deab99527ff2Fariborz Jahanian// Metadata flags
65056ade343d180d029fc61b17377553deab99527ff2Fariborz Jahanianenum MetaDataDlags {
65066ade343d180d029fc61b17377553deab99527ff2Fariborz Jahanian  CLS = 0x0,
65076ade343d180d029fc61b17377553deab99527ff2Fariborz Jahanian  CLS_META = 0x1,
65086ade343d180d029fc61b17377553deab99527ff2Fariborz Jahanian  CLS_ROOT = 0x2,
65096ade343d180d029fc61b17377553deab99527ff2Fariborz Jahanian  OBJC2_CLS_HIDDEN = 0x10,
65106ade343d180d029fc61b17377553deab99527ff2Fariborz Jahanian  CLS_EXCEPTION = 0x20,
65116ade343d180d029fc61b17377553deab99527ff2Fariborz Jahanian
65126ade343d180d029fc61b17377553deab99527ff2Fariborz Jahanian  /// (Obsolete) ARC-specific: this class has a .release_ivars method
65136ade343d180d029fc61b17377553deab99527ff2Fariborz Jahanian  CLS_HAS_IVAR_RELEASER = 0x40,
65146ade343d180d029fc61b17377553deab99527ff2Fariborz Jahanian  /// class was compiled with -fobjc-arr
65156ade343d180d029fc61b17377553deab99527ff2Fariborz Jahanian  CLS_COMPILED_BY_ARC = 0x80  // (1<<7)
65166ade343d180d029fc61b17377553deab99527ff2Fariborz Jahanian};
65176ade343d180d029fc61b17377553deab99527ff2Fariborz Jahanian
6518f1c1d9a99dd02b2cd9c4052ec2ec759783175e5eFariborz Jahanianstatic void Write__class_ro_t_initializer(ASTContext *Context, std::string &Result,
6519f1c1d9a99dd02b2cd9c4052ec2ec759783175e5eFariborz Jahanian                                          unsigned int flags,
6520f1c1d9a99dd02b2cd9c4052ec2ec759783175e5eFariborz Jahanian                                          const std::string &InstanceStart,
6521f1c1d9a99dd02b2cd9c4052ec2ec759783175e5eFariborz Jahanian                                          const std::string &InstanceSize,
6522f1c1d9a99dd02b2cd9c4052ec2ec759783175e5eFariborz Jahanian                                          ArrayRef<ObjCMethodDecl *>baseMethods,
6523f1c1d9a99dd02b2cd9c4052ec2ec759783175e5eFariborz Jahanian                                          ArrayRef<ObjCProtocolDecl *>baseProtocols,
6524f1c1d9a99dd02b2cd9c4052ec2ec759783175e5eFariborz Jahanian                                          ArrayRef<ObjCIvarDecl *>ivars,
6525f1c1d9a99dd02b2cd9c4052ec2ec759783175e5eFariborz Jahanian                                          ArrayRef<ObjCPropertyDecl *>Properties,
6526f1c1d9a99dd02b2cd9c4052ec2ec759783175e5eFariborz Jahanian                                          StringRef VarName,
6527f1c1d9a99dd02b2cd9c4052ec2ec759783175e5eFariborz Jahanian                                          StringRef ClassName) {
6528f1c1d9a99dd02b2cd9c4052ec2ec759783175e5eFariborz Jahanian  Result += "\nstatic struct _class_ro_t ";
6529f1c1d9a99dd02b2cd9c4052ec2ec759783175e5eFariborz Jahanian  Result += VarName; Result += ClassName;
6530f1c1d9a99dd02b2cd9c4052ec2ec759783175e5eFariborz Jahanian  Result += " __attribute__ ((used, section (\"__DATA,__objc_const\"))) = {\n";
6531f1c1d9a99dd02b2cd9c4052ec2ec759783175e5eFariborz Jahanian  Result += "\t";
6532f1c1d9a99dd02b2cd9c4052ec2ec759783175e5eFariborz Jahanian  Result += llvm::utostr(flags); Result += ", ";
6533f1c1d9a99dd02b2cd9c4052ec2ec759783175e5eFariborz Jahanian  Result += InstanceStart; Result += ", ";
6534f1c1d9a99dd02b2cd9c4052ec2ec759783175e5eFariborz Jahanian  Result += InstanceSize; Result += ", \n";
6535f1c1d9a99dd02b2cd9c4052ec2ec759783175e5eFariborz Jahanian  Result += "\t";
6536de5d946288bb3d68576c95974beb8cfd21d7043aFariborz Jahanian  const llvm::Triple &Triple(Context->getTargetInfo().getTriple());
6537de5d946288bb3d68576c95974beb8cfd21d7043aFariborz Jahanian  if (Triple.getArch() == llvm::Triple::x86_64)
6538de5d946288bb3d68576c95974beb8cfd21d7043aFariborz Jahanian    // uint32_t const reserved; // only when building for 64bit targets
6539de5d946288bb3d68576c95974beb8cfd21d7043aFariborz Jahanian    Result += "(unsigned int)0, \n\t";
6540f1c1d9a99dd02b2cd9c4052ec2ec759783175e5eFariborz Jahanian  // const uint8_t * const ivarLayout;
6541f1c1d9a99dd02b2cd9c4052ec2ec759783175e5eFariborz Jahanian  Result += "0, \n\t";
6542f1c1d9a99dd02b2cd9c4052ec2ec759783175e5eFariborz Jahanian  Result += "\""; Result += ClassName; Result += "\",\n\t";
65436ade343d180d029fc61b17377553deab99527ff2Fariborz Jahanian  bool metaclass = ((flags & CLS_META) != 0);
6544f1c1d9a99dd02b2cd9c4052ec2ec759783175e5eFariborz Jahanian  if (baseMethods.size() > 0) {
6545f1c1d9a99dd02b2cd9c4052ec2ec759783175e5eFariborz Jahanian    Result += "(const struct _method_list_t *)&";
65466ade343d180d029fc61b17377553deab99527ff2Fariborz Jahanian    if (metaclass)
65476ade343d180d029fc61b17377553deab99527ff2Fariborz Jahanian      Result += "_OBJC_$_CLASS_METHODS_";
65486ade343d180d029fc61b17377553deab99527ff2Fariborz Jahanian    else
65496ade343d180d029fc61b17377553deab99527ff2Fariborz Jahanian      Result += "_OBJC_$_INSTANCE_METHODS_";
65506ade343d180d029fc61b17377553deab99527ff2Fariborz Jahanian    Result += ClassName;
6551f1c1d9a99dd02b2cd9c4052ec2ec759783175e5eFariborz Jahanian    Result += ",\n\t";
6552f1c1d9a99dd02b2cd9c4052ec2ec759783175e5eFariborz Jahanian  }
6553f1c1d9a99dd02b2cd9c4052ec2ec759783175e5eFariborz Jahanian  else
6554f1c1d9a99dd02b2cd9c4052ec2ec759783175e5eFariborz Jahanian    Result += "0, \n\t";
6555f1c1d9a99dd02b2cd9c4052ec2ec759783175e5eFariborz Jahanian
65566ade343d180d029fc61b17377553deab99527ff2Fariborz Jahanian  if (!metaclass && baseProtocols.size() > 0) {
6557f1c1d9a99dd02b2cd9c4052ec2ec759783175e5eFariborz Jahanian    Result += "(const struct _objc_protocol_list *)&";
6558f1c1d9a99dd02b2cd9c4052ec2ec759783175e5eFariborz Jahanian    Result += "_OBJC_CLASS_PROTOCOLS_$_"; Result += ClassName;
6559f1c1d9a99dd02b2cd9c4052ec2ec759783175e5eFariborz Jahanian    Result += ",\n\t";
6560f1c1d9a99dd02b2cd9c4052ec2ec759783175e5eFariborz Jahanian  }
6561f1c1d9a99dd02b2cd9c4052ec2ec759783175e5eFariborz Jahanian  else
6562f1c1d9a99dd02b2cd9c4052ec2ec759783175e5eFariborz Jahanian    Result += "0, \n\t";
6563f1c1d9a99dd02b2cd9c4052ec2ec759783175e5eFariborz Jahanian
65646ade343d180d029fc61b17377553deab99527ff2Fariborz Jahanian  if (!metaclass && ivars.size() > 0) {
6565f1c1d9a99dd02b2cd9c4052ec2ec759783175e5eFariborz Jahanian    Result += "(const struct _ivar_list_t *)&";
6566f1c1d9a99dd02b2cd9c4052ec2ec759783175e5eFariborz Jahanian    Result += "_OBJC_$_INSTANCE_VARIABLES_"; Result += ClassName;
6567f1c1d9a99dd02b2cd9c4052ec2ec759783175e5eFariborz Jahanian    Result += ",\n\t";
6568f1c1d9a99dd02b2cd9c4052ec2ec759783175e5eFariborz Jahanian  }
6569f1c1d9a99dd02b2cd9c4052ec2ec759783175e5eFariborz Jahanian  else
6570f1c1d9a99dd02b2cd9c4052ec2ec759783175e5eFariborz Jahanian    Result += "0, \n\t";
6571f1c1d9a99dd02b2cd9c4052ec2ec759783175e5eFariborz Jahanian
6572f1c1d9a99dd02b2cd9c4052ec2ec759783175e5eFariborz Jahanian  // weakIvarLayout
6573f1c1d9a99dd02b2cd9c4052ec2ec759783175e5eFariborz Jahanian  Result += "0, \n\t";
65746ade343d180d029fc61b17377553deab99527ff2Fariborz Jahanian  if (!metaclass && Properties.size() > 0) {
6575f1c1d9a99dd02b2cd9c4052ec2ec759783175e5eFariborz Jahanian    Result += "(const struct _prop_list_t *)&";
6576eeabf381862e53519cd0f9f65c1cc2a983c72159Fariborz Jahanian    Result += "_OBJC_$_PROP_LIST_"; Result += ClassName;
6577f1c1d9a99dd02b2cd9c4052ec2ec759783175e5eFariborz Jahanian    Result += ",\n";
6578f1c1d9a99dd02b2cd9c4052ec2ec759783175e5eFariborz Jahanian  }
6579f1c1d9a99dd02b2cd9c4052ec2ec759783175e5eFariborz Jahanian  else
6580f1c1d9a99dd02b2cd9c4052ec2ec759783175e5eFariborz Jahanian    Result += "0, \n";
6581f1c1d9a99dd02b2cd9c4052ec2ec759783175e5eFariborz Jahanian
6582f1c1d9a99dd02b2cd9c4052ec2ec759783175e5eFariborz Jahanian  Result += "};\n";
6583f1c1d9a99dd02b2cd9c4052ec2ec759783175e5eFariborz Jahanian}
6584f1c1d9a99dd02b2cd9c4052ec2ec759783175e5eFariborz Jahanian
65853f77c7b56d515a6756dba63a3dfa0a332711a779Fariborz Jahanianstatic void Write_class_t(ASTContext *Context, std::string &Result,
65863f77c7b56d515a6756dba63a3dfa0a332711a779Fariborz Jahanian                          StringRef VarName,
6587a03e40ce9d729fca50e817351e3b1b48691dcd64Fariborz Jahanian                          const ObjCInterfaceDecl *CDecl, bool metaclass) {
6588a03e40ce9d729fca50e817351e3b1b48691dcd64Fariborz Jahanian  bool rootClass = (!CDecl->getSuperClass());
6589a03e40ce9d729fca50e817351e3b1b48691dcd64Fariborz Jahanian  const ObjCInterfaceDecl *RootClass = CDecl;
65903f77c7b56d515a6756dba63a3dfa0a332711a779Fariborz Jahanian
6591a03e40ce9d729fca50e817351e3b1b48691dcd64Fariborz Jahanian  if (!rootClass) {
6592a03e40ce9d729fca50e817351e3b1b48691dcd64Fariborz Jahanian    // Find the Root class
6593a03e40ce9d729fca50e817351e3b1b48691dcd64Fariborz Jahanian    RootClass = CDecl->getSuperClass();
6594a03e40ce9d729fca50e817351e3b1b48691dcd64Fariborz Jahanian    while (RootClass->getSuperClass()) {
6595a03e40ce9d729fca50e817351e3b1b48691dcd64Fariborz Jahanian      RootClass = RootClass->getSuperClass();
6596a03e40ce9d729fca50e817351e3b1b48691dcd64Fariborz Jahanian    }
6597a03e40ce9d729fca50e817351e3b1b48691dcd64Fariborz Jahanian  }
6598a03e40ce9d729fca50e817351e3b1b48691dcd64Fariborz Jahanian
6599a03e40ce9d729fca50e817351e3b1b48691dcd64Fariborz Jahanian  if (metaclass && rootClass) {
66003f77c7b56d515a6756dba63a3dfa0a332711a779Fariborz Jahanian    // Need to handle a case of use of forward declaration.
6601ce0d89744bdad195c991362bd6fc7b334e5c2d52Fariborz Jahanian    Result += "\n";
66023f162c398be7fd02167e7382b3a6728c7b2b672dFariborz Jahanian    Result += "extern \"C\" ";
6603ce0d89744bdad195c991362bd6fc7b334e5c2d52Fariborz Jahanian    if (CDecl->getImplementation())
6604ce0d89744bdad195c991362bd6fc7b334e5c2d52Fariborz Jahanian      Result += "__declspec(dllexport) ";
6605297976d3dc9a5c402b52c734dc06d69f2f987e1cFariborz Jahanian    else
6606297976d3dc9a5c402b52c734dc06d69f2f987e1cFariborz Jahanian      Result += "__declspec(dllimport) ";
6607297976d3dc9a5c402b52c734dc06d69f2f987e1cFariborz Jahanian
66083f162c398be7fd02167e7382b3a6728c7b2b672dFariborz Jahanian    Result += "struct _class_t OBJC_CLASS_$_";
66093f77c7b56d515a6756dba63a3dfa0a332711a779Fariborz Jahanian    Result += CDecl->getNameAsString();
66103f77c7b56d515a6756dba63a3dfa0a332711a779Fariborz Jahanian    Result += ";\n";
66113f77c7b56d515a6756dba63a3dfa0a332711a779Fariborz Jahanian  }
66123f77c7b56d515a6756dba63a3dfa0a332711a779Fariborz Jahanian  // Also, for possibility of 'super' metadata class not having been defined yet.
6613a03e40ce9d729fca50e817351e3b1b48691dcd64Fariborz Jahanian  if (!rootClass) {
6614868e985d4e2845cf19517dac932dfd013a8494b9Fariborz Jahanian    ObjCInterfaceDecl *SuperClass = CDecl->getSuperClass();
6615ce0d89744bdad195c991362bd6fc7b334e5c2d52Fariborz Jahanian    Result += "\n";
66163f162c398be7fd02167e7382b3a6728c7b2b672dFariborz Jahanian    Result += "extern \"C\" ";
6617868e985d4e2845cf19517dac932dfd013a8494b9Fariborz Jahanian    if (SuperClass->getImplementation())
6618ce0d89744bdad195c991362bd6fc7b334e5c2d52Fariborz Jahanian      Result += "__declspec(dllexport) ";
6619297976d3dc9a5c402b52c734dc06d69f2f987e1cFariborz Jahanian    else
6620297976d3dc9a5c402b52c734dc06d69f2f987e1cFariborz Jahanian      Result += "__declspec(dllimport) ";
6621297976d3dc9a5c402b52c734dc06d69f2f987e1cFariborz Jahanian
66223f162c398be7fd02167e7382b3a6728c7b2b672dFariborz Jahanian    Result += "struct _class_t ";
6623ce0d89744bdad195c991362bd6fc7b334e5c2d52Fariborz Jahanian    Result += VarName;
6624868e985d4e2845cf19517dac932dfd013a8494b9Fariborz Jahanian    Result += SuperClass->getNameAsString();
66253f77c7b56d515a6756dba63a3dfa0a332711a779Fariborz Jahanian    Result += ";\n";
6626452eac1fd71bc13c23eb034f5f66281ae27cf817Fariborz Jahanian
6627868e985d4e2845cf19517dac932dfd013a8494b9Fariborz Jahanian    if (metaclass && RootClass != SuperClass) {
66283f162c398be7fd02167e7382b3a6728c7b2b672dFariborz Jahanian      Result += "extern \"C\" ";
6629452eac1fd71bc13c23eb034f5f66281ae27cf817Fariborz Jahanian      if (RootClass->getImplementation())
6630452eac1fd71bc13c23eb034f5f66281ae27cf817Fariborz Jahanian        Result += "__declspec(dllexport) ";
6631297976d3dc9a5c402b52c734dc06d69f2f987e1cFariborz Jahanian      else
6632297976d3dc9a5c402b52c734dc06d69f2f987e1cFariborz Jahanian        Result += "__declspec(dllimport) ";
6633297976d3dc9a5c402b52c734dc06d69f2f987e1cFariborz Jahanian
66343f162c398be7fd02167e7382b3a6728c7b2b672dFariborz Jahanian      Result += "struct _class_t ";
6635452eac1fd71bc13c23eb034f5f66281ae27cf817Fariborz Jahanian      Result += VarName;
6636452eac1fd71bc13c23eb034f5f66281ae27cf817Fariborz Jahanian      Result += RootClass->getNameAsString();
6637452eac1fd71bc13c23eb034f5f66281ae27cf817Fariborz Jahanian      Result += ";\n";
6638452eac1fd71bc13c23eb034f5f66281ae27cf817Fariborz Jahanian    }
66393f77c7b56d515a6756dba63a3dfa0a332711a779Fariborz Jahanian  }
66403f77c7b56d515a6756dba63a3dfa0a332711a779Fariborz Jahanian
6641297976d3dc9a5c402b52c734dc06d69f2f987e1cFariborz Jahanian  Result += "\nextern \"C\" __declspec(dllexport) struct _class_t ";
6642297976d3dc9a5c402b52c734dc06d69f2f987e1cFariborz Jahanian  Result += VarName; Result += CDecl->getNameAsString();
66433f77c7b56d515a6756dba63a3dfa0a332711a779Fariborz Jahanian  Result += " __attribute__ ((used, section (\"__DATA,__objc_data\"))) = {\n";
66443f77c7b56d515a6756dba63a3dfa0a332711a779Fariborz Jahanian  Result += "\t";
6645a03e40ce9d729fca50e817351e3b1b48691dcd64Fariborz Jahanian  if (metaclass) {
6646a03e40ce9d729fca50e817351e3b1b48691dcd64Fariborz Jahanian    if (!rootClass) {
6647a03e40ce9d729fca50e817351e3b1b48691dcd64Fariborz Jahanian      Result += "0, // &"; Result += VarName;
6648a03e40ce9d729fca50e817351e3b1b48691dcd64Fariborz Jahanian      Result += RootClass->getNameAsString();
66493f77c7b56d515a6756dba63a3dfa0a332711a779Fariborz Jahanian      Result += ",\n\t";
6650a03e40ce9d729fca50e817351e3b1b48691dcd64Fariborz Jahanian      Result += "0, // &"; Result += VarName;
66513f77c7b56d515a6756dba63a3dfa0a332711a779Fariborz Jahanian      Result += CDecl->getSuperClass()->getNameAsString();
66523f77c7b56d515a6756dba63a3dfa0a332711a779Fariborz Jahanian      Result += ",\n\t";
66533f77c7b56d515a6756dba63a3dfa0a332711a779Fariborz Jahanian    }
66543f77c7b56d515a6756dba63a3dfa0a332711a779Fariborz Jahanian    else {
6655452eac1fd71bc13c23eb034f5f66281ae27cf817Fariborz Jahanian      Result += "0, // &"; Result += VarName;
66563f77c7b56d515a6756dba63a3dfa0a332711a779Fariborz Jahanian      Result += CDecl->getNameAsString();
66573f77c7b56d515a6756dba63a3dfa0a332711a779Fariborz Jahanian      Result += ",\n\t";
6658a03e40ce9d729fca50e817351e3b1b48691dcd64Fariborz Jahanian      Result += "0, // &OBJC_CLASS_$_"; Result += CDecl->getNameAsString();
66593f77c7b56d515a6756dba63a3dfa0a332711a779Fariborz Jahanian      Result += ",\n\t";
66603f77c7b56d515a6756dba63a3dfa0a332711a779Fariborz Jahanian    }
66613f77c7b56d515a6756dba63a3dfa0a332711a779Fariborz Jahanian  }
66623f77c7b56d515a6756dba63a3dfa0a332711a779Fariborz Jahanian  else {
6663a03e40ce9d729fca50e817351e3b1b48691dcd64Fariborz Jahanian    Result += "0, // &OBJC_METACLASS_$_";
66643f77c7b56d515a6756dba63a3dfa0a332711a779Fariborz Jahanian    Result += CDecl->getNameAsString();
66653f77c7b56d515a6756dba63a3dfa0a332711a779Fariborz Jahanian    Result += ",\n\t";
6666a03e40ce9d729fca50e817351e3b1b48691dcd64Fariborz Jahanian    if (!rootClass) {
6667a03e40ce9d729fca50e817351e3b1b48691dcd64Fariborz Jahanian      Result += "0, // &"; Result += VarName;
66683f77c7b56d515a6756dba63a3dfa0a332711a779Fariborz Jahanian      Result += CDecl->getSuperClass()->getNameAsString();
66693f77c7b56d515a6756dba63a3dfa0a332711a779Fariborz Jahanian      Result += ",\n\t";
66703f77c7b56d515a6756dba63a3dfa0a332711a779Fariborz Jahanian    }
66713f77c7b56d515a6756dba63a3dfa0a332711a779Fariborz Jahanian    else
66723f77c7b56d515a6756dba63a3dfa0a332711a779Fariborz Jahanian      Result += "0,\n\t";
66733f77c7b56d515a6756dba63a3dfa0a332711a779Fariborz Jahanian  }
6674a03e40ce9d729fca50e817351e3b1b48691dcd64Fariborz Jahanian  Result += "0, // (void *)&_objc_empty_cache,\n\t";
6675a03e40ce9d729fca50e817351e3b1b48691dcd64Fariborz Jahanian  Result += "0, // unused, was (void *)&_objc_empty_vtable,\n\t";
6676a03e40ce9d729fca50e817351e3b1b48691dcd64Fariborz Jahanian  if (metaclass)
66773f77c7b56d515a6756dba63a3dfa0a332711a779Fariborz Jahanian    Result += "&_OBJC_METACLASS_RO_$_";
66783f77c7b56d515a6756dba63a3dfa0a332711a779Fariborz Jahanian  else
66793f77c7b56d515a6756dba63a3dfa0a332711a779Fariborz Jahanian    Result += "&_OBJC_CLASS_RO_$_";
66803f77c7b56d515a6756dba63a3dfa0a332711a779Fariborz Jahanian  Result += CDecl->getNameAsString();
66813f77c7b56d515a6756dba63a3dfa0a332711a779Fariborz Jahanian  Result += ",\n};\n";
6682a03e40ce9d729fca50e817351e3b1b48691dcd64Fariborz Jahanian
6683a03e40ce9d729fca50e817351e3b1b48691dcd64Fariborz Jahanian  // Add static function to initialize some of the meta-data fields.
6684a03e40ce9d729fca50e817351e3b1b48691dcd64Fariborz Jahanian  // avoid doing it twice.
6685a03e40ce9d729fca50e817351e3b1b48691dcd64Fariborz Jahanian  if (metaclass)
6686a03e40ce9d729fca50e817351e3b1b48691dcd64Fariborz Jahanian    return;
6687a03e40ce9d729fca50e817351e3b1b48691dcd64Fariborz Jahanian
6688a03e40ce9d729fca50e817351e3b1b48691dcd64Fariborz Jahanian  const ObjCInterfaceDecl *SuperClass =
6689a03e40ce9d729fca50e817351e3b1b48691dcd64Fariborz Jahanian    rootClass ? CDecl : CDecl->getSuperClass();
6690a03e40ce9d729fca50e817351e3b1b48691dcd64Fariborz Jahanian
6691a03e40ce9d729fca50e817351e3b1b48691dcd64Fariborz Jahanian  Result += "static void OBJC_CLASS_SETUP_$_";
6692a03e40ce9d729fca50e817351e3b1b48691dcd64Fariborz Jahanian  Result += CDecl->getNameAsString();
6693a03e40ce9d729fca50e817351e3b1b48691dcd64Fariborz Jahanian  Result += "(void ) {\n";
6694a03e40ce9d729fca50e817351e3b1b48691dcd64Fariborz Jahanian  Result += "\tOBJC_METACLASS_$_"; Result += CDecl->getNameAsString();
6695a03e40ce9d729fca50e817351e3b1b48691dcd64Fariborz Jahanian  Result += ".isa = "; Result += "&OBJC_METACLASS_$_";
6696452eac1fd71bc13c23eb034f5f66281ae27cf817Fariborz Jahanian  Result += RootClass->getNameAsString(); Result += ";\n";
6697a03e40ce9d729fca50e817351e3b1b48691dcd64Fariborz Jahanian
6698a03e40ce9d729fca50e817351e3b1b48691dcd64Fariborz Jahanian  Result += "\tOBJC_METACLASS_$_"; Result += CDecl->getNameAsString();
6699452eac1fd71bc13c23eb034f5f66281ae27cf817Fariborz Jahanian  Result += ".superclass = ";
6700452eac1fd71bc13c23eb034f5f66281ae27cf817Fariborz Jahanian  if (rootClass)
6701452eac1fd71bc13c23eb034f5f66281ae27cf817Fariborz Jahanian    Result += "&OBJC_CLASS_$_";
6702452eac1fd71bc13c23eb034f5f66281ae27cf817Fariborz Jahanian  else
6703452eac1fd71bc13c23eb034f5f66281ae27cf817Fariborz Jahanian     Result += "&OBJC_METACLASS_$_";
6704452eac1fd71bc13c23eb034f5f66281ae27cf817Fariborz Jahanian
6705a03e40ce9d729fca50e817351e3b1b48691dcd64Fariborz Jahanian  Result += SuperClass->getNameAsString(); Result += ";\n";
6706a03e40ce9d729fca50e817351e3b1b48691dcd64Fariborz Jahanian
6707a03e40ce9d729fca50e817351e3b1b48691dcd64Fariborz Jahanian  Result += "\tOBJC_METACLASS_$_"; Result += CDecl->getNameAsString();
6708a03e40ce9d729fca50e817351e3b1b48691dcd64Fariborz Jahanian  Result += ".cache = "; Result += "&_objc_empty_cache"; Result += ";\n";
6709a03e40ce9d729fca50e817351e3b1b48691dcd64Fariborz Jahanian
6710a03e40ce9d729fca50e817351e3b1b48691dcd64Fariborz Jahanian  Result += "\tOBJC_CLASS_$_"; Result += CDecl->getNameAsString();
6711a03e40ce9d729fca50e817351e3b1b48691dcd64Fariborz Jahanian  Result += ".isa = "; Result += "&OBJC_METACLASS_$_";
6712a03e40ce9d729fca50e817351e3b1b48691dcd64Fariborz Jahanian  Result += CDecl->getNameAsString(); Result += ";\n";
6713a03e40ce9d729fca50e817351e3b1b48691dcd64Fariborz Jahanian
6714a03e40ce9d729fca50e817351e3b1b48691dcd64Fariborz Jahanian  if (!rootClass) {
6715a03e40ce9d729fca50e817351e3b1b48691dcd64Fariborz Jahanian    Result += "\tOBJC_CLASS_$_"; Result += CDecl->getNameAsString();
6716a03e40ce9d729fca50e817351e3b1b48691dcd64Fariborz Jahanian    Result += ".superclass = "; Result += "&OBJC_CLASS_$_";
6717a03e40ce9d729fca50e817351e3b1b48691dcd64Fariborz Jahanian    Result += SuperClass->getNameAsString(); Result += ";\n";
6718a03e40ce9d729fca50e817351e3b1b48691dcd64Fariborz Jahanian  }
6719a03e40ce9d729fca50e817351e3b1b48691dcd64Fariborz Jahanian
6720a03e40ce9d729fca50e817351e3b1b48691dcd64Fariborz Jahanian  Result += "\tOBJC_CLASS_$_"; Result += CDecl->getNameAsString();
6721a03e40ce9d729fca50e817351e3b1b48691dcd64Fariborz Jahanian  Result += ".cache = "; Result += "&_objc_empty_cache"; Result += ";\n";
6722a03e40ce9d729fca50e817351e3b1b48691dcd64Fariborz Jahanian  Result += "}\n";
67233f77c7b56d515a6756dba63a3dfa0a332711a779Fariborz Jahanian}
67243f77c7b56d515a6756dba63a3dfa0a332711a779Fariborz Jahanian
67256118612837887cbae365676d53cc3e1c258249aaFariborz Jahanianstatic void Write_category_t(RewriteModernObjC &RewriteObj, ASTContext *Context,
67266118612837887cbae365676d53cc3e1c258249aaFariborz Jahanian                             std::string &Result,
6727e0335786c17a6ca45966f66094146e9d8ba2d54aFariborz Jahanian                             ObjCCategoryDecl *CatDecl,
672888f7f75e35425f3f228473c4c84a2445793a39c1Fariborz Jahanian                             ObjCInterfaceDecl *ClassDecl,
67296118612837887cbae365676d53cc3e1c258249aaFariborz Jahanian                             ArrayRef<ObjCMethodDecl *> InstanceMethods,
67306118612837887cbae365676d53cc3e1c258249aaFariborz Jahanian                             ArrayRef<ObjCMethodDecl *> ClassMethods,
67316118612837887cbae365676d53cc3e1c258249aaFariborz Jahanian                             ArrayRef<ObjCProtocolDecl *> RefedProtocols,
67326118612837887cbae365676d53cc3e1c258249aaFariborz Jahanian                             ArrayRef<ObjCPropertyDecl *> ClassProperties) {
6733e0335786c17a6ca45966f66094146e9d8ba2d54aFariborz Jahanian  StringRef CatName = CatDecl->getName();
673420f89390c7f9eaf7c62bcc9145fbc5ba7725557bNAKAMURA Takumi  StringRef ClassName = ClassDecl->getName();
67358c00a1b66a1110d8354c3c48f0cbd037d5b04c38Fariborz Jahanian  // must declare an extern class object in case this class is not implemented
67368c00a1b66a1110d8354c3c48f0cbd037d5b04c38Fariborz Jahanian  // in this TU.
673788f7f75e35425f3f228473c4c84a2445793a39c1Fariborz Jahanian  Result += "\n";
67383f162c398be7fd02167e7382b3a6728c7b2b672dFariborz Jahanian  Result += "extern \"C\" ";
673988f7f75e35425f3f228473c4c84a2445793a39c1Fariborz Jahanian  if (ClassDecl->getImplementation())
674088f7f75e35425f3f228473c4c84a2445793a39c1Fariborz Jahanian    Result += "__declspec(dllexport) ";
6741297976d3dc9a5c402b52c734dc06d69f2f987e1cFariborz Jahanian  else
6742297976d3dc9a5c402b52c734dc06d69f2f987e1cFariborz Jahanian    Result += "__declspec(dllimport) ";
674388f7f75e35425f3f228473c4c84a2445793a39c1Fariborz Jahanian
67443f162c398be7fd02167e7382b3a6728c7b2b672dFariborz Jahanian  Result += "struct _class_t ";
67458c00a1b66a1110d8354c3c48f0cbd037d5b04c38Fariborz Jahanian  Result += "OBJC_CLASS_$_"; Result += ClassName;
67468c00a1b66a1110d8354c3c48f0cbd037d5b04c38Fariborz Jahanian  Result += ";\n";
67478c00a1b66a1110d8354c3c48f0cbd037d5b04c38Fariborz Jahanian
67486118612837887cbae365676d53cc3e1c258249aaFariborz Jahanian  Result += "\nstatic struct _category_t ";
67496118612837887cbae365676d53cc3e1c258249aaFariborz Jahanian  Result += "_OBJC_$_CATEGORY_";
67506118612837887cbae365676d53cc3e1c258249aaFariborz Jahanian  Result += ClassName; Result += "_$_"; Result += CatName;
67516118612837887cbae365676d53cc3e1c258249aaFariborz Jahanian  Result += " __attribute__ ((used, section (\"__DATA,__objc_const\"))) = \n";
67526118612837887cbae365676d53cc3e1c258249aaFariborz Jahanian  Result += "{\n";
67536118612837887cbae365676d53cc3e1c258249aaFariborz Jahanian  Result += "\t\""; Result += ClassName; Result += "\",\n";
67544b2fe6e48fe72122fc749a79953755c6fa055900Fariborz Jahanian  Result += "\t0, // &"; Result += "OBJC_CLASS_$_"; Result += ClassName;
67556118612837887cbae365676d53cc3e1c258249aaFariborz Jahanian  Result += ",\n";
67566118612837887cbae365676d53cc3e1c258249aaFariborz Jahanian  if (InstanceMethods.size() > 0) {
67576118612837887cbae365676d53cc3e1c258249aaFariborz Jahanian    Result += "\t(const struct _method_list_t *)&";
67586118612837887cbae365676d53cc3e1c258249aaFariborz Jahanian    Result += "_OBJC_$_CATEGORY_INSTANCE_METHODS_";
67596118612837887cbae365676d53cc3e1c258249aaFariborz Jahanian    Result += ClassName; Result += "_$_"; Result += CatName;
67606118612837887cbae365676d53cc3e1c258249aaFariborz Jahanian    Result += ",\n";
67616118612837887cbae365676d53cc3e1c258249aaFariborz Jahanian  }
67626118612837887cbae365676d53cc3e1c258249aaFariborz Jahanian  else
67636118612837887cbae365676d53cc3e1c258249aaFariborz Jahanian    Result += "\t0,\n";
67646118612837887cbae365676d53cc3e1c258249aaFariborz Jahanian
67656118612837887cbae365676d53cc3e1c258249aaFariborz Jahanian  if (ClassMethods.size() > 0) {
67666118612837887cbae365676d53cc3e1c258249aaFariborz Jahanian    Result += "\t(const struct _method_list_t *)&";
67676118612837887cbae365676d53cc3e1c258249aaFariborz Jahanian    Result += "_OBJC_$_CATEGORY_CLASS_METHODS_";
67686118612837887cbae365676d53cc3e1c258249aaFariborz Jahanian    Result += ClassName; Result += "_$_"; Result += CatName;
67696118612837887cbae365676d53cc3e1c258249aaFariborz Jahanian    Result += ",\n";
67706118612837887cbae365676d53cc3e1c258249aaFariborz Jahanian  }
67716118612837887cbae365676d53cc3e1c258249aaFariborz Jahanian  else
67726118612837887cbae365676d53cc3e1c258249aaFariborz Jahanian    Result += "\t0,\n";
67736118612837887cbae365676d53cc3e1c258249aaFariborz Jahanian
67746118612837887cbae365676d53cc3e1c258249aaFariborz Jahanian  if (RefedProtocols.size() > 0) {
67756118612837887cbae365676d53cc3e1c258249aaFariborz Jahanian    Result += "\t(const struct _protocol_list_t *)&";
67766118612837887cbae365676d53cc3e1c258249aaFariborz Jahanian    Result += "_OBJC_CATEGORY_PROTOCOLS_$_";
67776118612837887cbae365676d53cc3e1c258249aaFariborz Jahanian    Result += ClassName; Result += "_$_"; Result += CatName;
67786118612837887cbae365676d53cc3e1c258249aaFariborz Jahanian    Result += ",\n";
67796118612837887cbae365676d53cc3e1c258249aaFariborz Jahanian  }
67806118612837887cbae365676d53cc3e1c258249aaFariborz Jahanian  else
67816118612837887cbae365676d53cc3e1c258249aaFariborz Jahanian    Result += "\t0,\n";
67826118612837887cbae365676d53cc3e1c258249aaFariborz Jahanian
67836118612837887cbae365676d53cc3e1c258249aaFariborz Jahanian  if (ClassProperties.size() > 0) {
67846118612837887cbae365676d53cc3e1c258249aaFariborz Jahanian    Result += "\t(const struct _prop_list_t *)&";  Result += "_OBJC_$_PROP_LIST_";
67856118612837887cbae365676d53cc3e1c258249aaFariborz Jahanian    Result += ClassName; Result += "_$_"; Result += CatName;
67866118612837887cbae365676d53cc3e1c258249aaFariborz Jahanian    Result += ",\n";
67876118612837887cbae365676d53cc3e1c258249aaFariborz Jahanian  }
67886118612837887cbae365676d53cc3e1c258249aaFariborz Jahanian  else
67896118612837887cbae365676d53cc3e1c258249aaFariborz Jahanian    Result += "\t0,\n";
67906118612837887cbae365676d53cc3e1c258249aaFariborz Jahanian
67916118612837887cbae365676d53cc3e1c258249aaFariborz Jahanian  Result += "};\n";
67924b2fe6e48fe72122fc749a79953755c6fa055900Fariborz Jahanian
67934b2fe6e48fe72122fc749a79953755c6fa055900Fariborz Jahanian  // Add static function to initialize the class pointer in the category structure.
67944b2fe6e48fe72122fc749a79953755c6fa055900Fariborz Jahanian  Result += "static void OBJC_CATEGORY_SETUP_$_";
67954b2fe6e48fe72122fc749a79953755c6fa055900Fariborz Jahanian  Result += ClassDecl->getNameAsString();
67964b2fe6e48fe72122fc749a79953755c6fa055900Fariborz Jahanian  Result += "_$_";
67974b2fe6e48fe72122fc749a79953755c6fa055900Fariborz Jahanian  Result += CatName;
67984b2fe6e48fe72122fc749a79953755c6fa055900Fariborz Jahanian  Result += "(void ) {\n";
67994b2fe6e48fe72122fc749a79953755c6fa055900Fariborz Jahanian  Result += "\t_OBJC_$_CATEGORY_";
68004b2fe6e48fe72122fc749a79953755c6fa055900Fariborz Jahanian  Result += ClassDecl->getNameAsString();
68014b2fe6e48fe72122fc749a79953755c6fa055900Fariborz Jahanian  Result += "_$_";
68024b2fe6e48fe72122fc749a79953755c6fa055900Fariborz Jahanian  Result += CatName;
68034b2fe6e48fe72122fc749a79953755c6fa055900Fariborz Jahanian  Result += ".cls = "; Result += "&OBJC_CLASS_$_"; Result += ClassName;
68044b2fe6e48fe72122fc749a79953755c6fa055900Fariborz Jahanian  Result += ";\n}\n";
68056118612837887cbae365676d53cc3e1c258249aaFariborz Jahanian}
68066118612837887cbae365676d53cc3e1c258249aaFariborz Jahanian
6807e0adbd8386d9ff7312b74e4d2d1f27337f94732cFariborz Jahanianstatic void Write__extendedMethodTypes_initializer(RewriteModernObjC &RewriteObj,
6808e0adbd8386d9ff7312b74e4d2d1f27337f94732cFariborz Jahanian                                           ASTContext *Context, std::string &Result,
6809e0adbd8386d9ff7312b74e4d2d1f27337f94732cFariborz Jahanian                                           ArrayRef<ObjCMethodDecl *> Methods,
6810e0adbd8386d9ff7312b74e4d2d1f27337f94732cFariborz Jahanian                                           StringRef VarName,
6811e0adbd8386d9ff7312b74e4d2d1f27337f94732cFariborz Jahanian                                           StringRef ProtocolName) {
6812e0adbd8386d9ff7312b74e4d2d1f27337f94732cFariborz Jahanian  if (Methods.size() == 0)
6813e0adbd8386d9ff7312b74e4d2d1f27337f94732cFariborz Jahanian    return;
6814e0adbd8386d9ff7312b74e4d2d1f27337f94732cFariborz Jahanian
6815e0adbd8386d9ff7312b74e4d2d1f27337f94732cFariborz Jahanian  Result += "\nstatic const char *";
6816e0adbd8386d9ff7312b74e4d2d1f27337f94732cFariborz Jahanian  Result += VarName; Result += ProtocolName;
6817e0adbd8386d9ff7312b74e4d2d1f27337f94732cFariborz Jahanian  Result += " [] __attribute__ ((used, section (\"__DATA,__objc_const\"))) = \n";
6818e0adbd8386d9ff7312b74e4d2d1f27337f94732cFariborz Jahanian  Result += "{\n";
6819e0adbd8386d9ff7312b74e4d2d1f27337f94732cFariborz Jahanian  for (unsigned i = 0, e = Methods.size(); i < e; i++) {
6820e0adbd8386d9ff7312b74e4d2d1f27337f94732cFariborz Jahanian    ObjCMethodDecl *MD = Methods[i];
6821e0adbd8386d9ff7312b74e4d2d1f27337f94732cFariborz Jahanian    std::string MethodTypeString, QuoteMethodTypeString;
6822e0adbd8386d9ff7312b74e4d2d1f27337f94732cFariborz Jahanian    Context->getObjCEncodingForMethodDecl(MD, MethodTypeString, true);
6823e0adbd8386d9ff7312b74e4d2d1f27337f94732cFariborz Jahanian    RewriteObj.QuoteDoublequotes(MethodTypeString, QuoteMethodTypeString);
6824e0adbd8386d9ff7312b74e4d2d1f27337f94732cFariborz Jahanian    Result += "\t\""; Result += QuoteMethodTypeString; Result += "\"";
6825e0adbd8386d9ff7312b74e4d2d1f27337f94732cFariborz Jahanian    if (i == e-1)
6826e0adbd8386d9ff7312b74e4d2d1f27337f94732cFariborz Jahanian      Result += "\n};\n";
6827e0adbd8386d9ff7312b74e4d2d1f27337f94732cFariborz Jahanian    else {
6828e0adbd8386d9ff7312b74e4d2d1f27337f94732cFariborz Jahanian      Result += ",\n";
6829e0adbd8386d9ff7312b74e4d2d1f27337f94732cFariborz Jahanian    }
6830e0adbd8386d9ff7312b74e4d2d1f27337f94732cFariborz Jahanian  }
6831e0adbd8386d9ff7312b74e4d2d1f27337f94732cFariborz Jahanian}
6832e0adbd8386d9ff7312b74e4d2d1f27337f94732cFariborz Jahanian
6833acee1c9dbe180c6493d1bcda6a0a7ee4018ed7b1Fariborz Jahanianstatic void Write_IvarOffsetVar(RewriteModernObjC &RewriteObj,
6834acee1c9dbe180c6493d1bcda6a0a7ee4018ed7b1Fariborz Jahanian                                ASTContext *Context,
683540a777a157c00cc7e9c9db7197017d83311c76c6Fariborz Jahanian                                std::string &Result,
6836db64923b255daeb58c2168eb890e480c93a6c41cFariborz Jahanian                                ArrayRef<ObjCIvarDecl *> Ivars,
68377cb2a1b4b6ef60aa57a5f2e5e820a57adef3ea77Fariborz Jahanian                                ObjCInterfaceDecl *CDecl) {
6838db64923b255daeb58c2168eb890e480c93a6c41cFariborz Jahanian  // FIXME. visibilty of offset symbols may have to be set; for Darwin
6839db64923b255daeb58c2168eb890e480c93a6c41cFariborz Jahanian  // this is what happens:
6840db64923b255daeb58c2168eb890e480c93a6c41cFariborz Jahanian  /**
6841db64923b255daeb58c2168eb890e480c93a6c41cFariborz Jahanian   if (Ivar->getAccessControl() == ObjCIvarDecl::Private ||
6842db64923b255daeb58c2168eb890e480c93a6c41cFariborz Jahanian       Ivar->getAccessControl() == ObjCIvarDecl::Package ||
6843db64923b255daeb58c2168eb890e480c93a6c41cFariborz Jahanian       Class->getVisibility() == HiddenVisibility)
6844db64923b255daeb58c2168eb890e480c93a6c41cFariborz Jahanian     Visibility shoud be: HiddenVisibility;
6845db64923b255daeb58c2168eb890e480c93a6c41cFariborz Jahanian   else
6846db64923b255daeb58c2168eb890e480c93a6c41cFariborz Jahanian     Visibility shoud be: DefaultVisibility;
6847db64923b255daeb58c2168eb890e480c93a6c41cFariborz Jahanian  */
6848db64923b255daeb58c2168eb890e480c93a6c41cFariborz Jahanian
684907e5288c6532c8a61278fab4e0ae058ec81a0f5cFariborz Jahanian  Result += "\n";
685007e5288c6532c8a61278fab4e0ae058ec81a0f5cFariborz Jahanian  for (unsigned i =0, e = Ivars.size(); i < e; i++) {
685107e5288c6532c8a61278fab4e0ae058ec81a0f5cFariborz Jahanian    ObjCIvarDecl *IvarDecl = Ivars[i];
685240a777a157c00cc7e9c9db7197017d83311c76c6Fariborz Jahanian    if (Context->getLangOpts().MicrosoftExt)
685340a777a157c00cc7e9c9db7197017d83311c76c6Fariborz Jahanian      Result += "__declspec(allocate(\".objc_ivar$B\")) ";
685440a777a157c00cc7e9c9db7197017d83311c76c6Fariborz Jahanian
685540a777a157c00cc7e9c9db7197017d83311c76c6Fariborz Jahanian    if (!Context->getLangOpts().MicrosoftExt ||
685640a777a157c00cc7e9c9db7197017d83311c76c6Fariborz Jahanian        IvarDecl->getAccessControl() == ObjCIvarDecl::Private ||
6857117591f6247b186a4161459ad8603563cfd1c54cFariborz Jahanian        IvarDecl->getAccessControl() == ObjCIvarDecl::Package)
6858297976d3dc9a5c402b52c734dc06d69f2f987e1cFariborz Jahanian      Result += "extern \"C\" unsigned long int ";
6859d1c84d3c0206abdf8787dc5c00aaf3b016ed3226Fariborz Jahanian    else
6860297976d3dc9a5c402b52c734dc06d69f2f987e1cFariborz Jahanian      Result += "extern \"C\" __declspec(dllexport) unsigned long int ";
6861cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian    if (Ivars[i]->isBitField())
6862cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian      RewriteObj.ObjCIvarBitfieldGroupOffset(IvarDecl, Result);
6863cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian    else
6864cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian      WriteInternalIvarName(CDecl, IvarDecl, Result);
686507e5288c6532c8a61278fab4e0ae058ec81a0f5cFariborz Jahanian    Result += " __attribute__ ((used, section (\"__DATA,__objc_ivar\")))";
686607e5288c6532c8a61278fab4e0ae058ec81a0f5cFariborz Jahanian    Result += " = ";
6867acee1c9dbe180c6493d1bcda6a0a7ee4018ed7b1Fariborz Jahanian    RewriteObj.RewriteIvarOffsetComputation(IvarDecl, Result);
6868acee1c9dbe180c6493d1bcda6a0a7ee4018ed7b1Fariborz Jahanian    Result += ";\n";
6869cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian    if (Ivars[i]->isBitField()) {
6870cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian      // skip over rest of the ivar bitfields.
6871cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian      SKIP_BITFIELDS(i , e, Ivars);
6872cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian    }
6873db64923b255daeb58c2168eb890e480c93a6c41cFariborz Jahanian  }
6874db64923b255daeb58c2168eb890e480c93a6c41cFariborz Jahanian}
6875db64923b255daeb58c2168eb890e480c93a6c41cFariborz Jahanian
6876ae9329570ba16e48ffdfe3d55349b53fd893a711Fariborz Jahanianstatic void Write__ivar_list_t_initializer(RewriteModernObjC &RewriteObj,
6877ae9329570ba16e48ffdfe3d55349b53fd893a711Fariborz Jahanian                                           ASTContext *Context, std::string &Result,
6878cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian                                           ArrayRef<ObjCIvarDecl *> OriginalIvars,
6879ae9329570ba16e48ffdfe3d55349b53fd893a711Fariborz Jahanian                                           StringRef VarName,
68807cb2a1b4b6ef60aa57a5f2e5e820a57adef3ea77Fariborz Jahanian                                           ObjCInterfaceDecl *CDecl) {
6881cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian  if (OriginalIvars.size() > 0) {
6882cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian    Write_IvarOffsetVar(RewriteObj, Context, Result, OriginalIvars, CDecl);
6883cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian    SmallVector<ObjCIvarDecl *, 8> Ivars;
6884cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian    // strip off all but the first ivar bitfield from each group of ivars.
6885cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian    // Such ivars in the ivar list table will be replaced by their grouping struct
6886cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian    // 'ivar'.
6887cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian    for (unsigned i = 0, e = OriginalIvars.size(); i < e; i++) {
6888cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian      if (OriginalIvars[i]->isBitField()) {
6889cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian        Ivars.push_back(OriginalIvars[i]);
6890cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian        // skip over rest of the ivar bitfields.
6891cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian        SKIP_BITFIELDS(i , e, OriginalIvars);
6892cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian      }
6893cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian      else
6894cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian        Ivars.push_back(OriginalIvars[i]);
6895cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian    }
689607e5288c6532c8a61278fab4e0ae058ec81a0f5cFariborz Jahanian
6897ae9329570ba16e48ffdfe3d55349b53fd893a711Fariborz Jahanian    Result += "\nstatic ";
6898ae9329570ba16e48ffdfe3d55349b53fd893a711Fariborz Jahanian    Write__ivar_list_t_TypeDecl(Result, Ivars.size());
6899ae9329570ba16e48ffdfe3d55349b53fd893a711Fariborz Jahanian    Result += " "; Result += VarName;
69007cb2a1b4b6ef60aa57a5f2e5e820a57adef3ea77Fariborz Jahanian    Result += CDecl->getNameAsString();
6901ae9329570ba16e48ffdfe3d55349b53fd893a711Fariborz Jahanian    Result += " __attribute__ ((used, section (\"__DATA,__objc_const\"))) = {\n";
6902ae9329570ba16e48ffdfe3d55349b53fd893a711Fariborz Jahanian    Result += "\t"; Result += "sizeof(_ivar_t)"; Result += ",\n";
6903ae9329570ba16e48ffdfe3d55349b53fd893a711Fariborz Jahanian    Result += "\t"; Result += utostr(Ivars.size()); Result += ",\n";
6904ae9329570ba16e48ffdfe3d55349b53fd893a711Fariborz Jahanian    for (unsigned i =0, e = Ivars.size(); i < e; i++) {
6905ae9329570ba16e48ffdfe3d55349b53fd893a711Fariborz Jahanian      ObjCIvarDecl *IvarDecl = Ivars[i];
6906ae9329570ba16e48ffdfe3d55349b53fd893a711Fariborz Jahanian      if (i == 0)
6907ae9329570ba16e48ffdfe3d55349b53fd893a711Fariborz Jahanian        Result += "\t{{";
6908ae9329570ba16e48ffdfe3d55349b53fd893a711Fariborz Jahanian      else
6909ae9329570ba16e48ffdfe3d55349b53fd893a711Fariborz Jahanian        Result += "\t {";
69107cb2a1b4b6ef60aa57a5f2e5e820a57adef3ea77Fariborz Jahanian      Result += "(unsigned long int *)&";
6911cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian      if (Ivars[i]->isBitField())
6912cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian        RewriteObj.ObjCIvarBitfieldGroupOffset(IvarDecl, Result);
6913cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian      else
6914cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian        WriteInternalIvarName(CDecl, IvarDecl, Result);
6915db64923b255daeb58c2168eb890e480c93a6c41cFariborz Jahanian      Result += ", ";
6916ae9329570ba16e48ffdfe3d55349b53fd893a711Fariborz Jahanian
6917cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian      Result += "\"";
6918cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian      if (Ivars[i]->isBitField())
6919cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian        RewriteObj.ObjCIvarBitfieldGroupDecl(Ivars[i], Result);
6920cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian      else
6921cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian        Result += IvarDecl->getName();
6922cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian      Result += "\", ";
6923cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian
6924cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian      QualType IVQT = IvarDecl->getType();
6925cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian      if (IvarDecl->isBitField())
6926cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian        IVQT = RewriteObj.GetGroupRecordTypeForObjCIvarBitfield(IvarDecl);
6927cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian
6928ae9329570ba16e48ffdfe3d55349b53fd893a711Fariborz Jahanian      std::string IvarTypeString, QuoteIvarTypeString;
6929cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian      Context->getObjCEncodingForType(IVQT, IvarTypeString,
6930ae9329570ba16e48ffdfe3d55349b53fd893a711Fariborz Jahanian                                      IvarDecl);
6931ae9329570ba16e48ffdfe3d55349b53fd893a711Fariborz Jahanian      RewriteObj.QuoteDoublequotes(IvarTypeString, QuoteIvarTypeString);
6932ae9329570ba16e48ffdfe3d55349b53fd893a711Fariborz Jahanian      Result += "\""; Result += QuoteIvarTypeString; Result += "\", ";
6933ae9329570ba16e48ffdfe3d55349b53fd893a711Fariborz Jahanian
69348f1fed036eb78b747725560c10ad29d370d6ef62Fariborz Jahanian      // FIXME. this alignment represents the host alignment and need be changed to
69358f1fed036eb78b747725560c10ad29d370d6ef62Fariborz Jahanian      // represent the target alignment.
6936cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian      unsigned Align = Context->getTypeAlign(IVQT)/8;
69378f1fed036eb78b747725560c10ad29d370d6ef62Fariborz Jahanian      Align = llvm::Log2_32(Align);
6938ae9329570ba16e48ffdfe3d55349b53fd893a711Fariborz Jahanian      Result += llvm::utostr(Align); Result += ", ";
6939cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian      CharUnits Size = Context->getTypeSizeInChars(IVQT);
6940a63b422eda86b9ff5a08395dcfc288a31419038eFariborz Jahanian      Result += llvm::utostr(Size.getQuantity());
6941ae9329570ba16e48ffdfe3d55349b53fd893a711Fariborz Jahanian      if (i  == e-1)
6942ae9329570ba16e48ffdfe3d55349b53fd893a711Fariborz Jahanian        Result += "}}\n";
6943ae9329570ba16e48ffdfe3d55349b53fd893a711Fariborz Jahanian      else
6944ae9329570ba16e48ffdfe3d55349b53fd893a711Fariborz Jahanian        Result += "},\n";
6945ae9329570ba16e48ffdfe3d55349b53fd893a711Fariborz Jahanian    }
6946ae9329570ba16e48ffdfe3d55349b53fd893a711Fariborz Jahanian    Result += "};\n";
6947ae9329570ba16e48ffdfe3d55349b53fd893a711Fariborz Jahanian  }
6948ae9329570ba16e48ffdfe3d55349b53fd893a711Fariborz Jahanian}
6949ae9329570ba16e48ffdfe3d55349b53fd893a711Fariborz Jahanian
695064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian/// RewriteObjCProtocolMetaData - Rewrite protocols meta-data.
6951da9624a77352bc61b9713c31edd671c02a3ff260Fariborz Jahanianvoid RewriteModernObjC::RewriteObjCProtocolMetaData(ObjCProtocolDecl *PDecl,
6952da9624a77352bc61b9713c31edd671c02a3ff260Fariborz Jahanian                                                    std::string &Result) {
695364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
695464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  // Do not synthesize the protocol more than once.
695564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  if (ObjCSynthesizedProtocols.count(PDecl->getCanonicalDecl()))
695664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    return;
6957de5d946288bb3d68576c95974beb8cfd21d7043aFariborz Jahanian  WriteModernMetadataDeclarations(Context, Result);
695864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
695964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  if (ObjCProtocolDecl *Def = PDecl->getDefinition())
696064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    PDecl = Def;
6961da9624a77352bc61b9713c31edd671c02a3ff260Fariborz Jahanian  // Must write out all protocol definitions in current qualifier list,
6962da9624a77352bc61b9713c31edd671c02a3ff260Fariborz Jahanian  // and in their nested qualifiers before writing out current definition.
6963651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  for (auto *I : PDecl->protocols())
6964651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    RewriteObjCProtocolMetaData(I, Result);
696564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
696677e4bcacd5c80d8bffe19a4489b5f059b618d4bcFariborz Jahanian  // Construct method lists.
696777e4bcacd5c80d8bffe19a4489b5f059b618d4bcFariborz Jahanian  std::vector<ObjCMethodDecl *> InstanceMethods, ClassMethods;
696877e4bcacd5c80d8bffe19a4489b5f059b618d4bcFariborz Jahanian  std::vector<ObjCMethodDecl *> OptInstanceMethods, OptClassMethods;
6969651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  for (auto *MD : PDecl->instance_methods()) {
697077e4bcacd5c80d8bffe19a4489b5f059b618d4bcFariborz Jahanian    if (MD->getImplementationControl() == ObjCMethodDecl::Optional) {
697177e4bcacd5c80d8bffe19a4489b5f059b618d4bcFariborz Jahanian      OptInstanceMethods.push_back(MD);
697277e4bcacd5c80d8bffe19a4489b5f059b618d4bcFariborz Jahanian    } else {
697377e4bcacd5c80d8bffe19a4489b5f059b618d4bcFariborz Jahanian      InstanceMethods.push_back(MD);
697477e4bcacd5c80d8bffe19a4489b5f059b618d4bcFariborz Jahanian    }
697577e4bcacd5c80d8bffe19a4489b5f059b618d4bcFariborz Jahanian  }
697677e4bcacd5c80d8bffe19a4489b5f059b618d4bcFariborz Jahanian
6977651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  for (auto *MD : PDecl->class_methods()) {
697877e4bcacd5c80d8bffe19a4489b5f059b618d4bcFariborz Jahanian    if (MD->getImplementationControl() == ObjCMethodDecl::Optional) {
697977e4bcacd5c80d8bffe19a4489b5f059b618d4bcFariborz Jahanian      OptClassMethods.push_back(MD);
698077e4bcacd5c80d8bffe19a4489b5f059b618d4bcFariborz Jahanian    } else {
698177e4bcacd5c80d8bffe19a4489b5f059b618d4bcFariborz Jahanian      ClassMethods.push_back(MD);
698277e4bcacd5c80d8bffe19a4489b5f059b618d4bcFariborz Jahanian    }
698377e4bcacd5c80d8bffe19a4489b5f059b618d4bcFariborz Jahanian  }
6984e0adbd8386d9ff7312b74e4d2d1f27337f94732cFariborz Jahanian  std::vector<ObjCMethodDecl *> AllMethods;
6985e0adbd8386d9ff7312b74e4d2d1f27337f94732cFariborz Jahanian  for (unsigned i = 0, e = InstanceMethods.size(); i < e; i++)
6986e0adbd8386d9ff7312b74e4d2d1f27337f94732cFariborz Jahanian    AllMethods.push_back(InstanceMethods[i]);
6987e0adbd8386d9ff7312b74e4d2d1f27337f94732cFariborz Jahanian  for (unsigned i = 0, e = ClassMethods.size(); i < e; i++)
6988e0adbd8386d9ff7312b74e4d2d1f27337f94732cFariborz Jahanian    AllMethods.push_back(ClassMethods[i]);
6989e0adbd8386d9ff7312b74e4d2d1f27337f94732cFariborz Jahanian  for (unsigned i = 0, e = OptInstanceMethods.size(); i < e; i++)
6990e0adbd8386d9ff7312b74e4d2d1f27337f94732cFariborz Jahanian    AllMethods.push_back(OptInstanceMethods[i]);
6991e0adbd8386d9ff7312b74e4d2d1f27337f94732cFariborz Jahanian  for (unsigned i = 0, e = OptClassMethods.size(); i < e; i++)
6992e0adbd8386d9ff7312b74e4d2d1f27337f94732cFariborz Jahanian    AllMethods.push_back(OptClassMethods[i]);
6993e0adbd8386d9ff7312b74e4d2d1f27337f94732cFariborz Jahanian
6994e0adbd8386d9ff7312b74e4d2d1f27337f94732cFariborz Jahanian  Write__extendedMethodTypes_initializer(*this, Context, Result,
6995e0adbd8386d9ff7312b74e4d2d1f27337f94732cFariborz Jahanian                                         AllMethods,
6996e0adbd8386d9ff7312b74e4d2d1f27337f94732cFariborz Jahanian                                         "_OBJC_PROTOCOL_METHOD_TYPES_",
6997e0adbd8386d9ff7312b74e4d2d1f27337f94732cFariborz Jahanian                                         PDecl->getNameAsString());
6998da9624a77352bc61b9713c31edd671c02a3ff260Fariborz Jahanian  // Protocol's super protocol list
6999651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  SmallVector<ObjCProtocolDecl *, 8> SuperProtocols(PDecl->protocols());
7000da9624a77352bc61b9713c31edd671c02a3ff260Fariborz Jahanian  Write_protocol_list_initializer(Context, Result, SuperProtocols,
7001da9624a77352bc61b9713c31edd671c02a3ff260Fariborz Jahanian                                  "_OBJC_PROTOCOL_REFS_",
7002da9624a77352bc61b9713c31edd671c02a3ff260Fariborz Jahanian                                  PDecl->getNameAsString());
7003da9624a77352bc61b9713c31edd671c02a3ff260Fariborz Jahanian
700490af4e22a8fb83f159b512bfd48fb77699337b3dFariborz Jahanian  Write_method_list_t_initializer(*this, Context, Result, InstanceMethods,
700577e4bcacd5c80d8bffe19a4489b5f059b618d4bcFariborz Jahanian                                  "_OBJC_PROTOCOL_INSTANCE_METHODS_",
700690af4e22a8fb83f159b512bfd48fb77699337b3dFariborz Jahanian                                  PDecl->getNameAsString(), false);
700777e4bcacd5c80d8bffe19a4489b5f059b618d4bcFariborz Jahanian
700890af4e22a8fb83f159b512bfd48fb77699337b3dFariborz Jahanian  Write_method_list_t_initializer(*this, Context, Result, ClassMethods,
700977e4bcacd5c80d8bffe19a4489b5f059b618d4bcFariborz Jahanian                                  "_OBJC_PROTOCOL_CLASS_METHODS_",
701090af4e22a8fb83f159b512bfd48fb77699337b3dFariborz Jahanian                                  PDecl->getNameAsString(), false);
701177e4bcacd5c80d8bffe19a4489b5f059b618d4bcFariborz Jahanian
701290af4e22a8fb83f159b512bfd48fb77699337b3dFariborz Jahanian  Write_method_list_t_initializer(*this, Context, Result, OptInstanceMethods,
701377e4bcacd5c80d8bffe19a4489b5f059b618d4bcFariborz Jahanian                                  "_OBJC_PROTOCOL_OPT_INSTANCE_METHODS_",
701490af4e22a8fb83f159b512bfd48fb77699337b3dFariborz Jahanian                                  PDecl->getNameAsString(), false);
701577e4bcacd5c80d8bffe19a4489b5f059b618d4bcFariborz Jahanian
701690af4e22a8fb83f159b512bfd48fb77699337b3dFariborz Jahanian  Write_method_list_t_initializer(*this, Context, Result, OptClassMethods,
701777e4bcacd5c80d8bffe19a4489b5f059b618d4bcFariborz Jahanian                                  "_OBJC_PROTOCOL_OPT_CLASS_METHODS_",
701890af4e22a8fb83f159b512bfd48fb77699337b3dFariborz Jahanian                                  PDecl->getNameAsString(), false);
701977e4bcacd5c80d8bffe19a4489b5f059b618d4bcFariborz Jahanian
7020da35eacc6e05a99ab30f7290f1d42df32d06b22eFariborz Jahanian  // Protocol's property metadata.
7021651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  SmallVector<ObjCPropertyDecl *, 8> ProtocolProperties(PDecl->properties());
7022f1c1d9a99dd02b2cd9c4052ec2ec759783175e5eFariborz Jahanian  Write_prop_list_t_initializer(*this, Context, Result, ProtocolProperties,
70236bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines                                 /* Container */nullptr,
7024da35eacc6e05a99ab30f7290f1d42df32d06b22eFariborz Jahanian                                 "_OBJC_PROTOCOL_PROPERTIES_",
7025da35eacc6e05a99ab30f7290f1d42df32d06b22eFariborz Jahanian                                 PDecl->getNameAsString());
70266bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
702782848c26c896d46c0b98e1776a7781e754a8ee25Fariborz Jahanian  // Writer out root metadata for current protocol: struct _protocol_t
70281ca052c09868169d4de4da5d1d45f07f2fe8511aFariborz Jahanian  Result += "\n";
70291ca052c09868169d4de4da5d1d45f07f2fe8511aFariborz Jahanian  if (LangOpts.MicrosoftExt)
70308590d86ea35d0dd04711edd6b8dc57fa9a528305Fariborz Jahanian    Result += "static ";
703130650ebe652854d8bdce832cbdae1cf3c43e54aaFariborz Jahanian  Result += "struct _protocol_t _OBJC_PROTOCOL_";
703282848c26c896d46c0b98e1776a7781e754a8ee25Fariborz Jahanian  Result += PDecl->getNameAsString();
703382848c26c896d46c0b98e1776a7781e754a8ee25Fariborz Jahanian  Result += " __attribute__ ((used, section (\"__DATA,__datacoal_nt,coalesced\"))) = {\n";
703482848c26c896d46c0b98e1776a7781e754a8ee25Fariborz Jahanian  Result += "\t0,\n"; // id is; is null
703582848c26c896d46c0b98e1776a7781e754a8ee25Fariborz Jahanian  Result += "\t\""; Result += PDecl->getNameAsString(); Result += "\",\n";
7036da9624a77352bc61b9713c31edd671c02a3ff260Fariborz Jahanian  if (SuperProtocols.size() > 0) {
7037da9624a77352bc61b9713c31edd671c02a3ff260Fariborz Jahanian    Result += "\t(const struct _protocol_list_t *)&"; Result += "_OBJC_PROTOCOL_REFS_";
7038da9624a77352bc61b9713c31edd671c02a3ff260Fariborz Jahanian    Result += PDecl->getNameAsString(); Result += ",\n";
7039da9624a77352bc61b9713c31edd671c02a3ff260Fariborz Jahanian  }
7040da9624a77352bc61b9713c31edd671c02a3ff260Fariborz Jahanian  else
7041da9624a77352bc61b9713c31edd671c02a3ff260Fariborz Jahanian    Result += "\t0,\n";
704282848c26c896d46c0b98e1776a7781e754a8ee25Fariborz Jahanian  if (InstanceMethods.size() > 0) {
704382848c26c896d46c0b98e1776a7781e754a8ee25Fariborz Jahanian    Result += "\t(const struct method_list_t *)&_OBJC_PROTOCOL_INSTANCE_METHODS_";
704482848c26c896d46c0b98e1776a7781e754a8ee25Fariborz Jahanian    Result += PDecl->getNameAsString(); Result += ",\n";
704564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  }
704682848c26c896d46c0b98e1776a7781e754a8ee25Fariborz Jahanian  else
704782848c26c896d46c0b98e1776a7781e754a8ee25Fariborz Jahanian    Result += "\t0,\n";
704882848c26c896d46c0b98e1776a7781e754a8ee25Fariborz Jahanian
704982848c26c896d46c0b98e1776a7781e754a8ee25Fariborz Jahanian  if (ClassMethods.size() > 0) {
705082848c26c896d46c0b98e1776a7781e754a8ee25Fariborz Jahanian    Result += "\t(const struct method_list_t *)&_OBJC_PROTOCOL_CLASS_METHODS_";
705182848c26c896d46c0b98e1776a7781e754a8ee25Fariborz Jahanian    Result += PDecl->getNameAsString(); Result += ",\n";
705264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  }
705382848c26c896d46c0b98e1776a7781e754a8ee25Fariborz Jahanian  else
705482848c26c896d46c0b98e1776a7781e754a8ee25Fariborz Jahanian    Result += "\t0,\n";
705564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
705682848c26c896d46c0b98e1776a7781e754a8ee25Fariborz Jahanian  if (OptInstanceMethods.size() > 0) {
705782848c26c896d46c0b98e1776a7781e754a8ee25Fariborz Jahanian    Result += "\t(const struct method_list_t *)&_OBJC_PROTOCOL_OPT_INSTANCE_METHODS_";
705882848c26c896d46c0b98e1776a7781e754a8ee25Fariborz Jahanian    Result += PDecl->getNameAsString(); Result += ",\n";
705964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  }
706082848c26c896d46c0b98e1776a7781e754a8ee25Fariborz Jahanian  else
706182848c26c896d46c0b98e1776a7781e754a8ee25Fariborz Jahanian    Result += "\t0,\n";
706264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
706382848c26c896d46c0b98e1776a7781e754a8ee25Fariborz Jahanian  if (OptClassMethods.size() > 0) {
706482848c26c896d46c0b98e1776a7781e754a8ee25Fariborz Jahanian    Result += "\t(const struct method_list_t *)&_OBJC_PROTOCOL_OPT_CLASS_METHODS_";
706582848c26c896d46c0b98e1776a7781e754a8ee25Fariborz Jahanian    Result += PDecl->getNameAsString(); Result += ",\n";
706664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  }
706764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  else
706882848c26c896d46c0b98e1776a7781e754a8ee25Fariborz Jahanian    Result += "\t0,\n";
706982848c26c896d46c0b98e1776a7781e754a8ee25Fariborz Jahanian
707082848c26c896d46c0b98e1776a7781e754a8ee25Fariborz Jahanian  if (ProtocolProperties.size() > 0) {
707182848c26c896d46c0b98e1776a7781e754a8ee25Fariborz Jahanian    Result += "\t(const struct _prop_list_t *)&_OBJC_PROTOCOL_PROPERTIES_";
707282848c26c896d46c0b98e1776a7781e754a8ee25Fariborz Jahanian    Result += PDecl->getNameAsString(); Result += ",\n";
707364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  }
707464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  else
707582848c26c896d46c0b98e1776a7781e754a8ee25Fariborz Jahanian    Result += "\t0,\n";
707664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
707782848c26c896d46c0b98e1776a7781e754a8ee25Fariborz Jahanian  Result += "\t"; Result += "sizeof(_protocol_t)"; Result += ",\n";
707882848c26c896d46c0b98e1776a7781e754a8ee25Fariborz Jahanian  Result += "\t0,\n";
707982848c26c896d46c0b98e1776a7781e754a8ee25Fariborz Jahanian
7080e0adbd8386d9ff7312b74e4d2d1f27337f94732cFariborz Jahanian  if (AllMethods.size() > 0) {
7081e0adbd8386d9ff7312b74e4d2d1f27337f94732cFariborz Jahanian    Result += "\t(const char **)&"; Result += "_OBJC_PROTOCOL_METHOD_TYPES_";
7082e0adbd8386d9ff7312b74e4d2d1f27337f94732cFariborz Jahanian    Result += PDecl->getNameAsString();
7083e0adbd8386d9ff7312b74e4d2d1f27337f94732cFariborz Jahanian    Result += "\n};\n";
7084e0adbd8386d9ff7312b74e4d2d1f27337f94732cFariborz Jahanian  }
7085e0adbd8386d9ff7312b74e4d2d1f27337f94732cFariborz Jahanian  else
7086e0adbd8386d9ff7312b74e4d2d1f27337f94732cFariborz Jahanian    Result += "\t0\n};\n";
708710cde2fc0c1804427dd3e0c050c149ac6d415f51Fariborz Jahanian
708810cde2fc0c1804427dd3e0c050c149ac6d415f51Fariborz Jahanian  if (LangOpts.MicrosoftExt)
70898590d86ea35d0dd04711edd6b8dc57fa9a528305Fariborz Jahanian    Result += "static ";
709010cde2fc0c1804427dd3e0c050c149ac6d415f51Fariborz Jahanian  Result += "struct _protocol_t *";
709110cde2fc0c1804427dd3e0c050c149ac6d415f51Fariborz Jahanian  Result += "_OBJC_LABEL_PROTOCOL_$_"; Result += PDecl->getNameAsString();
709210cde2fc0c1804427dd3e0c050c149ac6d415f51Fariborz Jahanian  Result += " = &_OBJC_PROTOCOL_"; Result += PDecl->getNameAsString();
709310cde2fc0c1804427dd3e0c050c149ac6d415f51Fariborz Jahanian  Result += ";\n";
709482848c26c896d46c0b98e1776a7781e754a8ee25Fariborz Jahanian
709564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  // Mark this protocol as having been generated.
7096176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  if (!ObjCSynthesizedProtocols.insert(PDecl->getCanonicalDecl()).second)
709764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    llvm_unreachable("protocol already synthesized");
709864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
709964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian}
710064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
710164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanianvoid RewriteModernObjC::RewriteObjCProtocolListMetaData(
710264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                const ObjCList<ObjCProtocolDecl> &Protocols,
710364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                StringRef prefix, StringRef ClassName,
710464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                std::string &Result) {
710564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  if (Protocols.empty()) return;
710664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
710764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  for (unsigned i = 0; i != Protocols.size(); i++)
7108da9624a77352bc61b9713c31edd671c02a3ff260Fariborz Jahanian    RewriteObjCProtocolMetaData(Protocols[i], Result);
710964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
711064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  // Output the top lovel protocol meta-data for the class.
711164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  /* struct _objc_protocol_list {
711264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian   struct _objc_protocol_list *next;
711364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian   int    protocol_count;
711464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian   struct _objc_protocol *class_protocols[];
711564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian   }
711664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian   */
71171ca052c09868169d4de4da5d1d45f07f2fe8511aFariborz Jahanian  Result += "\n";
71181ca052c09868169d4de4da5d1d45f07f2fe8511aFariborz Jahanian  if (LangOpts.MicrosoftExt)
71191ca052c09868169d4de4da5d1d45f07f2fe8511aFariborz Jahanian    Result += "__declspec(allocate(\".cat_cls_meth$B\")) ";
71201ca052c09868169d4de4da5d1d45f07f2fe8511aFariborz Jahanian  Result += "static struct {\n";
712164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  Result += "\tstruct _objc_protocol_list *next;\n";
712264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  Result += "\tint    protocol_count;\n";
712364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  Result += "\tstruct _objc_protocol *class_protocols[";
712464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  Result += utostr(Protocols.size());
712564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  Result += "];\n} _OBJC_";
712664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  Result += prefix;
712764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  Result += "_PROTOCOLS_";
712864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  Result += ClassName;
712964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  Result += " __attribute__ ((used, section (\"__OBJC, __cat_cls_meth\")))= "
713064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  "{\n\t0, ";
713164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  Result += utostr(Protocols.size());
713264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  Result += "\n";
713364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
713464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  Result += "\t,{&_OBJC_PROTOCOL_";
713564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  Result += Protocols[0]->getNameAsString();
713664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  Result += " \n";
713764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
713864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  for (unsigned i = 1; i != Protocols.size(); i++) {
713964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    Result += "\t ,&_OBJC_PROTOCOL_";
714064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    Result += Protocols[i]->getNameAsString();
714164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    Result += "\n";
714264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  }
714364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  Result += "\t }\n};\n";
714464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian}
714564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
71466ade343d180d029fc61b17377553deab99527ff2Fariborz Jahanian/// hasObjCExceptionAttribute - Return true if this class or any super
71476ade343d180d029fc61b17377553deab99527ff2Fariborz Jahanian/// class has the __objc_exception__ attribute.
71486ade343d180d029fc61b17377553deab99527ff2Fariborz Jahanian/// FIXME. Move this to ASTContext.cpp as it is also used for IRGen.
71496ade343d180d029fc61b17377553deab99527ff2Fariborz Jahanianstatic bool hasObjCExceptionAttribute(ASTContext &Context,
71506ade343d180d029fc61b17377553deab99527ff2Fariborz Jahanian                                      const ObjCInterfaceDecl *OID) {
71516ade343d180d029fc61b17377553deab99527ff2Fariborz Jahanian  if (OID->hasAttr<ObjCExceptionAttr>())
71526ade343d180d029fc61b17377553deab99527ff2Fariborz Jahanian    return true;
71536ade343d180d029fc61b17377553deab99527ff2Fariborz Jahanian  if (const ObjCInterfaceDecl *Super = OID->getSuperClass())
71546ade343d180d029fc61b17377553deab99527ff2Fariborz Jahanian    return hasObjCExceptionAttribute(Context, Super);
71556ade343d180d029fc61b17377553deab99527ff2Fariborz Jahanian  return false;
71566ade343d180d029fc61b17377553deab99527ff2Fariborz Jahanian}
7157f1c1d9a99dd02b2cd9c4052ec2ec759783175e5eFariborz Jahanian
715864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanianvoid RewriteModernObjC::RewriteObjCClassMetaData(ObjCImplementationDecl *IDecl,
715964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                           std::string &Result) {
716064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  ObjCInterfaceDecl *CDecl = IDecl->getClassInterface();
716164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
716264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  // Explicitly declared @interface's are already synthesized.
7163ae9329570ba16e48ffdfe3d55349b53fd893a711Fariborz Jahanian  if (CDecl->isImplicitInterfaceDecl())
7164ae9329570ba16e48ffdfe3d55349b53fd893a711Fariborz Jahanian    assert(false &&
7165ae9329570ba16e48ffdfe3d55349b53fd893a711Fariborz Jahanian           "Legacy implicit interface rewriting not supported in moder abi");
71668f1fed036eb78b747725560c10ad29d370d6ef62Fariborz Jahanian
7167de5d946288bb3d68576c95974beb8cfd21d7043aFariborz Jahanian  WriteModernMetadataDeclarations(Context, Result);
7168ae9329570ba16e48ffdfe3d55349b53fd893a711Fariborz Jahanian  SmallVector<ObjCIvarDecl *, 8> IVars;
7169ae9329570ba16e48ffdfe3d55349b53fd893a711Fariborz Jahanian
7170ae9329570ba16e48ffdfe3d55349b53fd893a711Fariborz Jahanian  for (ObjCIvarDecl *IVD = CDecl->all_declared_ivar_begin();
7171ae9329570ba16e48ffdfe3d55349b53fd893a711Fariborz Jahanian      IVD; IVD = IVD->getNextIvar()) {
7172ae9329570ba16e48ffdfe3d55349b53fd893a711Fariborz Jahanian    // Ignore unnamed bit-fields.
7173ae9329570ba16e48ffdfe3d55349b53fd893a711Fariborz Jahanian    if (!IVD->getDeclName())
7174ae9329570ba16e48ffdfe3d55349b53fd893a711Fariborz Jahanian      continue;
7175ae9329570ba16e48ffdfe3d55349b53fd893a711Fariborz Jahanian    IVars.push_back(IVD);
717664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  }
717764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
7178ae9329570ba16e48ffdfe3d55349b53fd893a711Fariborz Jahanian  Write__ivar_list_t_initializer(*this, Context, Result, IVars,
7179f1c1d9a99dd02b2cd9c4052ec2ec759783175e5eFariborz Jahanian                                 "_OBJC_$_INSTANCE_VARIABLES_",
71807cb2a1b4b6ef60aa57a5f2e5e820a57adef3ea77Fariborz Jahanian                                 CDecl);
718190af4e22a8fb83f159b512bfd48fb77699337b3dFariborz Jahanian
718290af4e22a8fb83f159b512bfd48fb77699337b3dFariborz Jahanian  // Build _objc_method_list for class's instance methods if needed
7183651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  SmallVector<ObjCMethodDecl *, 32> InstanceMethods(IDecl->instance_methods());
718490af4e22a8fb83f159b512bfd48fb77699337b3dFariborz Jahanian
718590af4e22a8fb83f159b512bfd48fb77699337b3dFariborz Jahanian  // If any of our property implementations have associated getters or
718690af4e22a8fb83f159b512bfd48fb77699337b3dFariborz Jahanian  // setters, produce metadata for them as well.
7187651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  for (const auto *Prop : IDecl->property_impls()) {
7188262bc18e32500558af7cb0afa205b34bd37bafedDavid Blaikie    if (Prop->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic)
718990af4e22a8fb83f159b512bfd48fb77699337b3dFariborz Jahanian      continue;
7190262bc18e32500558af7cb0afa205b34bd37bafedDavid Blaikie    if (!Prop->getPropertyIvarDecl())
719190af4e22a8fb83f159b512bfd48fb77699337b3dFariborz Jahanian      continue;
7192262bc18e32500558af7cb0afa205b34bd37bafedDavid Blaikie    ObjCPropertyDecl *PD = Prop->getPropertyDecl();
719390af4e22a8fb83f159b512bfd48fb77699337b3dFariborz Jahanian    if (!PD)
719490af4e22a8fb83f159b512bfd48fb77699337b3dFariborz Jahanian      continue;
719590af4e22a8fb83f159b512bfd48fb77699337b3dFariborz Jahanian    if (ObjCMethodDecl *Getter = PD->getGetterMethodDecl())
7196301e2e40f9d56c2fa01d3021a4d8e2d343fafd35Fariborz Jahanian      if (mustSynthesizeSetterGetterMethod(IDecl, PD, true /*getter*/))
719790af4e22a8fb83f159b512bfd48fb77699337b3dFariborz Jahanian        InstanceMethods.push_back(Getter);
719890af4e22a8fb83f159b512bfd48fb77699337b3dFariborz Jahanian    if (PD->isReadOnly())
719990af4e22a8fb83f159b512bfd48fb77699337b3dFariborz Jahanian      continue;
720090af4e22a8fb83f159b512bfd48fb77699337b3dFariborz Jahanian    if (ObjCMethodDecl *Setter = PD->getSetterMethodDecl())
7201301e2e40f9d56c2fa01d3021a4d8e2d343fafd35Fariborz Jahanian      if (mustSynthesizeSetterGetterMethod(IDecl, PD, false /*setter*/))
720290af4e22a8fb83f159b512bfd48fb77699337b3dFariborz Jahanian        InstanceMethods.push_back(Setter);
720390af4e22a8fb83f159b512bfd48fb77699337b3dFariborz Jahanian  }
720490af4e22a8fb83f159b512bfd48fb77699337b3dFariborz Jahanian
720590af4e22a8fb83f159b512bfd48fb77699337b3dFariborz Jahanian  Write_method_list_t_initializer(*this, Context, Result, InstanceMethods,
720690af4e22a8fb83f159b512bfd48fb77699337b3dFariborz Jahanian                                  "_OBJC_$_INSTANCE_METHODS_",
720790af4e22a8fb83f159b512bfd48fb77699337b3dFariborz Jahanian                                  IDecl->getNameAsString(), true);
720890af4e22a8fb83f159b512bfd48fb77699337b3dFariborz Jahanian
7209651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  SmallVector<ObjCMethodDecl *, 32> ClassMethods(IDecl->class_methods());
721090af4e22a8fb83f159b512bfd48fb77699337b3dFariborz Jahanian
721190af4e22a8fb83f159b512bfd48fb77699337b3dFariborz Jahanian  Write_method_list_t_initializer(*this, Context, Result, ClassMethods,
721290af4e22a8fb83f159b512bfd48fb77699337b3dFariborz Jahanian                                  "_OBJC_$_CLASS_METHODS_",
721390af4e22a8fb83f159b512bfd48fb77699337b3dFariborz Jahanian                                  IDecl->getNameAsString(), true);
72140a525340ada570897ab34918c98de1cf94ad7770Fariborz Jahanian
72150a525340ada570897ab34918c98de1cf94ad7770Fariborz Jahanian  // Protocols referenced in class declaration?
72160a525340ada570897ab34918c98de1cf94ad7770Fariborz Jahanian  // Protocol's super protocol list
72170a525340ada570897ab34918c98de1cf94ad7770Fariborz Jahanian  std::vector<ObjCProtocolDecl *> RefedProtocols;
72180a525340ada570897ab34918c98de1cf94ad7770Fariborz Jahanian  const ObjCList<ObjCProtocolDecl> &Protocols = CDecl->getReferencedProtocols();
72190a525340ada570897ab34918c98de1cf94ad7770Fariborz Jahanian  for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
72200a525340ada570897ab34918c98de1cf94ad7770Fariborz Jahanian       E = Protocols.end();
72210a525340ada570897ab34918c98de1cf94ad7770Fariborz Jahanian       I != E; ++I) {
72220a525340ada570897ab34918c98de1cf94ad7770Fariborz Jahanian    RefedProtocols.push_back(*I);
72230a525340ada570897ab34918c98de1cf94ad7770Fariborz Jahanian    // Must write out all protocol definitions in current qualifier list,
72240a525340ada570897ab34918c98de1cf94ad7770Fariborz Jahanian    // and in their nested qualifiers before writing out current definition.
72250a525340ada570897ab34918c98de1cf94ad7770Fariborz Jahanian    RewriteObjCProtocolMetaData(*I, Result);
72260a525340ada570897ab34918c98de1cf94ad7770Fariborz Jahanian  }
72270a525340ada570897ab34918c98de1cf94ad7770Fariborz Jahanian
72280a525340ada570897ab34918c98de1cf94ad7770Fariborz Jahanian  Write_protocol_list_initializer(Context, Result,
72290a525340ada570897ab34918c98de1cf94ad7770Fariborz Jahanian                                  RefedProtocols,
72300a525340ada570897ab34918c98de1cf94ad7770Fariborz Jahanian                                  "_OBJC_CLASS_PROTOCOLS_$_",
72310a525340ada570897ab34918c98de1cf94ad7770Fariborz Jahanian                                  IDecl->getNameAsString());
7232f1c1d9a99dd02b2cd9c4052ec2ec759783175e5eFariborz Jahanian
7233f1c1d9a99dd02b2cd9c4052ec2ec759783175e5eFariborz Jahanian  // Protocol's property metadata.
7234651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  SmallVector<ObjCPropertyDecl *, 8> ClassProperties(CDecl->properties());
7235f1c1d9a99dd02b2cd9c4052ec2ec759783175e5eFariborz Jahanian  Write_prop_list_t_initializer(*this, Context, Result, ClassProperties,
72362df089d4d8d47c3d0d43325d5bb69ec49147f81fFariborz Jahanian                                 /* Container */IDecl,
7237eeabf381862e53519cd0f9f65c1cc2a983c72159Fariborz Jahanian                                 "_OBJC_$_PROP_LIST_",
7238f1c1d9a99dd02b2cd9c4052ec2ec759783175e5eFariborz Jahanian                                 CDecl->getNameAsString());
723990af4e22a8fb83f159b512bfd48fb77699337b3dFariborz Jahanian
7240f1c1d9a99dd02b2cd9c4052ec2ec759783175e5eFariborz Jahanian
72416ade343d180d029fc61b17377553deab99527ff2Fariborz Jahanian  // Data for initializing _class_ro_t  metaclass meta-data
72426ade343d180d029fc61b17377553deab99527ff2Fariborz Jahanian  uint32_t flags = CLS_META;
72436ade343d180d029fc61b17377553deab99527ff2Fariborz Jahanian  std::string InstanceSize;
72446ade343d180d029fc61b17377553deab99527ff2Fariborz Jahanian  std::string InstanceStart;
72456ade343d180d029fc61b17377553deab99527ff2Fariborz Jahanian
72466ade343d180d029fc61b17377553deab99527ff2Fariborz Jahanian
72476ade343d180d029fc61b17377553deab99527ff2Fariborz Jahanian  bool classIsHidden = CDecl->getVisibility() == HiddenVisibility;
72486ade343d180d029fc61b17377553deab99527ff2Fariborz Jahanian  if (classIsHidden)
72496ade343d180d029fc61b17377553deab99527ff2Fariborz Jahanian    flags |= OBJC2_CLS_HIDDEN;
72506ade343d180d029fc61b17377553deab99527ff2Fariborz Jahanian
72516ade343d180d029fc61b17377553deab99527ff2Fariborz Jahanian  if (!CDecl->getSuperClass())
72526ade343d180d029fc61b17377553deab99527ff2Fariborz Jahanian    // class is root
72536ade343d180d029fc61b17377553deab99527ff2Fariborz Jahanian    flags |= CLS_ROOT;
72546ade343d180d029fc61b17377553deab99527ff2Fariborz Jahanian  InstanceSize = "sizeof(struct _class_t)";
72556ade343d180d029fc61b17377553deab99527ff2Fariborz Jahanian  InstanceStart = InstanceSize;
72566ade343d180d029fc61b17377553deab99527ff2Fariborz Jahanian  Write__class_ro_t_initializer(Context, Result, flags,
72576ade343d180d029fc61b17377553deab99527ff2Fariborz Jahanian                                InstanceStart, InstanceSize,
72586ade343d180d029fc61b17377553deab99527ff2Fariborz Jahanian                                ClassMethods,
72596bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines                                nullptr,
72606bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines                                nullptr,
72616bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines                                nullptr,
72626ade343d180d029fc61b17377553deab99527ff2Fariborz Jahanian                                "_OBJC_METACLASS_RO_$_",
72636ade343d180d029fc61b17377553deab99527ff2Fariborz Jahanian                                CDecl->getNameAsString());
72646ade343d180d029fc61b17377553deab99527ff2Fariborz Jahanian
7265f1c1d9a99dd02b2cd9c4052ec2ec759783175e5eFariborz Jahanian  // Data for initializing _class_ro_t meta-data
72666ade343d180d029fc61b17377553deab99527ff2Fariborz Jahanian  flags = CLS;
72676ade343d180d029fc61b17377553deab99527ff2Fariborz Jahanian  if (classIsHidden)
72686ade343d180d029fc61b17377553deab99527ff2Fariborz Jahanian    flags |= OBJC2_CLS_HIDDEN;
72696ade343d180d029fc61b17377553deab99527ff2Fariborz Jahanian
72706ade343d180d029fc61b17377553deab99527ff2Fariborz Jahanian  if (hasObjCExceptionAttribute(*Context, CDecl))
72716ade343d180d029fc61b17377553deab99527ff2Fariborz Jahanian    flags |= CLS_EXCEPTION;
72726ade343d180d029fc61b17377553deab99527ff2Fariborz Jahanian
7273f1c1d9a99dd02b2cd9c4052ec2ec759783175e5eFariborz Jahanian  if (!CDecl->getSuperClass())
7274f1c1d9a99dd02b2cd9c4052ec2ec759783175e5eFariborz Jahanian    // class is root
7275f1c1d9a99dd02b2cd9c4052ec2ec759783175e5eFariborz Jahanian    flags |= CLS_ROOT;
7276f1c1d9a99dd02b2cd9c4052ec2ec759783175e5eFariborz Jahanian
72776ade343d180d029fc61b17377553deab99527ff2Fariborz Jahanian  InstanceSize.clear();
72786ade343d180d029fc61b17377553deab99527ff2Fariborz Jahanian  InstanceStart.clear();
7279f1c1d9a99dd02b2cd9c4052ec2ec759783175e5eFariborz Jahanian  if (!ObjCSynthesizedStructs.count(CDecl)) {
7280f1c1d9a99dd02b2cd9c4052ec2ec759783175e5eFariborz Jahanian    InstanceSize = "0";
7281f1c1d9a99dd02b2cd9c4052ec2ec759783175e5eFariborz Jahanian    InstanceStart = "0";
7282f1c1d9a99dd02b2cd9c4052ec2ec759783175e5eFariborz Jahanian  }
7283f1c1d9a99dd02b2cd9c4052ec2ec759783175e5eFariborz Jahanian  else {
7284f1c1d9a99dd02b2cd9c4052ec2ec759783175e5eFariborz Jahanian    InstanceSize = "sizeof(struct ";
7285f1c1d9a99dd02b2cd9c4052ec2ec759783175e5eFariborz Jahanian    InstanceSize += CDecl->getNameAsString();
7286f1c1d9a99dd02b2cd9c4052ec2ec759783175e5eFariborz Jahanian    InstanceSize += "_IMPL)";
7287f1c1d9a99dd02b2cd9c4052ec2ec759783175e5eFariborz Jahanian
7288f1c1d9a99dd02b2cd9c4052ec2ec759783175e5eFariborz Jahanian    ObjCIvarDecl *IVD = CDecl->all_declared_ivar_begin();
7289f1c1d9a99dd02b2cd9c4052ec2ec759783175e5eFariborz Jahanian    if (IVD) {
7290acee1c9dbe180c6493d1bcda6a0a7ee4018ed7b1Fariborz Jahanian      RewriteIvarOffsetComputation(IVD, InstanceStart);
7291f1c1d9a99dd02b2cd9c4052ec2ec759783175e5eFariborz Jahanian    }
7292f1c1d9a99dd02b2cd9c4052ec2ec759783175e5eFariborz Jahanian    else
7293f1c1d9a99dd02b2cd9c4052ec2ec759783175e5eFariborz Jahanian      InstanceStart = InstanceSize;
7294f1c1d9a99dd02b2cd9c4052ec2ec759783175e5eFariborz Jahanian  }
7295f1c1d9a99dd02b2cd9c4052ec2ec759783175e5eFariborz Jahanian  Write__class_ro_t_initializer(Context, Result, flags,
7296f1c1d9a99dd02b2cd9c4052ec2ec759783175e5eFariborz Jahanian                                InstanceStart, InstanceSize,
7297f1c1d9a99dd02b2cd9c4052ec2ec759783175e5eFariborz Jahanian                                InstanceMethods,
7298f1c1d9a99dd02b2cd9c4052ec2ec759783175e5eFariborz Jahanian                                RefedProtocols,
7299f1c1d9a99dd02b2cd9c4052ec2ec759783175e5eFariborz Jahanian                                IVars,
7300f1c1d9a99dd02b2cd9c4052ec2ec759783175e5eFariborz Jahanian                                ClassProperties,
7301f1c1d9a99dd02b2cd9c4052ec2ec759783175e5eFariborz Jahanian                                "_OBJC_CLASS_RO_$_",
7302f1c1d9a99dd02b2cd9c4052ec2ec759783175e5eFariborz Jahanian                                CDecl->getNameAsString());
73033f77c7b56d515a6756dba63a3dfa0a332711a779Fariborz Jahanian
73043f77c7b56d515a6756dba63a3dfa0a332711a779Fariborz Jahanian  Write_class_t(Context, Result,
73053f77c7b56d515a6756dba63a3dfa0a332711a779Fariborz Jahanian                "OBJC_METACLASS_$_",
73063f77c7b56d515a6756dba63a3dfa0a332711a779Fariborz Jahanian                CDecl, /*metaclass*/true);
73073f77c7b56d515a6756dba63a3dfa0a332711a779Fariborz Jahanian
73083f77c7b56d515a6756dba63a3dfa0a332711a779Fariborz Jahanian  Write_class_t(Context, Result,
73093f77c7b56d515a6756dba63a3dfa0a332711a779Fariborz Jahanian                "OBJC_CLASS_$_",
73103f77c7b56d515a6756dba63a3dfa0a332711a779Fariborz Jahanian                CDecl, /*metaclass*/false);
731188f7f75e35425f3f228473c4c84a2445793a39c1Fariborz Jahanian
731288f7f75e35425f3f228473c4c84a2445793a39c1Fariborz Jahanian  if (ImplementationIsNonLazy(IDecl))
731388f7f75e35425f3f228473c4c84a2445793a39c1Fariborz Jahanian    DefinedNonLazyClasses.push_back(CDecl);
73143f77c7b56d515a6756dba63a3dfa0a332711a779Fariborz Jahanian
731564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian}
731664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
7317e0335786c17a6ca45966f66094146e9d8ba2d54aFariborz Jahanianvoid RewriteModernObjC::RewriteClassSetupInitHook(std::string &Result) {
7318e0335786c17a6ca45966f66094146e9d8ba2d54aFariborz Jahanian  int ClsDefCount = ClassImplementation.size();
7319e0335786c17a6ca45966f66094146e9d8ba2d54aFariborz Jahanian  if (!ClsDefCount)
7320e0335786c17a6ca45966f66094146e9d8ba2d54aFariborz Jahanian    return;
7321e0335786c17a6ca45966f66094146e9d8ba2d54aFariborz Jahanian  Result += "#pragma section(\".objc_inithooks$B\", long, read, write)\n";
7322e0335786c17a6ca45966f66094146e9d8ba2d54aFariborz Jahanian  Result += "__declspec(allocate(\".objc_inithooks$B\")) ";
7323e0335786c17a6ca45966f66094146e9d8ba2d54aFariborz Jahanian  Result += "static void *OBJC_CLASS_SETUP[] = {\n";
7324e0335786c17a6ca45966f66094146e9d8ba2d54aFariborz Jahanian  for (int i = 0; i < ClsDefCount; i++) {
7325e0335786c17a6ca45966f66094146e9d8ba2d54aFariborz Jahanian    ObjCImplementationDecl *IDecl = ClassImplementation[i];
7326e0335786c17a6ca45966f66094146e9d8ba2d54aFariborz Jahanian    ObjCInterfaceDecl *CDecl = IDecl->getClassInterface();
7327e0335786c17a6ca45966f66094146e9d8ba2d54aFariborz Jahanian    Result += "\t(void *)&OBJC_CLASS_SETUP_$_";
7328e0335786c17a6ca45966f66094146e9d8ba2d54aFariborz Jahanian    Result  += CDecl->getName(); Result += ",\n";
7329e0335786c17a6ca45966f66094146e9d8ba2d54aFariborz Jahanian  }
7330e0335786c17a6ca45966f66094146e9d8ba2d54aFariborz Jahanian  Result += "};\n";
7331e0335786c17a6ca45966f66094146e9d8ba2d54aFariborz Jahanian}
7332e0335786c17a6ca45966f66094146e9d8ba2d54aFariborz Jahanian
733364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanianvoid RewriteModernObjC::RewriteMetaDataIntoBuffer(std::string &Result) {
733464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  int ClsDefCount = ClassImplementation.size();
733564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  int CatDefCount = CategoryImplementation.size();
733664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
733764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  // For each implemented class, write out all its meta data.
733864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  for (int i = 0; i < ClsDefCount; i++)
733964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    RewriteObjCClassMetaData(ClassImplementation[i], Result);
734064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
7341e0335786c17a6ca45966f66094146e9d8ba2d54aFariborz Jahanian  RewriteClassSetupInitHook(Result);
7342e0335786c17a6ca45966f66094146e9d8ba2d54aFariborz Jahanian
734364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  // For each implemented category, write out all its meta data.
734464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  for (int i = 0; i < CatDefCount; i++)
734564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    RewriteObjCCategoryImplDecl(CategoryImplementation[i], Result);
734664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
7347e0335786c17a6ca45966f66094146e9d8ba2d54aFariborz Jahanian  RewriteCategorySetupInitHook(Result);
7348e0335786c17a6ca45966f66094146e9d8ba2d54aFariborz Jahanian
7349df79567796fabb406156d881ebd3319aa55b6f83Fariborz Jahanian  if (ClsDefCount > 0) {
73501ca052c09868169d4de4da5d1d45f07f2fe8511aFariborz Jahanian    if (LangOpts.MicrosoftExt)
73511ca052c09868169d4de4da5d1d45f07f2fe8511aFariborz Jahanian      Result += "__declspec(allocate(\".objc_classlist$B\")) ";
7352df79567796fabb406156d881ebd3319aa55b6f83Fariborz Jahanian    Result += "static struct _class_t *L_OBJC_LABEL_CLASS_$ [";
7353df79567796fabb406156d881ebd3319aa55b6f83Fariborz Jahanian    Result += llvm::utostr(ClsDefCount); Result += "]";
7354df79567796fabb406156d881ebd3319aa55b6f83Fariborz Jahanian    Result +=
7355df79567796fabb406156d881ebd3319aa55b6f83Fariborz Jahanian      " __attribute__((used, section (\"__DATA, __objc_classlist,"
7356df79567796fabb406156d881ebd3319aa55b6f83Fariborz Jahanian      "regular,no_dead_strip\")))= {\n";
7357df79567796fabb406156d881ebd3319aa55b6f83Fariborz Jahanian    for (int i = 0; i < ClsDefCount; i++) {
7358df79567796fabb406156d881ebd3319aa55b6f83Fariborz Jahanian      Result += "\t&OBJC_CLASS_$_";
7359df79567796fabb406156d881ebd3319aa55b6f83Fariborz Jahanian      Result += ClassImplementation[i]->getNameAsString();
7360df79567796fabb406156d881ebd3319aa55b6f83Fariborz Jahanian      Result += ",\n";
736164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    }
7362df79567796fabb406156d881ebd3319aa55b6f83Fariborz Jahanian    Result += "};\n";
736388f7f75e35425f3f228473c4c84a2445793a39c1Fariborz Jahanian
736488f7f75e35425f3f228473c4c84a2445793a39c1Fariborz Jahanian    if (!DefinedNonLazyClasses.empty()) {
736588f7f75e35425f3f228473c4c84a2445793a39c1Fariborz Jahanian      if (LangOpts.MicrosoftExt)
736688f7f75e35425f3f228473c4c84a2445793a39c1Fariborz Jahanian        Result += "__declspec(allocate(\".objc_nlclslist$B\")) \n";
736788f7f75e35425f3f228473c4c84a2445793a39c1Fariborz Jahanian      Result += "static struct _class_t *_OBJC_LABEL_NONLAZY_CLASS_$[] = {\n\t";
736888f7f75e35425f3f228473c4c84a2445793a39c1Fariborz Jahanian      for (unsigned i = 0, e = DefinedNonLazyClasses.size(); i < e; i++) {
736988f7f75e35425f3f228473c4c84a2445793a39c1Fariborz Jahanian        Result += "\t&OBJC_CLASS_$_"; Result += DefinedNonLazyClasses[i]->getNameAsString();
737088f7f75e35425f3f228473c4c84a2445793a39c1Fariborz Jahanian        Result += ",\n";
737188f7f75e35425f3f228473c4c84a2445793a39c1Fariborz Jahanian      }
737288f7f75e35425f3f228473c4c84a2445793a39c1Fariborz Jahanian      Result += "};\n";
737388f7f75e35425f3f228473c4c84a2445793a39c1Fariborz Jahanian    }
737464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  }
73756118612837887cbae365676d53cc3e1c258249aaFariborz Jahanian
73766118612837887cbae365676d53cc3e1c258249aaFariborz Jahanian  if (CatDefCount > 0) {
73771ca052c09868169d4de4da5d1d45f07f2fe8511aFariborz Jahanian    if (LangOpts.MicrosoftExt)
73781ca052c09868169d4de4da5d1d45f07f2fe8511aFariborz Jahanian      Result += "__declspec(allocate(\".objc_catlist$B\")) ";
73796118612837887cbae365676d53cc3e1c258249aaFariborz Jahanian    Result += "static struct _category_t *L_OBJC_LABEL_CATEGORY_$ [";
73806118612837887cbae365676d53cc3e1c258249aaFariborz Jahanian    Result += llvm::utostr(CatDefCount); Result += "]";
73816118612837887cbae365676d53cc3e1c258249aaFariborz Jahanian    Result +=
73826118612837887cbae365676d53cc3e1c258249aaFariborz Jahanian    " __attribute__((used, section (\"__DATA, __objc_catlist,"
73836118612837887cbae365676d53cc3e1c258249aaFariborz Jahanian    "regular,no_dead_strip\")))= {\n";
73846118612837887cbae365676d53cc3e1c258249aaFariborz Jahanian    for (int i = 0; i < CatDefCount; i++) {
73856118612837887cbae365676d53cc3e1c258249aaFariborz Jahanian      Result += "\t&_OBJC_$_CATEGORY_";
73866118612837887cbae365676d53cc3e1c258249aaFariborz Jahanian      Result +=
73876118612837887cbae365676d53cc3e1c258249aaFariborz Jahanian        CategoryImplementation[i]->getClassInterface()->getNameAsString();
73886118612837887cbae365676d53cc3e1c258249aaFariborz Jahanian      Result += "_$_";
73896118612837887cbae365676d53cc3e1c258249aaFariborz Jahanian      Result += CategoryImplementation[i]->getNameAsString();
73906118612837887cbae365676d53cc3e1c258249aaFariborz Jahanian      Result += ",\n";
73916118612837887cbae365676d53cc3e1c258249aaFariborz Jahanian    }
73926118612837887cbae365676d53cc3e1c258249aaFariborz Jahanian    Result += "};\n";
73936118612837887cbae365676d53cc3e1c258249aaFariborz Jahanian  }
739488f7f75e35425f3f228473c4c84a2445793a39c1Fariborz Jahanian
739588f7f75e35425f3f228473c4c84a2445793a39c1Fariborz Jahanian  if (!DefinedNonLazyCategories.empty()) {
739688f7f75e35425f3f228473c4c84a2445793a39c1Fariborz Jahanian    if (LangOpts.MicrosoftExt)
739788f7f75e35425f3f228473c4c84a2445793a39c1Fariborz Jahanian      Result += "__declspec(allocate(\".objc_nlcatlist$B\")) \n";
739888f7f75e35425f3f228473c4c84a2445793a39c1Fariborz Jahanian    Result += "static struct _category_t *_OBJC_LABEL_NONLAZY_CATEGORY_$[] = {\n\t";
739988f7f75e35425f3f228473c4c84a2445793a39c1Fariborz Jahanian    for (unsigned i = 0, e = DefinedNonLazyCategories.size(); i < e; i++) {
740088f7f75e35425f3f228473c4c84a2445793a39c1Fariborz Jahanian      Result += "\t&_OBJC_$_CATEGORY_";
740188f7f75e35425f3f228473c4c84a2445793a39c1Fariborz Jahanian      Result +=
740288f7f75e35425f3f228473c4c84a2445793a39c1Fariborz Jahanian        DefinedNonLazyCategories[i]->getClassInterface()->getNameAsString();
740388f7f75e35425f3f228473c4c84a2445793a39c1Fariborz Jahanian      Result += "_$_";
740488f7f75e35425f3f228473c4c84a2445793a39c1Fariborz Jahanian      Result += DefinedNonLazyCategories[i]->getNameAsString();
740588f7f75e35425f3f228473c4c84a2445793a39c1Fariborz Jahanian      Result += ",\n";
740688f7f75e35425f3f228473c4c84a2445793a39c1Fariborz Jahanian    }
740788f7f75e35425f3f228473c4c84a2445793a39c1Fariborz Jahanian    Result += "};\n";
740888f7f75e35425f3f228473c4c84a2445793a39c1Fariborz Jahanian  }
740964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian}
741064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
741110cde2fc0c1804427dd3e0c050c149ac6d415f51Fariborz Jahanianvoid RewriteModernObjC::WriteImageInfo(std::string &Result) {
741210cde2fc0c1804427dd3e0c050c149ac6d415f51Fariborz Jahanian  if (LangOpts.MicrosoftExt)
741310cde2fc0c1804427dd3e0c050c149ac6d415f51Fariborz Jahanian    Result += "__declspec(allocate(\".objc_imageinfo$B\")) \n";
741410cde2fc0c1804427dd3e0c050c149ac6d415f51Fariborz Jahanian
741510cde2fc0c1804427dd3e0c050c149ac6d415f51Fariborz Jahanian  Result += "static struct IMAGE_INFO { unsigned version; unsigned flag; } ";
741610cde2fc0c1804427dd3e0c050c149ac6d415f51Fariborz Jahanian  // version 0, ObjCABI is 2
741730650ebe652854d8bdce832cbdae1cf3c43e54aaFariborz Jahanian  Result += "_OBJC_IMAGE_INFO = { 0, 2 };\n";
741810cde2fc0c1804427dd3e0c050c149ac6d415f51Fariborz Jahanian}
741910cde2fc0c1804427dd3e0c050c149ac6d415f51Fariborz Jahanian
742064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian/// RewriteObjCCategoryImplDecl - Rewrite metadata for each category
742164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian/// implementation.
742264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanianvoid RewriteModernObjC::RewriteObjCCategoryImplDecl(ObjCCategoryImplDecl *IDecl,
742364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                              std::string &Result) {
7424de5d946288bb3d68576c95974beb8cfd21d7043aFariborz Jahanian  WriteModernMetadataDeclarations(Context, Result);
742564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  ObjCInterfaceDecl *ClassDecl = IDecl->getClassInterface();
742664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  // Find category declaration for this implementation.
7427d329724745b49f894b768d47275b7c2713106e89Douglas Gregor  ObjCCategoryDecl *CDecl
7428d329724745b49f894b768d47275b7c2713106e89Douglas Gregor    = ClassDecl->FindCategoryDeclaration(IDecl->getIdentifier());
742964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
743064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  std::string FullCategoryName = ClassDecl->getNameAsString();
74316118612837887cbae365676d53cc3e1c258249aaFariborz Jahanian  FullCategoryName += "_$_";
74326118612837887cbae365676d53cc3e1c258249aaFariborz Jahanian  FullCategoryName += CDecl->getNameAsString();
743364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
743464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  // Build _objc_method_list for class's instance methods if needed
7435651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  SmallVector<ObjCMethodDecl *, 32> InstanceMethods(IDecl->instance_methods());
743664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
743764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  // If any of our property implementations have associated getters or
743864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  // setters, produce metadata for them as well.
7439651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  for (const auto *Prop : IDecl->property_impls()) {
7440262bc18e32500558af7cb0afa205b34bd37bafedDavid Blaikie    if (Prop->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic)
744164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      continue;
7442262bc18e32500558af7cb0afa205b34bd37bafedDavid Blaikie    if (!Prop->getPropertyIvarDecl())
744364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      continue;
7444262bc18e32500558af7cb0afa205b34bd37bafedDavid Blaikie    ObjCPropertyDecl *PD = Prop->getPropertyDecl();
744564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    if (!PD)
744664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      continue;
744764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    if (ObjCMethodDecl *Getter = PD->getGetterMethodDecl())
744864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      InstanceMethods.push_back(Getter);
744964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    if (PD->isReadOnly())
745064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      continue;
745164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    if (ObjCMethodDecl *Setter = PD->getSetterMethodDecl())
745264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      InstanceMethods.push_back(Setter);
745364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  }
745464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
74556118612837887cbae365676d53cc3e1c258249aaFariborz Jahanian  Write_method_list_t_initializer(*this, Context, Result, InstanceMethods,
74566118612837887cbae365676d53cc3e1c258249aaFariborz Jahanian                                  "_OBJC_$_CATEGORY_INSTANCE_METHODS_",
74576118612837887cbae365676d53cc3e1c258249aaFariborz Jahanian                                  FullCategoryName, true);
745864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
7459651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  SmallVector<ObjCMethodDecl *, 32> ClassMethods(IDecl->class_methods());
746064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
74616118612837887cbae365676d53cc3e1c258249aaFariborz Jahanian  Write_method_list_t_initializer(*this, Context, Result, ClassMethods,
74626118612837887cbae365676d53cc3e1c258249aaFariborz Jahanian                                  "_OBJC_$_CATEGORY_CLASS_METHODS_",
74636118612837887cbae365676d53cc3e1c258249aaFariborz Jahanian                                  FullCategoryName, true);
746464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
74656118612837887cbae365676d53cc3e1c258249aaFariborz Jahanian  // Protocols referenced in class declaration?
74666118612837887cbae365676d53cc3e1c258249aaFariborz Jahanian  // Protocol's super protocol list
7467651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  SmallVector<ObjCProtocolDecl *, 8> RefedProtocols(CDecl->protocols());
7468651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  for (auto *I : CDecl->protocols())
74696118612837887cbae365676d53cc3e1c258249aaFariborz Jahanian    // Must write out all protocol definitions in current qualifier list,
74706118612837887cbae365676d53cc3e1c258249aaFariborz Jahanian    // and in their nested qualifiers before writing out current definition.
7471651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    RewriteObjCProtocolMetaData(I, Result);
747264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
74736118612837887cbae365676d53cc3e1c258249aaFariborz Jahanian  Write_protocol_list_initializer(Context, Result,
74746118612837887cbae365676d53cc3e1c258249aaFariborz Jahanian                                  RefedProtocols,
74756118612837887cbae365676d53cc3e1c258249aaFariborz Jahanian                                  "_OBJC_CATEGORY_PROTOCOLS_$_",
74766118612837887cbae365676d53cc3e1c258249aaFariborz Jahanian                                  FullCategoryName);
74776118612837887cbae365676d53cc3e1c258249aaFariborz Jahanian
74786118612837887cbae365676d53cc3e1c258249aaFariborz Jahanian  // Protocol's property metadata.
7479651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  SmallVector<ObjCPropertyDecl *, 8> ClassProperties(CDecl->properties());
74806118612837887cbae365676d53cc3e1c258249aaFariborz Jahanian  Write_prop_list_t_initializer(*this, Context, Result, ClassProperties,
7481ebfa27205153c4b81bede598331c4e693253c2c7Fariborz Jahanian                                /* Container */IDecl,
74826118612837887cbae365676d53cc3e1c258249aaFariborz Jahanian                                "_OBJC_$_PROP_LIST_",
74836118612837887cbae365676d53cc3e1c258249aaFariborz Jahanian                                FullCategoryName);
74846118612837887cbae365676d53cc3e1c258249aaFariborz Jahanian
74856118612837887cbae365676d53cc3e1c258249aaFariborz Jahanian  Write_category_t(*this, Context, Result,
7486e0335786c17a6ca45966f66094146e9d8ba2d54aFariborz Jahanian                   CDecl,
748788f7f75e35425f3f228473c4c84a2445793a39c1Fariborz Jahanian                   ClassDecl,
74886118612837887cbae365676d53cc3e1c258249aaFariborz Jahanian                   InstanceMethods,
74896118612837887cbae365676d53cc3e1c258249aaFariborz Jahanian                   ClassMethods,
74906118612837887cbae365676d53cc3e1c258249aaFariborz Jahanian                   RefedProtocols,
74916118612837887cbae365676d53cc3e1c258249aaFariborz Jahanian                   ClassProperties);
74926118612837887cbae365676d53cc3e1c258249aaFariborz Jahanian
749388f7f75e35425f3f228473c4c84a2445793a39c1Fariborz Jahanian  // Determine if this category is also "non-lazy".
749488f7f75e35425f3f228473c4c84a2445793a39c1Fariborz Jahanian  if (ImplementationIsNonLazy(IDecl))
749588f7f75e35425f3f228473c4c84a2445793a39c1Fariborz Jahanian    DefinedNonLazyCategories.push_back(CDecl);
7496e0335786c17a6ca45966f66094146e9d8ba2d54aFariborz Jahanian
7497e0335786c17a6ca45966f66094146e9d8ba2d54aFariborz Jahanian}
7498e0335786c17a6ca45966f66094146e9d8ba2d54aFariborz Jahanian
7499e0335786c17a6ca45966f66094146e9d8ba2d54aFariborz Jahanianvoid RewriteModernObjC::RewriteCategorySetupInitHook(std::string &Result) {
7500e0335786c17a6ca45966f66094146e9d8ba2d54aFariborz Jahanian  int CatDefCount = CategoryImplementation.size();
7501e0335786c17a6ca45966f66094146e9d8ba2d54aFariborz Jahanian  if (!CatDefCount)
7502e0335786c17a6ca45966f66094146e9d8ba2d54aFariborz Jahanian    return;
7503e0335786c17a6ca45966f66094146e9d8ba2d54aFariborz Jahanian  Result += "#pragma section(\".objc_inithooks$B\", long, read, write)\n";
7504e0335786c17a6ca45966f66094146e9d8ba2d54aFariborz Jahanian  Result += "__declspec(allocate(\".objc_inithooks$B\")) ";
7505e0335786c17a6ca45966f66094146e9d8ba2d54aFariborz Jahanian  Result += "static void *OBJC_CATEGORY_SETUP[] = {\n";
7506e0335786c17a6ca45966f66094146e9d8ba2d54aFariborz Jahanian  for (int i = 0; i < CatDefCount; i++) {
7507e0335786c17a6ca45966f66094146e9d8ba2d54aFariborz Jahanian    ObjCCategoryImplDecl *IDecl = CategoryImplementation[i];
7508e0335786c17a6ca45966f66094146e9d8ba2d54aFariborz Jahanian    ObjCCategoryDecl *CatDecl= IDecl->getCategoryDecl();
7509e0335786c17a6ca45966f66094146e9d8ba2d54aFariborz Jahanian    ObjCInterfaceDecl *ClassDecl = IDecl->getClassInterface();
7510e0335786c17a6ca45966f66094146e9d8ba2d54aFariborz Jahanian    Result += "\t(void *)&OBJC_CATEGORY_SETUP_$_";
7511e0335786c17a6ca45966f66094146e9d8ba2d54aFariborz Jahanian    Result += ClassDecl->getName();
7512e0335786c17a6ca45966f66094146e9d8ba2d54aFariborz Jahanian    Result += "_$_";
7513e0335786c17a6ca45966f66094146e9d8ba2d54aFariborz Jahanian    Result += CatDecl->getName();
7514e0335786c17a6ca45966f66094146e9d8ba2d54aFariborz Jahanian    Result += ",\n";
7515e0335786c17a6ca45966f66094146e9d8ba2d54aFariborz Jahanian  }
7516e0335786c17a6ca45966f66094146e9d8ba2d54aFariborz Jahanian  Result += "};\n";
751764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian}
751864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
751964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian// RewriteObjCMethodsMetaData - Rewrite methods metadata for instance or
752064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian/// class methods.
752164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahaniantemplate<typename MethodIterator>
752264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanianvoid RewriteModernObjC::RewriteObjCMethodsMetaData(MethodIterator MethodBegin,
752364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                             MethodIterator MethodEnd,
752464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                             bool IsInstanceMethod,
752564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                             StringRef prefix,
752664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                             StringRef ClassName,
752764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                             std::string &Result) {
752864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  if (MethodBegin == MethodEnd) return;
752964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
753064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  if (!objc_impl_method) {
753164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    /* struct _objc_method {
753264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian     SEL _cmd;
753364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian     char *method_types;
753464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian     void *_imp;
753564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian     }
753664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian     */
753764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    Result += "\nstruct _objc_method {\n";
753864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    Result += "\tSEL _cmd;\n";
753964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    Result += "\tchar *method_types;\n";
754064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    Result += "\tvoid *_imp;\n";
754164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    Result += "};\n";
754264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
754364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    objc_impl_method = true;
754464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  }
754564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
754664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  // Build _objc_method_list for class's methods if needed
754764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
754864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  /* struct  {
754964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian   struct _objc_method_list *next_method;
755064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian   int method_count;
755164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian   struct _objc_method method_list[];
755264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian   }
755364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian   */
755464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  unsigned NumMethods = std::distance(MethodBegin, MethodEnd);
75551ca052c09868169d4de4da5d1d45f07f2fe8511aFariborz Jahanian  Result += "\n";
75561ca052c09868169d4de4da5d1d45f07f2fe8511aFariborz Jahanian  if (LangOpts.MicrosoftExt) {
75571ca052c09868169d4de4da5d1d45f07f2fe8511aFariborz Jahanian    if (IsInstanceMethod)
75581ca052c09868169d4de4da5d1d45f07f2fe8511aFariborz Jahanian      Result += "__declspec(allocate(\".inst_meth$B\")) ";
75591ca052c09868169d4de4da5d1d45f07f2fe8511aFariborz Jahanian    else
75601ca052c09868169d4de4da5d1d45f07f2fe8511aFariborz Jahanian      Result += "__declspec(allocate(\".cls_meth$B\")) ";
75611ca052c09868169d4de4da5d1d45f07f2fe8511aFariborz Jahanian  }
75621ca052c09868169d4de4da5d1d45f07f2fe8511aFariborz Jahanian  Result += "static struct {\n";
756364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  Result += "\tstruct _objc_method_list *next_method;\n";
756464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  Result += "\tint method_count;\n";
756564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  Result += "\tstruct _objc_method method_list[";
756664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  Result += utostr(NumMethods);
756764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  Result += "];\n} _OBJC_";
756864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  Result += prefix;
756964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  Result += IsInstanceMethod ? "INSTANCE" : "CLASS";
757064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  Result += "_METHODS_";
757164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  Result += ClassName;
757264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  Result += " __attribute__ ((used, section (\"__OBJC, __";
757364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  Result += IsInstanceMethod ? "inst" : "cls";
757464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  Result += "_meth\")))= ";
757564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  Result += "{\n\t0, " + utostr(NumMethods) + "\n";
757664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
757764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  Result += "\t,{{(SEL)\"";
757864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  Result += (*MethodBegin)->getSelector().getAsString().c_str();
757964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  std::string MethodTypeString;
758064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  Context->getObjCEncodingForMethodDecl(*MethodBegin, MethodTypeString);
758164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  Result += "\", \"";
758264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  Result += MethodTypeString;
758364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  Result += "\", (void *)";
758464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  Result += MethodInternalNames[*MethodBegin];
758564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  Result += "}\n";
758664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  for (++MethodBegin; MethodBegin != MethodEnd; ++MethodBegin) {
758764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    Result += "\t  ,{(SEL)\"";
758864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    Result += (*MethodBegin)->getSelector().getAsString().c_str();
758964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    std::string MethodTypeString;
759064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    Context->getObjCEncodingForMethodDecl(*MethodBegin, MethodTypeString);
759164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    Result += "\", \"";
759264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    Result += MethodTypeString;
759364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    Result += "\", (void *)";
759464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    Result += MethodInternalNames[*MethodBegin];
759564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    Result += "}\n";
759664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  }
759764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  Result += "\t }\n};\n";
759864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian}
759964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
760064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz JahanianStmt *RewriteModernObjC::RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV) {
760164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  SourceRange OldRange = IV->getSourceRange();
760264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  Expr *BaseExpr = IV->getBase();
760364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
760464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  // Rewrite the base, but without actually doing replaces.
760564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  {
760664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    DisableReplaceStmtScope S(*this);
760764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    BaseExpr = cast<Expr>(RewriteFunctionBodyOrGlobalInitializer(BaseExpr));
760864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    IV->setBase(BaseExpr);
760964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  }
761064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
761164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  ObjCIvarDecl *D = IV->getDecl();
761264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
761364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian  Expr *Replacement = IV;
7614e7b3fa73596305bcc443369569d123b0f1b513cbFariborz Jahanian
761564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    if (BaseExpr->getType()->isObjCObjectPointerType()) {
761664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      const ObjCInterfaceType *iFaceDecl =
7617163d3cef334169e41225d94a4c353e0d7159570bFariborz Jahanian        dyn_cast<ObjCInterfaceType>(BaseExpr->getType()->getPointeeType());
761864cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      assert(iFaceDecl && "RewriteObjCIvarRefExpr - iFaceDecl is null");
761964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      // lookup which class implements the instance variable.
76206bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      ObjCInterfaceDecl *clsDeclared = nullptr;
762164cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      iFaceDecl->getDecl()->lookupInstanceVariable(D->getIdentifier(),
762264cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                                   clsDeclared);
762364cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      assert(clsDeclared && "RewriteObjCIvarRefExpr(): Can't find class");
762464cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
7625e7b3fa73596305bcc443369569d123b0f1b513cbFariborz Jahanian      // Build name of symbol holding ivar offset.
76267cb2a1b4b6ef60aa57a5f2e5e820a57adef3ea77Fariborz Jahanian      std::string IvarOffsetName;
7627cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian      if (D->isBitField())
7628cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian        ObjCIvarBitfieldGroupOffset(D, IvarOffsetName);
7629cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian      else
7630cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian        WriteInternalIvarName(clsDeclared, D, IvarOffsetName);
76317cb2a1b4b6ef60aa57a5f2e5e820a57adef3ea77Fariborz Jahanian
763272c88f13f79e2012b8a5f84cf48c6af779dfd1baFariborz Jahanian      ReferencedIvars[clsDeclared].insert(D);
763372c88f13f79e2012b8a5f84cf48c6af779dfd1baFariborz Jahanian
7634e7b3fa73596305bcc443369569d123b0f1b513cbFariborz Jahanian      // cast offset to "char *".
7635e7b3fa73596305bcc443369569d123b0f1b513cbFariborz Jahanian      CastExpr *castExpr = NoTypeInfoCStyleCastExpr(Context,
7636e7b3fa73596305bcc443369569d123b0f1b513cbFariborz Jahanian                                                    Context->getPointerType(Context->CharTy),
763764cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian                                                    CK_BitCast,
7638e7b3fa73596305bcc443369569d123b0f1b513cbFariborz Jahanian                                                    BaseExpr);
7639e7b3fa73596305bcc443369569d123b0f1b513cbFariborz Jahanian      VarDecl *NewVD = VarDecl::Create(*Context, TUDecl, SourceLocation(),
7640e7b3fa73596305bcc443369569d123b0f1b513cbFariborz Jahanian                                       SourceLocation(), &Context->Idents.get(IvarOffsetName),
76416bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines                                       Context->UnsignedLongTy, nullptr,
76426bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines                                       SC_Extern);
7643f4b88a45902af1802a1cb42ba48b1c474474f228John McCall      DeclRefExpr *DRE = new (Context) DeclRefExpr(NewVD, false,
7644f4b88a45902af1802a1cb42ba48b1c474474f228John McCall                                                   Context->UnsignedLongTy, VK_LValue,
7645e7b3fa73596305bcc443369569d123b0f1b513cbFariborz Jahanian                                                   SourceLocation());
7646e7b3fa73596305bcc443369569d123b0f1b513cbFariborz Jahanian      BinaryOperator *addExpr =
7647e7b3fa73596305bcc443369569d123b0f1b513cbFariborz Jahanian        new (Context) BinaryOperator(castExpr, DRE, BO_Add,
7648e7b3fa73596305bcc443369569d123b0f1b513cbFariborz Jahanian                                     Context->getPointerType(Context->CharTy),
7649be9af1288881110e406b87914162eaa59f1e5918Lang Hames                                     VK_RValue, OK_Ordinary, SourceLocation(), false);
765064cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian      // Don't forget the parens to enforce the proper binding.
7651e7b3fa73596305bcc443369569d123b0f1b513cbFariborz Jahanian      ParenExpr *PE = new (Context) ParenExpr(SourceLocation(),
7652e7b3fa73596305bcc443369569d123b0f1b513cbFariborz Jahanian                                              SourceLocation(),
7653e7b3fa73596305bcc443369569d123b0f1b513cbFariborz Jahanian                                              addExpr);
76540d6e22a38314fd6a9bdb0d83fcc5c5215641d5e9Fariborz Jahanian      QualType IvarT = D->getType();
7655cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian      if (D->isBitField())
7656cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian        IvarT = GetGroupRecordTypeForObjCIvarBitfield(D);
765727fc81b580f75aeddf6d94d05a86576f1d9c4693Fariborz Jahanian
7658f5eac481ab6da79f05ca13fd859b67abfd2ed246Fariborz Jahanian      if (!isa<TypedefType>(IvarT) && IvarT->isRecordType()) {
765927fc81b580f75aeddf6d94d05a86576f1d9c4693Fariborz Jahanian        RecordDecl *RD = IvarT->getAs<RecordType>()->getDecl();
76608fba894335b979e6d213c685bca959168c1f2182Fariborz Jahanian        RD = RD->getDefinition();
76618fba894335b979e6d213c685bca959168c1f2182Fariborz Jahanian        if (RD && !RD->getDeclName().getAsIdentifierInfo()) {
766227fc81b580f75aeddf6d94d05a86576f1d9c4693Fariborz Jahanian          // decltype(((Foo_IMPL*)0)->bar) *
7663f5eac481ab6da79f05ca13fd859b67abfd2ed246Fariborz Jahanian          ObjCContainerDecl *CDecl =
7664f5eac481ab6da79f05ca13fd859b67abfd2ed246Fariborz Jahanian            dyn_cast<ObjCContainerDecl>(D->getDeclContext());
7665f5eac481ab6da79f05ca13fd859b67abfd2ed246Fariborz Jahanian          // ivar in class extensions requires special treatment.
7666f5eac481ab6da79f05ca13fd859b67abfd2ed246Fariborz Jahanian          if (ObjCCategoryDecl *CatDecl = dyn_cast<ObjCCategoryDecl>(CDecl))
7667f5eac481ab6da79f05ca13fd859b67abfd2ed246Fariborz Jahanian            CDecl = CatDecl->getClassInterface();
7668f5eac481ab6da79f05ca13fd859b67abfd2ed246Fariborz Jahanian          std::string RecName = CDecl->getName();
766927fc81b580f75aeddf6d94d05a86576f1d9c4693Fariborz Jahanian          RecName += "_IMPL";
767027fc81b580f75aeddf6d94d05a86576f1d9c4693Fariborz Jahanian          RecordDecl *RD = RecordDecl::Create(*Context, TTK_Struct, TUDecl,
767127fc81b580f75aeddf6d94d05a86576f1d9c4693Fariborz Jahanian                                              SourceLocation(), SourceLocation(),
767227fc81b580f75aeddf6d94d05a86576f1d9c4693Fariborz Jahanian                                              &Context->Idents.get(RecName.c_str()));
767327fc81b580f75aeddf6d94d05a86576f1d9c4693Fariborz Jahanian          QualType PtrStructIMPL = Context->getPointerType(Context->getTagDeclType(RD));
767427fc81b580f75aeddf6d94d05a86576f1d9c4693Fariborz Jahanian          unsigned UnsignedIntSize =
767527fc81b580f75aeddf6d94d05a86576f1d9c4693Fariborz Jahanian            static_cast<unsigned>(Context->getTypeSize(Context->UnsignedIntTy));
767627fc81b580f75aeddf6d94d05a86576f1d9c4693Fariborz Jahanian          Expr *Zero = IntegerLiteral::Create(*Context,
767727fc81b580f75aeddf6d94d05a86576f1d9c4693Fariborz Jahanian                                              llvm::APInt(UnsignedIntSize, 0),
767827fc81b580f75aeddf6d94d05a86576f1d9c4693Fariborz Jahanian                                              Context->UnsignedIntTy, SourceLocation());
767927fc81b580f75aeddf6d94d05a86576f1d9c4693Fariborz Jahanian          Zero = NoTypeInfoCStyleCastExpr(Context, PtrStructIMPL, CK_BitCast, Zero);
768027fc81b580f75aeddf6d94d05a86576f1d9c4693Fariborz Jahanian          ParenExpr *PE = new (Context) ParenExpr(SourceLocation(), SourceLocation(),
768127fc81b580f75aeddf6d94d05a86576f1d9c4693Fariborz Jahanian                                                  Zero);
76826bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines          FieldDecl *FD = FieldDecl::Create(*Context, nullptr, SourceLocation(),
768327fc81b580f75aeddf6d94d05a86576f1d9c4693Fariborz Jahanian                                            SourceLocation(),
768427fc81b580f75aeddf6d94d05a86576f1d9c4693Fariborz Jahanian                                            &Context->Idents.get(D->getNameAsString()),
768533337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar                                            IvarT, nullptr,
768633337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar                                            /*BitWidth=*/nullptr,
768733337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar                                            /*Mutable=*/true, ICIS_NoInit);
768833337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar          MemberExpr *ME = new (Context)
768933337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar              MemberExpr(PE, true, SourceLocation(), FD, SourceLocation(),
769033337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar                         FD->getType(), VK_LValue, OK_Ordinary);
769133337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar          IvarT = Context->getDecltypeType(ME, ME->getType());
769233337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar        }
769333337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar      }
76948e0913d4921e36ef82ecba565fd7b2c66165dd87Fariborz Jahanian      convertObjCTypeToCStyleType(IvarT);
76950d6e22a38314fd6a9bdb0d83fcc5c5215641d5e9Fariborz Jahanian      QualType castT = Context->getPointerType(IvarT);
769627fc81b580f75aeddf6d94d05a86576f1d9c4693Fariborz Jahanian
7697e7b3fa73596305bcc443369569d123b0f1b513cbFariborz Jahanian      castExpr = NoTypeInfoCStyleCastExpr(Context,
7698e7b3fa73596305bcc443369569d123b0f1b513cbFariborz Jahanian                                          castT,
7699e7b3fa73596305bcc443369569d123b0f1b513cbFariborz Jahanian                                          CK_BitCast,
7700e7b3fa73596305bcc443369569d123b0f1b513cbFariborz Jahanian                                          PE);
770127fc81b580f75aeddf6d94d05a86576f1d9c4693Fariborz Jahanian
770227fc81b580f75aeddf6d94d05a86576f1d9c4693Fariborz Jahanian
77038e0913d4921e36ef82ecba565fd7b2c66165dd87Fariborz Jahanian      Expr *Exp = new (Context) UnaryOperator(castExpr, UO_Deref, IvarT,
7704e7b3fa73596305bcc443369569d123b0f1b513cbFariborz Jahanian                                              VK_LValue, OK_Ordinary,
7705e7b3fa73596305bcc443369569d123b0f1b513cbFariborz Jahanian                                              SourceLocation());
7706e7b3fa73596305bcc443369569d123b0f1b513cbFariborz Jahanian      PE = new (Context) ParenExpr(OldRange.getBegin(),
7707e7b3fa73596305bcc443369569d123b0f1b513cbFariborz Jahanian                                   OldRange.getEnd(),
7708e7b3fa73596305bcc443369569d123b0f1b513cbFariborz Jahanian                                   Exp);
7709cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian
7710cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian      if (D->isBitField()) {
77116bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines        FieldDecl *FD = FieldDecl::Create(*Context, nullptr, SourceLocation(),
7712cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian                                          SourceLocation(),
7713cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian                                          &Context->Idents.get(D->getNameAsString()),
771433337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar                                          D->getType(), nullptr,
771533337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar                                          /*BitWidth=*/D->getBitWidth(),
771633337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar                                          /*Mutable=*/true, ICIS_NoInit);
771733337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar        MemberExpr *ME = new (Context)
771833337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar            MemberExpr(PE, /*isArrow*/ false, SourceLocation(), FD,
771933337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar                       SourceLocation(), FD->getType(), VK_LValue, OK_Ordinary);
772033337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar        Replacement = ME;
772133337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar
772233337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar      }
7723cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian      else
7724cd3b036dbdd29b0ddcaa12b5cce69b647b2ac5baFariborz Jahanian        Replacement = PE;
772564cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian    }
772664cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian
7727e7b3fa73596305bcc443369569d123b0f1b513cbFariborz Jahanian    ReplaceStmtWithRange(IV, Replacement, OldRange);
7728e7b3fa73596305bcc443369569d123b0f1b513cbFariborz Jahanian    return Replacement;
772964cb63a0cfa76b278e0791141c7b5a1b424ab434Fariborz Jahanian}
7730176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines
7731176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines#endif
7732