brintos

brintos / llvm-project-archived public Read only

0
0
Text · 223.4 KiB · b9c025d Raw
5870 lines · cpp
1//===--- RewriteObjC.cpp - Playground for the code rewriter ---------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9// Hacks and fun related to the code rewriter.10//11//===----------------------------------------------------------------------===//12 13#include "clang/Rewrite/Frontend/ASTConsumers.h"14#include "clang/AST/AST.h"15#include "clang/AST/ASTConsumer.h"16#include "clang/AST/Attr.h"17#include "clang/AST/ParentMap.h"18#include "clang/Basic/CharInfo.h"19#include "clang/Basic/Diagnostic.h"20#include "clang/Basic/IdentifierTable.h"21#include "clang/Basic/SourceManager.h"22#include "clang/Config/config.h"23#include "clang/Lex/Lexer.h"24#include "clang/Rewrite/Core/Rewriter.h"25#include "llvm/ADT/DenseSet.h"26#include "llvm/ADT/SmallPtrSet.h"27#include "llvm/ADT/StringExtras.h"28#include "llvm/Support/MemoryBuffer.h"29#include "llvm/Support/raw_ostream.h"30#include <memory>31 32#if CLANG_ENABLE_OBJC_REWRITER33 34using namespace clang;35using llvm::RewriteBuffer;36using llvm::utostr;37 38namespace {39  class RewriteObjC : public ASTConsumer {40  protected:41    enum {42      BLOCK_FIELD_IS_OBJECT   =  3,  /* id, NSObject, __attribute__((NSObject)),43                                        block, ... */44      BLOCK_FIELD_IS_BLOCK    =  7,  /* a block variable */45      BLOCK_FIELD_IS_BYREF    =  8,  /* the on stack structure holding the46                                        __block variable */47      BLOCK_FIELD_IS_WEAK     = 16,  /* declared __weak, only used in byref copy48                                        helpers */49      BLOCK_BYREF_CALLER      = 128, /* called from __block (byref) copy/dispose50                                        support routines */51      BLOCK_BYREF_CURRENT_MAX = 25652    };53 54    enum {55      BLOCK_NEEDS_FREE =        (1 << 24),56      BLOCK_HAS_COPY_DISPOSE =  (1 << 25),57      BLOCK_HAS_CXX_OBJ =       (1 << 26),58      BLOCK_IS_GC =             (1 << 27),59      BLOCK_IS_GLOBAL =         (1 << 28),60      BLOCK_HAS_DESCRIPTOR =    (1 << 29)61    };62    static const int OBJC_ABI_VERSION = 7;63 64    Rewriter Rewrite;65    DiagnosticsEngine &Diags;66    const LangOptions &LangOpts;67    ASTContext *Context;68    SourceManager *SM;69    TranslationUnitDecl *TUDecl;70    FileID MainFileID;71    const char *MainFileStart, *MainFileEnd;72    Stmt *CurrentBody;73    ParentMap *PropParentMap; // created lazily.74    std::string InFileName;75    std::unique_ptr<raw_ostream> OutFile;76    std::string Preamble;77 78    TypeDecl *ProtocolTypeDecl;79    VarDecl *GlobalVarDecl;80    unsigned RewriteFailedDiag;81    // ObjC string constant support.82    unsigned NumObjCStringLiterals;83    VarDecl *ConstantStringClassReference;84    RecordDecl *NSStringRecord;85 86    // ObjC foreach break/continue generation support.87    int BcLabelCount;88 89    unsigned TryFinallyContainsReturnDiag;90    // Needed for super.91    ObjCMethodDecl *CurMethodDef;92    RecordDecl *SuperStructDecl;93    RecordDecl *ConstantStringDecl;94 95    FunctionDecl *MsgSendFunctionDecl;96    FunctionDecl *MsgSendSuperFunctionDecl;97    FunctionDecl *MsgSendStretFunctionDecl;98    FunctionDecl *MsgSendSuperStretFunctionDecl;99    FunctionDecl *MsgSendFpretFunctionDecl;100    FunctionDecl *GetClassFunctionDecl;101    FunctionDecl *GetMetaClassFunctionDecl;102    FunctionDecl *GetSuperClassFunctionDecl;103    FunctionDecl *SelGetUidFunctionDecl;104    FunctionDecl *CFStringFunctionDecl;105    FunctionDecl *SuperConstructorFunctionDecl;106    FunctionDecl *CurFunctionDef;107    FunctionDecl *CurFunctionDeclToDeclareForBlock;108 109    /* Misc. containers needed for meta-data rewrite. */110    SmallVector<ObjCImplementationDecl *, 8> ClassImplementation;111    SmallVector<ObjCCategoryImplDecl *, 8> CategoryImplementation;112    llvm::SmallPtrSet<ObjCInterfaceDecl*, 8> ObjCSynthesizedStructs;113    llvm::SmallPtrSet<ObjCProtocolDecl*, 8> ObjCSynthesizedProtocols;114    llvm::SmallPtrSet<ObjCInterfaceDecl*, 8> ObjCForwardDecls;115    llvm::DenseMap<ObjCMethodDecl*, std::string> MethodInternalNames;116    SmallVector<Stmt *, 32> Stmts;117    SmallVector<int, 8> ObjCBcLabelNo;118    // Remember all the @protocol(<expr>) expressions.119    llvm::SmallPtrSet<ObjCProtocolDecl *, 32> ProtocolExprDecls;120 121    llvm::DenseSet<uint64_t> CopyDestroyCache;122 123    // Block expressions.124    SmallVector<BlockExpr *, 32> Blocks;125    SmallVector<int, 32> InnerDeclRefsCount;126    SmallVector<DeclRefExpr *, 32> InnerDeclRefs;127 128    SmallVector<DeclRefExpr *, 32> BlockDeclRefs;129 130    // Block related declarations.131    llvm::SmallSetVector<ValueDecl *, 8> BlockByCopyDecls;132    llvm::SmallSetVector<ValueDecl *, 8> BlockByRefDecls;133    llvm::DenseMap<ValueDecl *, unsigned> BlockByRefDeclNo;134    llvm::SmallPtrSet<ValueDecl *, 8> ImportedBlockDecls;135    llvm::SmallPtrSet<VarDecl *, 8> ImportedLocalExternalDecls;136 137    llvm::DenseMap<BlockExpr *, std::string> RewrittenBlockExprs;138 139    // This maps an original source AST to it's rewritten form. This allows140    // us to avoid rewriting the same node twice (which is very uncommon).141    // This is needed to support some of the exotic property rewriting.142    llvm::DenseMap<Stmt *, Stmt *> ReplacedNodes;143 144    // Needed for header files being rewritten145    bool IsHeader;146    bool SilenceRewriteMacroWarning;147    bool objc_impl_method;148 149    bool DisableReplaceStmt;150    class DisableReplaceStmtScope {151      RewriteObjC &R;152      bool SavedValue;153 154    public:155      DisableReplaceStmtScope(RewriteObjC &R)156        : R(R), SavedValue(R.DisableReplaceStmt) {157        R.DisableReplaceStmt = true;158      }159 160      ~DisableReplaceStmtScope() {161        R.DisableReplaceStmt = SavedValue;162      }163    };164 165    void InitializeCommon(ASTContext &context);166 167  public:168    // Top Level Driver code.169    bool HandleTopLevelDecl(DeclGroupRef D) override {170      for (DeclGroupRef::iterator I = D.begin(), E = D.end(); I != E; ++I) {171        if (ObjCInterfaceDecl *Class = dyn_cast<ObjCInterfaceDecl>(*I)) {172          if (!Class->isThisDeclarationADefinition()) {173            RewriteForwardClassDecl(D);174            break;175          }176        }177 178        if (ObjCProtocolDecl *Proto = dyn_cast<ObjCProtocolDecl>(*I)) {179          if (!Proto->isThisDeclarationADefinition()) {180            RewriteForwardProtocolDecl(D);181            break;182          }183        }184 185        HandleTopLevelSingleDecl(*I);186      }187      return true;188    }189 190    void HandleTopLevelSingleDecl(Decl *D);191    void HandleDeclInMainFile(Decl *D);192    RewriteObjC(std::string inFile, std::unique_ptr<raw_ostream> OS,193                DiagnosticsEngine &D, const LangOptions &LOpts,194                bool silenceMacroWarn);195 196    ~RewriteObjC() override {}197 198    void HandleTranslationUnit(ASTContext &C) override;199 200    void ReplaceStmt(Stmt *Old, Stmt *New) {201      ReplaceStmtWithRange(Old, New, Old->getSourceRange());202    }203 204    void ReplaceStmtWithRange(Stmt *Old, Stmt *New, SourceRange SrcRange) {205      assert(Old != nullptr && New != nullptr && "Expected non-null Stmt's");206 207      Stmt *ReplacingStmt = ReplacedNodes[Old];208      if (ReplacingStmt)209        return; // We can't rewrite the same node twice.210 211      if (DisableReplaceStmt)212        return;213 214      // Measure the old text.215      int Size = Rewrite.getRangeSize(SrcRange);216      if (Size == -1) {217        Diags.Report(Context->getFullLoc(Old->getBeginLoc()), RewriteFailedDiag)218            << Old->getSourceRange();219        return;220      }221      // Get the new text.222      std::string Str;223      llvm::raw_string_ostream S(Str);224      New->printPretty(S, nullptr, PrintingPolicy(LangOpts));225 226      // If replacement succeeded or warning disabled return with no warning.227      if (!Rewrite.ReplaceText(SrcRange.getBegin(), Size, Str)) {228        ReplacedNodes[Old] = New;229        return;230      }231      if (SilenceRewriteMacroWarning)232        return;233      Diags.Report(Context->getFullLoc(Old->getBeginLoc()), RewriteFailedDiag)234          << Old->getSourceRange();235    }236 237    void InsertText(SourceLocation Loc, StringRef Str,238                    bool InsertAfter = true) {239      // If insertion succeeded or warning disabled return with no warning.240      if (!Rewrite.InsertText(Loc, Str, InsertAfter) ||241          SilenceRewriteMacroWarning)242        return;243 244      Diags.Report(Context->getFullLoc(Loc), RewriteFailedDiag);245    }246 247    void ReplaceText(SourceLocation Start, unsigned OrigLength,248                     StringRef Str) {249      // If removal succeeded or warning disabled return with no warning.250      if (!Rewrite.ReplaceText(Start, OrigLength, Str) ||251          SilenceRewriteMacroWarning)252        return;253 254      Diags.Report(Context->getFullLoc(Start), RewriteFailedDiag);255    }256 257    // Syntactic Rewriting.258    void RewriteRecordBody(RecordDecl *RD);259    void RewriteInclude();260    void RewriteForwardClassDecl(DeclGroupRef D);261    void RewriteForwardClassDecl(const SmallVectorImpl<Decl *> &DG);262    void RewriteForwardClassEpilogue(ObjCInterfaceDecl *ClassDecl,263                                     const std::string &typedefString);264    void RewriteImplementations();265    void RewritePropertyImplDecl(ObjCPropertyImplDecl *PID,266                                 ObjCImplementationDecl *IMD,267                                 ObjCCategoryImplDecl *CID);268    void RewriteInterfaceDecl(ObjCInterfaceDecl *Dcl);269    void RewriteImplementationDecl(Decl *Dcl);270    void RewriteObjCMethodDecl(const ObjCInterfaceDecl *IDecl,271                               ObjCMethodDecl *MDecl, std::string &ResultStr);272    void RewriteTypeIntoString(QualType T, std::string &ResultStr,273                               const FunctionType *&FPRetType);274    void RewriteByRefString(std::string &ResultStr, const std::string &Name,275                            ValueDecl *VD, bool def=false);276    void RewriteCategoryDecl(ObjCCategoryDecl *Dcl);277    void RewriteProtocolDecl(ObjCProtocolDecl *Dcl);278    void RewriteForwardProtocolDecl(DeclGroupRef D);279    void RewriteForwardProtocolDecl(const SmallVectorImpl<Decl *> &DG);280    void RewriteMethodDeclaration(ObjCMethodDecl *Method);281    void RewriteProperty(ObjCPropertyDecl *prop);282    void RewriteFunctionDecl(FunctionDecl *FD);283    void RewriteBlockPointerType(std::string& Str, QualType Type);284    void RewriteBlockPointerTypeVariable(std::string& Str, ValueDecl *VD);285    void RewriteBlockLiteralFunctionDecl(FunctionDecl *FD);286    void RewriteObjCQualifiedInterfaceTypes(Decl *Dcl);287    void RewriteTypeOfDecl(VarDecl *VD);288    void RewriteObjCQualifiedInterfaceTypes(Expr *E);289 290    // Expression Rewriting.291    Stmt *RewriteFunctionBodyOrGlobalInitializer(Stmt *S);292    Stmt *RewriteAtEncode(ObjCEncodeExpr *Exp);293    Stmt *RewritePropertyOrImplicitGetter(PseudoObjectExpr *Pseudo);294    Stmt *RewritePropertyOrImplicitSetter(PseudoObjectExpr *Pseudo);295    Stmt *RewriteAtSelector(ObjCSelectorExpr *Exp);296    Stmt *RewriteMessageExpr(ObjCMessageExpr *Exp);297    Stmt *RewriteObjCStringLiteral(ObjCStringLiteral *Exp);298    Stmt *RewriteObjCProtocolExpr(ObjCProtocolExpr *Exp);299    void RewriteTryReturnStmts(Stmt *S);300    void RewriteSyncReturnStmts(Stmt *S, std::string buf);301    Stmt *RewriteObjCTryStmt(ObjCAtTryStmt *S);302    Stmt *RewriteObjCSynchronizedStmt(ObjCAtSynchronizedStmt *S);303    Stmt *RewriteObjCThrowStmt(ObjCAtThrowStmt *S);304    Stmt *RewriteObjCForCollectionStmt(ObjCForCollectionStmt *S,305                                       SourceLocation OrigEnd);306    Stmt *RewriteBreakStmt(BreakStmt *S);307    Stmt *RewriteContinueStmt(ContinueStmt *S);308    void RewriteCastExpr(CStyleCastExpr *CE);309 310    // Block rewriting.311    void RewriteBlocksInFunctionProtoType(QualType funcType, NamedDecl *D);312 313    // Block specific rewrite rules.314    void RewriteBlockPointerDecl(NamedDecl *VD);315    void RewriteByRefVar(VarDecl *VD);316    Stmt *RewriteBlockDeclRefExpr(DeclRefExpr *VD);317    Stmt *RewriteLocalVariableExternalStorage(DeclRefExpr *DRE);318    void RewriteBlockPointerFunctionArgs(FunctionDecl *FD);319 320    void RewriteObjCInternalStruct(ObjCInterfaceDecl *CDecl,321                                      std::string &Result);322 323    void Initialize(ASTContext &context) override = 0;324 325    // Metadata Rewriting.326    virtual void RewriteMetaDataIntoBuffer(std::string &Result) = 0;327    virtual void RewriteObjCProtocolListMetaData(const ObjCList<ObjCProtocolDecl> &Prots,328                                                 StringRef prefix,329                                                 StringRef ClassName,330                                                 std::string &Result) = 0;331    virtual void RewriteObjCCategoryImplDecl(ObjCCategoryImplDecl *CDecl,332                                             std::string &Result) = 0;333    virtual void RewriteObjCProtocolMetaData(ObjCProtocolDecl *Protocol,334                                     StringRef prefix,335                                     StringRef ClassName,336                                     std::string &Result) = 0;337    virtual void RewriteObjCClassMetaData(ObjCImplementationDecl *IDecl,338                                          std::string &Result) = 0;339 340    // Rewriting ivar access341    virtual Stmt *RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV) = 0;342    virtual void RewriteIvarOffsetComputation(ObjCIvarDecl *ivar,343                                         std::string &Result) = 0;344 345    // Misc. AST transformation routines. Sometimes they end up calling346    // rewriting routines on the new ASTs.347    CallExpr *SynthesizeCallToFunctionDecl(FunctionDecl *FD,348                                           ArrayRef<Expr *> Args,349                                           SourceLocation StartLoc=SourceLocation(),350                                           SourceLocation EndLoc=SourceLocation());351    CallExpr *SynthMsgSendStretCallExpr(FunctionDecl *MsgSendStretFlavor,352                                        QualType msgSendType,353                                        QualType returnType,354                                        SmallVectorImpl<QualType> &ArgTypes,355                                        SmallVectorImpl<Expr*> &MsgExprs,356                                        ObjCMethodDecl *Method);357    Stmt *SynthMessageExpr(ObjCMessageExpr *Exp,358                           SourceLocation StartLoc=SourceLocation(),359                           SourceLocation EndLoc=SourceLocation());360 361    void SynthCountByEnumWithState(std::string &buf);362    void SynthMsgSendFunctionDecl();363    void SynthMsgSendSuperFunctionDecl();364    void SynthMsgSendStretFunctionDecl();365    void SynthMsgSendFpretFunctionDecl();366    void SynthMsgSendSuperStretFunctionDecl();367    void SynthGetClassFunctionDecl();368    void SynthGetMetaClassFunctionDecl();369    void SynthGetSuperClassFunctionDecl();370    void SynthSelGetUidFunctionDecl();371    void SynthSuperConstructorFunctionDecl();372 373    std::string SynthesizeByrefCopyDestroyHelper(VarDecl *VD, int flag);374    std::string SynthesizeBlockHelperFuncs(BlockExpr *CE, int i,375                                      StringRef funcName, std::string Tag);376    std::string SynthesizeBlockFunc(BlockExpr *CE, int i,377                                      StringRef funcName, std::string Tag);378    std::string SynthesizeBlockImpl(BlockExpr *CE,379                                    std::string Tag, std::string Desc);380    std::string SynthesizeBlockDescriptor(std::string DescTag,381                                          std::string ImplTag,382                                          int i, StringRef funcName,383                                          unsigned hasCopy);384    Stmt *SynthesizeBlockCall(CallExpr *Exp, const Expr* BlockExp);385    void SynthesizeBlockLiterals(SourceLocation FunLocStart,386                                 StringRef FunName);387    FunctionDecl *SynthBlockInitFunctionDecl(StringRef name);388    Stmt *SynthBlockInitExpr(BlockExpr *Exp,389            const SmallVectorImpl<DeclRefExpr *> &InnerBlockDeclRefs);390 391    // Misc. helper routines.392    QualType getProtocolType();393    void WarnAboutReturnGotoStmts(Stmt *S);394    void HasReturnStmts(Stmt *S, bool &hasReturns);395    void CheckFunctionPointerDecl(QualType dType, NamedDecl *ND);396    void InsertBlockLiteralsWithinFunction(FunctionDecl *FD);397    void InsertBlockLiteralsWithinMethod(ObjCMethodDecl *MD);398 399    bool IsDeclStmtInForeachHeader(DeclStmt *DS);400    void CollectBlockDeclRefInfo(BlockExpr *Exp);401    void GetBlockDeclRefExprs(Stmt *S);402    void GetInnerBlockDeclRefExprs(Stmt *S,403                SmallVectorImpl<DeclRefExpr *> &InnerBlockDeclRefs,404                llvm::SmallPtrSetImpl<const DeclContext *> &InnerContexts);405 406    // We avoid calling Type::isBlockPointerType(), since it operates on the407    // canonical type. We only care if the top-level type is a closure pointer.408    bool isTopLevelBlockPointerType(QualType T) {409      return isa<BlockPointerType>(T);410    }411 412    /// convertBlockPointerToFunctionPointer - Converts a block-pointer type413    /// to a function pointer type and upon success, returns true; false414    /// otherwise.415    bool convertBlockPointerToFunctionPointer(QualType &T) {416      if (isTopLevelBlockPointerType(T)) {417        const auto *BPT = T->castAs<BlockPointerType>();418        T = Context->getPointerType(BPT->getPointeeType());419        return true;420      }421      return false;422    }423 424    bool needToScanForQualifiers(QualType T);425    QualType getSuperStructType();426    QualType getConstantStringStructType();427    QualType convertFunctionTypeOfBlocks(const FunctionType *FT);428    bool BufferContainsPPDirectives(const char *startBuf, const char *endBuf);429 430    void convertToUnqualifiedObjCType(QualType &T) {431      if (T->isObjCQualifiedIdType())432        T = Context->getObjCIdType();433      else if (T->isObjCQualifiedClassType())434        T = Context->getObjCClassType();435      else if (T->isObjCObjectPointerType() &&436               T->getPointeeType()->isObjCQualifiedInterfaceType()) {437        if (const ObjCObjectPointerType * OBJPT =438              T->getAsObjCInterfacePointerType()) {439          const ObjCInterfaceType *IFaceT = OBJPT->getInterfaceType();440          T = QualType(IFaceT, 0);441          T = Context->getPointerType(T);442        }443     }444    }445 446    // FIXME: This predicate seems like it would be useful to add to ASTContext.447    bool isObjCType(QualType T) {448      if (!LangOpts.ObjC)449        return false;450 451      QualType OCT = Context->getCanonicalType(T).getUnqualifiedType();452 453      if (OCT == Context->getCanonicalType(Context->getObjCIdType()) ||454          OCT == Context->getCanonicalType(Context->getObjCClassType()))455        return true;456 457      if (const PointerType *PT = OCT->getAs<PointerType>()) {458        if (isa<ObjCInterfaceType>(PT->getPointeeType()) ||459            PT->getPointeeType()->isObjCQualifiedIdType())460          return true;461      }462      return false;463    }464    bool PointerTypeTakesAnyBlockArguments(QualType QT);465    bool PointerTypeTakesAnyObjCQualifiedType(QualType QT);466    void GetExtentOfArgList(const char *Name, const char *&LParen,467                            const char *&RParen);468 469    void QuoteDoublequotes(std::string &From, std::string &To) {470      for (unsigned i = 0; i < From.length(); i++) {471        if (From[i] == '"')472          To += "\\\"";473        else474          To += From[i];475      }476    }477 478    QualType getSimpleFunctionType(QualType result,479                                   ArrayRef<QualType> args,480                                   bool variadic = false) {481      if (result == Context->getObjCInstanceType())482        result =  Context->getObjCIdType();483      FunctionProtoType::ExtProtoInfo fpi;484      fpi.Variadic = variadic;485      return Context->getFunctionType(result, args, fpi);486    }487 488    // Helper function: create a CStyleCastExpr with trivial type source info.489    CStyleCastExpr* NoTypeInfoCStyleCastExpr(ASTContext *Ctx, QualType Ty,490                                             CastKind Kind, Expr *E) {491      TypeSourceInfo *TInfo = Ctx->getTrivialTypeSourceInfo(Ty, SourceLocation());492      return CStyleCastExpr::Create(*Ctx, Ty, VK_PRValue, Kind, E, nullptr,493                                    FPOptionsOverride(), TInfo,494                                    SourceLocation(), SourceLocation());495    }496 497    StringLiteral *getStringLiteral(StringRef Str) {498      QualType StrType = Context->getConstantArrayType(499          Context->CharTy, llvm::APInt(32, Str.size() + 1), nullptr,500          ArraySizeModifier::Normal, 0);501      return StringLiteral::Create(*Context, Str, StringLiteralKind::Ordinary,502                                   /*Pascal=*/false, StrType, SourceLocation());503    }504  };505 506  class RewriteObjCFragileABI : public RewriteObjC {507  public:508    RewriteObjCFragileABI(std::string inFile, std::unique_ptr<raw_ostream> OS,509                          DiagnosticsEngine &D, const LangOptions &LOpts,510                          bool silenceMacroWarn)511        : RewriteObjC(inFile, std::move(OS), D, LOpts, silenceMacroWarn) {}512 513    ~RewriteObjCFragileABI() override {}514    void Initialize(ASTContext &context) override;515 516    // Rewriting metadata517    template<typename MethodIterator>518    void RewriteObjCMethodsMetaData(MethodIterator MethodBegin,519                                    MethodIterator MethodEnd,520                                    bool IsInstanceMethod,521                                    StringRef prefix,522                                    StringRef ClassName,523                                    std::string &Result);524    void RewriteObjCProtocolMetaData(ObjCProtocolDecl *Protocol,525                                     StringRef prefix, StringRef ClassName,526                                     std::string &Result) override;527    void RewriteObjCProtocolListMetaData(528          const ObjCList<ObjCProtocolDecl> &Prots,529          StringRef prefix, StringRef ClassName, std::string &Result) override;530    void RewriteObjCClassMetaData(ObjCImplementationDecl *IDecl,531                                  std::string &Result) override;532    void RewriteMetaDataIntoBuffer(std::string &Result) override;533    void RewriteObjCCategoryImplDecl(ObjCCategoryImplDecl *CDecl,534                                     std::string &Result) override;535 536    // Rewriting ivar537    void RewriteIvarOffsetComputation(ObjCIvarDecl *ivar,538                                      std::string &Result) override;539    Stmt *RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV) override;540  };541} // end anonymous namespace542 543void RewriteObjC::RewriteBlocksInFunctionProtoType(QualType funcType,544                                                   NamedDecl *D) {545  if (const FunctionProtoType *fproto546      = dyn_cast<FunctionProtoType>(funcType.IgnoreParens())) {547    for (const auto &I : fproto->param_types())548      if (isTopLevelBlockPointerType(I)) {549        // All the args are checked/rewritten. Don't call twice!550        RewriteBlockPointerDecl(D);551        break;552      }553  }554}555 556void RewriteObjC::CheckFunctionPointerDecl(QualType funcType, NamedDecl *ND) {557  const PointerType *PT = funcType->getAs<PointerType>();558  if (PT && PointerTypeTakesAnyBlockArguments(funcType))559    RewriteBlocksInFunctionProtoType(PT->getPointeeType(), ND);560}561 562static bool IsHeaderFile(const std::string &Filename) {563  std::string::size_type DotPos = Filename.rfind('.');564 565  if (DotPos == std::string::npos) {566    // no file extension567    return false;568  }569 570  std::string Ext = Filename.substr(DotPos + 1);571  // C header: .h572  // C++ header: .hh or .H;573  return Ext == "h" || Ext == "hh" || Ext == "H";574}575 576RewriteObjC::RewriteObjC(std::string inFile, std::unique_ptr<raw_ostream> OS,577                         DiagnosticsEngine &D, const LangOptions &LOpts,578                         bool silenceMacroWarn)579    : Diags(D), LangOpts(LOpts), InFileName(inFile), OutFile(std::move(OS)),580      SilenceRewriteMacroWarning(silenceMacroWarn) {581  IsHeader = IsHeaderFile(inFile);582  RewriteFailedDiag = Diags.getCustomDiagID(DiagnosticsEngine::Warning,583               "rewriting sub-expression within a macro (may not be correct)");584  TryFinallyContainsReturnDiag = Diags.getCustomDiagID(585               DiagnosticsEngine::Warning,586               "rewriter doesn't support user-specified control flow semantics "587               "for @try/@finally (code may not execute properly)");588}589 590std::unique_ptr<ASTConsumer>591clang::CreateObjCRewriter(const std::string &InFile,592                          std::unique_ptr<raw_ostream> OS,593                          DiagnosticsEngine &Diags, const LangOptions &LOpts,594                          bool SilenceRewriteMacroWarning) {595  return std::make_unique<RewriteObjCFragileABI>(596      InFile, std::move(OS), Diags, LOpts, SilenceRewriteMacroWarning);597}598 599void RewriteObjC::InitializeCommon(ASTContext &context) {600  Context = &context;601  SM = &Context->getSourceManager();602  TUDecl = Context->getTranslationUnitDecl();603  MsgSendFunctionDecl = nullptr;604  MsgSendSuperFunctionDecl = nullptr;605  MsgSendStretFunctionDecl = nullptr;606  MsgSendSuperStretFunctionDecl = nullptr;607  MsgSendFpretFunctionDecl = nullptr;608  GetClassFunctionDecl = nullptr;609  GetMetaClassFunctionDecl = nullptr;610  GetSuperClassFunctionDecl = nullptr;611  SelGetUidFunctionDecl = nullptr;612  CFStringFunctionDecl = nullptr;613  ConstantStringClassReference = nullptr;614  NSStringRecord = nullptr;615  CurMethodDef = nullptr;616  CurFunctionDef = nullptr;617  CurFunctionDeclToDeclareForBlock = nullptr;618  GlobalVarDecl = nullptr;619  SuperStructDecl = nullptr;620  ProtocolTypeDecl = nullptr;621  ConstantStringDecl = nullptr;622  BcLabelCount = 0;623  SuperConstructorFunctionDecl = nullptr;624  NumObjCStringLiterals = 0;625  PropParentMap = nullptr;626  CurrentBody = nullptr;627  DisableReplaceStmt = false;628  objc_impl_method = false;629 630  // Get the ID and start/end of the main file.631  MainFileID = SM->getMainFileID();632  llvm::MemoryBufferRef MainBuf = SM->getBufferOrFake(MainFileID);633  MainFileStart = MainBuf.getBufferStart();634  MainFileEnd = MainBuf.getBufferEnd();635 636  Rewrite.setSourceMgr(Context->getSourceManager(), Context->getLangOpts());637}638 639//===----------------------------------------------------------------------===//640// Top Level Driver Code641//===----------------------------------------------------------------------===//642 643void RewriteObjC::HandleTopLevelSingleDecl(Decl *D) {644  if (Diags.hasErrorOccurred())645    return;646 647  // Two cases: either the decl could be in the main file, or it could be in a648  // #included file.  If the former, rewrite it now.  If the later, check to see649  // if we rewrote the #include/#import.650  SourceLocation Loc = D->getLocation();651  Loc = SM->getExpansionLoc(Loc);652 653  // If this is for a builtin, ignore it.654  if (Loc.isInvalid()) return;655 656  // Look for built-in declarations that we need to refer during the rewrite.657  if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {658    RewriteFunctionDecl(FD);659  } else if (VarDecl *FVD = dyn_cast<VarDecl>(D)) {660    // declared in <Foundation/NSString.h>661    if (FVD->getName() == "_NSConstantStringClassReference") {662      ConstantStringClassReference = FVD;663      return;664    }665  } else if (ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(D)) {666    if (ID->isThisDeclarationADefinition())667      RewriteInterfaceDecl(ID);668  } else if (ObjCCategoryDecl *CD = dyn_cast<ObjCCategoryDecl>(D)) {669    RewriteCategoryDecl(CD);670  } else if (ObjCProtocolDecl *PD = dyn_cast<ObjCProtocolDecl>(D)) {671    if (PD->isThisDeclarationADefinition())672      RewriteProtocolDecl(PD);673  } else if (LinkageSpecDecl *LSD = dyn_cast<LinkageSpecDecl>(D)) {674    // Recurse into linkage specifications675    for (DeclContext::decl_iterator DI = LSD->decls_begin(),676                                 DIEnd = LSD->decls_end();677         DI != DIEnd; ) {678      if (ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>((*DI))) {679        if (!IFace->isThisDeclarationADefinition()) {680          SmallVector<Decl *, 8> DG;681          SourceLocation StartLoc = IFace->getBeginLoc();682          do {683            if (isa<ObjCInterfaceDecl>(*DI) &&684                !cast<ObjCInterfaceDecl>(*DI)->isThisDeclarationADefinition() &&685                StartLoc == (*DI)->getBeginLoc())686              DG.push_back(*DI);687            else688              break;689 690            ++DI;691          } while (DI != DIEnd);692          RewriteForwardClassDecl(DG);693          continue;694        }695      }696 697      if (ObjCProtocolDecl *Proto = dyn_cast<ObjCProtocolDecl>((*DI))) {698        if (!Proto->isThisDeclarationADefinition()) {699          SmallVector<Decl *, 8> DG;700          SourceLocation StartLoc = Proto->getBeginLoc();701          do {702            if (isa<ObjCProtocolDecl>(*DI) &&703                !cast<ObjCProtocolDecl>(*DI)->isThisDeclarationADefinition() &&704                StartLoc == (*DI)->getBeginLoc())705              DG.push_back(*DI);706            else707              break;708 709            ++DI;710          } while (DI != DIEnd);711          RewriteForwardProtocolDecl(DG);712          continue;713        }714      }715 716      HandleTopLevelSingleDecl(*DI);717      ++DI;718    }719  }720  // If we have a decl in the main file, see if we should rewrite it.721  if (SM->isWrittenInMainFile(Loc))722    return HandleDeclInMainFile(D);723}724 725//===----------------------------------------------------------------------===//726// Syntactic (non-AST) Rewriting Code727//===----------------------------------------------------------------------===//728 729void RewriteObjC::RewriteInclude() {730  SourceLocation LocStart = SM->getLocForStartOfFile(MainFileID);731  StringRef MainBuf = SM->getBufferData(MainFileID);732  const char *MainBufStart = MainBuf.begin();733  const char *MainBufEnd = MainBuf.end();734  size_t ImportLen = strlen("import");735 736  // Loop over the whole file, looking for includes.737  for (const char *BufPtr = MainBufStart; BufPtr < MainBufEnd; ++BufPtr) {738    if (*BufPtr == '#') {739      if (++BufPtr == MainBufEnd)740        return;741      while (*BufPtr == ' ' || *BufPtr == '\t')742        if (++BufPtr == MainBufEnd)743          return;744      if (!strncmp(BufPtr, "import", ImportLen)) {745        // replace import with include746        SourceLocation ImportLoc =747          LocStart.getLocWithOffset(BufPtr-MainBufStart);748        ReplaceText(ImportLoc, ImportLen, "include");749        BufPtr += ImportLen;750      }751    }752  }753}754 755static std::string getIvarAccessString(ObjCIvarDecl *OID) {756  const ObjCInterfaceDecl *ClassDecl = OID->getContainingInterface();757  std::string S;758  S = "((struct ";759  S += ClassDecl->getIdentifier()->getName();760  S += "_IMPL *)self)->";761  S += OID->getName();762  return S;763}764 765void RewriteObjC::RewritePropertyImplDecl(ObjCPropertyImplDecl *PID,766                                          ObjCImplementationDecl *IMD,767                                          ObjCCategoryImplDecl *CID) {768  static bool objcGetPropertyDefined = false;769  static bool objcSetPropertyDefined = false;770  SourceLocation startLoc = PID->getBeginLoc();771  InsertText(startLoc, "// ");772  const char *startBuf = SM->getCharacterData(startLoc);773  assert((*startBuf == '@') && "bogus @synthesize location");774  const char *semiBuf = strchr(startBuf, ';');775  assert((*semiBuf == ';') && "@synthesize: can't find ';'");776  SourceLocation onePastSemiLoc =777    startLoc.getLocWithOffset(semiBuf-startBuf+1);778 779  if (PID->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic)780    return; // FIXME: is this correct?781 782  // Generate the 'getter' function.783  ObjCPropertyDecl *PD = PID->getPropertyDecl();784  ObjCIvarDecl *OID = PID->getPropertyIvarDecl();785 786  if (!OID)787    return;788 789  unsigned Attributes = PD->getPropertyAttributes();790  if (PID->getGetterMethodDecl() && !PID->getGetterMethodDecl()->isDefined()) {791    bool GenGetProperty =792        !(Attributes & ObjCPropertyAttribute::kind_nonatomic) &&793        (Attributes & (ObjCPropertyAttribute::kind_retain |794                       ObjCPropertyAttribute::kind_copy));795    std::string Getr;796    if (GenGetProperty && !objcGetPropertyDefined) {797      objcGetPropertyDefined = true;798      // FIXME. Is this attribute correct in all cases?799      Getr = "\nextern \"C\" __declspec(dllimport) "800            "id objc_getProperty(id, SEL, long, bool);\n";801    }802    RewriteObjCMethodDecl(OID->getContainingInterface(),803                          PID->getGetterMethodDecl(), Getr);804    Getr += "{ ";805    // Synthesize an explicit cast to gain access to the ivar.806    // See objc-act.c:objc_synthesize_new_getter() for details.807    if (GenGetProperty) {808      // return objc_getProperty(self, _cmd, offsetof(ClassDecl, OID), 1)809      Getr += "typedef ";810      const FunctionType *FPRetType = nullptr;811      RewriteTypeIntoString(PID->getGetterMethodDecl()->getReturnType(), Getr,812                            FPRetType);813      Getr += " _TYPE";814      if (FPRetType) {815        Getr += ")"; // close the precedence "scope" for "*".816 817        // Now, emit the argument types (if any).818        if (const FunctionProtoType *FT = dyn_cast<FunctionProtoType>(FPRetType)){819          Getr += "(";820          for (unsigned i = 0, e = FT->getNumParams(); i != e; ++i) {821            if (i) Getr += ", ";822            std::string ParamStr =823                FT->getParamType(i).getAsString(Context->getPrintingPolicy());824            Getr += ParamStr;825          }826          if (FT->isVariadic()) {827            if (FT->getNumParams())828              Getr += ", ";829            Getr += "...";830          }831          Getr += ")";832        } else833          Getr += "()";834      }835      Getr += ";\n";836      Getr += "return (_TYPE)";837      Getr += "objc_getProperty(self, _cmd, ";838      RewriteIvarOffsetComputation(OID, Getr);839      Getr += ", 1)";840    }841    else842      Getr += "return " + getIvarAccessString(OID);843    Getr += "; }";844    InsertText(onePastSemiLoc, Getr);845  }846 847  if (PD->isReadOnly() || !PID->getSetterMethodDecl() ||848      PID->getSetterMethodDecl()->isDefined())849    return;850 851  // Generate the 'setter' function.852  std::string Setr;853  bool GenSetProperty = Attributes & (ObjCPropertyAttribute::kind_retain |854                                      ObjCPropertyAttribute::kind_copy);855  if (GenSetProperty && !objcSetPropertyDefined) {856    objcSetPropertyDefined = true;857    // FIXME. Is this attribute correct in all cases?858    Setr = "\nextern \"C\" __declspec(dllimport) "859    "void objc_setProperty (id, SEL, long, id, bool, bool);\n";860  }861 862  RewriteObjCMethodDecl(OID->getContainingInterface(),863                        PID->getSetterMethodDecl(), Setr);864  Setr += "{ ";865  // Synthesize an explicit cast to initialize the ivar.866  // See objc-act.c:objc_synthesize_new_setter() for details.867  if (GenSetProperty) {868    Setr += "objc_setProperty (self, _cmd, ";869    RewriteIvarOffsetComputation(OID, Setr);870    Setr += ", (id)";871    Setr += PD->getName();872    Setr += ", ";873    if (Attributes & ObjCPropertyAttribute::kind_nonatomic)874      Setr += "0, ";875    else876      Setr += "1, ";877    if (Attributes & ObjCPropertyAttribute::kind_copy)878      Setr += "1)";879    else880      Setr += "0)";881  }882  else {883    Setr += getIvarAccessString(OID) + " = ";884    Setr += PD->getName();885  }886  Setr += "; }";887  InsertText(onePastSemiLoc, Setr);888}889 890static void RewriteOneForwardClassDecl(ObjCInterfaceDecl *ForwardDecl,891                                       std::string &typedefString) {892  typedefString += "#ifndef _REWRITER_typedef_";893  typedefString += ForwardDecl->getNameAsString();894  typedefString += "\n";895  typedefString += "#define _REWRITER_typedef_";896  typedefString += ForwardDecl->getNameAsString();897  typedefString += "\n";898  typedefString += "typedef struct objc_object ";899  typedefString += ForwardDecl->getNameAsString();900  typedefString += ";\n#endif\n";901}902 903void RewriteObjC::RewriteForwardClassEpilogue(ObjCInterfaceDecl *ClassDecl,904                                              const std::string &typedefString) {905  SourceLocation startLoc = ClassDecl->getBeginLoc();906  const char *startBuf = SM->getCharacterData(startLoc);907  const char *semiPtr = strchr(startBuf, ';');908  // Replace the @class with typedefs corresponding to the classes.909  ReplaceText(startLoc, semiPtr - startBuf + 1, typedefString);910}911 912void RewriteObjC::RewriteForwardClassDecl(DeclGroupRef D) {913  std::string typedefString;914  for (DeclGroupRef::iterator I = D.begin(), E = D.end(); I != E; ++I) {915    ObjCInterfaceDecl *ForwardDecl = cast<ObjCInterfaceDecl>(*I);916    if (I == D.begin()) {917      // Translate to typedef's that forward reference structs with the same name918      // as the class. As a convenience, we include the original declaration919      // as a comment.920      typedefString += "// @class ";921      typedefString += ForwardDecl->getNameAsString();922      typedefString += ";\n";923    }924    RewriteOneForwardClassDecl(ForwardDecl, typedefString);925  }926  DeclGroupRef::iterator I = D.begin();927  RewriteForwardClassEpilogue(cast<ObjCInterfaceDecl>(*I), typedefString);928}929 930void RewriteObjC::RewriteForwardClassDecl(const SmallVectorImpl<Decl *> &D) {931  std::string typedefString;932  for (unsigned i = 0; i < D.size(); i++) {933    ObjCInterfaceDecl *ForwardDecl = cast<ObjCInterfaceDecl>(D[i]);934    if (i == 0) {935      typedefString += "// @class ";936      typedefString += ForwardDecl->getNameAsString();937      typedefString += ";\n";938    }939    RewriteOneForwardClassDecl(ForwardDecl, typedefString);940  }941  RewriteForwardClassEpilogue(cast<ObjCInterfaceDecl>(D[0]), typedefString);942}943 944void RewriteObjC::RewriteMethodDeclaration(ObjCMethodDecl *Method) {945  // When method is a synthesized one, such as a getter/setter there is946  // nothing to rewrite.947  if (Method->isImplicit())948    return;949  SourceLocation LocStart = Method->getBeginLoc();950  SourceLocation LocEnd = Method->getEndLoc();951 952  if (SM->getExpansionLineNumber(LocEnd) >953      SM->getExpansionLineNumber(LocStart)) {954    InsertText(LocStart, "#if 0\n");955    ReplaceText(LocEnd, 1, ";\n#endif\n");956  } else {957    InsertText(LocStart, "// ");958  }959}960 961void RewriteObjC::RewriteProperty(ObjCPropertyDecl *prop) {962  SourceLocation Loc = prop->getAtLoc();963 964  ReplaceText(Loc, 0, "// ");965  // FIXME: handle properties that are declared across multiple lines.966}967 968void RewriteObjC::RewriteCategoryDecl(ObjCCategoryDecl *CatDecl) {969  SourceLocation LocStart = CatDecl->getBeginLoc();970 971  // FIXME: handle category headers that are declared across multiple lines.972  ReplaceText(LocStart, 0, "// ");973 974  for (auto *I : CatDecl->instance_properties())975    RewriteProperty(I);976  for (auto *I : CatDecl->instance_methods())977    RewriteMethodDeclaration(I);978  for (auto *I : CatDecl->class_methods())979    RewriteMethodDeclaration(I);980 981  // Lastly, comment out the @end.982  ReplaceText(CatDecl->getAtEndRange().getBegin(),983              strlen("@end"), "/* @end */");984}985 986void RewriteObjC::RewriteProtocolDecl(ObjCProtocolDecl *PDecl) {987  SourceLocation LocStart = PDecl->getBeginLoc();988  assert(PDecl->isThisDeclarationADefinition());989 990  // FIXME: handle protocol headers that are declared across multiple lines.991  ReplaceText(LocStart, 0, "// ");992 993  for (auto *I : PDecl->instance_methods())994    RewriteMethodDeclaration(I);995  for (auto *I : PDecl->class_methods())996    RewriteMethodDeclaration(I);997  for (auto *I : PDecl->instance_properties())998    RewriteProperty(I);999 1000  // Lastly, comment out the @end.1001  SourceLocation LocEnd = PDecl->getAtEndRange().getBegin();1002  ReplaceText(LocEnd, strlen("@end"), "/* @end */");1003 1004  // Must comment out @optional/@required1005  const char *startBuf = SM->getCharacterData(LocStart);1006  const char *endBuf = SM->getCharacterData(LocEnd);1007  for (const char *p = startBuf; p < endBuf; p++) {1008    if (*p == '@' && !strncmp(p+1, "optional", strlen("optional"))) {1009      SourceLocation OptionalLoc = LocStart.getLocWithOffset(p-startBuf);1010      ReplaceText(OptionalLoc, strlen("@optional"), "/* @optional */");1011 1012    }1013    else if (*p == '@' && !strncmp(p+1, "required", strlen("required"))) {1014      SourceLocation OptionalLoc = LocStart.getLocWithOffset(p-startBuf);1015      ReplaceText(OptionalLoc, strlen("@required"), "/* @required */");1016 1017    }1018  }1019}1020 1021void RewriteObjC::RewriteForwardProtocolDecl(DeclGroupRef D) {1022  SourceLocation LocStart = (*D.begin())->getBeginLoc();1023  if (LocStart.isInvalid())1024    llvm_unreachable("Invalid SourceLocation");1025  // FIXME: handle forward protocol that are declared across multiple lines.1026  ReplaceText(LocStart, 0, "// ");1027}1028 1029void1030RewriteObjC::RewriteForwardProtocolDecl(const SmallVectorImpl<Decl *> &DG) {1031  SourceLocation LocStart = DG[0]->getBeginLoc();1032  if (LocStart.isInvalid())1033    llvm_unreachable("Invalid SourceLocation");1034  // FIXME: handle forward protocol that are declared across multiple lines.1035  ReplaceText(LocStart, 0, "// ");1036}1037 1038void RewriteObjC::RewriteTypeIntoString(QualType T, std::string &ResultStr,1039                                        const FunctionType *&FPRetType) {1040  if (T->isObjCQualifiedIdType())1041    ResultStr += "id";1042  else if (T->isFunctionPointerType() ||1043           T->isBlockPointerType()) {1044    // needs special handling, since pointer-to-functions have special1045    // syntax (where a decaration models use).1046    QualType retType = T;1047    QualType PointeeTy;1048    if (const PointerType* PT = retType->getAs<PointerType>())1049      PointeeTy = PT->getPointeeType();1050    else if (const BlockPointerType *BPT = retType->getAs<BlockPointerType>())1051      PointeeTy = BPT->getPointeeType();1052    if ((FPRetType = PointeeTy->getAs<FunctionType>())) {1053      ResultStr +=1054          FPRetType->getReturnType().getAsString(Context->getPrintingPolicy());1055      ResultStr += "(*";1056    }1057  } else1058    ResultStr += T.getAsString(Context->getPrintingPolicy());1059}1060 1061void RewriteObjC::RewriteObjCMethodDecl(const ObjCInterfaceDecl *IDecl,1062                                        ObjCMethodDecl *OMD,1063                                        std::string &ResultStr) {1064  //fprintf(stderr,"In RewriteObjCMethodDecl\n");1065  const FunctionType *FPRetType = nullptr;1066  ResultStr += "\nstatic ";1067  RewriteTypeIntoString(OMD->getReturnType(), ResultStr, FPRetType);1068  ResultStr += " ";1069 1070  // Unique method name1071  std::string NameStr;1072 1073  if (OMD->isInstanceMethod())1074    NameStr += "_I_";1075  else1076    NameStr += "_C_";1077 1078  NameStr += IDecl->getNameAsString();1079  NameStr += "_";1080 1081  if (ObjCCategoryImplDecl *CID =1082      dyn_cast<ObjCCategoryImplDecl>(OMD->getDeclContext())) {1083    NameStr += CID->getNameAsString();1084    NameStr += "_";1085  }1086  // Append selector names, replacing ':' with '_'1087  {1088    std::string selString = OMD->getSelector().getAsString();1089    int len = selString.size();1090    for (int i = 0; i < len; i++)1091      if (selString[i] == ':')1092        selString[i] = '_';1093    NameStr += selString;1094  }1095  // Remember this name for metadata emission1096  MethodInternalNames[OMD] = NameStr;1097  ResultStr += NameStr;1098 1099  // Rewrite arguments1100  ResultStr += "(";1101 1102  // invisible arguments1103  if (OMD->isInstanceMethod()) {1104    QualType selfTy = Context->getObjCInterfaceType(IDecl);1105    selfTy = Context->getPointerType(selfTy);1106    if (!LangOpts.MicrosoftExt) {1107      if (ObjCSynthesizedStructs.count(const_cast<ObjCInterfaceDecl*>(IDecl)))1108        ResultStr += "struct ";1109    }1110    // When rewriting for Microsoft, explicitly omit the structure name.1111    ResultStr += IDecl->getNameAsString();1112    ResultStr += " *";1113  }1114  else1115    ResultStr += Context->getObjCClassType().getAsString(1116      Context->getPrintingPolicy());1117 1118  ResultStr += " self, ";1119  ResultStr += Context->getObjCSelType().getAsString(Context->getPrintingPolicy());1120  ResultStr += " _cmd";1121 1122  // Method arguments.1123  for (const auto *PDecl : OMD->parameters()) {1124    ResultStr += ", ";1125    if (PDecl->getType()->isObjCQualifiedIdType()) {1126      ResultStr += "id ";1127      ResultStr += PDecl->getNameAsString();1128    } else {1129      std::string Name = PDecl->getNameAsString();1130      QualType QT = PDecl->getType();1131      // Make sure we convert "t (^)(...)" to "t (*)(...)".1132      (void)convertBlockPointerToFunctionPointer(QT);1133      QT.getAsStringInternal(Name, Context->getPrintingPolicy());1134      ResultStr += Name;1135    }1136  }1137  if (OMD->isVariadic())1138    ResultStr += ", ...";1139  ResultStr += ") ";1140 1141  if (FPRetType) {1142    ResultStr += ")"; // close the precedence "scope" for "*".1143 1144    // Now, emit the argument types (if any).1145    if (const FunctionProtoType *FT = dyn_cast<FunctionProtoType>(FPRetType)) {1146      ResultStr += "(";1147      for (unsigned i = 0, e = FT->getNumParams(); i != e; ++i) {1148        if (i) ResultStr += ", ";1149        std::string ParamStr =1150            FT->getParamType(i).getAsString(Context->getPrintingPolicy());1151        ResultStr += ParamStr;1152      }1153      if (FT->isVariadic()) {1154        if (FT->getNumParams())1155          ResultStr += ", ";1156        ResultStr += "...";1157      }1158      ResultStr += ")";1159    } else {1160      ResultStr += "()";1161    }1162  }1163}1164 1165void RewriteObjC::RewriteImplementationDecl(Decl *OID) {1166  ObjCImplementationDecl *IMD = dyn_cast<ObjCImplementationDecl>(OID);1167  ObjCCategoryImplDecl *CID = dyn_cast<ObjCCategoryImplDecl>(OID);1168  assert((IMD || CID) && "Unknown ImplementationDecl");1169 1170  InsertText(IMD ? IMD->getBeginLoc() : CID->getBeginLoc(), "// ");1171 1172  for (auto *OMD : IMD ? IMD->instance_methods() : CID->instance_methods()) {1173    if (!OMD->getBody())1174      continue;1175    std::string ResultStr;1176    RewriteObjCMethodDecl(OMD->getClassInterface(), OMD, ResultStr);1177    SourceLocation LocStart = OMD->getBeginLoc();1178    SourceLocation LocEnd = OMD->getCompoundBody()->getBeginLoc();1179 1180    const char *startBuf = SM->getCharacterData(LocStart);1181    const char *endBuf = SM->getCharacterData(LocEnd);1182    ReplaceText(LocStart, endBuf-startBuf, ResultStr);1183  }1184 1185  for (auto *OMD : IMD ? IMD->class_methods() : CID->class_methods()) {1186    if (!OMD->getBody())1187      continue;1188    std::string ResultStr;1189    RewriteObjCMethodDecl(OMD->getClassInterface(), OMD, ResultStr);1190    SourceLocation LocStart = OMD->getBeginLoc();1191    SourceLocation LocEnd = OMD->getCompoundBody()->getBeginLoc();1192 1193    const char *startBuf = SM->getCharacterData(LocStart);1194    const char *endBuf = SM->getCharacterData(LocEnd);1195    ReplaceText(LocStart, endBuf-startBuf, ResultStr);1196  }1197  for (auto *I : IMD ? IMD->property_impls() : CID->property_impls())1198    RewritePropertyImplDecl(I, IMD, CID);1199 1200  InsertText(IMD ? IMD->getEndLoc() : CID->getEndLoc(), "// ");1201}1202 1203void RewriteObjC::RewriteInterfaceDecl(ObjCInterfaceDecl *ClassDecl) {1204  std::string ResultStr;1205  if (!ObjCForwardDecls.count(ClassDecl->getCanonicalDecl())) {1206    // we haven't seen a forward decl - generate a typedef.1207    ResultStr = "#ifndef _REWRITER_typedef_";1208    ResultStr += ClassDecl->getNameAsString();1209    ResultStr += "\n";1210    ResultStr += "#define _REWRITER_typedef_";1211    ResultStr += ClassDecl->getNameAsString();1212    ResultStr += "\n";1213    ResultStr += "typedef struct objc_object ";1214    ResultStr += ClassDecl->getNameAsString();1215    ResultStr += ";\n#endif\n";1216    // Mark this typedef as having been generated.1217    ObjCForwardDecls.insert(ClassDecl->getCanonicalDecl());1218  }1219  RewriteObjCInternalStruct(ClassDecl, ResultStr);1220 1221  for (auto *I : ClassDecl->instance_properties())1222    RewriteProperty(I);1223  for (auto *I : ClassDecl->instance_methods())1224    RewriteMethodDeclaration(I);1225  for (auto *I : ClassDecl->class_methods())1226    RewriteMethodDeclaration(I);1227 1228  // Lastly, comment out the @end.1229  ReplaceText(ClassDecl->getAtEndRange().getBegin(), strlen("@end"),1230              "/* @end */");1231}1232 1233Stmt *RewriteObjC::RewritePropertyOrImplicitSetter(PseudoObjectExpr *PseudoOp) {1234  SourceRange OldRange = PseudoOp->getSourceRange();1235 1236  // We just magically know some things about the structure of this1237  // expression.1238  ObjCMessageExpr *OldMsg =1239    cast<ObjCMessageExpr>(PseudoOp->getSemanticExpr(1240                            PseudoOp->getNumSemanticExprs() - 1));1241 1242  // Because the rewriter doesn't allow us to rewrite rewritten code,1243  // we need to suppress rewriting the sub-statements.1244  Expr *Base, *RHS;1245  {1246    DisableReplaceStmtScope S(*this);1247 1248    // Rebuild the base expression if we have one.1249    Base = nullptr;1250    if (OldMsg->getReceiverKind() == ObjCMessageExpr::Instance) {1251      Base = OldMsg->getInstanceReceiver();1252      Base = cast<OpaqueValueExpr>(Base)->getSourceExpr();1253      Base = cast<Expr>(RewriteFunctionBodyOrGlobalInitializer(Base));1254    }1255 1256    // Rebuild the RHS.1257    RHS = cast<BinaryOperator>(PseudoOp->getSyntacticForm())->getRHS();1258    RHS = cast<OpaqueValueExpr>(RHS)->getSourceExpr();1259    RHS = cast<Expr>(RewriteFunctionBodyOrGlobalInitializer(RHS));1260  }1261 1262  // TODO: avoid this copy.1263  SmallVector<SourceLocation, 1> SelLocs;1264  OldMsg->getSelectorLocs(SelLocs);1265 1266  ObjCMessageExpr *NewMsg = nullptr;1267  switch (OldMsg->getReceiverKind()) {1268  case ObjCMessageExpr::Class:1269    NewMsg = ObjCMessageExpr::Create(*Context, OldMsg->getType(),1270                                     OldMsg->getValueKind(),1271                                     OldMsg->getLeftLoc(),1272                                     OldMsg->getClassReceiverTypeInfo(),1273                                     OldMsg->getSelector(),1274                                     SelLocs,1275                                     OldMsg->getMethodDecl(),1276                                     RHS,1277                                     OldMsg->getRightLoc(),1278                                     OldMsg->isImplicit());1279    break;1280 1281  case ObjCMessageExpr::Instance:1282    NewMsg = ObjCMessageExpr::Create(*Context, OldMsg->getType(),1283                                     OldMsg->getValueKind(),1284                                     OldMsg->getLeftLoc(),1285                                     Base,1286                                     OldMsg->getSelector(),1287                                     SelLocs,1288                                     OldMsg->getMethodDecl(),1289                                     RHS,1290                                     OldMsg->getRightLoc(),1291                                     OldMsg->isImplicit());1292    break;1293 1294  case ObjCMessageExpr::SuperClass:1295  case ObjCMessageExpr::SuperInstance:1296    NewMsg = ObjCMessageExpr::Create(*Context, OldMsg->getType(),1297                                     OldMsg->getValueKind(),1298                                     OldMsg->getLeftLoc(),1299                                     OldMsg->getSuperLoc(),1300                 OldMsg->getReceiverKind() == ObjCMessageExpr::SuperInstance,1301                                     OldMsg->getSuperType(),1302                                     OldMsg->getSelector(),1303                                     SelLocs,1304                                     OldMsg->getMethodDecl(),1305                                     RHS,1306                                     OldMsg->getRightLoc(),1307                                     OldMsg->isImplicit());1308    break;1309  }1310 1311  Stmt *Replacement = SynthMessageExpr(NewMsg);1312  ReplaceStmtWithRange(PseudoOp, Replacement, OldRange);1313  return Replacement;1314}1315 1316Stmt *RewriteObjC::RewritePropertyOrImplicitGetter(PseudoObjectExpr *PseudoOp) {1317  SourceRange OldRange = PseudoOp->getSourceRange();1318 1319  // We just magically know some things about the structure of this1320  // expression.1321  ObjCMessageExpr *OldMsg =1322    cast<ObjCMessageExpr>(PseudoOp->getResultExpr()->IgnoreImplicit());1323 1324  // Because the rewriter doesn't allow us to rewrite rewritten code,1325  // we need to suppress rewriting the sub-statements.1326  Expr *Base = nullptr;1327  {1328    DisableReplaceStmtScope S(*this);1329 1330    // Rebuild the base expression if we have one.1331    if (OldMsg->getReceiverKind() == ObjCMessageExpr::Instance) {1332      Base = OldMsg->getInstanceReceiver();1333      Base = cast<OpaqueValueExpr>(Base)->getSourceExpr();1334      Base = cast<Expr>(RewriteFunctionBodyOrGlobalInitializer(Base));1335    }1336  }1337 1338  // Intentionally empty.1339  SmallVector<SourceLocation, 1> SelLocs;1340  SmallVector<Expr*, 1> Args;1341 1342  ObjCMessageExpr *NewMsg = nullptr;1343  switch (OldMsg->getReceiverKind()) {1344  case ObjCMessageExpr::Class:1345    NewMsg = ObjCMessageExpr::Create(*Context, OldMsg->getType(),1346                                     OldMsg->getValueKind(),1347                                     OldMsg->getLeftLoc(),1348                                     OldMsg->getClassReceiverTypeInfo(),1349                                     OldMsg->getSelector(),1350                                     SelLocs,1351                                     OldMsg->getMethodDecl(),1352                                     Args,1353                                     OldMsg->getRightLoc(),1354                                     OldMsg->isImplicit());1355    break;1356 1357  case ObjCMessageExpr::Instance:1358    NewMsg = ObjCMessageExpr::Create(*Context, OldMsg->getType(),1359                                     OldMsg->getValueKind(),1360                                     OldMsg->getLeftLoc(),1361                                     Base,1362                                     OldMsg->getSelector(),1363                                     SelLocs,1364                                     OldMsg->getMethodDecl(),1365                                     Args,1366                                     OldMsg->getRightLoc(),1367                                     OldMsg->isImplicit());1368    break;1369 1370  case ObjCMessageExpr::SuperClass:1371  case ObjCMessageExpr::SuperInstance:1372    NewMsg = ObjCMessageExpr::Create(*Context, OldMsg->getType(),1373                                     OldMsg->getValueKind(),1374                                     OldMsg->getLeftLoc(),1375                                     OldMsg->getSuperLoc(),1376                 OldMsg->getReceiverKind() == ObjCMessageExpr::SuperInstance,1377                                     OldMsg->getSuperType(),1378                                     OldMsg->getSelector(),1379                                     SelLocs,1380                                     OldMsg->getMethodDecl(),1381                                     Args,1382                                     OldMsg->getRightLoc(),1383                                     OldMsg->isImplicit());1384    break;1385  }1386 1387  Stmt *Replacement = SynthMessageExpr(NewMsg);1388  ReplaceStmtWithRange(PseudoOp, Replacement, OldRange);1389  return Replacement;1390}1391 1392/// SynthCountByEnumWithState - To print:1393/// ((unsigned int (*)1394///  (id, SEL, struct __objcFastEnumerationState *, id *, unsigned int))1395///  (void *)objc_msgSend)((id)l_collection,1396///                        sel_registerName(1397///                          "countByEnumeratingWithState:objects:count:"),1398///                        &enumState,1399///                        (id *)__rw_items, (unsigned int)16)1400///1401void RewriteObjC::SynthCountByEnumWithState(std::string &buf) {1402  buf += "((unsigned int (*) (id, SEL, struct __objcFastEnumerationState *, "1403  "id *, unsigned int))(void *)objc_msgSend)";1404  buf += "\n\t\t";1405  buf += "((id)l_collection,\n\t\t";1406  buf += "sel_registerName(\"countByEnumeratingWithState:objects:count:\"),";1407  buf += "\n\t\t";1408  buf += "&enumState, "1409         "(id *)__rw_items, (unsigned int)16)";1410}1411 1412/// RewriteBreakStmt - Rewrite for a break-stmt inside an ObjC2's foreach1413/// statement to exit to its outer synthesized loop.1414///1415Stmt *RewriteObjC::RewriteBreakStmt(BreakStmt *S) {1416  if (Stmts.empty() || !isa<ObjCForCollectionStmt>(Stmts.back()))1417    return S;1418  // replace break with goto __break_label1419  std::string buf;1420 1421  SourceLocation startLoc = S->getBeginLoc();1422  buf = "goto __break_label_";1423  buf += utostr(ObjCBcLabelNo.back());1424  ReplaceText(startLoc, strlen("break"), buf);1425 1426  return nullptr;1427}1428 1429/// RewriteContinueStmt - Rewrite for a continue-stmt inside an ObjC2's foreach1430/// statement to continue with its inner synthesized loop.1431///1432Stmt *RewriteObjC::RewriteContinueStmt(ContinueStmt *S) {1433  if (Stmts.empty() || !isa<ObjCForCollectionStmt>(Stmts.back()))1434    return S;1435  // replace continue with goto __continue_label1436  std::string buf;1437 1438  SourceLocation startLoc = S->getBeginLoc();1439  buf = "goto __continue_label_";1440  buf += utostr(ObjCBcLabelNo.back());1441  ReplaceText(startLoc, strlen("continue"), buf);1442 1443  return nullptr;1444}1445 1446/// RewriteObjCForCollectionStmt - Rewriter for ObjC2's foreach statement.1447///  It rewrites:1448/// for ( type elem in collection) { stmts; }1449 1450/// Into:1451/// {1452///   type elem;1453///   struct __objcFastEnumerationState enumState = { 0 };1454///   id __rw_items[16];1455///   id l_collection = (id)collection;1456///   unsigned long limit = [l_collection countByEnumeratingWithState:&enumState1457///                                       objects:__rw_items count:16];1458/// if (limit) {1459///   unsigned long startMutations = *enumState.mutationsPtr;1460///   do {1461///        unsigned long counter = 0;1462///        do {1463///             if (startMutations != *enumState.mutationsPtr)1464///               objc_enumerationMutation(l_collection);1465///             elem = (type)enumState.itemsPtr[counter++];1466///             stmts;1467///             __continue_label: ;1468///        } while (counter < limit);1469///   } while (limit = [l_collection countByEnumeratingWithState:&enumState1470///                                  objects:__rw_items count:16]);1471///   elem = nil;1472///   __break_label: ;1473///  }1474///  else1475///       elem = nil;1476///  }1477///1478Stmt *RewriteObjC::RewriteObjCForCollectionStmt(ObjCForCollectionStmt *S,1479                                                SourceLocation OrigEnd) {1480  assert(!Stmts.empty() && "ObjCForCollectionStmt - Statement stack empty");1481  assert(isa<ObjCForCollectionStmt>(Stmts.back()) &&1482         "ObjCForCollectionStmt Statement stack mismatch");1483  assert(!ObjCBcLabelNo.empty() &&1484         "ObjCForCollectionStmt - Label No stack empty");1485 1486  SourceLocation startLoc = S->getBeginLoc();1487  const char *startBuf = SM->getCharacterData(startLoc);1488  StringRef elementName;1489  std::string elementTypeAsString;1490  std::string buf;1491  buf = "\n{\n\t";1492  if (DeclStmt *DS = dyn_cast<DeclStmt>(S->getElement())) {1493    // type elem;1494    NamedDecl* D = cast<NamedDecl>(DS->getSingleDecl());1495    QualType ElementType = cast<ValueDecl>(D)->getType();1496    if (ElementType->isObjCQualifiedIdType() ||1497        ElementType->isObjCQualifiedInterfaceType())1498      // Simply use 'id' for all qualified types.1499      elementTypeAsString = "id";1500    else1501      elementTypeAsString = ElementType.getAsString(Context->getPrintingPolicy());1502    buf += elementTypeAsString;1503    buf += " ";1504    elementName = D->getName();1505    buf += elementName;1506    buf += ";\n\t";1507  }1508  else {1509    DeclRefExpr *DR = cast<DeclRefExpr>(S->getElement());1510    elementName = DR->getDecl()->getName();1511    ValueDecl *VD = DR->getDecl();1512    if (VD->getType()->isObjCQualifiedIdType() ||1513        VD->getType()->isObjCQualifiedInterfaceType())1514      // Simply use 'id' for all qualified types.1515      elementTypeAsString = "id";1516    else1517      elementTypeAsString = VD->getType().getAsString(Context->getPrintingPolicy());1518  }1519 1520  // struct __objcFastEnumerationState enumState = { 0 };1521  buf += "struct __objcFastEnumerationState enumState = { 0 };\n\t";1522  // id __rw_items[16];1523  buf += "id __rw_items[16];\n\t";1524  // id l_collection = (id)1525  buf += "id l_collection = (id)";1526  // Find start location of 'collection' the hard way!1527  const char *startCollectionBuf = startBuf;1528  startCollectionBuf += 3;  // skip 'for'1529  startCollectionBuf = strchr(startCollectionBuf, '(');1530  startCollectionBuf++; // skip '('1531  // find 'in' and skip it.1532  while (*startCollectionBuf != ' ' ||1533         *(startCollectionBuf+1) != 'i' || *(startCollectionBuf+2) != 'n' ||1534         (*(startCollectionBuf+3) != ' ' &&1535          *(startCollectionBuf+3) != '[' && *(startCollectionBuf+3) != '('))1536    startCollectionBuf++;1537  startCollectionBuf += 3;1538 1539  // Replace: "for (type element in" with string constructed thus far.1540  ReplaceText(startLoc, startCollectionBuf - startBuf, buf);1541  // Replace ')' in for '(' type elem in collection ')' with ';'1542  SourceLocation rightParenLoc = S->getRParenLoc();1543  const char *rparenBuf = SM->getCharacterData(rightParenLoc);1544  SourceLocation lparenLoc = startLoc.getLocWithOffset(rparenBuf-startBuf);1545  buf = ";\n\t";1546 1547  // unsigned long limit = [l_collection countByEnumeratingWithState:&enumState1548  //                                   objects:__rw_items count:16];1549  // which is synthesized into:1550  // unsigned int limit =1551  // ((unsigned int (*)1552  //  (id, SEL, struct __objcFastEnumerationState *, id *, unsigned int))1553  //  (void *)objc_msgSend)((id)l_collection,1554  //                        sel_registerName(1555  //                          "countByEnumeratingWithState:objects:count:"),1556  //                        (struct __objcFastEnumerationState *)&state,1557  //                        (id *)__rw_items, (unsigned int)16);1558  buf += "unsigned long limit =\n\t\t";1559  SynthCountByEnumWithState(buf);1560  buf += ";\n\t";1561  /// if (limit) {1562  ///   unsigned long startMutations = *enumState.mutationsPtr;1563  ///   do {1564  ///        unsigned long counter = 0;1565  ///        do {1566  ///             if (startMutations != *enumState.mutationsPtr)1567  ///               objc_enumerationMutation(l_collection);1568  ///             elem = (type)enumState.itemsPtr[counter++];1569  buf += "if (limit) {\n\t";1570  buf += "unsigned long startMutations = *enumState.mutationsPtr;\n\t";1571  buf += "do {\n\t\t";1572  buf += "unsigned long counter = 0;\n\t\t";1573  buf += "do {\n\t\t\t";1574  buf += "if (startMutations != *enumState.mutationsPtr)\n\t\t\t\t";1575  buf += "objc_enumerationMutation(l_collection);\n\t\t\t";1576  buf += elementName;1577  buf += " = (";1578  buf += elementTypeAsString;1579  buf += ")enumState.itemsPtr[counter++];";1580  // Replace ')' in for '(' type elem in collection ')' with all of these.1581  ReplaceText(lparenLoc, 1, buf);1582 1583  ///            __continue_label: ;1584  ///        } while (counter < limit);1585  ///   } while (limit = [l_collection countByEnumeratingWithState:&enumState1586  ///                                  objects:__rw_items count:16]);1587  ///   elem = nil;1588  ///   __break_label: ;1589  ///  }1590  ///  else1591  ///       elem = nil;1592  ///  }1593  ///1594  buf = ";\n\t";1595  buf += "__continue_label_";1596  buf += utostr(ObjCBcLabelNo.back());1597  buf += ": ;";1598  buf += "\n\t\t";1599  buf += "} while (counter < limit);\n\t";1600  buf += "} while (limit = ";1601  SynthCountByEnumWithState(buf);1602  buf += ");\n\t";1603  buf += elementName;1604  buf += " = ((";1605  buf += elementTypeAsString;1606  buf += ")0);\n\t";1607  buf += "__break_label_";1608  buf += utostr(ObjCBcLabelNo.back());1609  buf += ": ;\n\t";1610  buf += "}\n\t";1611  buf += "else\n\t\t";1612  buf += elementName;1613  buf += " = ((";1614  buf += elementTypeAsString;1615  buf += ")0);\n\t";1616  buf += "}\n";1617 1618  // Insert all these *after* the statement body.1619  // FIXME: If this should support Obj-C++, support CXXTryStmt1620  if (isa<CompoundStmt>(S->getBody())) {1621    SourceLocation endBodyLoc = OrigEnd.getLocWithOffset(1);1622    InsertText(endBodyLoc, buf);1623  } else {1624    /* Need to treat single statements specially. For example:1625     *1626     *     for (A *a in b) if (stuff()) break;1627     *     for (A *a in b) xxxyy;1628     *1629     * The following code simply scans ahead to the semi to find the actual end.1630     */1631    const char *stmtBuf = SM->getCharacterData(OrigEnd);1632    const char *semiBuf = strchr(stmtBuf, ';');1633    assert(semiBuf && "Can't find ';'");1634    SourceLocation endBodyLoc = OrigEnd.getLocWithOffset(semiBuf-stmtBuf+1);1635    InsertText(endBodyLoc, buf);1636  }1637  Stmts.pop_back();1638  ObjCBcLabelNo.pop_back();1639  return nullptr;1640}1641 1642/// RewriteObjCSynchronizedStmt -1643/// This routine rewrites @synchronized(expr) stmt;1644/// into:1645/// objc_sync_enter(expr);1646/// @try stmt @finally { objc_sync_exit(expr); }1647///1648Stmt *RewriteObjC::RewriteObjCSynchronizedStmt(ObjCAtSynchronizedStmt *S) {1649  // Get the start location and compute the semi location.1650  SourceLocation startLoc = S->getBeginLoc();1651  const char *startBuf = SM->getCharacterData(startLoc);1652 1653  assert((*startBuf == '@') && "bogus @synchronized location");1654 1655  std::string buf;1656  buf = "objc_sync_enter((id)";1657  const char *lparenBuf = startBuf;1658  while (*lparenBuf != '(') lparenBuf++;1659  ReplaceText(startLoc, lparenBuf-startBuf+1, buf);1660  // We can't use S->getSynchExpr()->getEndLoc() to find the end location, since1661  // the sync expression is typically a message expression that's already1662  // been rewritten! (which implies the SourceLocation's are invalid).1663  SourceLocation endLoc = S->getSynchBody()->getBeginLoc();1664  const char *endBuf = SM->getCharacterData(endLoc);1665  while (*endBuf != ')') endBuf--;1666  SourceLocation rparenLoc = startLoc.getLocWithOffset(endBuf-startBuf);1667  buf = ");\n";1668  // declare a new scope with two variables, _stack and _rethrow.1669  buf += "/* @try scope begin */ \n{ struct _objc_exception_data {\n";1670  buf += "int buf[18/*32-bit i386*/];\n";1671  buf += "char *pointers[4];} _stack;\n";1672  buf += "id volatile _rethrow = 0;\n";1673  buf += "objc_exception_try_enter(&_stack);\n";1674  buf += "if (!_setjmp(_stack.buf)) /* @try block continue */\n";1675  ReplaceText(rparenLoc, 1, buf);1676  startLoc = S->getSynchBody()->getEndLoc();1677  startBuf = SM->getCharacterData(startLoc);1678 1679  assert((*startBuf == '}') && "bogus @synchronized block");1680  SourceLocation lastCurlyLoc = startLoc;1681  buf = "}\nelse {\n";1682  buf += "  _rethrow = objc_exception_extract(&_stack);\n";1683  buf += "}\n";1684  buf += "{ /* implicit finally clause */\n";1685  buf += "  if (!_rethrow) objc_exception_try_exit(&_stack);\n";1686 1687  std::string syncBuf;1688  syncBuf += " objc_sync_exit(";1689 1690  Expr *syncExpr = S->getSynchExpr();1691  CastKind CK = syncExpr->getType()->isObjCObjectPointerType()1692                  ? CK_BitCast :1693                syncExpr->getType()->isBlockPointerType()1694                  ? CK_BlockPointerToObjCPointerCast1695                  : CK_CPointerToObjCPointerCast;1696  syncExpr = NoTypeInfoCStyleCastExpr(Context, Context->getObjCIdType(),1697                                      CK, syncExpr);1698  std::string syncExprBufS;1699  llvm::raw_string_ostream syncExprBuf(syncExprBufS);1700  assert(syncExpr != nullptr && "Expected non-null Expr");1701  syncExpr->printPretty(syncExprBuf, nullptr, PrintingPolicy(LangOpts));1702  syncBuf += syncExprBufS;1703  syncBuf += ");";1704 1705  buf += syncBuf;1706  buf += "\n  if (_rethrow) objc_exception_throw(_rethrow);\n";1707  buf += "}\n";1708  buf += "}";1709 1710  ReplaceText(lastCurlyLoc, 1, buf);1711 1712  bool hasReturns = false;1713  HasReturnStmts(S->getSynchBody(), hasReturns);1714  if (hasReturns)1715    RewriteSyncReturnStmts(S->getSynchBody(), syncBuf);1716 1717  return nullptr;1718}1719 1720void RewriteObjC::WarnAboutReturnGotoStmts(Stmt *S)1721{1722  // Perform a bottom up traversal of all children.1723  for (Stmt *SubStmt : S->children())1724    if (SubStmt)1725      WarnAboutReturnGotoStmts(SubStmt);1726 1727  if (isa<ReturnStmt>(S) || isa<GotoStmt>(S)) {1728    Diags.Report(Context->getFullLoc(S->getBeginLoc()),1729                 TryFinallyContainsReturnDiag);1730  }1731}1732 1733void RewriteObjC::HasReturnStmts(Stmt *S, bool &hasReturns)1734{1735  // Perform a bottom up traversal of all children.1736  for (Stmt *SubStmt : S->children())1737    if (SubStmt)1738      HasReturnStmts(SubStmt, hasReturns);1739 1740  if (isa<ReturnStmt>(S))1741    hasReturns = true;1742}1743 1744void RewriteObjC::RewriteTryReturnStmts(Stmt *S) {1745  // Perform a bottom up traversal of all children.1746  for (Stmt *SubStmt : S->children())1747    if (SubStmt) {1748      RewriteTryReturnStmts(SubStmt);1749    }1750  if (isa<ReturnStmt>(S)) {1751    SourceLocation startLoc = S->getBeginLoc();1752    const char *startBuf = SM->getCharacterData(startLoc);1753    const char *semiBuf = strchr(startBuf, ';');1754    assert((*semiBuf == ';') && "RewriteTryReturnStmts: can't find ';'");1755    SourceLocation onePastSemiLoc = startLoc.getLocWithOffset(semiBuf-startBuf+1);1756 1757    std::string buf;1758    buf = "{ objc_exception_try_exit(&_stack); return";1759 1760    ReplaceText(startLoc, 6, buf);1761    InsertText(onePastSemiLoc, "}");1762  }1763}1764 1765void RewriteObjC::RewriteSyncReturnStmts(Stmt *S, std::string syncExitBuf) {1766  // Perform a bottom up traversal of all children.1767  for (Stmt *SubStmt : S->children())1768    if (SubStmt) {1769      RewriteSyncReturnStmts(SubStmt, syncExitBuf);1770    }1771  if (isa<ReturnStmt>(S)) {1772    SourceLocation startLoc = S->getBeginLoc();1773    const char *startBuf = SM->getCharacterData(startLoc);1774 1775    const char *semiBuf = strchr(startBuf, ';');1776    assert((*semiBuf == ';') && "RewriteSyncReturnStmts: can't find ';'");1777    SourceLocation onePastSemiLoc = startLoc.getLocWithOffset(semiBuf-startBuf+1);1778 1779    std::string buf;1780    buf = "{ objc_exception_try_exit(&_stack);";1781    buf += syncExitBuf;1782    buf += " return";1783 1784    ReplaceText(startLoc, 6, buf);1785    InsertText(onePastSemiLoc, "}");1786  }1787}1788 1789Stmt *RewriteObjC::RewriteObjCTryStmt(ObjCAtTryStmt *S) {1790  // Get the start location and compute the semi location.1791  SourceLocation startLoc = S->getBeginLoc();1792  const char *startBuf = SM->getCharacterData(startLoc);1793 1794  assert((*startBuf == '@') && "bogus @try location");1795 1796  std::string buf;1797  // declare a new scope with two variables, _stack and _rethrow.1798  buf = "/* @try scope begin */ { struct _objc_exception_data {\n";1799  buf += "int buf[18/*32-bit i386*/];\n";1800  buf += "char *pointers[4];} _stack;\n";1801  buf += "id volatile _rethrow = 0;\n";1802  buf += "objc_exception_try_enter(&_stack);\n";1803  buf += "if (!_setjmp(_stack.buf)) /* @try block continue */\n";1804 1805  ReplaceText(startLoc, 4, buf);1806 1807  startLoc = S->getTryBody()->getEndLoc();1808  startBuf = SM->getCharacterData(startLoc);1809 1810  assert((*startBuf == '}') && "bogus @try block");1811 1812  SourceLocation lastCurlyLoc = startLoc;1813  if (S->getNumCatchStmts()) {1814    startLoc = startLoc.getLocWithOffset(1);1815    buf = " /* @catch begin */ else {\n";1816    buf += " id _caught = objc_exception_extract(&_stack);\n";1817    buf += " objc_exception_try_enter (&_stack);\n";1818    buf += " if (_setjmp(_stack.buf))\n";1819    buf += "   _rethrow = objc_exception_extract(&_stack);\n";1820    buf += " else { /* @catch continue */";1821 1822    InsertText(startLoc, buf);1823  } else { /* no catch list */1824    buf = "}\nelse {\n";1825    buf += "  _rethrow = objc_exception_extract(&_stack);\n";1826    buf += "}";1827    ReplaceText(lastCurlyLoc, 1, buf);1828  }1829  Stmt *lastCatchBody = nullptr;1830  for (unsigned I = 0, N = S->getNumCatchStmts(); I != N; ++I) {1831    ObjCAtCatchStmt *Catch = S->getCatchStmt(I);1832    VarDecl *catchDecl = Catch->getCatchParamDecl();1833 1834    if (I == 0)1835      buf = "if ("; // we are generating code for the first catch clause1836    else1837      buf = "else if (";1838    startLoc = Catch->getBeginLoc();1839    startBuf = SM->getCharacterData(startLoc);1840 1841    assert((*startBuf == '@') && "bogus @catch location");1842 1843    const char *lParenLoc = strchr(startBuf, '(');1844 1845    if (Catch->hasEllipsis()) {1846      // Now rewrite the body...1847      lastCatchBody = Catch->getCatchBody();1848      SourceLocation bodyLoc = lastCatchBody->getBeginLoc();1849      const char *bodyBuf = SM->getCharacterData(bodyLoc);1850      assert(*SM->getCharacterData(Catch->getRParenLoc()) == ')' &&1851             "bogus @catch paren location");1852      assert((*bodyBuf == '{') && "bogus @catch body location");1853 1854      buf += "1) { id _tmp = _caught;";1855      Rewrite.ReplaceText(startLoc, bodyBuf-startBuf+1, buf);1856    } else if (catchDecl) {1857      QualType t = catchDecl->getType();1858      if (t == Context->getObjCIdType()) {1859        buf += "1) { ";1860        ReplaceText(startLoc, lParenLoc-startBuf+1, buf);1861      } else if (const ObjCObjectPointerType *Ptr =1862                   t->getAs<ObjCObjectPointerType>()) {1863        // Should be a pointer to a class.1864        ObjCInterfaceDecl *IDecl = Ptr->getObjectType()->getInterface();1865        if (IDecl) {1866          buf += "objc_exception_match((struct objc_class *)objc_getClass(\"";1867          buf += IDecl->getNameAsString();1868          buf += "\"), (struct objc_object *)_caught)) { ";1869          ReplaceText(startLoc, lParenLoc-startBuf+1, buf);1870        }1871      }1872      // Now rewrite the body...1873      lastCatchBody = Catch->getCatchBody();1874      SourceLocation rParenLoc = Catch->getRParenLoc();1875      SourceLocation bodyLoc = lastCatchBody->getBeginLoc();1876      const char *bodyBuf = SM->getCharacterData(bodyLoc);1877      const char *rParenBuf = SM->getCharacterData(rParenLoc);1878      assert((*rParenBuf == ')') && "bogus @catch paren location");1879      assert((*bodyBuf == '{') && "bogus @catch body location");1880 1881      // Here we replace ") {" with "= _caught;" (which initializes and1882      // declares the @catch parameter).1883      ReplaceText(rParenLoc, bodyBuf-rParenBuf+1, " = _caught;");1884    } else {1885      llvm_unreachable("@catch rewrite bug");1886    }1887  }1888  // Complete the catch list...1889  if (lastCatchBody) {1890    SourceLocation bodyLoc = lastCatchBody->getEndLoc();1891    assert(*SM->getCharacterData(bodyLoc) == '}' &&1892           "bogus @catch body location");1893 1894    // Insert the last (implicit) else clause *before* the right curly brace.1895    bodyLoc = bodyLoc.getLocWithOffset(-1);1896    buf = "} /* last catch end */\n";1897    buf += "else {\n";1898    buf += " _rethrow = _caught;\n";1899    buf += " objc_exception_try_exit(&_stack);\n";1900    buf += "} } /* @catch end */\n";1901    if (!S->getFinallyStmt())1902      buf += "}\n";1903    InsertText(bodyLoc, buf);1904 1905    // Set lastCurlyLoc1906    lastCurlyLoc = lastCatchBody->getEndLoc();1907  }1908  if (ObjCAtFinallyStmt *finalStmt = S->getFinallyStmt()) {1909    startLoc = finalStmt->getBeginLoc();1910    startBuf = SM->getCharacterData(startLoc);1911    assert((*startBuf == '@') && "bogus @finally start");1912 1913    ReplaceText(startLoc, 8, "/* @finally */");1914 1915    Stmt *body = finalStmt->getFinallyBody();1916    SourceLocation startLoc = body->getBeginLoc();1917    SourceLocation endLoc = body->getEndLoc();1918    assert(*SM->getCharacterData(startLoc) == '{' &&1919           "bogus @finally body location");1920    assert(*SM->getCharacterData(endLoc) == '}' &&1921           "bogus @finally body location");1922 1923    startLoc = startLoc.getLocWithOffset(1);1924    InsertText(startLoc, " if (!_rethrow) objc_exception_try_exit(&_stack);\n");1925    endLoc = endLoc.getLocWithOffset(-1);1926    InsertText(endLoc, " if (_rethrow) objc_exception_throw(_rethrow);\n");1927 1928    // Set lastCurlyLoc1929    lastCurlyLoc = body->getEndLoc();1930 1931    // Now check for any return/continue/go statements within the @try.1932    WarnAboutReturnGotoStmts(S->getTryBody());1933  } else { /* no finally clause - make sure we synthesize an implicit one */1934    buf = "{ /* implicit finally clause */\n";1935    buf += " if (!_rethrow) objc_exception_try_exit(&_stack);\n";1936    buf += " if (_rethrow) objc_exception_throw(_rethrow);\n";1937    buf += "}";1938    ReplaceText(lastCurlyLoc, 1, buf);1939 1940    // Now check for any return/continue/go statements within the @try.1941    // The implicit finally clause won't called if the @try contains any1942    // jump statements.1943    bool hasReturns = false;1944    HasReturnStmts(S->getTryBody(), hasReturns);1945    if (hasReturns)1946      RewriteTryReturnStmts(S->getTryBody());1947  }1948  // Now emit the final closing curly brace...1949  lastCurlyLoc = lastCurlyLoc.getLocWithOffset(1);1950  InsertText(lastCurlyLoc, " } /* @try scope end */\n");1951  return nullptr;1952}1953 1954// This can't be done with ReplaceStmt(S, ThrowExpr), since1955// the throw expression is typically a message expression that's already1956// been rewritten! (which implies the SourceLocation's are invalid).1957Stmt *RewriteObjC::RewriteObjCThrowStmt(ObjCAtThrowStmt *S) {1958  // Get the start location and compute the semi location.1959  SourceLocation startLoc = S->getBeginLoc();1960  const char *startBuf = SM->getCharacterData(startLoc);1961 1962  assert((*startBuf == '@') && "bogus @throw location");1963 1964  std::string buf;1965  /* void objc_exception_throw(id) __attribute__((noreturn)); */1966  if (S->getThrowExpr())1967    buf = "objc_exception_throw(";1968  else // add an implicit argument1969    buf = "objc_exception_throw(_caught";1970 1971  // handle "@  throw" correctly.1972  const char *wBuf = strchr(startBuf, 'w');1973  assert((*wBuf == 'w') && "@throw: can't find 'w'");1974  ReplaceText(startLoc, wBuf-startBuf+1, buf);1975 1976  const char *semiBuf = strchr(startBuf, ';');1977  assert((*semiBuf == ';') && "@throw: can't find ';'");1978  SourceLocation semiLoc = startLoc.getLocWithOffset(semiBuf-startBuf);1979  ReplaceText(semiLoc, 1, ");");1980  return nullptr;1981}1982 1983Stmt *RewriteObjC::RewriteAtEncode(ObjCEncodeExpr *Exp) {1984  // Create a new string expression.1985  std::string StrEncoding;1986  Context->getObjCEncodingForType(Exp->getEncodedType(), StrEncoding);1987  Expr *Replacement = getStringLiteral(StrEncoding);1988  ReplaceStmt(Exp, Replacement);1989 1990  // Replace this subexpr in the parent.1991  // delete Exp; leak for now, see RewritePropertyOrImplicitSetter() usage for more info.1992  return Replacement;1993}1994 1995Stmt *RewriteObjC::RewriteAtSelector(ObjCSelectorExpr *Exp) {1996  if (!SelGetUidFunctionDecl)1997    SynthSelGetUidFunctionDecl();1998  assert(SelGetUidFunctionDecl && "Can't find sel_registerName() decl");1999  // Create a call to sel_registerName("selName").2000  SmallVector<Expr*, 8> SelExprs;2001  SelExprs.push_back(getStringLiteral(Exp->getSelector().getAsString()));2002  CallExpr *SelExp = SynthesizeCallToFunctionDecl(SelGetUidFunctionDecl,2003                                                  SelExprs);2004  ReplaceStmt(Exp, SelExp);2005  // delete Exp; leak for now, see RewritePropertyOrImplicitSetter() usage for more info.2006  return SelExp;2007}2008 2009CallExpr *2010RewriteObjC::SynthesizeCallToFunctionDecl(FunctionDecl *FD,2011                                          ArrayRef<Expr *> Args,2012                                          SourceLocation StartLoc,2013                                          SourceLocation EndLoc) {2014  // Get the type, we will need to reference it in a couple spots.2015  QualType msgSendType = FD->getType();2016 2017  // Create a reference to the objc_msgSend() declaration.2018  DeclRefExpr *DRE = new (Context) DeclRefExpr(*Context, FD, false, msgSendType,2019                                               VK_LValue, SourceLocation());2020 2021  // Now, we cast the reference to a pointer to the objc_msgSend type.2022  QualType pToFunc = Context->getPointerType(msgSendType);2023  ImplicitCastExpr *ICE =2024      ImplicitCastExpr::Create(*Context, pToFunc, CK_FunctionToPointerDecay,2025                               DRE, nullptr, VK_PRValue, FPOptionsOverride());2026 2027  const auto *FT = msgSendType->castAs<FunctionType>();2028 2029  CallExpr *Exp =2030      CallExpr::Create(*Context, ICE, Args, FT->getCallResultType(*Context),2031                       VK_PRValue, EndLoc, FPOptionsOverride());2032  return Exp;2033}2034 2035static bool scanForProtocolRefs(const char *startBuf, const char *endBuf,2036                                const char *&startRef, const char *&endRef) {2037  while (startBuf < endBuf) {2038    if (*startBuf == '<')2039      startRef = startBuf; // mark the start.2040    if (*startBuf == '>') {2041      if (startRef && *startRef == '<') {2042        endRef = startBuf; // mark the end.2043        return true;2044      }2045      return false;2046    }2047    startBuf++;2048  }2049  return false;2050}2051 2052static void scanToNextArgument(const char *&argRef) {2053  int angle = 0;2054  while (*argRef != ')' && (*argRef != ',' || angle > 0)) {2055    if (*argRef == '<')2056      angle++;2057    else if (*argRef == '>')2058      angle--;2059    argRef++;2060  }2061  assert(angle == 0 && "scanToNextArgument - bad protocol type syntax");2062}2063 2064bool RewriteObjC::needToScanForQualifiers(QualType T) {2065  if (T->isObjCQualifiedIdType())2066    return true;2067  if (const PointerType *PT = T->getAs<PointerType>()) {2068    if (PT->getPointeeType()->isObjCQualifiedIdType())2069      return true;2070  }2071  if (T->isObjCObjectPointerType()) {2072    T = T->getPointeeType();2073    return T->isObjCQualifiedInterfaceType();2074  }2075  if (T->isArrayType()) {2076    QualType ElemTy = Context->getBaseElementType(T);2077    return needToScanForQualifiers(ElemTy);2078  }2079  return false;2080}2081 2082void RewriteObjC::RewriteObjCQualifiedInterfaceTypes(Expr *E) {2083  QualType Type = E->getType();2084  if (needToScanForQualifiers(Type)) {2085    SourceLocation Loc, EndLoc;2086 2087    if (const CStyleCastExpr *ECE = dyn_cast<CStyleCastExpr>(E)) {2088      Loc = ECE->getLParenLoc();2089      EndLoc = ECE->getRParenLoc();2090    } else {2091      Loc = E->getBeginLoc();2092      EndLoc = E->getEndLoc();2093    }2094    // This will defend against trying to rewrite synthesized expressions.2095    if (Loc.isInvalid() || EndLoc.isInvalid())2096      return;2097 2098    const char *startBuf = SM->getCharacterData(Loc);2099    const char *endBuf = SM->getCharacterData(EndLoc);2100    const char *startRef = nullptr, *endRef = nullptr;2101    if (scanForProtocolRefs(startBuf, endBuf, startRef, endRef)) {2102      // Get the locations of the startRef, endRef.2103      SourceLocation LessLoc = Loc.getLocWithOffset(startRef-startBuf);2104      SourceLocation GreaterLoc = Loc.getLocWithOffset(endRef-startBuf+1);2105      // Comment out the protocol references.2106      InsertText(LessLoc, "/*");2107      InsertText(GreaterLoc, "*/");2108    }2109  }2110}2111 2112void RewriteObjC::RewriteObjCQualifiedInterfaceTypes(Decl *Dcl) {2113  SourceLocation Loc;2114  QualType Type;2115  const FunctionProtoType *proto = nullptr;2116  if (VarDecl *VD = dyn_cast<VarDecl>(Dcl)) {2117    Loc = VD->getLocation();2118    Type = VD->getType();2119  }2120  else if (FunctionDecl *FD = dyn_cast<FunctionDecl>(Dcl)) {2121    Loc = FD->getLocation();2122    // Check for ObjC 'id' and class types that have been adorned with protocol2123    // information (id<p>, C<p>*). The protocol references need to be rewritten!2124    const FunctionType *funcType = FD->getType()->getAs<FunctionType>();2125    assert(funcType && "missing function type");2126    proto = dyn_cast<FunctionProtoType>(funcType);2127    if (!proto)2128      return;2129    Type = proto->getReturnType();2130  }2131  else if (FieldDecl *FD = dyn_cast<FieldDecl>(Dcl)) {2132    Loc = FD->getLocation();2133    Type = FD->getType();2134  }2135  else2136    return;2137 2138  if (needToScanForQualifiers(Type)) {2139    // Since types are unique, we need to scan the buffer.2140 2141    const char *endBuf = SM->getCharacterData(Loc);2142    const char *startBuf = endBuf;2143    while (*startBuf != ';' && *startBuf != '<' && startBuf != MainFileStart)2144      startBuf--; // scan backward (from the decl location) for return type.2145    const char *startRef = nullptr, *endRef = nullptr;2146    if (scanForProtocolRefs(startBuf, endBuf, startRef, endRef)) {2147      // Get the locations of the startRef, endRef.2148      SourceLocation LessLoc = Loc.getLocWithOffset(startRef-endBuf);2149      SourceLocation GreaterLoc = Loc.getLocWithOffset(endRef-endBuf+1);2150      // Comment out the protocol references.2151      InsertText(LessLoc, "/*");2152      InsertText(GreaterLoc, "*/");2153    }2154  }2155  if (!proto)2156      return; // most likely, was a variable2157  // Now check arguments.2158  const char *startBuf = SM->getCharacterData(Loc);2159  const char *startFuncBuf = startBuf;2160  for (unsigned i = 0; i < proto->getNumParams(); i++) {2161    if (needToScanForQualifiers(proto->getParamType(i))) {2162      // Since types are unique, we need to scan the buffer.2163 2164      const char *endBuf = startBuf;2165      // scan forward (from the decl location) for argument types.2166      scanToNextArgument(endBuf);2167      const char *startRef = nullptr, *endRef = nullptr;2168      if (scanForProtocolRefs(startBuf, endBuf, startRef, endRef)) {2169        // Get the locations of the startRef, endRef.2170        SourceLocation LessLoc =2171          Loc.getLocWithOffset(startRef-startFuncBuf);2172        SourceLocation GreaterLoc =2173          Loc.getLocWithOffset(endRef-startFuncBuf+1);2174        // Comment out the protocol references.2175        InsertText(LessLoc, "/*");2176        InsertText(GreaterLoc, "*/");2177      }2178      startBuf = ++endBuf;2179    }2180    else {2181      // If the function name is derived from a macro expansion, then the2182      // argument buffer will not follow the name. Need to speak with Chris.2183      while (*startBuf && *startBuf != ')' && *startBuf != ',')2184        startBuf++; // scan forward (from the decl location) for argument types.2185      startBuf++;2186    }2187  }2188}2189 2190void RewriteObjC::RewriteTypeOfDecl(VarDecl *ND) {2191  QualType QT = ND->getType();2192  const Type* TypePtr = QT->getAs<Type>();2193  if (!isa<TypeOfExprType>(TypePtr))2194    return;2195  while (isa<TypeOfExprType>(TypePtr)) {2196    const TypeOfExprType *TypeOfExprTypePtr = cast<TypeOfExprType>(TypePtr);2197    QT = TypeOfExprTypePtr->getUnderlyingExpr()->getType();2198    TypePtr = QT->getAs<Type>();2199  }2200  // FIXME. This will not work for multiple declarators; as in:2201  // __typeof__(a) b,c,d;2202  std::string TypeAsString(QT.getAsString(Context->getPrintingPolicy()));2203  SourceLocation DeclLoc = ND->getTypeSpecStartLoc();2204  const char *startBuf = SM->getCharacterData(DeclLoc);2205  if (ND->getInit()) {2206    std::string Name(ND->getNameAsString());2207    TypeAsString += " " + Name + " = ";2208    Expr *E = ND->getInit();2209    SourceLocation startLoc;2210    if (const CStyleCastExpr *ECE = dyn_cast<CStyleCastExpr>(E))2211      startLoc = ECE->getLParenLoc();2212    else2213      startLoc = E->getBeginLoc();2214    startLoc = SM->getExpansionLoc(startLoc);2215    const char *endBuf = SM->getCharacterData(startLoc);2216    ReplaceText(DeclLoc, endBuf-startBuf-1, TypeAsString);2217  }2218  else {2219    SourceLocation X = ND->getEndLoc();2220    X = SM->getExpansionLoc(X);2221    const char *endBuf = SM->getCharacterData(X);2222    ReplaceText(DeclLoc, endBuf-startBuf-1, TypeAsString);2223  }2224}2225 2226// SynthSelGetUidFunctionDecl - SEL sel_registerName(const char *str);2227void RewriteObjC::SynthSelGetUidFunctionDecl() {2228  IdentifierInfo *SelGetUidIdent = &Context->Idents.get("sel_registerName");2229  SmallVector<QualType, 16> ArgTys;2230  ArgTys.push_back(Context->getPointerType(Context->CharTy.withConst()));2231  QualType getFuncType =2232    getSimpleFunctionType(Context->getObjCSelType(), ArgTys);2233  SelGetUidFunctionDecl = FunctionDecl::Create(*Context, TUDecl,2234                                               SourceLocation(),2235                                               SourceLocation(),2236                                               SelGetUidIdent, getFuncType,2237                                               nullptr, SC_Extern);2238}2239 2240void RewriteObjC::RewriteFunctionDecl(FunctionDecl *FD) {2241  // declared in <objc/objc.h>2242  if (FD->getIdentifier() &&2243      FD->getName() == "sel_registerName") {2244    SelGetUidFunctionDecl = FD;2245    return;2246  }2247  RewriteObjCQualifiedInterfaceTypes(FD);2248}2249 2250void RewriteObjC::RewriteBlockPointerType(std::string& Str, QualType Type) {2251  std::string TypeString(Type.getAsString(Context->getPrintingPolicy()));2252  const char *argPtr = TypeString.c_str();2253  if (!strchr(argPtr, '^')) {2254    Str += TypeString;2255    return;2256  }2257  while (*argPtr) {2258    Str += (*argPtr == '^' ? '*' : *argPtr);2259    argPtr++;2260  }2261}2262 2263// FIXME. Consolidate this routine with RewriteBlockPointerType.2264void RewriteObjC::RewriteBlockPointerTypeVariable(std::string& Str,2265                                                  ValueDecl *VD) {2266  QualType Type = VD->getType();2267  std::string TypeString(Type.getAsString(Context->getPrintingPolicy()));2268  const char *argPtr = TypeString.c_str();2269  int paren = 0;2270  while (*argPtr) {2271    switch (*argPtr) {2272      case '(':2273        Str += *argPtr;2274        paren++;2275        break;2276      case ')':2277        Str += *argPtr;2278        paren--;2279        break;2280      case '^':2281        Str += '*';2282        if (paren == 1)2283          Str += VD->getNameAsString();2284        break;2285      default:2286        Str += *argPtr;2287        break;2288    }2289    argPtr++;2290  }2291}2292 2293void RewriteObjC::RewriteBlockLiteralFunctionDecl(FunctionDecl *FD) {2294  SourceLocation FunLocStart = FD->getTypeSpecStartLoc();2295  const FunctionType *funcType = FD->getType()->getAs<FunctionType>();2296  const FunctionProtoType *proto = dyn_cast_or_null<FunctionProtoType>(funcType);2297  if (!proto)2298    return;2299  QualType Type = proto->getReturnType();2300  std::string FdStr = Type.getAsString(Context->getPrintingPolicy());2301  FdStr += " ";2302  FdStr += FD->getName();2303  FdStr +=  "(";2304  unsigned numArgs = proto->getNumParams();2305  for (unsigned i = 0; i < numArgs; i++) {2306    QualType ArgType = proto->getParamType(i);2307    RewriteBlockPointerType(FdStr, ArgType);2308    if (i+1 < numArgs)2309      FdStr += ", ";2310  }2311  FdStr +=  ");\n";2312  InsertText(FunLocStart, FdStr);2313  CurFunctionDeclToDeclareForBlock = nullptr;2314}2315 2316// SynthSuperConstructorFunctionDecl - id objc_super(id obj, id super);2317void RewriteObjC::SynthSuperConstructorFunctionDecl() {2318  if (SuperConstructorFunctionDecl)2319    return;2320  IdentifierInfo *msgSendIdent = &Context->Idents.get("__rw_objc_super");2321  SmallVector<QualType, 16> ArgTys;2322  QualType argT = Context->getObjCIdType();2323  assert(!argT.isNull() && "Can't find 'id' type");2324  ArgTys.push_back(argT);2325  ArgTys.push_back(argT);2326  QualType msgSendType = getSimpleFunctionType(Context->getObjCIdType(),2327                                               ArgTys);2328  SuperConstructorFunctionDecl = FunctionDecl::Create(*Context, TUDecl,2329                                                     SourceLocation(),2330                                                     SourceLocation(),2331                                                     msgSendIdent, msgSendType,2332                                                     nullptr, SC_Extern);2333}2334 2335// SynthMsgSendFunctionDecl - id objc_msgSend(id self, SEL op, ...);2336void RewriteObjC::SynthMsgSendFunctionDecl() {2337  IdentifierInfo *msgSendIdent = &Context->Idents.get("objc_msgSend");2338  SmallVector<QualType, 16> ArgTys;2339  QualType argT = Context->getObjCIdType();2340  assert(!argT.isNull() && "Can't find 'id' type");2341  ArgTys.push_back(argT);2342  argT = Context->getObjCSelType();2343  assert(!argT.isNull() && "Can't find 'SEL' type");2344  ArgTys.push_back(argT);2345  QualType msgSendType = getSimpleFunctionType(Context->getObjCIdType(),2346                                               ArgTys, /*variadic=*/true);2347  MsgSendFunctionDecl = FunctionDecl::Create(*Context, TUDecl,2348                                             SourceLocation(),2349                                             SourceLocation(),2350                                             msgSendIdent, msgSendType,2351                                             nullptr, SC_Extern);2352}2353 2354// SynthMsgSendSuperFunctionDecl - id objc_msgSendSuper(struct objc_super *, SEL op, ...);2355void RewriteObjC::SynthMsgSendSuperFunctionDecl() {2356  IdentifierInfo *msgSendIdent = &Context->Idents.get("objc_msgSendSuper");2357  SmallVector<QualType, 16> ArgTys;2358  RecordDecl *RD = RecordDecl::Create(*Context, TagTypeKind::Struct, TUDecl,2359                                      SourceLocation(), SourceLocation(),2360                                      &Context->Idents.get("objc_super"));2361  QualType argT = Context->getPointerType(Context->getCanonicalTagType(RD));2362  assert(!argT.isNull() && "Can't build 'struct objc_super *' type");2363  ArgTys.push_back(argT);2364  argT = Context->getObjCSelType();2365  assert(!argT.isNull() && "Can't find 'SEL' type");2366  ArgTys.push_back(argT);2367  QualType msgSendType = getSimpleFunctionType(Context->getObjCIdType(),2368                                               ArgTys, /*variadic=*/true);2369  MsgSendSuperFunctionDecl = FunctionDecl::Create(*Context, TUDecl,2370                                                  SourceLocation(),2371                                                  SourceLocation(),2372                                                  msgSendIdent, msgSendType,2373                                                  nullptr, SC_Extern);2374}2375 2376// SynthMsgSendStretFunctionDecl - id objc_msgSend_stret(id self, SEL op, ...);2377void RewriteObjC::SynthMsgSendStretFunctionDecl() {2378  IdentifierInfo *msgSendIdent = &Context->Idents.get("objc_msgSend_stret");2379  SmallVector<QualType, 16> ArgTys;2380  QualType argT = Context->getObjCIdType();2381  assert(!argT.isNull() && "Can't find 'id' type");2382  ArgTys.push_back(argT);2383  argT = Context->getObjCSelType();2384  assert(!argT.isNull() && "Can't find 'SEL' type");2385  ArgTys.push_back(argT);2386  QualType msgSendType = getSimpleFunctionType(Context->getObjCIdType(),2387                                               ArgTys, /*variadic=*/true);2388  MsgSendStretFunctionDecl = FunctionDecl::Create(*Context, TUDecl,2389                                                  SourceLocation(),2390                                                  SourceLocation(),2391                                                  msgSendIdent, msgSendType,2392                                                  nullptr, SC_Extern);2393}2394 2395// SynthMsgSendSuperStretFunctionDecl -2396// id objc_msgSendSuper_stret(struct objc_super *, SEL op, ...);2397void RewriteObjC::SynthMsgSendSuperStretFunctionDecl() {2398  IdentifierInfo *msgSendIdent =2399    &Context->Idents.get("objc_msgSendSuper_stret");2400  SmallVector<QualType, 16> ArgTys;2401  RecordDecl *RD = RecordDecl::Create(*Context, TagTypeKind::Struct, TUDecl,2402                                      SourceLocation(), SourceLocation(),2403                                      &Context->Idents.get("objc_super"));2404  QualType argT = Context->getPointerType(Context->getCanonicalTagType(RD));2405  assert(!argT.isNull() && "Can't build 'struct objc_super *' type");2406  ArgTys.push_back(argT);2407  argT = Context->getObjCSelType();2408  assert(!argT.isNull() && "Can't find 'SEL' type");2409  ArgTys.push_back(argT);2410  QualType msgSendType = getSimpleFunctionType(Context->getObjCIdType(),2411                                               ArgTys, /*variadic=*/true);2412  MsgSendSuperStretFunctionDecl = FunctionDecl::Create(*Context, TUDecl,2413                                                       SourceLocation(),2414                                                       SourceLocation(),2415                                                       msgSendIdent,2416                                                       msgSendType, nullptr,2417                                                       SC_Extern);2418}2419 2420// SynthMsgSendFpretFunctionDecl - double objc_msgSend_fpret(id self, SEL op, ...);2421void RewriteObjC::SynthMsgSendFpretFunctionDecl() {2422  IdentifierInfo *msgSendIdent = &Context->Idents.get("objc_msgSend_fpret");2423  SmallVector<QualType, 16> ArgTys;2424  QualType argT = Context->getObjCIdType();2425  assert(!argT.isNull() && "Can't find 'id' type");2426  ArgTys.push_back(argT);2427  argT = Context->getObjCSelType();2428  assert(!argT.isNull() && "Can't find 'SEL' type");2429  ArgTys.push_back(argT);2430  QualType msgSendType = getSimpleFunctionType(Context->DoubleTy,2431                                               ArgTys, /*variadic=*/true);2432  MsgSendFpretFunctionDecl = FunctionDecl::Create(*Context, TUDecl,2433                                                  SourceLocation(),2434                                                  SourceLocation(),2435                                                  msgSendIdent, msgSendType,2436                                                  nullptr, SC_Extern);2437}2438 2439// SynthGetClassFunctionDecl - id objc_getClass(const char *name);2440void RewriteObjC::SynthGetClassFunctionDecl() {2441  IdentifierInfo *getClassIdent = &Context->Idents.get("objc_getClass");2442  SmallVector<QualType, 16> ArgTys;2443  ArgTys.push_back(Context->getPointerType(Context->CharTy.withConst()));2444  QualType getClassType = getSimpleFunctionType(Context->getObjCIdType(),2445                                                ArgTys);2446  GetClassFunctionDecl = FunctionDecl::Create(*Context, TUDecl,2447                                              SourceLocation(),2448                                              SourceLocation(),2449                                              getClassIdent, getClassType,2450                                              nullptr, SC_Extern);2451}2452 2453// SynthGetSuperClassFunctionDecl - Class class_getSuperclass(Class cls);2454void RewriteObjC::SynthGetSuperClassFunctionDecl() {2455  IdentifierInfo *getSuperClassIdent =2456    &Context->Idents.get("class_getSuperclass");2457  SmallVector<QualType, 16> ArgTys;2458  ArgTys.push_back(Context->getObjCClassType());2459  QualType getClassType = getSimpleFunctionType(Context->getObjCClassType(),2460                                                ArgTys);2461  GetSuperClassFunctionDecl = FunctionDecl::Create(*Context, TUDecl,2462                                                   SourceLocation(),2463                                                   SourceLocation(),2464                                                   getSuperClassIdent,2465                                                   getClassType, nullptr,2466                                                   SC_Extern);2467}2468 2469// SynthGetMetaClassFunctionDecl - id objc_getMetaClass(const char *name);2470void RewriteObjC::SynthGetMetaClassFunctionDecl() {2471  IdentifierInfo *getClassIdent = &Context->Idents.get("objc_getMetaClass");2472  SmallVector<QualType, 16> ArgTys;2473  ArgTys.push_back(Context->getPointerType(Context->CharTy.withConst()));2474  QualType getClassType = getSimpleFunctionType(Context->getObjCIdType(),2475                                                ArgTys);2476  GetMetaClassFunctionDecl = FunctionDecl::Create(*Context, TUDecl,2477                                                  SourceLocation(),2478                                                  SourceLocation(),2479                                                  getClassIdent, getClassType,2480                                                  nullptr, SC_Extern);2481}2482 2483Stmt *RewriteObjC::RewriteObjCStringLiteral(ObjCStringLiteral *Exp) {2484  assert(Exp != nullptr && "Expected non-null ObjCStringLiteral");2485  QualType strType = getConstantStringStructType();2486 2487  std::string S = "__NSConstantStringImpl_";2488 2489  std::string tmpName = InFileName;2490  unsigned i;2491  for (i=0; i < tmpName.length(); i++) {2492    char c = tmpName.at(i);2493    // replace any non-alphanumeric characters with '_'.2494    if (!isAlphanumeric(c))2495      tmpName[i] = '_';2496  }2497  S += tmpName;2498  S += "_";2499  S += utostr(NumObjCStringLiterals++);2500 2501  Preamble += "static __NSConstantStringImpl " + S;2502  Preamble += " __attribute__ ((section (\"__DATA, __cfstring\"))) = {__CFConstantStringClassReference,";2503  Preamble += "0x000007c8,"; // utf8_str2504  // The pretty printer for StringLiteral handles escape characters properly.2505  std::string prettyBufS;2506  llvm::raw_string_ostream prettyBuf(prettyBufS);2507  Exp->getString()->printPretty(prettyBuf, nullptr, PrintingPolicy(LangOpts));2508  Preamble += prettyBufS;2509  Preamble += ",";2510  Preamble += utostr(Exp->getString()->getByteLength()) + "};\n";2511 2512  VarDecl *NewVD = VarDecl::Create(*Context, TUDecl, SourceLocation(),2513                                   SourceLocation(), &Context->Idents.get(S),2514                                   strType, nullptr, SC_Static);2515  DeclRefExpr *DRE = new (Context)2516      DeclRefExpr(*Context, NewVD, false, strType, VK_LValue, SourceLocation());2517  Expr *Unop = UnaryOperator::Create(2518      const_cast<ASTContext &>(*Context), DRE, UO_AddrOf,2519      Context->getPointerType(DRE->getType()), VK_PRValue, OK_Ordinary,2520      SourceLocation(), false, FPOptionsOverride());2521  // cast to NSConstantString *2522  CastExpr *cast = NoTypeInfoCStyleCastExpr(Context, Exp->getType(),2523                                            CK_CPointerToObjCPointerCast, Unop);2524  ReplaceStmt(Exp, cast);2525  // delete Exp; leak for now, see RewritePropertyOrImplicitSetter() usage for more info.2526  return cast;2527}2528 2529// struct objc_super { struct objc_object *receiver; struct objc_class *super; };2530QualType RewriteObjC::getSuperStructType() {2531  if (!SuperStructDecl) {2532    SuperStructDecl = RecordDecl::Create(*Context, TagTypeKind::Struct, TUDecl,2533                                         SourceLocation(), SourceLocation(),2534                                         &Context->Idents.get("objc_super"));2535    QualType FieldTypes[2];2536 2537    // struct objc_object *receiver;2538    FieldTypes[0] = Context->getObjCIdType();2539    // struct objc_class *super;2540    FieldTypes[1] = Context->getObjCClassType();2541 2542    // Create fields2543    for (unsigned i = 0; i < 2; ++i) {2544      SuperStructDecl->addDecl(FieldDecl::Create(*Context, SuperStructDecl,2545                                                 SourceLocation(),2546                                                 SourceLocation(), nullptr,2547                                                 FieldTypes[i], nullptr,2548                                                 /*BitWidth=*/nullptr,2549                                                 /*Mutable=*/false,2550                                                 ICIS_NoInit));2551    }2552 2553    SuperStructDecl->completeDefinition();2554  }2555  return Context->getCanonicalTagType(SuperStructDecl);2556}2557 2558QualType RewriteObjC::getConstantStringStructType() {2559  if (!ConstantStringDecl) {2560    ConstantStringDecl = RecordDecl::Create(2561        *Context, TagTypeKind::Struct, TUDecl, SourceLocation(),2562        SourceLocation(), &Context->Idents.get("__NSConstantStringImpl"));2563    QualType FieldTypes[4];2564 2565    // struct objc_object *receiver;2566    FieldTypes[0] = Context->getObjCIdType();2567    // int flags;2568    FieldTypes[1] = Context->IntTy;2569    // char *str;2570    FieldTypes[2] = Context->getPointerType(Context->CharTy);2571    // long length;2572    FieldTypes[3] = Context->LongTy;2573 2574    // Create fields2575    for (unsigned i = 0; i < 4; ++i) {2576      ConstantStringDecl->addDecl(FieldDecl::Create(*Context,2577                                                    ConstantStringDecl,2578                                                    SourceLocation(),2579                                                    SourceLocation(), nullptr,2580                                                    FieldTypes[i], nullptr,2581                                                    /*BitWidth=*/nullptr,2582                                                    /*Mutable=*/true,2583                                                    ICIS_NoInit));2584    }2585 2586    ConstantStringDecl->completeDefinition();2587  }2588  return Context->getCanonicalTagType(ConstantStringDecl);2589}2590 2591CallExpr *RewriteObjC::SynthMsgSendStretCallExpr(FunctionDecl *MsgSendStretFlavor,2592                                                QualType msgSendType,2593                                                QualType returnType,2594                                                SmallVectorImpl<QualType> &ArgTypes,2595                                                SmallVectorImpl<Expr*> &MsgExprs,2596                                                ObjCMethodDecl *Method) {2597  // Create a reference to the objc_msgSend_stret() declaration.2598  DeclRefExpr *STDRE =2599      new (Context) DeclRefExpr(*Context, MsgSendStretFlavor, false,2600                                msgSendType, VK_LValue, SourceLocation());2601  // Need to cast objc_msgSend_stret to "void *" (see above comment).2602  CastExpr *cast = NoTypeInfoCStyleCastExpr(Context,2603                                  Context->getPointerType(Context->VoidTy),2604                                  CK_BitCast, STDRE);2605  // Now do the "normal" pointer to function cast.2606  QualType castType = getSimpleFunctionType(returnType, ArgTypes,2607                                            Method ? Method->isVariadic()2608                                                   : false);2609  castType = Context->getPointerType(castType);2610  cast = NoTypeInfoCStyleCastExpr(Context, castType, CK_BitCast,2611                                            cast);2612 2613  // Don't forget the parens to enforce the proper binding.2614  ParenExpr *PE = new (Context) ParenExpr(SourceLocation(), SourceLocation(), cast);2615 2616  const auto *FT = msgSendType->castAs<FunctionType>();2617  CallExpr *STCE =2618      CallExpr::Create(*Context, PE, MsgExprs, FT->getReturnType(), VK_PRValue,2619                       SourceLocation(), FPOptionsOverride());2620  return STCE;2621}2622 2623Stmt *RewriteObjC::SynthMessageExpr(ObjCMessageExpr *Exp,2624                                    SourceLocation StartLoc,2625                                    SourceLocation EndLoc) {2626  if (!SelGetUidFunctionDecl)2627    SynthSelGetUidFunctionDecl();2628  if (!MsgSendFunctionDecl)2629    SynthMsgSendFunctionDecl();2630  if (!MsgSendSuperFunctionDecl)2631    SynthMsgSendSuperFunctionDecl();2632  if (!MsgSendStretFunctionDecl)2633    SynthMsgSendStretFunctionDecl();2634  if (!MsgSendSuperStretFunctionDecl)2635    SynthMsgSendSuperStretFunctionDecl();2636  if (!MsgSendFpretFunctionDecl)2637    SynthMsgSendFpretFunctionDecl();2638  if (!GetClassFunctionDecl)2639    SynthGetClassFunctionDecl();2640  if (!GetSuperClassFunctionDecl)2641    SynthGetSuperClassFunctionDecl();2642  if (!GetMetaClassFunctionDecl)2643    SynthGetMetaClassFunctionDecl();2644 2645  // default to objc_msgSend().2646  FunctionDecl *MsgSendFlavor = MsgSendFunctionDecl;2647  // May need to use objc_msgSend_stret() as well.2648  FunctionDecl *MsgSendStretFlavor = nullptr;2649  if (ObjCMethodDecl *mDecl = Exp->getMethodDecl()) {2650    QualType resultType = mDecl->getReturnType();2651    if (resultType->isRecordType())2652      MsgSendStretFlavor = MsgSendStretFunctionDecl;2653    else if (resultType->isRealFloatingType())2654      MsgSendFlavor = MsgSendFpretFunctionDecl;2655  }2656 2657  // Synthesize a call to objc_msgSend().2658  SmallVector<Expr*, 8> MsgExprs;2659  switch (Exp->getReceiverKind()) {2660  case ObjCMessageExpr::SuperClass: {2661    MsgSendFlavor = MsgSendSuperFunctionDecl;2662    if (MsgSendStretFlavor)2663      MsgSendStretFlavor = MsgSendSuperStretFunctionDecl;2664    assert(MsgSendFlavor && "MsgSendFlavor is NULL!");2665 2666    ObjCInterfaceDecl *ClassDecl = CurMethodDef->getClassInterface();2667 2668    SmallVector<Expr*, 4> InitExprs;2669 2670    // set the receiver to self, the first argument to all methods.2671    InitExprs.push_back(NoTypeInfoCStyleCastExpr(2672        Context, Context->getObjCIdType(), CK_BitCast,2673        new (Context) DeclRefExpr(*Context, CurMethodDef->getSelfDecl(), false,2674                                  Context->getObjCIdType(), VK_PRValue,2675                                  SourceLocation()))); // set the 'receiver'.2676 2677    // (id)class_getSuperclass((Class)objc_getClass("CurrentClass"))2678    SmallVector<Expr*, 8> ClsExprs;2679    ClsExprs.push_back(getStringLiteral(ClassDecl->getIdentifier()->getName()));2680    CallExpr *Cls = SynthesizeCallToFunctionDecl(GetMetaClassFunctionDecl,2681                                                 ClsExprs, StartLoc, EndLoc);2682    // (Class)objc_getClass("CurrentClass")2683    CastExpr *ArgExpr = NoTypeInfoCStyleCastExpr(Context,2684                                             Context->getObjCClassType(),2685                                             CK_BitCast, Cls);2686    ClsExprs.clear();2687    ClsExprs.push_back(ArgExpr);2688    Cls = SynthesizeCallToFunctionDecl(GetSuperClassFunctionDecl, ClsExprs,2689                                       StartLoc, EndLoc);2690    // (id)class_getSuperclass((Class)objc_getClass("CurrentClass"))2691    // To turn off a warning, type-cast to 'id'2692    InitExprs.push_back( // set 'super class', using class_getSuperclass().2693                        NoTypeInfoCStyleCastExpr(Context,2694                                                 Context->getObjCIdType(),2695                                                 CK_BitCast, Cls));2696    // struct objc_super2697    QualType superType = getSuperStructType();2698    Expr *SuperRep;2699 2700    if (LangOpts.MicrosoftExt) {2701      SynthSuperConstructorFunctionDecl();2702      // Simulate a constructor call...2703      DeclRefExpr *DRE = new (Context)2704          DeclRefExpr(*Context, SuperConstructorFunctionDecl, false, superType,2705                      VK_LValue, SourceLocation());2706      SuperRep =2707          CallExpr::Create(*Context, DRE, InitExprs, superType, VK_LValue,2708                           SourceLocation(), FPOptionsOverride());2709      // The code for super is a little tricky to prevent collision with2710      // the structure definition in the header. The rewriter has it's own2711      // internal definition (__rw_objc_super) that is uses. This is why2712      // we need the cast below. For example:2713      // (struct objc_super *)&__rw_objc_super((id)self, (id)objc_getClass("SUPER"))2714      //2715      SuperRep = UnaryOperator::Create(2716          const_cast<ASTContext &>(*Context), SuperRep, UO_AddrOf,2717          Context->getPointerType(SuperRep->getType()), VK_PRValue, OK_Ordinary,2718          SourceLocation(), false, FPOptionsOverride());2719      SuperRep = NoTypeInfoCStyleCastExpr(Context,2720                                          Context->getPointerType(superType),2721                                          CK_BitCast, SuperRep);2722    } else {2723      // (struct objc_super) { <exprs from above> }2724      InitListExpr *ILE =2725        new (Context) InitListExpr(*Context, SourceLocation(), InitExprs,2726                                   SourceLocation());2727      TypeSourceInfo *superTInfo2728        = Context->getTrivialTypeSourceInfo(superType);2729      SuperRep = new (Context) CompoundLiteralExpr(SourceLocation(), superTInfo,2730                                                   superType, VK_LValue,2731                                                   ILE, false);2732      // struct objc_super *2733      SuperRep = UnaryOperator::Create(2734          const_cast<ASTContext &>(*Context), SuperRep, UO_AddrOf,2735          Context->getPointerType(SuperRep->getType()), VK_PRValue, OK_Ordinary,2736          SourceLocation(), false, FPOptionsOverride());2737    }2738    MsgExprs.push_back(SuperRep);2739    break;2740  }2741 2742  case ObjCMessageExpr::Class: {2743    SmallVector<Expr*, 8> ClsExprs;2744    auto *Class =2745        Exp->getClassReceiver()->castAs<ObjCObjectType>()->getInterface();2746    IdentifierInfo *clsName = Class->getIdentifier();2747    ClsExprs.push_back(getStringLiteral(clsName->getName()));2748    CallExpr *Cls = SynthesizeCallToFunctionDecl(GetClassFunctionDecl, ClsExprs,2749                                                 StartLoc, EndLoc);2750    MsgExprs.push_back(Cls);2751    break;2752  }2753 2754  case ObjCMessageExpr::SuperInstance:{2755    MsgSendFlavor = MsgSendSuperFunctionDecl;2756    if (MsgSendStretFlavor)2757      MsgSendStretFlavor = MsgSendSuperStretFunctionDecl;2758    assert(MsgSendFlavor && "MsgSendFlavor is NULL!");2759    ObjCInterfaceDecl *ClassDecl = CurMethodDef->getClassInterface();2760    SmallVector<Expr*, 4> InitExprs;2761 2762    InitExprs.push_back(NoTypeInfoCStyleCastExpr(2763        Context, Context->getObjCIdType(), CK_BitCast,2764        new (Context) DeclRefExpr(*Context, CurMethodDef->getSelfDecl(), false,2765                                  Context->getObjCIdType(), VK_PRValue,2766                                  SourceLocation()))); // set the 'receiver'.2767 2768    // (id)class_getSuperclass((Class)objc_getClass("CurrentClass"))2769    SmallVector<Expr*, 8> ClsExprs;2770    ClsExprs.push_back(getStringLiteral(ClassDecl->getIdentifier()->getName()));2771    CallExpr *Cls = SynthesizeCallToFunctionDecl(GetClassFunctionDecl, ClsExprs,2772                                                 StartLoc, EndLoc);2773    // (Class)objc_getClass("CurrentClass")2774    CastExpr *ArgExpr = NoTypeInfoCStyleCastExpr(Context,2775                                                 Context->getObjCClassType(),2776                                                 CK_BitCast, Cls);2777    ClsExprs.clear();2778    ClsExprs.push_back(ArgExpr);2779    Cls = SynthesizeCallToFunctionDecl(GetSuperClassFunctionDecl, ClsExprs,2780                                       StartLoc, EndLoc);2781 2782    // (id)class_getSuperclass((Class)objc_getClass("CurrentClass"))2783    // To turn off a warning, type-cast to 'id'2784    InitExprs.push_back(2785      // set 'super class', using class_getSuperclass().2786      NoTypeInfoCStyleCastExpr(Context, Context->getObjCIdType(),2787                               CK_BitCast, Cls));2788    // struct objc_super2789    QualType superType = getSuperStructType();2790    Expr *SuperRep;2791 2792    if (LangOpts.MicrosoftExt) {2793      SynthSuperConstructorFunctionDecl();2794      // Simulate a constructor call...2795      DeclRefExpr *DRE = new (Context)2796          DeclRefExpr(*Context, SuperConstructorFunctionDecl, false, superType,2797                      VK_LValue, SourceLocation());2798      SuperRep =2799          CallExpr::Create(*Context, DRE, InitExprs, superType, VK_LValue,2800                           SourceLocation(), FPOptionsOverride());2801      // The code for super is a little tricky to prevent collision with2802      // the structure definition in the header. The rewriter has it's own2803      // internal definition (__rw_objc_super) that is uses. This is why2804      // we need the cast below. For example:2805      // (struct objc_super *)&__rw_objc_super((id)self, (id)objc_getClass("SUPER"))2806      //2807      SuperRep = UnaryOperator::Create(2808          const_cast<ASTContext &>(*Context), SuperRep, UO_AddrOf,2809          Context->getPointerType(SuperRep->getType()), VK_PRValue, OK_Ordinary,2810          SourceLocation(), false, FPOptionsOverride());2811      SuperRep = NoTypeInfoCStyleCastExpr(Context,2812                               Context->getPointerType(superType),2813                               CK_BitCast, SuperRep);2814    } else {2815      // (struct objc_super) { <exprs from above> }2816      InitListExpr *ILE =2817        new (Context) InitListExpr(*Context, SourceLocation(), InitExprs,2818                                   SourceLocation());2819      TypeSourceInfo *superTInfo2820        = Context->getTrivialTypeSourceInfo(superType);2821      SuperRep = new (Context) CompoundLiteralExpr(2822          SourceLocation(), superTInfo, superType, VK_PRValue, ILE, false);2823    }2824    MsgExprs.push_back(SuperRep);2825    break;2826  }2827 2828  case ObjCMessageExpr::Instance: {2829    // Remove all type-casts because it may contain objc-style types; e.g.2830    // Foo<Proto> *.2831    Expr *recExpr = Exp->getInstanceReceiver();2832    while (CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(recExpr))2833      recExpr = CE->getSubExpr();2834    CastKind CK = recExpr->getType()->isObjCObjectPointerType()2835                    ? CK_BitCast : recExpr->getType()->isBlockPointerType()2836                                     ? CK_BlockPointerToObjCPointerCast2837                                     : CK_CPointerToObjCPointerCast;2838 2839    recExpr = NoTypeInfoCStyleCastExpr(Context, Context->getObjCIdType(),2840                                       CK, recExpr);2841    MsgExprs.push_back(recExpr);2842    break;2843  }2844  }2845 2846  // Create a call to sel_registerName("selName"), it will be the 2nd argument.2847  SmallVector<Expr*, 8> SelExprs;2848  SelExprs.push_back(getStringLiteral(Exp->getSelector().getAsString()));2849  CallExpr *SelExp = SynthesizeCallToFunctionDecl(SelGetUidFunctionDecl,2850                                                  SelExprs, StartLoc, EndLoc);2851  MsgExprs.push_back(SelExp);2852 2853  // Now push any user supplied arguments.2854  for (unsigned i = 0; i < Exp->getNumArgs(); i++) {2855    Expr *userExpr = Exp->getArg(i);2856    // Make all implicit casts explicit...ICE comes in handy:-)2857    if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(userExpr)) {2858      // Reuse the ICE type, it is exactly what the doctor ordered.2859      QualType type = ICE->getType();2860      if (needToScanForQualifiers(type))2861        type = Context->getObjCIdType();2862      // Make sure we convert "type (^)(...)" to "type (*)(...)".2863      (void)convertBlockPointerToFunctionPointer(type);2864      const Expr *SubExpr = ICE->IgnoreParenImpCasts();2865      CastKind CK;2866      if (SubExpr->getType()->isIntegralType(*Context) &&2867          type->isBooleanType()) {2868        CK = CK_IntegralToBoolean;2869      } else if (type->isObjCObjectPointerType()) {2870        if (SubExpr->getType()->isBlockPointerType()) {2871          CK = CK_BlockPointerToObjCPointerCast;2872        } else if (SubExpr->getType()->isPointerType()) {2873          CK = CK_CPointerToObjCPointerCast;2874        } else {2875          CK = CK_BitCast;2876        }2877      } else {2878        CK = CK_BitCast;2879      }2880 2881      userExpr = NoTypeInfoCStyleCastExpr(Context, type, CK, userExpr);2882    }2883    // Make id<P...> cast into an 'id' cast.2884    else if (CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(userExpr)) {2885      if (CE->getType()->isObjCQualifiedIdType()) {2886        while ((CE = dyn_cast<CStyleCastExpr>(userExpr)))2887          userExpr = CE->getSubExpr();2888        CastKind CK;2889        if (userExpr->getType()->isIntegralType(*Context)) {2890          CK = CK_IntegralToPointer;2891        } else if (userExpr->getType()->isBlockPointerType()) {2892          CK = CK_BlockPointerToObjCPointerCast;2893        } else if (userExpr->getType()->isPointerType()) {2894          CK = CK_CPointerToObjCPointerCast;2895        } else {2896          CK = CK_BitCast;2897        }2898        userExpr = NoTypeInfoCStyleCastExpr(Context, Context->getObjCIdType(),2899                                            CK, userExpr);2900      }2901    }2902    MsgExprs.push_back(userExpr);2903    // We've transferred the ownership to MsgExprs. For now, we *don't* null2904    // out the argument in the original expression (since we aren't deleting2905    // the ObjCMessageExpr). See RewritePropertyOrImplicitSetter() usage for more info.2906    //Exp->setArg(i, 0);2907  }2908  // Generate the funky cast.2909  CastExpr *cast;2910  SmallVector<QualType, 8> ArgTypes;2911  QualType returnType;2912 2913  // Push 'id' and 'SEL', the 2 implicit arguments.2914  if (MsgSendFlavor == MsgSendSuperFunctionDecl)2915    ArgTypes.push_back(Context->getPointerType(getSuperStructType()));2916  else2917    ArgTypes.push_back(Context->getObjCIdType());2918  ArgTypes.push_back(Context->getObjCSelType());2919  if (ObjCMethodDecl *OMD = Exp->getMethodDecl()) {2920    // Push any user argument types.2921    for (const auto *PI : OMD->parameters()) {2922      QualType t = PI->getType()->isObjCQualifiedIdType()2923                     ? Context->getObjCIdType()2924                     : PI->getType();2925      // Make sure we convert "t (^)(...)" to "t (*)(...)".2926      (void)convertBlockPointerToFunctionPointer(t);2927      ArgTypes.push_back(t);2928    }2929    returnType = Exp->getType();2930    convertToUnqualifiedObjCType(returnType);2931    (void)convertBlockPointerToFunctionPointer(returnType);2932  } else {2933    returnType = Context->getObjCIdType();2934  }2935  // Get the type, we will need to reference it in a couple spots.2936  QualType msgSendType = MsgSendFlavor->getType();2937 2938  // Create a reference to the objc_msgSend() declaration.2939  DeclRefExpr *DRE = new (Context) DeclRefExpr(2940      *Context, MsgSendFlavor, false, msgSendType, VK_LValue, SourceLocation());2941 2942  // Need to cast objc_msgSend to "void *" (to workaround a GCC bandaid).2943  // If we don't do this cast, we get the following bizarre warning/note:2944  // xx.m:13: warning: function called through a non-compatible type2945  // xx.m:13: note: if this code is reached, the program will abort2946  cast = NoTypeInfoCStyleCastExpr(Context,2947                                  Context->getPointerType(Context->VoidTy),2948                                  CK_BitCast, DRE);2949 2950  // Now do the "normal" pointer to function cast.2951  // If we don't have a method decl, force a variadic cast.2952  const ObjCMethodDecl *MD = Exp->getMethodDecl();2953  QualType castType =2954    getSimpleFunctionType(returnType, ArgTypes, MD ? MD->isVariadic() : true);2955  castType = Context->getPointerType(castType);2956  cast = NoTypeInfoCStyleCastExpr(Context, castType, CK_BitCast,2957                                  cast);2958 2959  // Don't forget the parens to enforce the proper binding.2960  ParenExpr *PE = new (Context) ParenExpr(StartLoc, EndLoc, cast);2961 2962  const auto *FT = msgSendType->castAs<FunctionType>();2963  CallExpr *CE = CallExpr::Create(*Context, PE, MsgExprs, FT->getReturnType(),2964                                  VK_PRValue, EndLoc, FPOptionsOverride());2965  Stmt *ReplacingStmt = CE;2966  if (MsgSendStretFlavor) {2967    // We have the method which returns a struct/union. Must also generate2968    // call to objc_msgSend_stret and hang both varieties on a conditional2969    // expression which dictate which one to envoke depending on size of2970    // method's return type.2971 2972    CallExpr *STCE = SynthMsgSendStretCallExpr(MsgSendStretFlavor,2973                                               msgSendType, returnType,2974                                               ArgTypes, MsgExprs,2975                                               Exp->getMethodDecl());2976 2977    // Build sizeof(returnType)2978    UnaryExprOrTypeTraitExpr *sizeofExpr =2979       new (Context) UnaryExprOrTypeTraitExpr(UETT_SizeOf,2980                                 Context->getTrivialTypeSourceInfo(returnType),2981                                 Context->getSizeType(), SourceLocation(),2982                                 SourceLocation());2983    // (sizeof(returnType) <= 8 ? objc_msgSend(...) : objc_msgSend_stret(...))2984    // FIXME: Value of 8 is base on ppc32/x86 ABI for the most common cases.2985    // For X86 it is more complicated and some kind of target specific routine2986    // is needed to decide what to do.2987    unsigned IntSize =2988      static_cast<unsigned>(Context->getTypeSize(Context->IntTy));2989    IntegerLiteral *limit = IntegerLiteral::Create(*Context,2990                                                   llvm::APInt(IntSize, 8),2991                                                   Context->IntTy,2992                                                   SourceLocation());2993    BinaryOperator *lessThanExpr = BinaryOperator::Create(2994        *Context, sizeofExpr, limit, BO_LE, Context->IntTy, VK_PRValue,2995        OK_Ordinary, SourceLocation(), FPOptionsOverride());2996    // (sizeof(returnType) <= 8 ? objc_msgSend(...) : objc_msgSend_stret(...))2997    ConditionalOperator *CondExpr = new (Context) ConditionalOperator(2998        lessThanExpr, SourceLocation(), CE, SourceLocation(), STCE, returnType,2999        VK_PRValue, OK_Ordinary);3000    ReplacingStmt = new (Context) ParenExpr(SourceLocation(), SourceLocation(),3001                                            CondExpr);3002  }3003  // delete Exp; leak for now, see RewritePropertyOrImplicitSetter() usage for more info.3004  return ReplacingStmt;3005}3006 3007Stmt *RewriteObjC::RewriteMessageExpr(ObjCMessageExpr *Exp) {3008  Stmt *ReplacingStmt =3009      SynthMessageExpr(Exp, Exp->getBeginLoc(), Exp->getEndLoc());3010 3011  // Now do the actual rewrite.3012  ReplaceStmt(Exp, ReplacingStmt);3013 3014  // delete Exp; leak for now, see RewritePropertyOrImplicitSetter() usage for more info.3015  return ReplacingStmt;3016}3017 3018// typedef struct objc_object Protocol;3019QualType RewriteObjC::getProtocolType() {3020  if (!ProtocolTypeDecl) {3021    TypeSourceInfo *TInfo3022      = Context->getTrivialTypeSourceInfo(Context->getObjCIdType());3023    ProtocolTypeDecl = TypedefDecl::Create(*Context, TUDecl,3024                                           SourceLocation(), SourceLocation(),3025                                           &Context->Idents.get("Protocol"),3026                                           TInfo);3027  }3028  return Context->getTypeDeclType(ProtocolTypeDecl);3029}3030 3031/// RewriteObjCProtocolExpr - Rewrite a protocol expression into3032/// a synthesized/forward data reference (to the protocol's metadata).3033/// The forward references (and metadata) are generated in3034/// RewriteObjC::HandleTranslationUnit().3035Stmt *RewriteObjC::RewriteObjCProtocolExpr(ObjCProtocolExpr *Exp) {3036  std::string Name = "_OBJC_PROTOCOL_" + Exp->getProtocol()->getNameAsString();3037  IdentifierInfo *ID = &Context->Idents.get(Name);3038  VarDecl *VD = VarDecl::Create(*Context, TUDecl, SourceLocation(),3039                                SourceLocation(), ID, getProtocolType(),3040                                nullptr, SC_Extern);3041  DeclRefExpr *DRE = new (Context) DeclRefExpr(3042      *Context, VD, false, getProtocolType(), VK_LValue, SourceLocation());3043  Expr *DerefExpr = UnaryOperator::Create(3044      const_cast<ASTContext &>(*Context), DRE, UO_AddrOf,3045      Context->getPointerType(DRE->getType()), VK_PRValue, OK_Ordinary,3046      SourceLocation(), false, FPOptionsOverride());3047  CastExpr *castExpr = NoTypeInfoCStyleCastExpr(Context, DerefExpr->getType(),3048                                                CK_BitCast,3049                                                DerefExpr);3050  ReplaceStmt(Exp, castExpr);3051  ProtocolExprDecls.insert(Exp->getProtocol()->getCanonicalDecl());3052  // delete Exp; leak for now, see RewritePropertyOrImplicitSetter() usage for more info.3053  return castExpr;3054}3055 3056bool RewriteObjC::BufferContainsPPDirectives(const char *startBuf,3057                                             const char *endBuf) {3058  while (startBuf < endBuf) {3059    if (*startBuf == '#') {3060      // Skip whitespace.3061      for (++startBuf; startBuf[0] == ' ' || startBuf[0] == '\t'; ++startBuf)3062        ;3063      if (!strncmp(startBuf, "if", strlen("if")) ||3064          !strncmp(startBuf, "ifdef", strlen("ifdef")) ||3065          !strncmp(startBuf, "ifndef", strlen("ifndef")) ||3066          !strncmp(startBuf, "define", strlen("define")) ||3067          !strncmp(startBuf, "undef", strlen("undef")) ||3068          !strncmp(startBuf, "else", strlen("else")) ||3069          !strncmp(startBuf, "elif", strlen("elif")) ||3070          !strncmp(startBuf, "endif", strlen("endif")) ||3071          !strncmp(startBuf, "pragma", strlen("pragma")) ||3072          !strncmp(startBuf, "include", strlen("include")) ||3073          !strncmp(startBuf, "import", strlen("import")) ||3074          !strncmp(startBuf, "include_next", strlen("include_next")))3075        return true;3076    }3077    startBuf++;3078  }3079  return false;3080}3081 3082/// RewriteObjCInternalStruct - Rewrite one internal struct corresponding to3083/// an objective-c class with ivars.3084void RewriteObjC::RewriteObjCInternalStruct(ObjCInterfaceDecl *CDecl,3085                                               std::string &Result) {3086  assert(CDecl && "Class missing in SynthesizeObjCInternalStruct");3087  assert(CDecl->getName() != "" &&3088         "Name missing in SynthesizeObjCInternalStruct");3089  // Do not synthesize more than once.3090  if (ObjCSynthesizedStructs.count(CDecl))3091    return;3092  ObjCInterfaceDecl *RCDecl = CDecl->getSuperClass();3093  int NumIvars = CDecl->ivar_size();3094  SourceLocation LocStart = CDecl->getBeginLoc();3095  SourceLocation LocEnd = CDecl->getEndOfDefinitionLoc();3096 3097  const char *startBuf = SM->getCharacterData(LocStart);3098  const char *endBuf = SM->getCharacterData(LocEnd);3099 3100  // If no ivars and no root or if its root, directly or indirectly,3101  // have no ivars (thus not synthesized) then no need to synthesize this class.3102  if ((!CDecl->isThisDeclarationADefinition() || NumIvars == 0) &&3103      (!RCDecl || !ObjCSynthesizedStructs.count(RCDecl))) {3104    endBuf += Lexer::MeasureTokenLength(LocEnd, *SM, LangOpts);3105    ReplaceText(LocStart, endBuf-startBuf, Result);3106    return;3107  }3108 3109  // FIXME: This has potential of causing problem. If3110  // SynthesizeObjCInternalStruct is ever called recursively.3111  Result += "\nstruct ";3112  Result += CDecl->getNameAsString();3113  if (LangOpts.MicrosoftExt)3114    Result += "_IMPL";3115 3116  if (NumIvars > 0) {3117    const char *cursor = strchr(startBuf, '{');3118    assert((cursor && endBuf)3119           && "SynthesizeObjCInternalStruct - malformed @interface");3120    // If the buffer contains preprocessor directives, we do more fine-grained3121    // rewrites. This is intended to fix code that looks like (which occurs in3122    // NSURL.h, for example):3123    //3124    // #ifdef XYZ3125    // @interface Foo : NSObject3126    // #else3127    // @interface FooBar : NSObject3128    // #endif3129    // {3130    //    int i;3131    // }3132    // @end3133    //3134    // This clause is segregated to avoid breaking the common case.3135    if (BufferContainsPPDirectives(startBuf, cursor)) {3136      SourceLocation L = RCDecl ? CDecl->getSuperClassLoc() :3137                                  CDecl->getAtStartLoc();3138      const char *endHeader = SM->getCharacterData(L);3139      endHeader += Lexer::MeasureTokenLength(L, *SM, LangOpts);3140 3141      if (CDecl->protocol_begin() != CDecl->protocol_end()) {3142        // advance to the end of the referenced protocols.3143        while (endHeader < cursor && *endHeader != '>') endHeader++;3144        endHeader++;3145      }3146      // rewrite the original header3147      ReplaceText(LocStart, endHeader-startBuf, Result);3148    } else {3149      // rewrite the original header *without* disturbing the '{'3150      ReplaceText(LocStart, cursor-startBuf, Result);3151    }3152    if (RCDecl && ObjCSynthesizedStructs.count(RCDecl)) {3153      Result = "\n    struct ";3154      Result += RCDecl->getNameAsString();3155      Result += "_IMPL ";3156      Result += RCDecl->getNameAsString();3157      Result += "_IVARS;\n";3158 3159      // insert the super class structure definition.3160      SourceLocation OnePastCurly =3161        LocStart.getLocWithOffset(cursor-startBuf+1);3162      InsertText(OnePastCurly, Result);3163    }3164    cursor++; // past '{'3165 3166    // Now comment out any visibility specifiers.3167    while (cursor < endBuf) {3168      if (*cursor == '@') {3169        SourceLocation atLoc = LocStart.getLocWithOffset(cursor-startBuf);3170        // Skip whitespace.3171        for (++cursor; cursor[0] == ' ' || cursor[0] == '\t'; ++cursor)3172          /*scan*/;3173 3174        // FIXME: presence of @public, etc. inside comment results in3175        // this transformation as well, which is still correct c-code.3176        if (!strncmp(cursor, "public", strlen("public")) ||3177            !strncmp(cursor, "private", strlen("private")) ||3178            !strncmp(cursor, "package", strlen("package")) ||3179            !strncmp(cursor, "protected", strlen("protected")))3180          InsertText(atLoc, "// ");3181      }3182      // FIXME: If there are cases where '<' is used in ivar declaration part3183      // of user code, then scan the ivar list and use needToScanForQualifiers3184      // for type checking.3185      else if (*cursor == '<') {3186        SourceLocation atLoc = LocStart.getLocWithOffset(cursor-startBuf);3187        InsertText(atLoc, "/* ");3188        cursor = strchr(cursor, '>');3189        cursor++;3190        atLoc = LocStart.getLocWithOffset(cursor-startBuf);3191        InsertText(atLoc, " */");3192      } else if (*cursor == '^') { // rewrite block specifier.3193        SourceLocation caretLoc = LocStart.getLocWithOffset(cursor-startBuf);3194        ReplaceText(caretLoc, 1, "*");3195      }3196      cursor++;3197    }3198    // Don't forget to add a ';'!!3199    InsertText(LocEnd.getLocWithOffset(1), ";");3200  } else { // we don't have any instance variables - insert super struct.3201    endBuf += Lexer::MeasureTokenLength(LocEnd, *SM, LangOpts);3202    Result += " {\n    struct ";3203    Result += RCDecl->getNameAsString();3204    Result += "_IMPL ";3205    Result += RCDecl->getNameAsString();3206    Result += "_IVARS;\n};\n";3207    ReplaceText(LocStart, endBuf-startBuf, Result);3208  }3209  // Mark this struct as having been generated.3210  if (!ObjCSynthesizedStructs.insert(CDecl).second)3211    llvm_unreachable("struct already synthesize- SynthesizeObjCInternalStruct");3212}3213 3214//===----------------------------------------------------------------------===//3215// Meta Data Emission3216//===----------------------------------------------------------------------===//3217 3218/// RewriteImplementations - This routine rewrites all method implementations3219/// and emits meta-data.3220 3221void RewriteObjC::RewriteImplementations() {3222  int ClsDefCount = ClassImplementation.size();3223  int CatDefCount = CategoryImplementation.size();3224 3225  // Rewrite implemented methods3226  for (int i = 0; i < ClsDefCount; i++)3227    RewriteImplementationDecl(ClassImplementation[i]);3228 3229  for (int i = 0; i < CatDefCount; i++)3230    RewriteImplementationDecl(CategoryImplementation[i]);3231}3232 3233void RewriteObjC::RewriteByRefString(std::string &ResultStr,3234                                     const std::string &Name,3235                                     ValueDecl *VD, bool def) {3236  assert(BlockByRefDeclNo.count(VD) &&3237         "RewriteByRefString: ByRef decl missing");3238  if (def)3239    ResultStr += "struct ";3240  ResultStr += "__Block_byref_" + Name +3241    "_" + utostr(BlockByRefDeclNo[VD]) ;3242}3243 3244static bool HasLocalVariableExternalStorage(ValueDecl *VD) {3245  if (VarDecl *Var = dyn_cast<VarDecl>(VD))3246    return (Var->isFunctionOrMethodVarDecl() && !Var->hasLocalStorage());3247  return false;3248}3249 3250std::string RewriteObjC::SynthesizeBlockFunc(BlockExpr *CE, int i,3251                                                   StringRef funcName,3252                                                   std::string Tag) {3253  const FunctionType *AFT = CE->getFunctionType();3254  QualType RT = AFT->getReturnType();3255  std::string StructRef = "struct " + Tag;3256  std::string S = "static " + RT.getAsString(Context->getPrintingPolicy()) + " __" +3257                  funcName.str() + "_" + "block_func_" + utostr(i);3258 3259  BlockDecl *BD = CE->getBlockDecl();3260 3261  if (isa<FunctionNoProtoType>(AFT)) {3262    // No user-supplied arguments. Still need to pass in a pointer to the3263    // block (to reference imported block decl refs).3264    S += "(" + StructRef + " *__cself)";3265  } else if (BD->param_empty()) {3266    S += "(" + StructRef + " *__cself)";3267  } else {3268    const FunctionProtoType *FT = cast<FunctionProtoType>(AFT);3269    assert(FT && "SynthesizeBlockFunc: No function proto");3270    S += '(';3271    // first add the implicit argument.3272    S += StructRef + " *__cself, ";3273    std::string ParamStr;3274    for (BlockDecl::param_iterator AI = BD->param_begin(),3275         E = BD->param_end(); AI != E; ++AI) {3276      if (AI != BD->param_begin()) S += ", ";3277      ParamStr = (*AI)->getNameAsString();3278      QualType QT = (*AI)->getType();3279      (void)convertBlockPointerToFunctionPointer(QT);3280      QT.getAsStringInternal(ParamStr, Context->getPrintingPolicy());3281      S += ParamStr;3282    }3283    if (FT->isVariadic()) {3284      if (!BD->param_empty()) S += ", ";3285      S += "...";3286    }3287    S += ')';3288  }3289  S += " {\n";3290 3291  // Create local declarations to avoid rewriting all closure decl ref exprs.3292  // First, emit a declaration for all "by ref" decls.3293  for (auto I = BlockByRefDecls.begin(), E = BlockByRefDecls.end(); I != E;3294       ++I) {3295    S += "  ";3296    std::string Name = (*I)->getNameAsString();3297    std::string TypeString;3298    RewriteByRefString(TypeString, Name, (*I));3299    TypeString += " *";3300    Name = TypeString + Name;3301    S += Name + " = __cself->" + (*I)->getNameAsString() + "; // bound by ref\n";3302  }3303  // Next, emit a declaration for all "by copy" declarations.3304  for (auto I = BlockByCopyDecls.begin(), E = BlockByCopyDecls.end(); I != E;3305       ++I) {3306    S += "  ";3307    // Handle nested closure invocation. For example:3308    //3309    //   void (^myImportedClosure)(void);3310    //   myImportedClosure  = ^(void) { setGlobalInt(x + y); };3311    //3312    //   void (^anotherClosure)(void);3313    //   anotherClosure = ^(void) {3314    //     myImportedClosure(); // import and invoke the closure3315    //   };3316    //3317    if (isTopLevelBlockPointerType((*I)->getType())) {3318      RewriteBlockPointerTypeVariable(S, (*I));3319      S += " = (";3320      RewriteBlockPointerType(S, (*I)->getType());3321      S += ")";3322      S += "__cself->" + (*I)->getNameAsString() + "; // bound by copy\n";3323    }3324    else {3325      std::string Name = (*I)->getNameAsString();3326      QualType QT = (*I)->getType();3327      if (HasLocalVariableExternalStorage(*I))3328        QT = Context->getPointerType(QT);3329      QT.getAsStringInternal(Name, Context->getPrintingPolicy());3330      S += Name + " = __cself->" +3331                              (*I)->getNameAsString() + "; // bound by copy\n";3332    }3333  }3334  std::string RewrittenStr = RewrittenBlockExprs[CE];3335  const char *cstr = RewrittenStr.c_str();3336  while (*cstr++ != '{') ;3337  S += cstr;3338  S += "\n";3339  return S;3340}3341 3342std::string RewriteObjC::SynthesizeBlockHelperFuncs(BlockExpr *CE, int i,3343                                                   StringRef funcName,3344                                                   std::string Tag) {3345  std::string StructRef = "struct " + Tag;3346  std::string S = "static void __";3347 3348  S += funcName;3349  S += "_block_copy_" + utostr(i);3350  S += "(" + StructRef;3351  S += "*dst, " + StructRef;3352  S += "*src) {";3353  for (ValueDecl *VD : ImportedBlockDecls) {3354    S += "_Block_object_assign((void*)&dst->";3355    S += VD->getNameAsString();3356    S += ", (void*)src->";3357    S += VD->getNameAsString();3358    if (BlockByRefDecls.contains(VD))3359      S += ", " + utostr(BLOCK_FIELD_IS_BYREF) + "/*BLOCK_FIELD_IS_BYREF*/);";3360    else if (VD->getType()->isBlockPointerType())3361      S += ", " + utostr(BLOCK_FIELD_IS_BLOCK) + "/*BLOCK_FIELD_IS_BLOCK*/);";3362    else3363      S += ", " + utostr(BLOCK_FIELD_IS_OBJECT) + "/*BLOCK_FIELD_IS_OBJECT*/);";3364  }3365  S += "}\n";3366 3367  S += "\nstatic void __";3368  S += funcName;3369  S += "_block_dispose_" + utostr(i);3370  S += "(" + StructRef;3371  S += "*src) {";3372  for (ValueDecl *VD : ImportedBlockDecls) {3373    S += "_Block_object_dispose((void*)src->";3374    S += VD->getNameAsString();3375    if (BlockByRefDecls.contains(VD))3376      S += ", " + utostr(BLOCK_FIELD_IS_BYREF) + "/*BLOCK_FIELD_IS_BYREF*/);";3377    else if (VD->getType()->isBlockPointerType())3378      S += ", " + utostr(BLOCK_FIELD_IS_BLOCK) + "/*BLOCK_FIELD_IS_BLOCK*/);";3379    else3380      S += ", " + utostr(BLOCK_FIELD_IS_OBJECT) + "/*BLOCK_FIELD_IS_OBJECT*/);";3381  }3382  S += "}\n";3383  return S;3384}3385 3386std::string RewriteObjC::SynthesizeBlockImpl(BlockExpr *CE, std::string Tag,3387                                             std::string Desc) {3388  std::string S = "\nstruct " + Tag;3389  std::string Constructor = "  " + Tag;3390 3391  S += " {\n  struct __block_impl impl;\n";3392  S += "  struct " + Desc;3393  S += "* Desc;\n";3394 3395  Constructor += "(void *fp, "; // Invoke function pointer.3396  Constructor += "struct " + Desc; // Descriptor pointer.3397  Constructor += " *desc";3398 3399  if (BlockDeclRefs.size()) {3400    // Output all "by copy" declarations.3401    for (auto I = BlockByCopyDecls.begin(), E = BlockByCopyDecls.end(); I != E;3402         ++I) {3403      S += "  ";3404      std::string FieldName = (*I)->getNameAsString();3405      std::string ArgName = "_" + FieldName;3406      // Handle nested closure invocation. For example:3407      //3408      //   void (^myImportedBlock)(void);3409      //   myImportedBlock  = ^(void) { setGlobalInt(x + y); };3410      //3411      //   void (^anotherBlock)(void);3412      //   anotherBlock = ^(void) {3413      //     myImportedBlock(); // import and invoke the closure3414      //   };3415      //3416      if (isTopLevelBlockPointerType((*I)->getType())) {3417        S += "struct __block_impl *";3418        Constructor += ", void *" + ArgName;3419      } else {3420        QualType QT = (*I)->getType();3421        if (HasLocalVariableExternalStorage(*I))3422          QT = Context->getPointerType(QT);3423        QT.getAsStringInternal(FieldName, Context->getPrintingPolicy());3424        QT.getAsStringInternal(ArgName, Context->getPrintingPolicy());3425        Constructor += ", " + ArgName;3426      }3427      S += FieldName + ";\n";3428    }3429    // Output all "by ref" declarations.3430    for (auto I = BlockByRefDecls.begin(), E = BlockByRefDecls.end(); I != E;3431         ++I) {3432      S += "  ";3433      std::string FieldName = (*I)->getNameAsString();3434      std::string ArgName = "_" + FieldName;3435      {3436        std::string TypeString;3437        RewriteByRefString(TypeString, FieldName, (*I));3438        TypeString += " *";3439        FieldName = TypeString + FieldName;3440        ArgName = TypeString + ArgName;3441        Constructor += ", " + ArgName;3442      }3443      S += FieldName + "; // by ref\n";3444    }3445    // Finish writing the constructor.3446    Constructor += ", int flags=0)";3447    // Initialize all "by copy" arguments.3448    bool firsTime = true;3449    for (auto I = BlockByCopyDecls.begin(), E = BlockByCopyDecls.end(); I != E;3450         ++I) {3451      std::string Name = (*I)->getNameAsString();3452        if (firsTime) {3453          Constructor += " : ";3454          firsTime = false;3455        }3456        else3457          Constructor += ", ";3458        if (isTopLevelBlockPointerType((*I)->getType()))3459          Constructor += Name + "((struct __block_impl *)_" + Name + ")";3460        else3461          Constructor += Name + "(_" + Name + ")";3462    }3463    // Initialize all "by ref" arguments.3464    for (auto I = BlockByRefDecls.begin(), E = BlockByRefDecls.end(); I != E;3465         ++I) {3466      std::string Name = (*I)->getNameAsString();3467      if (firsTime) {3468        Constructor += " : ";3469        firsTime = false;3470      }3471      else3472        Constructor += ", ";3473      Constructor += Name + "(_" + Name + "->__forwarding)";3474    }3475 3476    Constructor += " {\n";3477    if (GlobalVarDecl)3478      Constructor += "    impl.isa = &_NSConcreteGlobalBlock;\n";3479    else3480      Constructor += "    impl.isa = &_NSConcreteStackBlock;\n";3481    Constructor += "    impl.Flags = flags;\n    impl.FuncPtr = fp;\n";3482 3483    Constructor += "    Desc = desc;\n";3484  } else {3485    // Finish writing the constructor.3486    Constructor += ", int flags=0) {\n";3487    if (GlobalVarDecl)3488      Constructor += "    impl.isa = &_NSConcreteGlobalBlock;\n";3489    else3490      Constructor += "    impl.isa = &_NSConcreteStackBlock;\n";3491    Constructor += "    impl.Flags = flags;\n    impl.FuncPtr = fp;\n";3492    Constructor += "    Desc = desc;\n";3493  }3494  Constructor += "  ";3495  Constructor += "}\n";3496  S += Constructor;3497  S += "};\n";3498  return S;3499}3500 3501std::string RewriteObjC::SynthesizeBlockDescriptor(std::string DescTag,3502                                                   std::string ImplTag, int i,3503                                                   StringRef FunName,3504                                                   unsigned hasCopy) {3505  std::string S = "\nstatic struct " + DescTag;3506 3507  S += " {\n  unsigned long reserved;\n";3508  S += "  unsigned long Block_size;\n";3509  if (hasCopy) {3510    S += "  void (*copy)(struct ";3511    S += ImplTag; S += "*, struct ";3512    S += ImplTag; S += "*);\n";3513 3514    S += "  void (*dispose)(struct ";3515    S += ImplTag; S += "*);\n";3516  }3517  S += "} ";3518 3519  S += DescTag + "_DATA = { 0, sizeof(struct ";3520  S += ImplTag + ")";3521  if (hasCopy) {3522    S += ", __" + FunName.str() + "_block_copy_" + utostr(i);3523    S += ", __" + FunName.str() + "_block_dispose_" + utostr(i);3524  }3525  S += "};\n";3526  return S;3527}3528 3529void RewriteObjC::SynthesizeBlockLiterals(SourceLocation FunLocStart,3530                                          StringRef FunName) {3531  // Insert declaration for the function in which block literal is used.3532  if (CurFunctionDeclToDeclareForBlock && !Blocks.empty())3533    RewriteBlockLiteralFunctionDecl(CurFunctionDeclToDeclareForBlock);3534  bool RewriteSC = (GlobalVarDecl &&3535                    !Blocks.empty() &&3536                    GlobalVarDecl->getStorageClass() == SC_Static &&3537                    GlobalVarDecl->getType().getCVRQualifiers());3538  if (RewriteSC) {3539    std::string SC(" void __");3540    SC += GlobalVarDecl->getNameAsString();3541    SC += "() {}";3542    InsertText(FunLocStart, SC);3543  }3544 3545  // Insert closures that were part of the function.3546  for (unsigned i = 0, count=0; i < Blocks.size(); i++) {3547    CollectBlockDeclRefInfo(Blocks[i]);3548    // Need to copy-in the inner copied-in variables not actually used in this3549    // block.3550    for (int j = 0; j < InnerDeclRefsCount[i]; j++) {3551      DeclRefExpr *Exp = InnerDeclRefs[count++];3552      ValueDecl *VD = Exp->getDecl();3553      BlockDeclRefs.push_back(Exp);3554      if (VD->hasAttr<BlocksAttr>())3555        BlockByRefDecls.insert(VD);3556      else3557        BlockByCopyDecls.insert(VD);3558      // imported objects in the inner blocks not used in the outer3559      // blocks must be copied/disposed in the outer block as well.3560      if (VD->hasAttr<BlocksAttr>() ||3561          VD->getType()->isObjCObjectPointerType() ||3562          VD->getType()->isBlockPointerType())3563        ImportedBlockDecls.insert(VD);3564    }3565 3566    std::string ImplTag = "__" + FunName.str() + "_block_impl_" + utostr(i);3567    std::string DescTag = "__" + FunName.str() + "_block_desc_" + utostr(i);3568 3569    std::string CI = SynthesizeBlockImpl(Blocks[i], ImplTag, DescTag);3570 3571    InsertText(FunLocStart, CI);3572 3573    std::string CF = SynthesizeBlockFunc(Blocks[i], i, FunName, ImplTag);3574 3575    InsertText(FunLocStart, CF);3576 3577    if (ImportedBlockDecls.size()) {3578      std::string HF = SynthesizeBlockHelperFuncs(Blocks[i], i, FunName, ImplTag);3579      InsertText(FunLocStart, HF);3580    }3581    std::string BD = SynthesizeBlockDescriptor(DescTag, ImplTag, i, FunName,3582                                               ImportedBlockDecls.size() > 0);3583    InsertText(FunLocStart, BD);3584 3585    BlockDeclRefs.clear();3586    BlockByRefDecls.clear();3587    BlockByCopyDecls.clear();3588    ImportedBlockDecls.clear();3589  }3590  if (RewriteSC) {3591    // Must insert any 'const/volatile/static here. Since it has been3592    // removed as result of rewriting of block literals.3593    std::string SC;3594    if (GlobalVarDecl->getStorageClass() == SC_Static)3595      SC = "static ";3596    if (GlobalVarDecl->getType().isConstQualified())3597      SC += "const ";3598    if (GlobalVarDecl->getType().isVolatileQualified())3599      SC += "volatile ";3600    if (GlobalVarDecl->getType().isRestrictQualified())3601      SC += "restrict ";3602    InsertText(FunLocStart, SC);3603  }3604 3605  Blocks.clear();3606  InnerDeclRefsCount.clear();3607  InnerDeclRefs.clear();3608  RewrittenBlockExprs.clear();3609}3610 3611void RewriteObjC::InsertBlockLiteralsWithinFunction(FunctionDecl *FD) {3612  SourceLocation FunLocStart = FD->getTypeSpecStartLoc();3613  StringRef FuncName = FD->getName();3614 3615  SynthesizeBlockLiterals(FunLocStart, FuncName);3616}3617 3618static void BuildUniqueMethodName(std::string &Name,3619                                  ObjCMethodDecl *MD) {3620  ObjCInterfaceDecl *IFace = MD->getClassInterface();3621  Name = std::string(IFace->getName());3622  Name += "__" + MD->getSelector().getAsString();3623  // Convert colons to underscores.3624  std::string::size_type loc = 0;3625  while ((loc = Name.find(':', loc)) != std::string::npos)3626    Name.replace(loc, 1, "_");3627}3628 3629void RewriteObjC::InsertBlockLiteralsWithinMethod(ObjCMethodDecl *MD) {3630  // fprintf(stderr,"In InsertBlockLiteralsWitinMethod\n");3631  // SourceLocation FunLocStart = MD->getBeginLoc();3632  SourceLocation FunLocStart = MD->getBeginLoc();3633  std::string FuncName;3634  BuildUniqueMethodName(FuncName, MD);3635  SynthesizeBlockLiterals(FunLocStart, FuncName);3636}3637 3638void RewriteObjC::GetBlockDeclRefExprs(Stmt *S) {3639  for (Stmt *SubStmt : S->children())3640    if (SubStmt) {3641      if (BlockExpr *CBE = dyn_cast<BlockExpr>(SubStmt))3642        GetBlockDeclRefExprs(CBE->getBody());3643      else3644        GetBlockDeclRefExprs(SubStmt);3645    }3646  // Handle specific things.3647  if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(S))3648    if (DRE->refersToEnclosingVariableOrCapture() ||3649        HasLocalVariableExternalStorage(DRE->getDecl()))3650      // FIXME: Handle enums.3651      BlockDeclRefs.push_back(DRE);3652}3653 3654void RewriteObjC::GetInnerBlockDeclRefExprs(Stmt *S,3655                SmallVectorImpl<DeclRefExpr *> &InnerBlockDeclRefs,3656                llvm::SmallPtrSetImpl<const DeclContext *> &InnerContexts) {3657  for (Stmt *SubStmt : S->children())3658    if (SubStmt) {3659      if (BlockExpr *CBE = dyn_cast<BlockExpr>(SubStmt)) {3660        InnerContexts.insert(cast<DeclContext>(CBE->getBlockDecl()));3661        GetInnerBlockDeclRefExprs(CBE->getBody(),3662                                  InnerBlockDeclRefs,3663                                  InnerContexts);3664      }3665      else3666        GetInnerBlockDeclRefExprs(SubStmt, InnerBlockDeclRefs, InnerContexts);3667    }3668  // Handle specific things.3669  if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(S)) {3670    if (DRE->refersToEnclosingVariableOrCapture() ||3671        HasLocalVariableExternalStorage(DRE->getDecl())) {3672      if (!InnerContexts.count(DRE->getDecl()->getDeclContext()))3673        InnerBlockDeclRefs.push_back(DRE);3674      if (VarDecl *Var = cast<VarDecl>(DRE->getDecl()))3675        if (Var->isFunctionOrMethodVarDecl())3676          ImportedLocalExternalDecls.insert(Var);3677    }3678  }3679}3680 3681/// convertFunctionTypeOfBlocks - This routine converts a function type3682/// whose result type may be a block pointer or whose argument type(s)3683/// might be block pointers to an equivalent function type replacing3684/// all block pointers to function pointers.3685QualType RewriteObjC::convertFunctionTypeOfBlocks(const FunctionType *FT) {3686  const FunctionProtoType *FTP = dyn_cast<FunctionProtoType>(FT);3687  // FTP will be null for closures that don't take arguments.3688  // Generate a funky cast.3689  SmallVector<QualType, 8> ArgTypes;3690  QualType Res = FT->getReturnType();3691  bool HasBlockType = convertBlockPointerToFunctionPointer(Res);3692 3693  if (FTP) {3694    for (auto &I : FTP->param_types()) {3695      QualType t = I;3696      // Make sure we convert "t (^)(...)" to "t (*)(...)".3697      if (convertBlockPointerToFunctionPointer(t))3698        HasBlockType = true;3699      ArgTypes.push_back(t);3700    }3701  }3702  QualType FuncType;3703  // FIXME. Does this work if block takes no argument but has a return type3704  // which is of block type?3705  if (HasBlockType)3706    FuncType = getSimpleFunctionType(Res, ArgTypes);3707  else FuncType = QualType(FT, 0);3708  return FuncType;3709}3710 3711Stmt *RewriteObjC::SynthesizeBlockCall(CallExpr *Exp, const Expr *BlockExp) {3712  // Navigate to relevant type information.3713  const BlockPointerType *CPT = nullptr;3714 3715  if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(BlockExp)) {3716    CPT = DRE->getType()->getAs<BlockPointerType>();3717  } else if (const MemberExpr *MExpr = dyn_cast<MemberExpr>(BlockExp)) {3718    CPT = MExpr->getType()->getAs<BlockPointerType>();3719  }3720  else if (const ParenExpr *PRE = dyn_cast<ParenExpr>(BlockExp)) {3721    return SynthesizeBlockCall(Exp, PRE->getSubExpr());3722  }3723  else if (const ImplicitCastExpr *IEXPR = dyn_cast<ImplicitCastExpr>(BlockExp))3724    CPT = IEXPR->getType()->getAs<BlockPointerType>();3725  else if (const ConditionalOperator *CEXPR =3726            dyn_cast<ConditionalOperator>(BlockExp)) {3727    Expr *LHSExp = CEXPR->getLHS();3728    Stmt *LHSStmt = SynthesizeBlockCall(Exp, LHSExp);3729    Expr *RHSExp = CEXPR->getRHS();3730    Stmt *RHSStmt = SynthesizeBlockCall(Exp, RHSExp);3731    Expr *CONDExp = CEXPR->getCond();3732    ConditionalOperator *CondExpr = new (Context) ConditionalOperator(3733        CONDExp, SourceLocation(), cast<Expr>(LHSStmt), SourceLocation(),3734        cast<Expr>(RHSStmt), Exp->getType(), VK_PRValue, OK_Ordinary);3735    return CondExpr;3736  } else if (const ObjCIvarRefExpr *IRE = dyn_cast<ObjCIvarRefExpr>(BlockExp)) {3737    CPT = IRE->getType()->getAs<BlockPointerType>();3738  } else if (const PseudoObjectExpr *POE3739               = dyn_cast<PseudoObjectExpr>(BlockExp)) {3740    CPT = POE->getType()->castAs<BlockPointerType>();3741  } else {3742    assert(false && "RewriteBlockClass: Bad type");3743  }3744  assert(CPT && "RewriteBlockClass: Bad type");3745  const FunctionType *FT = CPT->getPointeeType()->getAs<FunctionType>();3746  assert(FT && "RewriteBlockClass: Bad type");3747  const FunctionProtoType *FTP = dyn_cast<FunctionProtoType>(FT);3748  // FTP will be null for closures that don't take arguments.3749 3750  RecordDecl *RD = RecordDecl::Create(*Context, TagTypeKind::Struct, TUDecl,3751                                      SourceLocation(), SourceLocation(),3752                                      &Context->Idents.get("__block_impl"));3753  QualType PtrBlock = Context->getPointerType(Context->getCanonicalTagType(RD));3754 3755  // Generate a funky cast.3756  SmallVector<QualType, 8> ArgTypes;3757 3758  // Push the block argument type.3759  ArgTypes.push_back(PtrBlock);3760  if (FTP) {3761    for (auto &I : FTP->param_types()) {3762      QualType t = I;3763      // Make sure we convert "t (^)(...)" to "t (*)(...)".3764      if (!convertBlockPointerToFunctionPointer(t))3765        convertToUnqualifiedObjCType(t);3766      ArgTypes.push_back(t);3767    }3768  }3769  // Now do the pointer to function cast.3770  QualType PtrToFuncCastType = getSimpleFunctionType(Exp->getType(), ArgTypes);3771 3772  PtrToFuncCastType = Context->getPointerType(PtrToFuncCastType);3773 3774  CastExpr *BlkCast = NoTypeInfoCStyleCastExpr(Context, PtrBlock,3775                                               CK_BitCast,3776                                               const_cast<Expr*>(BlockExp));3777  // Don't forget the parens to enforce the proper binding.3778  ParenExpr *PE = new (Context) ParenExpr(SourceLocation(), SourceLocation(),3779                                          BlkCast);3780  //PE->dump();3781 3782  FieldDecl *FD = FieldDecl::Create(*Context, nullptr, SourceLocation(),3783                                    SourceLocation(),3784                                    &Context->Idents.get("FuncPtr"),3785                                    Context->VoidPtrTy, nullptr,3786                                    /*BitWidth=*/nullptr, /*Mutable=*/true,3787                                    ICIS_NoInit);3788  MemberExpr *ME = MemberExpr::CreateImplicit(3789      *Context, PE, true, FD, FD->getType(), VK_LValue, OK_Ordinary);3790 3791  CastExpr *FunkCast = NoTypeInfoCStyleCastExpr(Context, PtrToFuncCastType,3792                                                CK_BitCast, ME);3793  PE = new (Context) ParenExpr(SourceLocation(), SourceLocation(), FunkCast);3794 3795  SmallVector<Expr*, 8> BlkExprs;3796  // Add the implicit argument.3797  BlkExprs.push_back(BlkCast);3798  // Add the user arguments.3799  for (CallExpr::arg_iterator I = Exp->arg_begin(),3800       E = Exp->arg_end(); I != E; ++I) {3801    BlkExprs.push_back(*I);3802  }3803  CallExpr *CE =3804      CallExpr::Create(*Context, PE, BlkExprs, Exp->getType(), VK_PRValue,3805                       SourceLocation(), FPOptionsOverride());3806  return CE;3807}3808 3809// We need to return the rewritten expression to handle cases where the3810// BlockDeclRefExpr is embedded in another expression being rewritten.3811// For example:3812//3813// int main() {3814//    __block Foo *f;3815//    __block int i;3816//3817//    void (^myblock)() = ^() {3818//        [f test]; // f is a BlockDeclRefExpr embedded in a message (which is being rewritten).3819//        i = 77;3820//    };3821//}3822Stmt *RewriteObjC::RewriteBlockDeclRefExpr(DeclRefExpr *DeclRefExp) {3823  // Rewrite the byref variable into BYREFVAR->__forwarding->BYREFVAR3824  // for each DeclRefExp where BYREFVAR is name of the variable.3825  ValueDecl *VD = DeclRefExp->getDecl();3826  bool isArrow = DeclRefExp->refersToEnclosingVariableOrCapture() ||3827                 HasLocalVariableExternalStorage(DeclRefExp->getDecl());3828 3829  FieldDecl *FD = FieldDecl::Create(*Context, nullptr, SourceLocation(),3830                                    SourceLocation(),3831                                    &Context->Idents.get("__forwarding"),3832                                    Context->VoidPtrTy, nullptr,3833                                    /*BitWidth=*/nullptr, /*Mutable=*/true,3834                                    ICIS_NoInit);3835  MemberExpr *ME =3836      MemberExpr::CreateImplicit(*Context, DeclRefExp, isArrow, FD,3837                                 FD->getType(), VK_LValue, OK_Ordinary);3838 3839  StringRef Name = VD->getName();3840  FD = FieldDecl::Create(*Context, nullptr, SourceLocation(), SourceLocation(),3841                         &Context->Idents.get(Name),3842                         Context->VoidPtrTy, nullptr,3843                         /*BitWidth=*/nullptr, /*Mutable=*/true,3844                         ICIS_NoInit);3845  ME = MemberExpr::CreateImplicit(*Context, ME, true, FD, DeclRefExp->getType(),3846                                  VK_LValue, OK_Ordinary);3847 3848  // Need parens to enforce precedence.3849  ParenExpr *PE = new (Context) ParenExpr(DeclRefExp->getExprLoc(),3850                                          DeclRefExp->getExprLoc(),3851                                          ME);3852  ReplaceStmt(DeclRefExp, PE);3853  return PE;3854}3855 3856// Rewrites the imported local variable V with external storage3857// (static, extern, etc.) as *V3858//3859Stmt *RewriteObjC::RewriteLocalVariableExternalStorage(DeclRefExpr *DRE) {3860  ValueDecl *VD = DRE->getDecl();3861  if (VarDecl *Var = dyn_cast<VarDecl>(VD))3862    if (!ImportedLocalExternalDecls.count(Var))3863      return DRE;3864  Expr *Exp = UnaryOperator::Create(3865      const_cast<ASTContext &>(*Context), DRE, UO_Deref, DRE->getType(),3866      VK_LValue, OK_Ordinary, DRE->getLocation(), false, FPOptionsOverride());3867  // Need parens to enforce precedence.3868  ParenExpr *PE = new (Context) ParenExpr(SourceLocation(), SourceLocation(),3869                                          Exp);3870  ReplaceStmt(DRE, PE);3871  return PE;3872}3873 3874void RewriteObjC::RewriteCastExpr(CStyleCastExpr *CE) {3875  SourceLocation LocStart = CE->getLParenLoc();3876  SourceLocation LocEnd = CE->getRParenLoc();3877 3878  // Need to avoid trying to rewrite synthesized casts.3879  if (LocStart.isInvalid())3880    return;3881  // Need to avoid trying to rewrite casts contained in macros.3882  if (!Rewriter::isRewritable(LocStart) || !Rewriter::isRewritable(LocEnd))3883    return;3884 3885  const char *startBuf = SM->getCharacterData(LocStart);3886  const char *endBuf = SM->getCharacterData(LocEnd);3887  QualType QT = CE->getType();3888  const Type* TypePtr = QT->getAs<Type>();3889  if (isa<TypeOfExprType>(TypePtr)) {3890    const TypeOfExprType *TypeOfExprTypePtr = cast<TypeOfExprType>(TypePtr);3891    QT = TypeOfExprTypePtr->getUnderlyingExpr()->getType();3892    std::string TypeAsString = "(";3893    RewriteBlockPointerType(TypeAsString, QT);3894    TypeAsString += ")";3895    ReplaceText(LocStart, endBuf-startBuf+1, TypeAsString);3896    return;3897  }3898  // advance the location to startArgList.3899  const char *argPtr = startBuf;3900 3901  while (*argPtr++ && (argPtr < endBuf)) {3902    switch (*argPtr) {3903    case '^':3904      // Replace the '^' with '*'.3905      LocStart = LocStart.getLocWithOffset(argPtr-startBuf);3906      ReplaceText(LocStart, 1, "*");3907      break;3908    }3909  }3910}3911 3912void RewriteObjC::RewriteBlockPointerFunctionArgs(FunctionDecl *FD) {3913  SourceLocation DeclLoc = FD->getLocation();3914  unsigned parenCount = 0;3915 3916  // We have 1 or more arguments that have closure pointers.3917  const char *startBuf = SM->getCharacterData(DeclLoc);3918  const char *startArgList = strchr(startBuf, '(');3919 3920  assert((*startArgList == '(') && "Rewriter fuzzy parser confused");3921 3922  parenCount++;3923  // advance the location to startArgList.3924  DeclLoc = DeclLoc.getLocWithOffset(startArgList-startBuf);3925  assert((DeclLoc.isValid()) && "Invalid DeclLoc");3926 3927  const char *argPtr = startArgList;3928 3929  while (*argPtr++ && parenCount) {3930    switch (*argPtr) {3931    case '^':3932      // Replace the '^' with '*'.3933      DeclLoc = DeclLoc.getLocWithOffset(argPtr-startArgList);3934      ReplaceText(DeclLoc, 1, "*");3935      break;3936    case '(':3937      parenCount++;3938      break;3939    case ')':3940      parenCount--;3941      break;3942    }3943  }3944}3945 3946bool RewriteObjC::PointerTypeTakesAnyBlockArguments(QualType QT) {3947  const FunctionProtoType *FTP;3948  const PointerType *PT = QT->getAs<PointerType>();3949  if (PT) {3950    FTP = PT->getPointeeType()->getAs<FunctionProtoType>();3951  } else {3952    const BlockPointerType *BPT = QT->getAs<BlockPointerType>();3953    assert(BPT && "BlockPointerTypeTakeAnyBlockArguments(): not a block pointer type");3954    FTP = BPT->getPointeeType()->getAs<FunctionProtoType>();3955  }3956  if (FTP) {3957    for (const auto &I : FTP->param_types())3958      if (isTopLevelBlockPointerType(I))3959        return true;3960  }3961  return false;3962}3963 3964bool RewriteObjC::PointerTypeTakesAnyObjCQualifiedType(QualType QT) {3965  const FunctionProtoType *FTP;3966  const PointerType *PT = QT->getAs<PointerType>();3967  if (PT) {3968    FTP = PT->getPointeeType()->getAs<FunctionProtoType>();3969  } else {3970    const BlockPointerType *BPT = QT->getAs<BlockPointerType>();3971    assert(BPT && "BlockPointerTypeTakeAnyBlockArguments(): not a block pointer type");3972    FTP = BPT->getPointeeType()->getAs<FunctionProtoType>();3973  }3974  if (FTP) {3975    for (const auto &I : FTP->param_types()) {3976      if (I->isObjCQualifiedIdType())3977        return true;3978      if (I->isObjCObjectPointerType() &&3979          I->getPointeeType()->isObjCQualifiedInterfaceType())3980        return true;3981    }3982 3983  }3984  return false;3985}3986 3987void RewriteObjC::GetExtentOfArgList(const char *Name, const char *&LParen,3988                                     const char *&RParen) {3989  const char *argPtr = strchr(Name, '(');3990  assert((*argPtr == '(') && "Rewriter fuzzy parser confused");3991 3992  LParen = argPtr; // output the start.3993  argPtr++; // skip past the left paren.3994  unsigned parenCount = 1;3995 3996  while (*argPtr && parenCount) {3997    switch (*argPtr) {3998    case '(': parenCount++; break;3999    case ')': parenCount--; break;4000    default: break;4001    }4002    if (parenCount) argPtr++;4003  }4004  assert((*argPtr == ')') && "Rewriter fuzzy parser confused");4005  RParen = argPtr; // output the end4006}4007 4008void RewriteObjC::RewriteBlockPointerDecl(NamedDecl *ND) {4009  if (FunctionDecl *FD = dyn_cast<FunctionDecl>(ND)) {4010    RewriteBlockPointerFunctionArgs(FD);4011    return;4012  }4013  // Handle Variables and Typedefs.4014  SourceLocation DeclLoc = ND->getLocation();4015  QualType DeclT;4016  if (VarDecl *VD = dyn_cast<VarDecl>(ND))4017    DeclT = VD->getType();4018  else if (TypedefNameDecl *TDD = dyn_cast<TypedefNameDecl>(ND))4019    DeclT = TDD->getUnderlyingType();4020  else if (FieldDecl *FD = dyn_cast<FieldDecl>(ND))4021    DeclT = FD->getType();4022  else4023    llvm_unreachable("RewriteBlockPointerDecl(): Decl type not yet handled");4024 4025  const char *startBuf = SM->getCharacterData(DeclLoc);4026  const char *endBuf = startBuf;4027  // scan backward (from the decl location) for the end of the previous decl.4028  while (*startBuf != '^' && *startBuf != ';' && startBuf != MainFileStart)4029    startBuf--;4030  SourceLocation Start = DeclLoc.getLocWithOffset(startBuf-endBuf);4031  std::string buf;4032  unsigned OrigLength=0;4033  // *startBuf != '^' if we are dealing with a pointer to function that4034  // may take block argument types (which will be handled below).4035  if (*startBuf == '^') {4036    // Replace the '^' with '*', computing a negative offset.4037    buf = '*';4038    startBuf++;4039    OrigLength++;4040  }4041  while (*startBuf != ')') {4042    buf += *startBuf;4043    startBuf++;4044    OrigLength++;4045  }4046  buf += ')';4047  OrigLength++;4048 4049  if (PointerTypeTakesAnyBlockArguments(DeclT) ||4050      PointerTypeTakesAnyObjCQualifiedType(DeclT)) {4051    // Replace the '^' with '*' for arguments.4052    // Replace id<P> with id/*<>*/4053    DeclLoc = ND->getLocation();4054    startBuf = SM->getCharacterData(DeclLoc);4055    const char *argListBegin, *argListEnd;4056    GetExtentOfArgList(startBuf, argListBegin, argListEnd);4057    while (argListBegin < argListEnd) {4058      if (*argListBegin == '^')4059        buf += '*';4060      else if (*argListBegin ==  '<') {4061        buf += "/*";4062        buf += *argListBegin++;4063        OrigLength++;4064        while (*argListBegin != '>') {4065          buf += *argListBegin++;4066          OrigLength++;4067        }4068        buf += *argListBegin;4069        buf += "*/";4070      }4071      else4072        buf += *argListBegin;4073      argListBegin++;4074      OrigLength++;4075    }4076    buf += ')';4077    OrigLength++;4078  }4079  ReplaceText(Start, OrigLength, buf);4080}4081 4082/// SynthesizeByrefCopyDestroyHelper - This routine synthesizes:4083/// void __Block_byref_id_object_copy(struct Block_byref_id_object *dst,4084///                    struct Block_byref_id_object *src) {4085///  _Block_object_assign (&_dest->object, _src->object,4086///                        BLOCK_BYREF_CALLER | BLOCK_FIELD_IS_OBJECT4087///                        [|BLOCK_FIELD_IS_WEAK]) // object4088///  _Block_object_assign(&_dest->object, _src->object,4089///                       BLOCK_BYREF_CALLER | BLOCK_FIELD_IS_BLOCK4090///                       [|BLOCK_FIELD_IS_WEAK]) // block4091/// }4092/// And:4093/// void __Block_byref_id_object_dispose(struct Block_byref_id_object *_src) {4094///  _Block_object_dispose(_src->object,4095///                        BLOCK_BYREF_CALLER | BLOCK_FIELD_IS_OBJECT4096///                        [|BLOCK_FIELD_IS_WEAK]) // object4097///  _Block_object_dispose(_src->object,4098///                         BLOCK_BYREF_CALLER | BLOCK_FIELD_IS_BLOCK4099///                         [|BLOCK_FIELD_IS_WEAK]) // block4100/// }4101 4102std::string RewriteObjC::SynthesizeByrefCopyDestroyHelper(VarDecl *VD,4103                                                          int flag) {4104  std::string S;4105  if (!CopyDestroyCache.insert(flag).second)4106    return S;4107  S = "static void __Block_byref_id_object_copy_";4108  S += utostr(flag);4109  S += "(void *dst, void *src) {\n";4110 4111  // offset into the object pointer is computed as:4112  // void * + void* + int + int + void* + void *4113  unsigned IntSize =4114  static_cast<unsigned>(Context->getTypeSize(Context->IntTy));4115  unsigned VoidPtrSize =4116  static_cast<unsigned>(Context->getTypeSize(Context->VoidPtrTy));4117 4118  unsigned offset = (VoidPtrSize*4 + IntSize + IntSize)/Context->getCharWidth();4119  S += " _Block_object_assign((char*)dst + ";4120  S += utostr(offset);4121  S += ", *(void * *) ((char*)src + ";4122  S += utostr(offset);4123  S += "), ";4124  S += utostr(flag);4125  S += ");\n}\n";4126 4127  S += "static void __Block_byref_id_object_dispose_";4128  S += utostr(flag);4129  S += "(void *src) {\n";4130  S += " _Block_object_dispose(*(void * *) ((char*)src + ";4131  S += utostr(offset);4132  S += "), ";4133  S += utostr(flag);4134  S += ");\n}\n";4135  return S;4136}4137 4138/// RewriteByRefVar - For each __block typex ND variable this routine transforms4139/// the declaration into:4140/// struct __Block_byref_ND {4141/// void *__isa;                  // NULL for everything except __weak pointers4142/// struct __Block_byref_ND *__forwarding;4143/// int32_t __flags;4144/// int32_t __size;4145/// void *__Block_byref_id_object_copy; // If variable is __block ObjC object4146/// void *__Block_byref_id_object_dispose; // If variable is __block ObjC object4147/// typex ND;4148/// };4149///4150/// It then replaces declaration of ND variable with:4151/// struct __Block_byref_ND ND = {__isa=0B, __forwarding=&ND, __flags=some_flag,4152///                               __size=sizeof(struct __Block_byref_ND),4153///                               ND=initializer-if-any};4154///4155///4156void RewriteObjC::RewriteByRefVar(VarDecl *ND) {4157  // Insert declaration for the function in which block literal is4158  // used.4159  if (CurFunctionDeclToDeclareForBlock)4160    RewriteBlockLiteralFunctionDecl(CurFunctionDeclToDeclareForBlock);4161  int flag = 0;4162  int isa = 0;4163  SourceLocation DeclLoc = ND->getTypeSpecStartLoc();4164  if (DeclLoc.isInvalid())4165    // If type location is missing, it is because of missing type (a warning).4166    // Use variable's location which is good for this case.4167    DeclLoc = ND->getLocation();4168  const char *startBuf = SM->getCharacterData(DeclLoc);4169  SourceLocation X = ND->getEndLoc();4170  X = SM->getExpansionLoc(X);4171  const char *endBuf = SM->getCharacterData(X);4172  std::string Name(ND->getNameAsString());4173  std::string ByrefType;4174  RewriteByRefString(ByrefType, Name, ND, true);4175  ByrefType += " {\n";4176  ByrefType += "  void *__isa;\n";4177  RewriteByRefString(ByrefType, Name, ND);4178  ByrefType += " *__forwarding;\n";4179  ByrefType += " int __flags;\n";4180  ByrefType += " int __size;\n";4181  // Add void *__Block_byref_id_object_copy;4182  // void *__Block_byref_id_object_dispose; if needed.4183  QualType Ty = ND->getType();4184  bool HasCopyAndDispose = Context->BlockRequiresCopying(Ty, ND);4185  if (HasCopyAndDispose) {4186    ByrefType += " void (*__Block_byref_id_object_copy)(void*, void*);\n";4187    ByrefType += " void (*__Block_byref_id_object_dispose)(void*);\n";4188  }4189 4190  QualType T = Ty;4191  (void)convertBlockPointerToFunctionPointer(T);4192  T.getAsStringInternal(Name, Context->getPrintingPolicy());4193 4194  ByrefType += " " + Name + ";\n";4195  ByrefType += "};\n";4196  // Insert this type in global scope. It is needed by helper function.4197  SourceLocation FunLocStart;4198  if (CurFunctionDef)4199     FunLocStart = CurFunctionDef->getTypeSpecStartLoc();4200  else {4201    assert(CurMethodDef && "RewriteByRefVar - CurMethodDef is null");4202    FunLocStart = CurMethodDef->getBeginLoc();4203  }4204  InsertText(FunLocStart, ByrefType);4205  if (Ty.isObjCGCWeak()) {4206    flag |= BLOCK_FIELD_IS_WEAK;4207    isa = 1;4208  }4209 4210  if (HasCopyAndDispose) {4211    flag = BLOCK_BYREF_CALLER;4212    QualType Ty = ND->getType();4213    // FIXME. Handle __weak variable (BLOCK_FIELD_IS_WEAK) as well.4214    if (Ty->isBlockPointerType())4215      flag |= BLOCK_FIELD_IS_BLOCK;4216    else4217      flag |= BLOCK_FIELD_IS_OBJECT;4218    std::string HF = SynthesizeByrefCopyDestroyHelper(ND, flag);4219    if (!HF.empty())4220      InsertText(FunLocStart, HF);4221  }4222 4223  // struct __Block_byref_ND ND =4224  // {0, &ND, some_flag, __size=sizeof(struct __Block_byref_ND),4225  //  initializer-if-any};4226  bool hasInit = (ND->getInit() != nullptr);4227  unsigned flags = 0;4228  if (HasCopyAndDispose)4229    flags |= BLOCK_HAS_COPY_DISPOSE;4230  Name = ND->getNameAsString();4231  ByrefType.clear();4232  RewriteByRefString(ByrefType, Name, ND);4233  std::string ForwardingCastType("(");4234  ForwardingCastType += ByrefType + " *)";4235  if (!hasInit) {4236    ByrefType += " " + Name + " = {(void*)";4237    ByrefType += utostr(isa);4238    ByrefType += "," +  ForwardingCastType + "&" + Name + ", ";4239    ByrefType += utostr(flags);4240    ByrefType += ", ";4241    ByrefType += "sizeof(";4242    RewriteByRefString(ByrefType, Name, ND);4243    ByrefType += ")";4244    if (HasCopyAndDispose) {4245      ByrefType += ", __Block_byref_id_object_copy_";4246      ByrefType += utostr(flag);4247      ByrefType += ", __Block_byref_id_object_dispose_";4248      ByrefType += utostr(flag);4249    }4250    ByrefType += "};\n";4251    unsigned nameSize = Name.size();4252    // for block or function pointer declaration. Name is already4253    // part of the declaration.4254    if (Ty->isBlockPointerType() || Ty->isFunctionPointerType())4255      nameSize = 1;4256    ReplaceText(DeclLoc, endBuf-startBuf+nameSize, ByrefType);4257  }4258  else {4259    SourceLocation startLoc;4260    Expr *E = ND->getInit();4261    if (const CStyleCastExpr *ECE = dyn_cast<CStyleCastExpr>(E))4262      startLoc = ECE->getLParenLoc();4263    else4264      startLoc = E->getBeginLoc();4265    startLoc = SM->getExpansionLoc(startLoc);4266    endBuf = SM->getCharacterData(startLoc);4267    ByrefType += " " + Name;4268    ByrefType += " = {(void*)";4269    ByrefType += utostr(isa);4270    ByrefType += "," +  ForwardingCastType + "&" + Name + ", ";4271    ByrefType += utostr(flags);4272    ByrefType += ", ";4273    ByrefType += "sizeof(";4274    RewriteByRefString(ByrefType, Name, ND);4275    ByrefType += "), ";4276    if (HasCopyAndDispose) {4277      ByrefType += "__Block_byref_id_object_copy_";4278      ByrefType += utostr(flag);4279      ByrefType += ", __Block_byref_id_object_dispose_";4280      ByrefType += utostr(flag);4281      ByrefType += ", ";4282    }4283    ReplaceText(DeclLoc, endBuf-startBuf, ByrefType);4284 4285    // Complete the newly synthesized compound expression by inserting a right4286    // curly brace before the end of the declaration.4287    // FIXME: This approach avoids rewriting the initializer expression. It4288    // also assumes there is only one declarator. For example, the following4289    // isn't currently supported by this routine (in general):4290    //4291    // double __block BYREFVAR = 1.34, BYREFVAR2 = 1.37;4292    //4293    const char *startInitializerBuf = SM->getCharacterData(startLoc);4294    const char *semiBuf = strchr(startInitializerBuf, ';');4295    assert((*semiBuf == ';') && "RewriteByRefVar: can't find ';'");4296    SourceLocation semiLoc =4297      startLoc.getLocWithOffset(semiBuf-startInitializerBuf);4298 4299    InsertText(semiLoc, "}");4300  }4301}4302 4303void RewriteObjC::CollectBlockDeclRefInfo(BlockExpr *Exp) {4304  // Add initializers for any closure decl refs.4305  GetBlockDeclRefExprs(Exp->getBody());4306  if (BlockDeclRefs.size()) {4307    // Unique all "by copy" declarations.4308    for (unsigned i = 0; i < BlockDeclRefs.size(); i++)4309      if (!BlockDeclRefs[i]->getDecl()->hasAttr<BlocksAttr>())4310        BlockByCopyDecls.insert(BlockDeclRefs[i]->getDecl());4311    // Unique all "by ref" declarations.4312    for (unsigned i = 0; i < BlockDeclRefs.size(); i++)4313      if (BlockDeclRefs[i]->getDecl()->hasAttr<BlocksAttr>())4314        BlockByRefDecls.insert(BlockDeclRefs[i]->getDecl());4315    // Find any imported blocks...they will need special attention.4316    for (unsigned i = 0; i < BlockDeclRefs.size(); i++)4317      if (BlockDeclRefs[i]->getDecl()->hasAttr<BlocksAttr>() ||4318          BlockDeclRefs[i]->getType()->isObjCObjectPointerType() ||4319          BlockDeclRefs[i]->getType()->isBlockPointerType())4320        ImportedBlockDecls.insert(BlockDeclRefs[i]->getDecl());4321  }4322}4323 4324FunctionDecl *RewriteObjC::SynthBlockInitFunctionDecl(StringRef name) {4325  IdentifierInfo *ID = &Context->Idents.get(name);4326  QualType FType = Context->getFunctionNoProtoType(Context->VoidPtrTy);4327  return FunctionDecl::Create(*Context, TUDecl, SourceLocation(),4328                              SourceLocation(), ID, FType, nullptr, SC_Extern,4329                              false, false);4330}4331 4332Stmt *RewriteObjC::SynthBlockInitExpr(BlockExpr *Exp,4333                     const SmallVectorImpl<DeclRefExpr *> &InnerBlockDeclRefs) {4334  const BlockDecl *block = Exp->getBlockDecl();4335  Blocks.push_back(Exp);4336 4337  CollectBlockDeclRefInfo(Exp);4338 4339  // Add inner imported variables now used in current block.4340 int countOfInnerDecls = 0;4341  if (!InnerBlockDeclRefs.empty()) {4342    for (unsigned i = 0; i < InnerBlockDeclRefs.size(); i++) {4343      DeclRefExpr *Exp = InnerBlockDeclRefs[i];4344      ValueDecl *VD = Exp->getDecl();4345      if (!VD->hasAttr<BlocksAttr>() && BlockByCopyDecls.insert(VD)) {4346        // We need to save the copied-in variables in nested4347        // blocks because it is needed at the end for some of the API4348        // generations. See SynthesizeBlockLiterals routine.4349        InnerDeclRefs.push_back(Exp);4350        countOfInnerDecls++;4351        BlockDeclRefs.push_back(Exp);4352      }4353      if (VD->hasAttr<BlocksAttr>() && BlockByRefDecls.insert(VD)) {4354        InnerDeclRefs.push_back(Exp);4355        countOfInnerDecls++;4356        BlockDeclRefs.push_back(Exp);4357      }4358    }4359    // Find any imported blocks...they will need special attention.4360    for (unsigned i = 0; i < InnerBlockDeclRefs.size(); i++)4361      if (InnerBlockDeclRefs[i]->getDecl()->hasAttr<BlocksAttr>() ||4362          InnerBlockDeclRefs[i]->getType()->isObjCObjectPointerType() ||4363          InnerBlockDeclRefs[i]->getType()->isBlockPointerType())4364        ImportedBlockDecls.insert(InnerBlockDeclRefs[i]->getDecl());4365  }4366  InnerDeclRefsCount.push_back(countOfInnerDecls);4367 4368  std::string FuncName;4369 4370  if (CurFunctionDef)4371    FuncName = CurFunctionDef->getNameAsString();4372  else if (CurMethodDef)4373    BuildUniqueMethodName(FuncName, CurMethodDef);4374  else if (GlobalVarDecl)4375    FuncName = std::string(GlobalVarDecl->getNameAsString());4376 4377  std::string BlockNumber = utostr(Blocks.size()-1);4378 4379  std::string Tag = "__" + FuncName + "_block_impl_" + BlockNumber;4380  std::string Func = "__" + FuncName + "_block_func_" + BlockNumber;4381 4382  // Get a pointer to the function type so we can cast appropriately.4383  QualType BFT = convertFunctionTypeOfBlocks(Exp->getFunctionType());4384  QualType FType = Context->getPointerType(BFT);4385 4386  FunctionDecl *FD;4387  Expr *NewRep;4388 4389  // Simulate a constructor call...4390  FD = SynthBlockInitFunctionDecl(Tag);4391  DeclRefExpr *DRE = new (Context)4392      DeclRefExpr(*Context, FD, false, FType, VK_PRValue, SourceLocation());4393 4394  SmallVector<Expr*, 4> InitExprs;4395 4396  // Initialize the block function.4397  FD = SynthBlockInitFunctionDecl(Func);4398  DeclRefExpr *Arg = new (Context) DeclRefExpr(4399      *Context, FD, false, FD->getType(), VK_LValue, SourceLocation());4400  CastExpr *castExpr =4401      NoTypeInfoCStyleCastExpr(Context, Context->VoidPtrTy, CK_BitCast, Arg);4402  InitExprs.push_back(castExpr);4403 4404  // Initialize the block descriptor.4405  std::string DescData = "__" + FuncName + "_block_desc_" + BlockNumber + "_DATA";4406 4407  VarDecl *NewVD = VarDecl::Create(4408      *Context, TUDecl, SourceLocation(), SourceLocation(),4409      &Context->Idents.get(DescData), Context->VoidPtrTy, nullptr, SC_Static);4410  UnaryOperator *DescRefExpr = UnaryOperator::Create(4411      const_cast<ASTContext &>(*Context),4412      new (Context) DeclRefExpr(*Context, NewVD, false, Context->VoidPtrTy,4413                                VK_LValue, SourceLocation()),4414      UO_AddrOf, Context->getPointerType(Context->VoidPtrTy), VK_PRValue,4415      OK_Ordinary, SourceLocation(), false, FPOptionsOverride());4416  InitExprs.push_back(DescRefExpr);4417 4418  // Add initializers for any closure decl refs.4419  if (BlockDeclRefs.size()) {4420    Expr *Exp;4421    // Output all "by copy" declarations.4422    for (auto I = BlockByCopyDecls.begin(), E = BlockByCopyDecls.end(); I != E;4423         ++I) {4424      if (isObjCType((*I)->getType())) {4425        // FIXME: Conform to ABI ([[obj retain] autorelease]).4426        FD = SynthBlockInitFunctionDecl((*I)->getName());4427        Exp = new (Context) DeclRefExpr(*Context, FD, false, FD->getType(),4428                                        VK_LValue, SourceLocation());4429        if (HasLocalVariableExternalStorage(*I)) {4430          QualType QT = (*I)->getType();4431          QT = Context->getPointerType(QT);4432          Exp = UnaryOperator::Create(const_cast<ASTContext &>(*Context), Exp,4433                                      UO_AddrOf, QT, VK_PRValue, OK_Ordinary,4434                                      SourceLocation(), false,4435                                      FPOptionsOverride());4436        }4437      } else if (isTopLevelBlockPointerType((*I)->getType())) {4438        FD = SynthBlockInitFunctionDecl((*I)->getName());4439        Arg = new (Context) DeclRefExpr(*Context, FD, false, FD->getType(),4440                                        VK_LValue, SourceLocation());4441        Exp = NoTypeInfoCStyleCastExpr(Context, Context->VoidPtrTy, CK_BitCast,4442                                       Arg);4443      } else {4444        FD = SynthBlockInitFunctionDecl((*I)->getName());4445        Exp = new (Context) DeclRefExpr(*Context, FD, false, FD->getType(),4446                                        VK_LValue, SourceLocation());4447        if (HasLocalVariableExternalStorage(*I)) {4448          QualType QT = (*I)->getType();4449          QT = Context->getPointerType(QT);4450          Exp = UnaryOperator::Create(const_cast<ASTContext &>(*Context), Exp,4451                                      UO_AddrOf, QT, VK_PRValue, OK_Ordinary,4452                                      SourceLocation(), false,4453                                      FPOptionsOverride());4454        }4455      }4456      InitExprs.push_back(Exp);4457    }4458    // Output all "by ref" declarations.4459    for (auto I = BlockByRefDecls.begin(), E = BlockByRefDecls.end(); I != E;4460         ++I) {4461      ValueDecl *ND = (*I);4462      std::string Name(ND->getNameAsString());4463      std::string RecName;4464      RewriteByRefString(RecName, Name, ND, true);4465      IdentifierInfo *II = &Context->Idents.get(RecName.c_str()4466                                                + sizeof("struct"));4467      RecordDecl *RD =4468          RecordDecl::Create(*Context, TagTypeKind::Struct, TUDecl,4469                             SourceLocation(), SourceLocation(), II);4470      assert(RD && "SynthBlockInitExpr(): Can't find RecordDecl");4471      QualType castT =4472          Context->getPointerType(Context->getCanonicalTagType(RD));4473 4474      FD = SynthBlockInitFunctionDecl((*I)->getName());4475      Exp = new (Context) DeclRefExpr(*Context, FD, false, FD->getType(),4476                                      VK_LValue, SourceLocation());4477      bool isNestedCapturedVar = false;4478      if (block)4479        for (const auto &CI : block->captures()) {4480          const VarDecl *variable = CI.getVariable();4481          if (variable == ND && CI.isNested()) {4482            assert (CI.isByRef() &&4483                    "SynthBlockInitExpr - captured block variable is not byref");4484            isNestedCapturedVar = true;4485            break;4486          }4487        }4488      // captured nested byref variable has its address passed. Do not take4489      // its address again.4490      if (!isNestedCapturedVar)4491        Exp = UnaryOperator::Create(4492            const_cast<ASTContext &>(*Context), Exp, UO_AddrOf,4493            Context->getPointerType(Exp->getType()), VK_PRValue, OK_Ordinary,4494            SourceLocation(), false, FPOptionsOverride());4495      Exp = NoTypeInfoCStyleCastExpr(Context, castT, CK_BitCast, Exp);4496      InitExprs.push_back(Exp);4497    }4498  }4499  if (ImportedBlockDecls.size()) {4500    // generate BLOCK_HAS_COPY_DISPOSE(have helper funcs) | BLOCK_HAS_DESCRIPTOR4501    int flag = (BLOCK_HAS_COPY_DISPOSE | BLOCK_HAS_DESCRIPTOR);4502    unsigned IntSize =4503      static_cast<unsigned>(Context->getTypeSize(Context->IntTy));4504    Expr *FlagExp = IntegerLiteral::Create(*Context, llvm::APInt(IntSize, flag),4505                                           Context->IntTy, SourceLocation());4506    InitExprs.push_back(FlagExp);4507  }4508  NewRep = CallExpr::Create(*Context, DRE, InitExprs, FType, VK_LValue,4509                            SourceLocation(), FPOptionsOverride());4510  NewRep = UnaryOperator::Create(4511      const_cast<ASTContext &>(*Context), NewRep, UO_AddrOf,4512      Context->getPointerType(NewRep->getType()), VK_PRValue, OK_Ordinary,4513      SourceLocation(), false, FPOptionsOverride());4514  NewRep = NoTypeInfoCStyleCastExpr(Context, FType, CK_BitCast,4515                                    NewRep);4516  BlockDeclRefs.clear();4517  BlockByRefDecls.clear();4518  BlockByCopyDecls.clear();4519  ImportedBlockDecls.clear();4520  return NewRep;4521}4522 4523bool RewriteObjC::IsDeclStmtInForeachHeader(DeclStmt *DS) {4524  if (const ObjCForCollectionStmt * CS =4525      dyn_cast<ObjCForCollectionStmt>(Stmts.back()))4526        return CS->getElement() == DS;4527  return false;4528}4529 4530//===----------------------------------------------------------------------===//4531// Function Body / Expression rewriting4532//===----------------------------------------------------------------------===//4533 4534Stmt *RewriteObjC::RewriteFunctionBodyOrGlobalInitializer(Stmt *S) {4535  if (isa<SwitchStmt>(S) || isa<WhileStmt>(S) ||4536      isa<DoStmt>(S) || isa<ForStmt>(S))4537    Stmts.push_back(S);4538  else if (isa<ObjCForCollectionStmt>(S)) {4539    Stmts.push_back(S);4540    ObjCBcLabelNo.push_back(++BcLabelCount);4541  }4542 4543  // Pseudo-object operations and ivar references need special4544  // treatment because we're going to recursively rewrite them.4545  if (PseudoObjectExpr *PseudoOp = dyn_cast<PseudoObjectExpr>(S)) {4546    if (isa<BinaryOperator>(PseudoOp->getSyntacticForm())) {4547      return RewritePropertyOrImplicitSetter(PseudoOp);4548    } else {4549      return RewritePropertyOrImplicitGetter(PseudoOp);4550    }4551  } else if (ObjCIvarRefExpr *IvarRefExpr = dyn_cast<ObjCIvarRefExpr>(S)) {4552    return RewriteObjCIvarRefExpr(IvarRefExpr);4553  }4554 4555  SourceRange OrigStmtRange = S->getSourceRange();4556 4557  // Perform a bottom up rewrite of all children.4558  for (Stmt *&childStmt : S->children())4559    if (childStmt) {4560      Stmt *newStmt = RewriteFunctionBodyOrGlobalInitializer(childStmt);4561      if (newStmt) {4562        childStmt = newStmt;4563      }4564    }4565 4566  if (BlockExpr *BE = dyn_cast<BlockExpr>(S)) {4567    SmallVector<DeclRefExpr *, 8> InnerBlockDeclRefs;4568    llvm::SmallPtrSet<const DeclContext *, 8> InnerContexts;4569    InnerContexts.insert(BE->getBlockDecl());4570    ImportedLocalExternalDecls.clear();4571    GetInnerBlockDeclRefExprs(BE->getBody(),4572                              InnerBlockDeclRefs, InnerContexts);4573    // Rewrite the block body in place.4574    Stmt *SaveCurrentBody = CurrentBody;4575    CurrentBody = BE->getBody();4576    PropParentMap = nullptr;4577    // block literal on rhs of a property-dot-sytax assignment4578    // must be replaced by its synthesize ast so getRewrittenText4579    // works as expected. In this case, what actually ends up on RHS4580    // is the blockTranscribed which is the helper function for the4581    // block literal; as in: self.c = ^() {[ace ARR];};4582    bool saveDisableReplaceStmt = DisableReplaceStmt;4583    DisableReplaceStmt = false;4584    RewriteFunctionBodyOrGlobalInitializer(BE->getBody());4585    DisableReplaceStmt = saveDisableReplaceStmt;4586    CurrentBody = SaveCurrentBody;4587    PropParentMap = nullptr;4588    ImportedLocalExternalDecls.clear();4589    // Now we snarf the rewritten text and stash it away for later use.4590    std::string Str = Rewrite.getRewrittenText(BE->getSourceRange());4591    RewrittenBlockExprs[BE] = Str;4592 4593    Stmt *blockTranscribed = SynthBlockInitExpr(BE, InnerBlockDeclRefs);4594 4595    //blockTranscribed->dump();4596    ReplaceStmt(S, blockTranscribed);4597    return blockTranscribed;4598  }4599  // Handle specific things.4600  if (ObjCEncodeExpr *AtEncode = dyn_cast<ObjCEncodeExpr>(S))4601    return RewriteAtEncode(AtEncode);4602 4603  if (ObjCSelectorExpr *AtSelector = dyn_cast<ObjCSelectorExpr>(S))4604    return RewriteAtSelector(AtSelector);4605 4606  if (ObjCStringLiteral *AtString = dyn_cast<ObjCStringLiteral>(S))4607    return RewriteObjCStringLiteral(AtString);4608 4609  if (ObjCMessageExpr *MessExpr = dyn_cast<ObjCMessageExpr>(S)) {4610#if 04611    // Before we rewrite it, put the original message expression in a comment.4612    SourceLocation startLoc = MessExpr->getBeginLoc();4613    SourceLocation endLoc = MessExpr->getEndLoc();4614 4615    const char *startBuf = SM->getCharacterData(startLoc);4616    const char *endBuf = SM->getCharacterData(endLoc);4617 4618    std::string messString;4619    messString += "// ";4620    messString.append(startBuf, endBuf-startBuf+1);4621    messString += "\n";4622 4623    // FIXME: Missing definition of4624    // InsertText(clang::SourceLocation, char const*, unsigned int).4625    // InsertText(startLoc, messString);4626    // Tried this, but it didn't work either...4627    // ReplaceText(startLoc, 0, messString.c_str(), messString.size());4628#endif4629    return RewriteMessageExpr(MessExpr);4630  }4631 4632  if (ObjCAtTryStmt *StmtTry = dyn_cast<ObjCAtTryStmt>(S))4633    return RewriteObjCTryStmt(StmtTry);4634 4635  if (ObjCAtSynchronizedStmt *StmtTry = dyn_cast<ObjCAtSynchronizedStmt>(S))4636    return RewriteObjCSynchronizedStmt(StmtTry);4637 4638  if (ObjCAtThrowStmt *StmtThrow = dyn_cast<ObjCAtThrowStmt>(S))4639    return RewriteObjCThrowStmt(StmtThrow);4640 4641  if (ObjCProtocolExpr *ProtocolExp = dyn_cast<ObjCProtocolExpr>(S))4642    return RewriteObjCProtocolExpr(ProtocolExp);4643 4644  if (ObjCForCollectionStmt *StmtForCollection =4645        dyn_cast<ObjCForCollectionStmt>(S))4646    return RewriteObjCForCollectionStmt(StmtForCollection,4647                                        OrigStmtRange.getEnd());4648  if (BreakStmt *StmtBreakStmt =4649      dyn_cast<BreakStmt>(S))4650    return RewriteBreakStmt(StmtBreakStmt);4651  if (ContinueStmt *StmtContinueStmt =4652      dyn_cast<ContinueStmt>(S))4653    return RewriteContinueStmt(StmtContinueStmt);4654 4655  // Need to check for protocol refs (id <P>, Foo <P> *) in variable decls4656  // and cast exprs.4657  if (DeclStmt *DS = dyn_cast<DeclStmt>(S)) {4658    // FIXME: What we're doing here is modifying the type-specifier that4659    // precedes the first Decl.  In the future the DeclGroup should have4660    // a separate type-specifier that we can rewrite.4661    // NOTE: We need to avoid rewriting the DeclStmt if it is within4662    // the context of an ObjCForCollectionStmt. For example:4663    //   NSArray *someArray;4664    //   for (id <FooProtocol> index in someArray) ;4665    // This is because RewriteObjCForCollectionStmt() does textual rewriting4666    // and it depends on the original text locations/positions.4667    if (Stmts.empty() || !IsDeclStmtInForeachHeader(DS))4668      RewriteObjCQualifiedInterfaceTypes(*DS->decl_begin());4669 4670    // Blocks rewrite rules.4671    for (auto *SD : DS->decls()) {4672      if (ValueDecl *ND = dyn_cast<ValueDecl>(SD)) {4673        if (isTopLevelBlockPointerType(ND->getType()))4674          RewriteBlockPointerDecl(ND);4675        else if (ND->getType()->isFunctionPointerType())4676          CheckFunctionPointerDecl(ND->getType(), ND);4677        if (VarDecl *VD = dyn_cast<VarDecl>(SD)) {4678          if (VD->hasAttr<BlocksAttr>()) {4679            static unsigned uniqueByrefDeclCount = 0;4680            assert(!BlockByRefDeclNo.count(ND) &&4681              "RewriteFunctionBodyOrGlobalInitializer: Duplicate byref decl");4682            BlockByRefDeclNo[ND] = uniqueByrefDeclCount++;4683            RewriteByRefVar(VD);4684          }4685          else4686            RewriteTypeOfDecl(VD);4687        }4688      }4689      if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(SD)) {4690        if (isTopLevelBlockPointerType(TD->getUnderlyingType()))4691          RewriteBlockPointerDecl(TD);4692        else if (TD->getUnderlyingType()->isFunctionPointerType())4693          CheckFunctionPointerDecl(TD->getUnderlyingType(), TD);4694      }4695    }4696  }4697 4698  if (CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(S))4699    RewriteObjCQualifiedInterfaceTypes(CE);4700 4701  if (isa<SwitchStmt>(S) || isa<WhileStmt>(S) ||4702      isa<DoStmt>(S) || isa<ForStmt>(S)) {4703    assert(!Stmts.empty() && "Statement stack is empty");4704    assert ((isa<SwitchStmt>(Stmts.back()) || isa<WhileStmt>(Stmts.back()) ||4705             isa<DoStmt>(Stmts.back()) || isa<ForStmt>(Stmts.back()))4706            && "Statement stack mismatch");4707    Stmts.pop_back();4708  }4709  // Handle blocks rewriting.4710  if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(S)) {4711    ValueDecl *VD = DRE->getDecl();4712    if (VD->hasAttr<BlocksAttr>())4713      return RewriteBlockDeclRefExpr(DRE);4714    if (HasLocalVariableExternalStorage(VD))4715      return RewriteLocalVariableExternalStorage(DRE);4716  }4717 4718  if (CallExpr *CE = dyn_cast<CallExpr>(S)) {4719    if (CE->getCallee()->getType()->isBlockPointerType()) {4720      Stmt *BlockCall = SynthesizeBlockCall(CE, CE->getCallee());4721      ReplaceStmt(S, BlockCall);4722      return BlockCall;4723    }4724  }4725  if (CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(S)) {4726    RewriteCastExpr(CE);4727  }4728#if 04729  if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(S)) {4730    CastExpr *Replacement = new (Context) CastExpr(ICE->getType(),4731                                                   ICE->getSubExpr(),4732                                                   SourceLocation());4733    // Get the new text.4734    std::string SStr;4735    llvm::raw_string_ostream Buf(SStr);4736    Replacement->printPretty(Buf);4737    const std::string &Str = Buf.str();4738 4739    printf("CAST = %s\n", &Str[0]);4740    InsertText(ICE->getSubExpr()->getBeginLoc(), Str);4741    delete S;4742    return Replacement;4743  }4744#endif4745  // Return this stmt unmodified.4746  return S;4747}4748 4749void RewriteObjC::RewriteRecordBody(RecordDecl *RD) {4750  for (auto *FD : RD->fields()) {4751    if (isTopLevelBlockPointerType(FD->getType()))4752      RewriteBlockPointerDecl(FD);4753    if (FD->getType()->isObjCQualifiedIdType() ||4754        FD->getType()->isObjCQualifiedInterfaceType())4755      RewriteObjCQualifiedInterfaceTypes(FD);4756  }4757}4758 4759/// HandleDeclInMainFile - This is called for each top-level decl defined in the4760/// main file of the input.4761void RewriteObjC::HandleDeclInMainFile(Decl *D) {4762  switch (D->getKind()) {4763    case Decl::Function: {4764      FunctionDecl *FD = cast<FunctionDecl>(D);4765      if (FD->isOverloadedOperator())4766        return;4767 4768      // Since function prototypes don't have ParmDecl's, we check the function4769      // prototype. This enables us to rewrite function declarations and4770      // definitions using the same code.4771      RewriteBlocksInFunctionProtoType(FD->getType(), FD);4772 4773      if (!FD->isThisDeclarationADefinition())4774        break;4775 4776      // FIXME: If this should support Obj-C++, support CXXTryStmt4777      if (CompoundStmt *Body = dyn_cast_or_null<CompoundStmt>(FD->getBody())) {4778        CurFunctionDef = FD;4779        CurFunctionDeclToDeclareForBlock = FD;4780        CurrentBody = Body;4781        Body =4782        cast_or_null<CompoundStmt>(RewriteFunctionBodyOrGlobalInitializer(Body));4783        FD->setBody(Body);4784        CurrentBody = nullptr;4785        if (PropParentMap) {4786          delete PropParentMap;4787          PropParentMap = nullptr;4788        }4789        // This synthesizes and inserts the block "impl" struct, invoke function,4790        // and any copy/dispose helper functions.4791        InsertBlockLiteralsWithinFunction(FD);4792        CurFunctionDef = nullptr;4793        CurFunctionDeclToDeclareForBlock = nullptr;4794      }4795      break;4796    }4797    case Decl::ObjCMethod: {4798      ObjCMethodDecl *MD = cast<ObjCMethodDecl>(D);4799      if (CompoundStmt *Body = MD->getCompoundBody()) {4800        CurMethodDef = MD;4801        CurrentBody = Body;4802        Body =4803          cast_or_null<CompoundStmt>(RewriteFunctionBodyOrGlobalInitializer(Body));4804        MD->setBody(Body);4805        CurrentBody = nullptr;4806        if (PropParentMap) {4807          delete PropParentMap;4808          PropParentMap = nullptr;4809        }4810        InsertBlockLiteralsWithinMethod(MD);4811        CurMethodDef = nullptr;4812      }4813      break;4814    }4815    case Decl::ObjCImplementation: {4816      ObjCImplementationDecl *CI = cast<ObjCImplementationDecl>(D);4817      ClassImplementation.push_back(CI);4818      break;4819    }4820    case Decl::ObjCCategoryImpl: {4821      ObjCCategoryImplDecl *CI = cast<ObjCCategoryImplDecl>(D);4822      CategoryImplementation.push_back(CI);4823      break;4824    }4825    case Decl::Var: {4826      VarDecl *VD = cast<VarDecl>(D);4827      RewriteObjCQualifiedInterfaceTypes(VD);4828      if (isTopLevelBlockPointerType(VD->getType()))4829        RewriteBlockPointerDecl(VD);4830      else if (VD->getType()->isFunctionPointerType()) {4831        CheckFunctionPointerDecl(VD->getType(), VD);4832        if (VD->getInit()) {4833          if (CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(VD->getInit())) {4834            RewriteCastExpr(CE);4835          }4836        }4837      } else if (VD->getType()->isRecordType()) {4838        auto *RD = VD->getType()->castAsRecordDecl();4839        if (RD->isCompleteDefinition())4840          RewriteRecordBody(RD);4841      }4842      if (VD->getInit()) {4843        GlobalVarDecl = VD;4844        CurrentBody = VD->getInit();4845        RewriteFunctionBodyOrGlobalInitializer(VD->getInit());4846        CurrentBody = nullptr;4847        if (PropParentMap) {4848          delete PropParentMap;4849          PropParentMap = nullptr;4850        }4851        SynthesizeBlockLiterals(VD->getTypeSpecStartLoc(), VD->getName());4852        GlobalVarDecl = nullptr;4853 4854        // This is needed for blocks.4855        if (CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(VD->getInit())) {4856            RewriteCastExpr(CE);4857        }4858      }4859      break;4860    }4861    case Decl::TypeAlias:4862    case Decl::Typedef: {4863      if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(D)) {4864        if (isTopLevelBlockPointerType(TD->getUnderlyingType()))4865          RewriteBlockPointerDecl(TD);4866        else if (TD->getUnderlyingType()->isFunctionPointerType())4867          CheckFunctionPointerDecl(TD->getUnderlyingType(), TD);4868      }4869      break;4870    }4871    case Decl::CXXRecord:4872    case Decl::Record: {4873      RecordDecl *RD = cast<RecordDecl>(D);4874      if (RD->isCompleteDefinition())4875        RewriteRecordBody(RD);4876      break;4877    }4878    default:4879      break;4880  }4881  // Nothing yet.4882}4883 4884void RewriteObjC::HandleTranslationUnit(ASTContext &C) {4885  if (Diags.hasErrorOccurred())4886    return;4887 4888  RewriteInclude();4889 4890  // Here's a great place to add any extra declarations that may be needed.4891  // Write out meta data for each @protocol(<expr>).4892  for (ObjCProtocolDecl *ProtDecl : ProtocolExprDecls)4893    RewriteObjCProtocolMetaData(ProtDecl, "", "", Preamble);4894 4895  InsertText(SM->getLocForStartOfFile(MainFileID), Preamble, false);4896  if (ClassImplementation.size() || CategoryImplementation.size())4897    RewriteImplementations();4898 4899  // Get the buffer corresponding to MainFileID.  If we haven't changed it, then4900  // we are done.4901  if (const RewriteBuffer *RewriteBuf =4902      Rewrite.getRewriteBufferFor(MainFileID)) {4903    //printf("Changed:\n");4904    *OutFile << std::string(RewriteBuf->begin(), RewriteBuf->end());4905  } else {4906    llvm::errs() << "No changes\n";4907  }4908 4909  if (ClassImplementation.size() || CategoryImplementation.size() ||4910      ProtocolExprDecls.size()) {4911    // Rewrite Objective-c meta data*4912    std::string ResultStr;4913    RewriteMetaDataIntoBuffer(ResultStr);4914    // Emit metadata.4915    *OutFile << ResultStr;4916  }4917  OutFile->flush();4918}4919 4920void RewriteObjCFragileABI::Initialize(ASTContext &context) {4921  InitializeCommon(context);4922 4923  // declaring objc_selector outside the parameter list removes a silly4924  // scope related warning...4925  if (IsHeader)4926    Preamble = "#pragma once\n";4927  Preamble += "struct objc_selector; struct objc_class;\n";4928  Preamble += "struct __rw_objc_super { struct objc_object *object; ";4929  Preamble += "struct objc_object *superClass; ";4930  if (LangOpts.MicrosoftExt) {4931    // Add a constructor for creating temporary objects.4932    Preamble += "__rw_objc_super(struct objc_object *o, struct objc_object *s) "4933    ": ";4934    Preamble += "object(o), superClass(s) {} ";4935  }4936  Preamble += "};\n";4937  Preamble += "#ifndef _REWRITER_typedef_Protocol\n";4938  Preamble += "typedef struct objc_object Protocol;\n";4939  Preamble += "#define _REWRITER_typedef_Protocol\n";4940  Preamble += "#endif\n";4941  if (LangOpts.MicrosoftExt) {4942    Preamble += "#define __OBJC_RW_DLLIMPORT extern \"C\" __declspec(dllimport)\n";4943    Preamble += "#define __OBJC_RW_STATICIMPORT extern \"C\"\n";4944  } else4945    Preamble += "#define __OBJC_RW_DLLIMPORT extern\n";4946  Preamble += "__OBJC_RW_DLLIMPORT struct objc_object *objc_msgSend";4947  Preamble += "(struct objc_object *, struct objc_selector *, ...);\n";4948  Preamble += "__OBJC_RW_DLLIMPORT struct objc_object *objc_msgSendSuper";4949  Preamble += "(struct objc_super *, struct objc_selector *, ...);\n";4950  Preamble += "__OBJC_RW_DLLIMPORT struct objc_object* objc_msgSend_stret";4951  Preamble += "(struct objc_object *, struct objc_selector *, ...);\n";4952  Preamble += "__OBJC_RW_DLLIMPORT struct objc_object* objc_msgSendSuper_stret";4953  Preamble += "(struct objc_super *, struct objc_selector *, ...);\n";4954  Preamble += "__OBJC_RW_DLLIMPORT double objc_msgSend_fpret";4955  Preamble += "(struct objc_object *, struct objc_selector *, ...);\n";4956  Preamble += "__OBJC_RW_DLLIMPORT struct objc_object *objc_getClass";4957  Preamble += "(const char *);\n";4958  Preamble += "__OBJC_RW_DLLIMPORT struct objc_class *class_getSuperclass";4959  Preamble += "(struct objc_class *);\n";4960  Preamble += "__OBJC_RW_DLLIMPORT struct objc_object *objc_getMetaClass";4961  Preamble += "(const char *);\n";4962  Preamble += "__OBJC_RW_DLLIMPORT void objc_exception_throw(struct objc_object *);\n";4963  Preamble += "__OBJC_RW_DLLIMPORT void objc_exception_try_enter(void *);\n";4964  Preamble += "__OBJC_RW_DLLIMPORT void objc_exception_try_exit(void *);\n";4965  Preamble += "__OBJC_RW_DLLIMPORT struct objc_object *objc_exception_extract(void *);\n";4966  Preamble += "__OBJC_RW_DLLIMPORT int objc_exception_match";4967  Preamble += "(struct objc_class *, struct objc_object *);\n";4968  // @synchronized hooks.4969  Preamble += "__OBJC_RW_DLLIMPORT int objc_sync_enter(struct objc_object *);\n";4970  Preamble += "__OBJC_RW_DLLIMPORT int objc_sync_exit(struct objc_object *);\n";4971  Preamble += "__OBJC_RW_DLLIMPORT Protocol *objc_getProtocol(const char *);\n";4972  Preamble += "#ifndef __FASTENUMERATIONSTATE\n";4973  Preamble += "struct __objcFastEnumerationState {\n\t";4974  Preamble += "unsigned long state;\n\t";4975  Preamble += "void **itemsPtr;\n\t";4976  Preamble += "unsigned long *mutationsPtr;\n\t";4977  Preamble += "unsigned long extra[5];\n};\n";4978  Preamble += "__OBJC_RW_DLLIMPORT void objc_enumerationMutation(struct objc_object *);\n";4979  Preamble += "#define __FASTENUMERATIONSTATE\n";4980  Preamble += "#endif\n";4981  Preamble += "#ifndef __NSCONSTANTSTRINGIMPL\n";4982  Preamble += "struct __NSConstantStringImpl {\n";4983  Preamble += "  int *isa;\n";4984  Preamble += "  int flags;\n";4985  Preamble += "  char *str;\n";4986  Preamble += "  long length;\n";4987  Preamble += "};\n";4988  Preamble += "#ifdef CF_EXPORT_CONSTANT_STRING\n";4989  Preamble += "extern \"C\" __declspec(dllexport) int __CFConstantStringClassReference[];\n";4990  Preamble += "#else\n";4991  Preamble += "__OBJC_RW_DLLIMPORT int __CFConstantStringClassReference[];\n";4992  Preamble += "#endif\n";4993  Preamble += "#define __NSCONSTANTSTRINGIMPL\n";4994  Preamble += "#endif\n";4995  // Blocks preamble.4996  Preamble += "#ifndef BLOCK_IMPL\n";4997  Preamble += "#define BLOCK_IMPL\n";4998  Preamble += "struct __block_impl {\n";4999  Preamble += "  void *isa;\n";5000  Preamble += "  int Flags;\n";5001  Preamble += "  int Reserved;\n";5002  Preamble += "  void *FuncPtr;\n";5003  Preamble += "};\n";5004  Preamble += "// Runtime copy/destroy helper functions (from Block_private.h)\n";5005  Preamble += "#ifdef __OBJC_EXPORT_BLOCKS\n";5006  Preamble += "extern \"C\" __declspec(dllexport) "5007  "void _Block_object_assign(void *, const void *, const int);\n";5008  Preamble += "extern \"C\" __declspec(dllexport) void _Block_object_dispose(const void *, const int);\n";5009  Preamble += "extern \"C\" __declspec(dllexport) void *_NSConcreteGlobalBlock[32];\n";5010  Preamble += "extern \"C\" __declspec(dllexport) void *_NSConcreteStackBlock[32];\n";5011  Preamble += "#else\n";5012  Preamble += "__OBJC_RW_DLLIMPORT void _Block_object_assign(void *, const void *, const int);\n";5013  Preamble += "__OBJC_RW_DLLIMPORT void _Block_object_dispose(const void *, const int);\n";5014  Preamble += "__OBJC_RW_DLLIMPORT void *_NSConcreteGlobalBlock[32];\n";5015  Preamble += "__OBJC_RW_DLLIMPORT void *_NSConcreteStackBlock[32];\n";5016  Preamble += "#endif\n";5017  Preamble += "#endif\n";5018  if (LangOpts.MicrosoftExt) {5019    Preamble += "#undef __OBJC_RW_DLLIMPORT\n";5020    Preamble += "#undef __OBJC_RW_STATICIMPORT\n";5021    Preamble += "#ifndef KEEP_ATTRIBUTES\n";  // We use this for clang tests.5022    Preamble += "#define __attribute__(X)\n";5023    Preamble += "#endif\n";5024    Preamble += "#define __weak\n";5025  }5026  else {5027    Preamble += "#define __block\n";5028    Preamble += "#define __weak\n";5029  }5030  // NOTE! Windows uses LLP64 for 64bit mode. So, cast pointer to long long5031  // as this avoids warning in any 64bit/32bit compilation model.5032  Preamble += "\n#define __OFFSETOFIVAR__(TYPE, MEMBER) ((long long) &((TYPE *)0)->MEMBER)\n";5033}5034 5035/// RewriteIvarOffsetComputation - This routine synthesizes computation of5036/// ivar offset.5037void RewriteObjCFragileABI::RewriteIvarOffsetComputation(ObjCIvarDecl *ivar,5038                                                         std::string &Result) {5039  if (ivar->isBitField()) {5040    // FIXME: The hack below doesn't work for bitfields. For now, we simply5041    // place all bitfields at offset 0.5042    Result += "0";5043  } else {5044    Result += "__OFFSETOFIVAR__(struct ";5045    Result += ivar->getContainingInterface()->getNameAsString();5046    if (LangOpts.MicrosoftExt)5047      Result += "_IMPL";5048    Result += ", ";5049    Result += ivar->getNameAsString();5050    Result += ")";5051  }5052}5053 5054/// RewriteObjCProtocolMetaData - Rewrite protocols meta-data.5055void RewriteObjCFragileABI::RewriteObjCProtocolMetaData(5056                            ObjCProtocolDecl *PDecl, StringRef prefix,5057                            StringRef ClassName, std::string &Result) {5058  static bool objc_protocol_methods = false;5059 5060  // Output struct protocol_methods holder of method selector and type.5061  if (!objc_protocol_methods && PDecl->hasDefinition()) {5062    /* struct protocol_methods {5063     SEL _cmd;5064     char *method_types;5065     }5066     */5067    Result += "\nstruct _protocol_methods {\n";5068    Result += "\tstruct objc_selector *_cmd;\n";5069    Result += "\tchar *method_types;\n";5070    Result += "};\n";5071 5072    objc_protocol_methods = true;5073  }5074  // Do not synthesize the protocol more than once.5075  if (ObjCSynthesizedProtocols.count(PDecl->getCanonicalDecl()))5076    return;5077 5078  if (ObjCProtocolDecl *Def = PDecl->getDefinition())5079    PDecl = Def;5080 5081  if (PDecl->instmeth_begin() != PDecl->instmeth_end()) {5082    unsigned NumMethods = std::distance(PDecl->instmeth_begin(),5083                                        PDecl->instmeth_end());5084    /* struct _objc_protocol_method_list {5085     int protocol_method_count;5086     struct protocol_methods protocols[];5087     }5088     */5089    Result += "\nstatic struct {\n";5090    Result += "\tint protocol_method_count;\n";5091    Result += "\tstruct _protocol_methods protocol_methods[";5092    Result += utostr(NumMethods);5093    Result += "];\n} _OBJC_PROTOCOL_INSTANCE_METHODS_";5094    Result += PDecl->getNameAsString();5095    Result += " __attribute__ ((used, section (\"__OBJC, __cat_inst_meth\")))= "5096    "{\n\t" + utostr(NumMethods) + "\n";5097 5098    // Output instance methods declared in this protocol.5099    for (ObjCProtocolDecl::instmeth_iterator5100         I = PDecl->instmeth_begin(), E = PDecl->instmeth_end();5101         I != E; ++I) {5102      if (I == PDecl->instmeth_begin())5103        Result += "\t  ,{{(struct objc_selector *)\"";5104      else5105        Result += "\t  ,{(struct objc_selector *)\"";5106      Result += (*I)->getSelector().getAsString();5107      std::string MethodTypeString = Context->getObjCEncodingForMethodDecl(*I);5108      Result += "\", \"";5109      Result += MethodTypeString;5110      Result += "\"}\n";5111    }5112    Result += "\t }\n};\n";5113  }5114 5115  // Output class methods declared in this protocol.5116  unsigned NumMethods = std::distance(PDecl->classmeth_begin(),5117                                      PDecl->classmeth_end());5118  if (NumMethods > 0) {5119    /* struct _objc_protocol_method_list {5120     int protocol_method_count;5121     struct protocol_methods protocols[];5122     }5123     */5124    Result += "\nstatic struct {\n";5125    Result += "\tint protocol_method_count;\n";5126    Result += "\tstruct _protocol_methods protocol_methods[";5127    Result += utostr(NumMethods);5128    Result += "];\n} _OBJC_PROTOCOL_CLASS_METHODS_";5129    Result += PDecl->getNameAsString();5130    Result += " __attribute__ ((used, section (\"__OBJC, __cat_cls_meth\")))= "5131    "{\n\t";5132    Result += utostr(NumMethods);5133    Result += "\n";5134 5135    // Output instance methods declared in this protocol.5136    for (ObjCProtocolDecl::classmeth_iterator5137         I = PDecl->classmeth_begin(), E = PDecl->classmeth_end();5138         I != E; ++I) {5139      if (I == PDecl->classmeth_begin())5140        Result += "\t  ,{{(struct objc_selector *)\"";5141      else5142        Result += "\t  ,{(struct objc_selector *)\"";5143      Result += (*I)->getSelector().getAsString();5144      std::string MethodTypeString = Context->getObjCEncodingForMethodDecl(*I);5145      Result += "\", \"";5146      Result += MethodTypeString;5147      Result += "\"}\n";5148    }5149    Result += "\t }\n};\n";5150  }5151 5152  // Output:5153  /* struct _objc_protocol {5154   // Objective-C 1.0 extensions5155   struct _objc_protocol_extension *isa;5156   char *protocol_name;5157   struct _objc_protocol **protocol_list;5158   struct _objc_protocol_method_list *instance_methods;5159   struct _objc_protocol_method_list *class_methods;5160   };5161   */5162  static bool objc_protocol = false;5163  if (!objc_protocol) {5164    Result += "\nstruct _objc_protocol {\n";5165    Result += "\tstruct _objc_protocol_extension *isa;\n";5166    Result += "\tchar *protocol_name;\n";5167    Result += "\tstruct _objc_protocol **protocol_list;\n";5168    Result += "\tstruct _objc_protocol_method_list *instance_methods;\n";5169    Result += "\tstruct _objc_protocol_method_list *class_methods;\n";5170    Result += "};\n";5171 5172    objc_protocol = true;5173  }5174 5175  Result += "\nstatic struct _objc_protocol _OBJC_PROTOCOL_";5176  Result += PDecl->getNameAsString();5177  Result += " __attribute__ ((used, section (\"__OBJC, __protocol\")))= "5178  "{\n\t0, \"";5179  Result += PDecl->getNameAsString();5180  Result += "\", 0, ";5181  if (PDecl->instmeth_begin() != PDecl->instmeth_end()) {5182    Result += "(struct _objc_protocol_method_list *)&_OBJC_PROTOCOL_INSTANCE_METHODS_";5183    Result += PDecl->getNameAsString();5184    Result += ", ";5185  }5186  else5187    Result += "0, ";5188  if (PDecl->classmeth_begin() != PDecl->classmeth_end()) {5189    Result += "(struct _objc_protocol_method_list *)&_OBJC_PROTOCOL_CLASS_METHODS_";5190    Result += PDecl->getNameAsString();5191    Result += "\n";5192  }5193  else5194    Result += "0\n";5195  Result += "};\n";5196 5197  // Mark this protocol as having been generated.5198  if (!ObjCSynthesizedProtocols.insert(PDecl->getCanonicalDecl()).second)5199    llvm_unreachable("protocol already synthesized");5200}5201 5202void RewriteObjCFragileABI::RewriteObjCProtocolListMetaData(5203                                const ObjCList<ObjCProtocolDecl> &Protocols,5204                                StringRef prefix, StringRef ClassName,5205                                std::string &Result) {5206  if (Protocols.empty()) return;5207 5208  for (unsigned i = 0; i != Protocols.size(); i++)5209    RewriteObjCProtocolMetaData(Protocols[i], prefix, ClassName, Result);5210 5211  // Output the top lovel protocol meta-data for the class.5212  /* struct _objc_protocol_list {5213   struct _objc_protocol_list *next;5214   int    protocol_count;5215   struct _objc_protocol *class_protocols[];5216   }5217   */5218  Result += "\nstatic struct {\n";5219  Result += "\tstruct _objc_protocol_list *next;\n";5220  Result += "\tint    protocol_count;\n";5221  Result += "\tstruct _objc_protocol *class_protocols[";5222  Result += utostr(Protocols.size());5223  Result += "];\n} _OBJC_";5224  Result += prefix;5225  Result += "_PROTOCOLS_";5226  Result += ClassName;5227  Result += " __attribute__ ((used, section (\"__OBJC, __cat_cls_meth\")))= "5228  "{\n\t0, ";5229  Result += utostr(Protocols.size());5230  Result += "\n";5231 5232  Result += "\t,{&_OBJC_PROTOCOL_";5233  Result += Protocols[0]->getNameAsString();5234  Result += " \n";5235 5236  for (unsigned i = 1; i != Protocols.size(); i++) {5237    Result += "\t ,&_OBJC_PROTOCOL_";5238    Result += Protocols[i]->getNameAsString();5239    Result += "\n";5240  }5241  Result += "\t }\n};\n";5242}5243 5244void RewriteObjCFragileABI::RewriteObjCClassMetaData(ObjCImplementationDecl *IDecl,5245                                           std::string &Result) {5246  ObjCInterfaceDecl *CDecl = IDecl->getClassInterface();5247 5248  // Explicitly declared @interface's are already synthesized.5249  if (CDecl->isImplicitInterfaceDecl()) {5250    // FIXME: Implementation of a class with no @interface (legacy) does not5251    // produce correct synthesis as yet.5252    RewriteObjCInternalStruct(CDecl, Result);5253  }5254 5255  // Build _objc_ivar_list metadata for classes ivars if needed5256  unsigned NumIvars =5257      !IDecl->ivar_empty() ? IDecl->ivar_size() : CDecl->ivar_size();5258  if (NumIvars > 0) {5259    static bool objc_ivar = false;5260    if (!objc_ivar) {5261      /* struct _objc_ivar {5262       char *ivar_name;5263       char *ivar_type;5264       int ivar_offset;5265       };5266       */5267      Result += "\nstruct _objc_ivar {\n";5268      Result += "\tchar *ivar_name;\n";5269      Result += "\tchar *ivar_type;\n";5270      Result += "\tint ivar_offset;\n";5271      Result += "};\n";5272 5273      objc_ivar = true;5274    }5275 5276    /* struct {5277     int ivar_count;5278     struct _objc_ivar ivar_list[nIvars];5279     };5280     */5281    Result += "\nstatic struct {\n";5282    Result += "\tint ivar_count;\n";5283    Result += "\tstruct _objc_ivar ivar_list[";5284    Result += utostr(NumIvars);5285    Result += "];\n} _OBJC_INSTANCE_VARIABLES_";5286    Result += IDecl->getNameAsString();5287    Result += " __attribute__ ((used, section (\"__OBJC, __instance_vars\")))= "5288    "{\n\t";5289    Result += utostr(NumIvars);5290    Result += "\n";5291 5292    ObjCInterfaceDecl::ivar_iterator IVI, IVE;5293    SmallVector<ObjCIvarDecl *, 8> IVars;5294    if (!IDecl->ivar_empty()) {5295      for (auto *IV : IDecl->ivars())5296        IVars.push_back(IV);5297      IVI = IDecl->ivar_begin();5298      IVE = IDecl->ivar_end();5299    } else {5300      IVI = CDecl->ivar_begin();5301      IVE = CDecl->ivar_end();5302    }5303    Result += "\t,{{\"";5304    Result += IVI->getNameAsString();5305    Result += "\", \"";5306    std::string TmpString, StrEncoding;5307    Context->getObjCEncodingForType(IVI->getType(), TmpString, *IVI);5308    QuoteDoublequotes(TmpString, StrEncoding);5309    Result += StrEncoding;5310    Result += "\", ";5311    RewriteIvarOffsetComputation(*IVI, Result);5312    Result += "}\n";5313    for (++IVI; IVI != IVE; ++IVI) {5314      Result += "\t  ,{\"";5315      Result += IVI->getNameAsString();5316      Result += "\", \"";5317      std::string TmpString, StrEncoding;5318      Context->getObjCEncodingForType(IVI->getType(), TmpString, *IVI);5319      QuoteDoublequotes(TmpString, StrEncoding);5320      Result += StrEncoding;5321      Result += "\", ";5322      RewriteIvarOffsetComputation(*IVI, Result);5323      Result += "}\n";5324    }5325 5326    Result += "\t }\n};\n";5327  }5328 5329  // Build _objc_method_list for class's instance methods if needed5330  SmallVector<ObjCMethodDecl *, 32> InstanceMethods(IDecl->instance_methods());5331 5332  // If any of our property implementations have associated getters or5333  // setters, produce metadata for them as well.5334  for (const auto *Prop : IDecl->property_impls()) {5335    if (Prop->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic)5336      continue;5337    if (!Prop->getPropertyIvarDecl())5338      continue;5339    ObjCPropertyDecl *PD = Prop->getPropertyDecl();5340    if (!PD)5341      continue;5342    if (ObjCMethodDecl *Getter = Prop->getGetterMethodDecl())5343      if (!Getter->isDefined())5344        InstanceMethods.push_back(Getter);5345    if (PD->isReadOnly())5346      continue;5347    if (ObjCMethodDecl *Setter = Prop->getSetterMethodDecl())5348      if (!Setter->isDefined())5349        InstanceMethods.push_back(Setter);5350  }5351  RewriteObjCMethodsMetaData(InstanceMethods.begin(), InstanceMethods.end(),5352                             true, "", IDecl->getName(), Result);5353 5354  // Build _objc_method_list for class's class methods if needed5355  RewriteObjCMethodsMetaData(IDecl->classmeth_begin(), IDecl->classmeth_end(),5356                             false, "", IDecl->getName(), Result);5357 5358  // Protocols referenced in class declaration?5359  RewriteObjCProtocolListMetaData(CDecl->getReferencedProtocols(),5360                                  "CLASS", CDecl->getName(), Result);5361 5362  // Declaration of class/meta-class metadata5363  /* struct _objc_class {5364   struct _objc_class *isa; // or const char *root_class_name when metadata5365   const char *super_class_name;5366   char *name;5367   long version;5368   long info;5369   long instance_size;5370   struct _objc_ivar_list *ivars;5371   struct _objc_method_list *methods;5372   struct objc_cache *cache;5373   struct objc_protocol_list *protocols;5374   const char *ivar_layout;5375   struct _objc_class_ext  *ext;5376   };5377   */5378  static bool objc_class = false;5379  if (!objc_class) {5380    Result += "\nstruct _objc_class {\n";5381    Result += "\tstruct _objc_class *isa;\n";5382    Result += "\tconst char *super_class_name;\n";5383    Result += "\tchar *name;\n";5384    Result += "\tlong version;\n";5385    Result += "\tlong info;\n";5386    Result += "\tlong instance_size;\n";5387    Result += "\tstruct _objc_ivar_list *ivars;\n";5388    Result += "\tstruct _objc_method_list *methods;\n";5389    Result += "\tstruct objc_cache *cache;\n";5390    Result += "\tstruct _objc_protocol_list *protocols;\n";5391    Result += "\tconst char *ivar_layout;\n";5392    Result += "\tstruct _objc_class_ext  *ext;\n";5393    Result += "};\n";5394    objc_class = true;5395  }5396 5397  // Meta-class metadata generation.5398  ObjCInterfaceDecl *RootClass = nullptr;5399  ObjCInterfaceDecl *SuperClass = CDecl->getSuperClass();5400  while (SuperClass) {5401    RootClass = SuperClass;5402    SuperClass = SuperClass->getSuperClass();5403  }5404  SuperClass = CDecl->getSuperClass();5405 5406  Result += "\nstatic struct _objc_class _OBJC_METACLASS_";5407  Result += CDecl->getNameAsString();5408  Result += " __attribute__ ((used, section (\"__OBJC, __meta_class\")))= "5409  "{\n\t(struct _objc_class *)\"";5410  Result += (RootClass ? RootClass->getNameAsString() : CDecl->getNameAsString());5411  Result += "\"";5412 5413  if (SuperClass) {5414    Result += ", \"";5415    Result += SuperClass->getNameAsString();5416    Result += "\", \"";5417    Result += CDecl->getNameAsString();5418    Result += "\"";5419  }5420  else {5421    Result += ", 0, \"";5422    Result += CDecl->getNameAsString();5423    Result += "\"";5424  }5425  // Set 'ivars' field for root class to 0. ObjC1 runtime does not use it.5426  // 'info' field is initialized to CLS_META(2) for metaclass5427  Result += ", 0,2, sizeof(struct _objc_class), 0";5428  if (IDecl->classmeth_begin() != IDecl->classmeth_end()) {5429    Result += "\n\t, (struct _objc_method_list *)&_OBJC_CLASS_METHODS_";5430    Result += IDecl->getNameAsString();5431    Result += "\n";5432  }5433  else5434    Result += ", 0\n";5435  if (CDecl->protocol_begin() != CDecl->protocol_end()) {5436    Result += "\t,0, (struct _objc_protocol_list *)&_OBJC_CLASS_PROTOCOLS_";5437    Result += CDecl->getNameAsString();5438    Result += ",0,0\n";5439  }5440  else5441    Result += "\t,0,0,0,0\n";5442  Result += "};\n";5443 5444  // class metadata generation.5445  Result += "\nstatic struct _objc_class _OBJC_CLASS_";5446  Result += CDecl->getNameAsString();5447  Result += " __attribute__ ((used, section (\"__OBJC, __class\")))= "5448  "{\n\t&_OBJC_METACLASS_";5449  Result += CDecl->getNameAsString();5450  if (SuperClass) {5451    Result += ", \"";5452    Result += SuperClass->getNameAsString();5453    Result += "\", \"";5454    Result += CDecl->getNameAsString();5455    Result += "\"";5456  }5457  else {5458    Result += ", 0, \"";5459    Result += CDecl->getNameAsString();5460    Result += "\"";5461  }5462  // 'info' field is initialized to CLS_CLASS(1) for class5463  Result += ", 0,1";5464  if (!ObjCSynthesizedStructs.count(CDecl))5465    Result += ",0";5466  else {5467    // class has size. Must synthesize its size.5468    Result += ",sizeof(struct ";5469    Result += CDecl->getNameAsString();5470    if (LangOpts.MicrosoftExt)5471      Result += "_IMPL";5472    Result += ")";5473  }5474  if (NumIvars > 0) {5475    Result += ", (struct _objc_ivar_list *)&_OBJC_INSTANCE_VARIABLES_";5476    Result += CDecl->getNameAsString();5477    Result += "\n\t";5478  }5479  else5480    Result += ",0";5481  if (IDecl->instmeth_begin() != IDecl->instmeth_end()) {5482    Result += ", (struct _objc_method_list *)&_OBJC_INSTANCE_METHODS_";5483    Result += CDecl->getNameAsString();5484    Result += ", 0\n\t";5485  }5486  else5487    Result += ",0,0";5488  if (CDecl->protocol_begin() != CDecl->protocol_end()) {5489    Result += ", (struct _objc_protocol_list*)&_OBJC_CLASS_PROTOCOLS_";5490    Result += CDecl->getNameAsString();5491    Result += ", 0,0\n";5492  }5493  else5494    Result += ",0,0,0\n";5495  Result += "};\n";5496}5497 5498void RewriteObjCFragileABI::RewriteMetaDataIntoBuffer(std::string &Result) {5499  int ClsDefCount = ClassImplementation.size();5500  int CatDefCount = CategoryImplementation.size();5501 5502  // For each implemented class, write out all its meta data.5503  for (int i = 0; i < ClsDefCount; i++)5504    RewriteObjCClassMetaData(ClassImplementation[i], Result);5505 5506  // For each implemented category, write out all its meta data.5507  for (int i = 0; i < CatDefCount; i++)5508    RewriteObjCCategoryImplDecl(CategoryImplementation[i], Result);5509 5510  // Write objc_symtab metadata5511  /*5512   struct _objc_symtab5513   {5514   long sel_ref_cnt;5515   SEL *refs;5516   short cls_def_cnt;5517   short cat_def_cnt;5518   void *defs[cls_def_cnt + cat_def_cnt];5519   };5520   */5521 5522  Result += "\nstruct _objc_symtab {\n";5523  Result += "\tlong sel_ref_cnt;\n";5524  Result += "\tSEL *refs;\n";5525  Result += "\tshort cls_def_cnt;\n";5526  Result += "\tshort cat_def_cnt;\n";5527  Result += "\tvoid *defs[" + utostr(ClsDefCount + CatDefCount)+ "];\n";5528  Result += "};\n\n";5529 5530  Result += "static struct _objc_symtab "5531  "_OBJC_SYMBOLS __attribute__((used, section (\"__OBJC, __symbols\")))= {\n";5532  Result += "\t0, 0, " + utostr(ClsDefCount)5533  + ", " + utostr(CatDefCount) + "\n";5534  for (int i = 0; i < ClsDefCount; i++) {5535    Result += "\t,&_OBJC_CLASS_";5536    Result += ClassImplementation[i]->getNameAsString();5537    Result += "\n";5538  }5539 5540  for (int i = 0; i < CatDefCount; i++) {5541    Result += "\t,&_OBJC_CATEGORY_";5542    Result += CategoryImplementation[i]->getClassInterface()->getNameAsString();5543    Result += "_";5544    Result += CategoryImplementation[i]->getNameAsString();5545    Result += "\n";5546  }5547 5548  Result += "};\n\n";5549 5550  // Write objc_module metadata5551 5552  /*5553   struct _objc_module {5554   long version;5555   long size;5556   const char *name;5557   struct _objc_symtab *symtab;5558   }5559   */5560 5561  Result += "\nstruct _objc_module {\n";5562  Result += "\tlong version;\n";5563  Result += "\tlong size;\n";5564  Result += "\tconst char *name;\n";5565  Result += "\tstruct _objc_symtab *symtab;\n";5566  Result += "};\n\n";5567  Result += "static struct _objc_module "5568  "_OBJC_MODULES __attribute__ ((used, section (\"__OBJC, __module_info\")))= {\n";5569  Result += "\t" + utostr(OBJC_ABI_VERSION) +5570  ", sizeof(struct _objc_module), \"\", &_OBJC_SYMBOLS\n";5571  Result += "};\n\n";5572 5573  if (LangOpts.MicrosoftExt) {5574    if (ProtocolExprDecls.size()) {5575      Result += "#pragma section(\".objc_protocol$B\",long,read,write)\n";5576      Result += "#pragma data_seg(push, \".objc_protocol$B\")\n";5577      for (ObjCProtocolDecl *ProtDecl : ProtocolExprDecls) {5578        Result += "static struct _objc_protocol *_POINTER_OBJC_PROTOCOL_";5579        Result += ProtDecl->getNameAsString();5580        Result += " = &_OBJC_PROTOCOL_";5581        Result += ProtDecl->getNameAsString();5582        Result += ";\n";5583      }5584      Result += "#pragma data_seg(pop)\n\n";5585    }5586    Result += "#pragma section(\".objc_module_info$B\",long,read,write)\n";5587    Result += "#pragma data_seg(push, \".objc_module_info$B\")\n";5588    Result += "static struct _objc_module *_POINTER_OBJC_MODULES = ";5589    Result += "&_OBJC_MODULES;\n";5590    Result += "#pragma data_seg(pop)\n\n";5591  }5592}5593 5594/// RewriteObjCCategoryImplDecl - Rewrite metadata for each category5595/// implementation.5596void RewriteObjCFragileABI::RewriteObjCCategoryImplDecl(ObjCCategoryImplDecl *IDecl,5597                                              std::string &Result) {5598  ObjCInterfaceDecl *ClassDecl = IDecl->getClassInterface();5599  // Find category declaration for this implementation.5600  ObjCCategoryDecl *CDecl5601    = ClassDecl->FindCategoryDeclaration(IDecl->getIdentifier());5602 5603  std::string FullCategoryName = ClassDecl->getNameAsString();5604  FullCategoryName += '_';5605  FullCategoryName += IDecl->getNameAsString();5606 5607  // Build _objc_method_list for class's instance methods if needed5608  SmallVector<ObjCMethodDecl *, 32> InstanceMethods(IDecl->instance_methods());5609 5610  // If any of our property implementations have associated getters or5611  // setters, produce metadata for them as well.5612  for (const auto *Prop : IDecl->property_impls()) {5613    if (Prop->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic)5614      continue;5615    if (!Prop->getPropertyIvarDecl())5616      continue;5617    ObjCPropertyDecl *PD = Prop->getPropertyDecl();5618    if (!PD)5619      continue;5620    if (ObjCMethodDecl *Getter = Prop->getGetterMethodDecl())5621      InstanceMethods.push_back(Getter);5622    if (PD->isReadOnly())5623      continue;5624    if (ObjCMethodDecl *Setter = Prop->getSetterMethodDecl())5625      InstanceMethods.push_back(Setter);5626  }5627  RewriteObjCMethodsMetaData(InstanceMethods.begin(), InstanceMethods.end(),5628                             true, "CATEGORY_", FullCategoryName, Result);5629 5630  // Build _objc_method_list for class's class methods if needed5631  RewriteObjCMethodsMetaData(IDecl->classmeth_begin(), IDecl->classmeth_end(),5632                             false, "CATEGORY_", FullCategoryName, Result);5633 5634  // Protocols referenced in class declaration?5635  // Null CDecl is case of a category implementation with no category interface5636  if (CDecl)5637    RewriteObjCProtocolListMetaData(CDecl->getReferencedProtocols(), "CATEGORY",5638                                    FullCategoryName, Result);5639  /* struct _objc_category {5640   char *category_name;5641   char *class_name;5642   struct _objc_method_list *instance_methods;5643   struct _objc_method_list *class_methods;5644   struct _objc_protocol_list *protocols;5645   // Objective-C 1.0 extensions5646   uint32_t size;     // sizeof (struct _objc_category)5647   struct _objc_property_list *instance_properties;  // category's own5648   // @property decl.5649   };5650   */5651 5652  static bool objc_category = false;5653  if (!objc_category) {5654    Result += "\nstruct _objc_category {\n";5655    Result += "\tchar *category_name;\n";5656    Result += "\tchar *class_name;\n";5657    Result += "\tstruct _objc_method_list *instance_methods;\n";5658    Result += "\tstruct _objc_method_list *class_methods;\n";5659    Result += "\tstruct _objc_protocol_list *protocols;\n";5660    Result += "\tunsigned int size;\n";5661    Result += "\tstruct _objc_property_list *instance_properties;\n";5662    Result += "};\n";5663    objc_category = true;5664  }5665  Result += "\nstatic struct _objc_category _OBJC_CATEGORY_";5666  Result += FullCategoryName;5667  Result += " __attribute__ ((used, section (\"__OBJC, __category\")))= {\n\t\"";5668  Result += IDecl->getNameAsString();5669  Result += "\"\n\t, \"";5670  Result += ClassDecl->getNameAsString();5671  Result += "\"\n";5672 5673  if (IDecl->instmeth_begin() != IDecl->instmeth_end()) {5674    Result += "\t, (struct _objc_method_list *)"5675    "&_OBJC_CATEGORY_INSTANCE_METHODS_";5676    Result += FullCategoryName;5677    Result += "\n";5678  }5679  else5680    Result += "\t, 0\n";5681  if (IDecl->classmeth_begin() != IDecl->classmeth_end()) {5682    Result += "\t, (struct _objc_method_list *)"5683    "&_OBJC_CATEGORY_CLASS_METHODS_";5684    Result += FullCategoryName;5685    Result += "\n";5686  }5687  else5688    Result += "\t, 0\n";5689 5690  if (CDecl && CDecl->protocol_begin() != CDecl->protocol_end()) {5691    Result += "\t, (struct _objc_protocol_list *)&_OBJC_CATEGORY_PROTOCOLS_";5692    Result += FullCategoryName;5693    Result += "\n";5694  }5695  else5696    Result += "\t, 0\n";5697  Result += "\t, sizeof(struct _objc_category), 0\n};\n";5698}5699 5700// RewriteObjCMethodsMetaData - Rewrite methods metadata for instance or5701/// class methods.5702template<typename MethodIterator>5703void RewriteObjCFragileABI::RewriteObjCMethodsMetaData(MethodIterator MethodBegin,5704                                             MethodIterator MethodEnd,5705                                             bool IsInstanceMethod,5706                                             StringRef prefix,5707                                             StringRef ClassName,5708                                             std::string &Result) {5709  if (MethodBegin == MethodEnd) return;5710 5711  if (!objc_impl_method) {5712    /* struct _objc_method {5713     SEL _cmd;5714     char *method_types;5715     void *_imp;5716     }5717     */5718    Result += "\nstruct _objc_method {\n";5719    Result += "\tSEL _cmd;\n";5720    Result += "\tchar *method_types;\n";5721    Result += "\tvoid *_imp;\n";5722    Result += "};\n";5723 5724    objc_impl_method = true;5725  }5726 5727  // Build _objc_method_list for class's methods if needed5728 5729  /* struct  {5730   struct _objc_method_list *next_method;5731   int method_count;5732   struct _objc_method method_list[];5733   }5734   */5735  unsigned NumMethods = std::distance(MethodBegin, MethodEnd);5736  Result += "\nstatic struct {\n";5737  Result += "\tstruct _objc_method_list *next_method;\n";5738  Result += "\tint method_count;\n";5739  Result += "\tstruct _objc_method method_list[";5740  Result += utostr(NumMethods);5741  Result += "];\n} _OBJC_";5742  Result += prefix;5743  Result += IsInstanceMethod ? "INSTANCE" : "CLASS";5744  Result += "_METHODS_";5745  Result += ClassName;5746  Result += " __attribute__ ((used, section (\"__OBJC, __";5747  Result += IsInstanceMethod ? "inst" : "cls";5748  Result += "_meth\")))= ";5749  Result += "{\n\t0, " + utostr(NumMethods) + "\n";5750 5751  Result += "\t,{{(SEL)\"";5752  Result += (*MethodBegin)->getSelector().getAsString();5753  std::string MethodTypeString =5754    Context->getObjCEncodingForMethodDecl(*MethodBegin);5755  Result += "\", \"";5756  Result += MethodTypeString;5757  Result += "\", (void *)";5758  Result += MethodInternalNames[*MethodBegin];5759  Result += "}\n";5760  for (++MethodBegin; MethodBegin != MethodEnd; ++MethodBegin) {5761    Result += "\t  ,{(SEL)\"";5762    Result += (*MethodBegin)->getSelector().getAsString();5763    std::string MethodTypeString =5764      Context->getObjCEncodingForMethodDecl(*MethodBegin);5765    Result += "\", \"";5766    Result += MethodTypeString;5767    Result += "\", (void *)";5768    Result += MethodInternalNames[*MethodBegin];5769    Result += "}\n";5770  }5771  Result += "\t }\n};\n";5772}5773 5774Stmt *RewriteObjCFragileABI::RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV) {5775  SourceRange OldRange = IV->getSourceRange();5776  Expr *BaseExpr = IV->getBase();5777 5778  // Rewrite the base, but without actually doing replaces.5779  {5780    DisableReplaceStmtScope S(*this);5781    BaseExpr = cast<Expr>(RewriteFunctionBodyOrGlobalInitializer(BaseExpr));5782    IV->setBase(BaseExpr);5783  }5784 5785  ObjCIvarDecl *D = IV->getDecl();5786 5787  Expr *Replacement = IV;5788  if (CurMethodDef) {5789    if (BaseExpr->getType()->isObjCObjectPointerType()) {5790      const ObjCInterfaceType *iFaceDecl =5791      dyn_cast<ObjCInterfaceType>(BaseExpr->getType()->getPointeeType());5792      assert(iFaceDecl && "RewriteObjCIvarRefExpr - iFaceDecl is null");5793      // lookup which class implements the instance variable.5794      ObjCInterfaceDecl *clsDeclared = nullptr;5795      iFaceDecl->getDecl()->lookupInstanceVariable(D->getIdentifier(),5796                                                   clsDeclared);5797      assert(clsDeclared && "RewriteObjCIvarRefExpr(): Can't find class");5798 5799      // Synthesize an explicit cast to gain access to the ivar.5800      std::string RecName =5801          std::string(clsDeclared->getIdentifier()->getName());5802      RecName += "_IMPL";5803      IdentifierInfo *II = &Context->Idents.get(RecName);5804      RecordDecl *RD =5805          RecordDecl::Create(*Context, TagTypeKind::Struct, TUDecl,5806                             SourceLocation(), SourceLocation(), II);5807      assert(RD && "RewriteObjCIvarRefExpr(): Can't find RecordDecl");5808      QualType castT =5809          Context->getPointerType(Context->getCanonicalTagType(RD));5810      CastExpr *castExpr = NoTypeInfoCStyleCastExpr(Context, castT,5811                                                    CK_BitCast,5812                                                    IV->getBase());5813      // Don't forget the parens to enforce the proper binding.5814      ParenExpr *PE = new (Context) ParenExpr(OldRange.getBegin(),5815                                              OldRange.getEnd(),5816                                              castExpr);5817      if (IV->isFreeIvar() &&5818          declaresSameEntity(CurMethodDef->getClassInterface(),5819                             iFaceDecl->getDecl())) {5820        MemberExpr *ME = MemberExpr::CreateImplicit(5821            *Context, PE, true, D, D->getType(), VK_LValue, OK_Ordinary);5822        Replacement = ME;5823      } else {5824        IV->setBase(PE);5825      }5826    }5827  } else { // we are outside a method.5828    assert(!IV->isFreeIvar() && "Cannot have a free standing ivar outside a method");5829 5830    // Explicit ivar refs need to have a cast inserted.5831    // FIXME: consider sharing some of this code with the code above.5832    if (BaseExpr->getType()->isObjCObjectPointerType()) {5833      const ObjCInterfaceType *iFaceDecl =5834      dyn_cast<ObjCInterfaceType>(BaseExpr->getType()->getPointeeType());5835      // lookup which class implements the instance variable.5836      ObjCInterfaceDecl *clsDeclared = nullptr;5837      iFaceDecl->getDecl()->lookupInstanceVariable(D->getIdentifier(),5838                                                   clsDeclared);5839      assert(clsDeclared && "RewriteObjCIvarRefExpr(): Can't find class");5840 5841      // Synthesize an explicit cast to gain access to the ivar.5842      std::string RecName =5843          std::string(clsDeclared->getIdentifier()->getName());5844      RecName += "_IMPL";5845      IdentifierInfo *II = &Context->Idents.get(RecName);5846      RecordDecl *RD =5847          RecordDecl::Create(*Context, TagTypeKind::Struct, TUDecl,5848                             SourceLocation(), SourceLocation(), II);5849      assert(RD && "RewriteObjCIvarRefExpr(): Can't find RecordDecl");5850      QualType castT =5851          Context->getPointerType(Context->getCanonicalTagType(RD));5852      CastExpr *castExpr = NoTypeInfoCStyleCastExpr(Context, castT,5853                                                    CK_BitCast,5854                                                    IV->getBase());5855      // Don't forget the parens to enforce the proper binding.5856      ParenExpr *PE = new (Context) ParenExpr(5857          IV->getBase()->getBeginLoc(), IV->getBase()->getEndLoc(), castExpr);5858      // Cannot delete IV->getBase(), since PE points to it.5859      // Replace the old base with the cast. This is important when doing5860      // embedded rewrites. For example, [newInv->_container addObject:0].5861      IV->setBase(PE);5862    }5863  }5864 5865  ReplaceStmtWithRange(IV, Replacement, OldRange);5866  return Replacement;5867}5868 5869#endif // CLANG_ENABLE_OBJC_REWRITER5870