brintos

brintos / llvm-project-archived public Read only

0
0
Text · 286.3 KiB · dee29fe Raw
7527 lines · cpp
1//===-- RewriteModernObjC.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/AST/AST.h"14#include "clang/AST/ASTConsumer.h"15#include "clang/AST/Attr.h"16#include "clang/AST/ParentMap.h"17#include "clang/Basic/CharInfo.h"18#include "clang/Basic/Diagnostic.h"19#include "clang/Basic/IdentifierTable.h"20#include "clang/Basic/SourceManager.h"21#include "clang/Basic/TargetInfo.h"22#include "clang/Config/config.h"23#include "clang/Lex/Lexer.h"24#include "clang/Rewrite/Core/Rewriter.h"25#include "clang/Rewrite/Frontend/ASTConsumers.h"26#include "llvm/ADT/DenseSet.h"27#include "llvm/ADT/SetVector.h"28#include "llvm/ADT/SmallPtrSet.h"29#include "llvm/ADT/StringExtras.h"30#include "llvm/Support/MemoryBuffer.h"31#include "llvm/Support/raw_ostream.h"32#include <memory>33 34#if CLANG_ENABLE_OBJC_REWRITER35 36using namespace clang;37using llvm::RewriteBuffer;38using llvm::utostr;39 40namespace {41  class RewriteModernObjC : public ASTConsumer {42  protected:43 44    enum {45      BLOCK_FIELD_IS_OBJECT   =  3,  /* id, NSObject, __attribute__((NSObject)),46                                        block, ... */47      BLOCK_FIELD_IS_BLOCK    =  7,  /* a block variable */48      BLOCK_FIELD_IS_BYREF    =  8,  /* the on stack structure holding the49                                        __block variable */50      BLOCK_FIELD_IS_WEAK     = 16,  /* declared __weak, only used in byref copy51                                        helpers */52      BLOCK_BYREF_CALLER      = 128, /* called from __block (byref) copy/dispose53                                        support routines */54      BLOCK_BYREF_CURRENT_MAX = 25655    };56 57    enum {58      BLOCK_NEEDS_FREE =        (1 << 24),59      BLOCK_HAS_COPY_DISPOSE =  (1 << 25),60      BLOCK_HAS_CXX_OBJ =       (1 << 26),61      BLOCK_IS_GC =             (1 << 27),62      BLOCK_IS_GLOBAL =         (1 << 28),63      BLOCK_HAS_DESCRIPTOR =    (1 << 29)64    };65 66    Rewriter Rewrite;67    DiagnosticsEngine &Diags;68    const LangOptions &LangOpts;69    ASTContext *Context;70    SourceManager *SM;71    TranslationUnitDecl *TUDecl;72    FileID MainFileID;73    const char *MainFileStart, *MainFileEnd;74    Stmt *CurrentBody;75    ParentMap *PropParentMap; // created lazily.76    std::string InFileName;77    std::unique_ptr<raw_ostream> OutFile;78    std::string Preamble;79 80    TypeDecl *ProtocolTypeDecl;81    VarDecl *GlobalVarDecl;82    Expr *GlobalConstructionExp;83    unsigned RewriteFailedDiag;84    unsigned GlobalBlockRewriteFailedDiag;85    // ObjC string constant support.86    unsigned NumObjCStringLiterals;87    VarDecl *ConstantStringClassReference;88    RecordDecl *NSStringRecord;89 90    // ObjC foreach break/continue generation support.91    int BcLabelCount;92 93    unsigned TryFinallyContainsReturnDiag;94    // Needed for super.95    ObjCMethodDecl *CurMethodDef;96    RecordDecl *SuperStructDecl;97    RecordDecl *ConstantStringDecl;98 99    FunctionDecl *MsgSendFunctionDecl;100    FunctionDecl *MsgSendSuperFunctionDecl;101    FunctionDecl *MsgSendStretFunctionDecl;102    FunctionDecl *MsgSendSuperStretFunctionDecl;103    FunctionDecl *MsgSendFpretFunctionDecl;104    FunctionDecl *GetClassFunctionDecl;105    FunctionDecl *GetMetaClassFunctionDecl;106    FunctionDecl *GetSuperClassFunctionDecl;107    FunctionDecl *SelGetUidFunctionDecl;108    FunctionDecl *CFStringFunctionDecl;109    FunctionDecl *SuperConstructorFunctionDecl;110    FunctionDecl *CurFunctionDef;111 112    /* Misc. containers needed for meta-data rewrite. */113    SmallVector<ObjCImplementationDecl *, 8> ClassImplementation;114    SmallVector<ObjCCategoryImplDecl *, 8> CategoryImplementation;115    llvm::SmallPtrSet<ObjCInterfaceDecl*, 8> ObjCSynthesizedStructs;116    llvm::SmallPtrSet<ObjCProtocolDecl*, 8> ObjCSynthesizedProtocols;117    llvm::SmallPtrSet<ObjCInterfaceDecl*, 8> ObjCWrittenInterfaces;118    llvm::SmallPtrSet<TagDecl*, 32> GlobalDefinedTags;119    SmallVector<ObjCInterfaceDecl*, 32> ObjCInterfacesSeen;120    /// DefinedNonLazyClasses - List of defined "non-lazy" classes.121    SmallVector<ObjCInterfaceDecl*, 8> DefinedNonLazyClasses;122 123    /// DefinedNonLazyCategories - List of defined "non-lazy" categories.124    SmallVector<ObjCCategoryDecl *, 8> DefinedNonLazyCategories;125 126    SmallVector<Stmt *, 32> Stmts;127    SmallVector<int, 8> ObjCBcLabelNo;128    // Remember all the @protocol(<expr>) expressions.129    llvm::SmallPtrSet<ObjCProtocolDecl *, 32> ProtocolExprDecls;130 131    llvm::DenseSet<uint64_t> CopyDestroyCache;132 133    // Block expressions.134    SmallVector<BlockExpr *, 32> Blocks;135    SmallVector<int, 32> InnerDeclRefsCount;136    SmallVector<DeclRefExpr *, 32> InnerDeclRefs;137 138    SmallVector<DeclRefExpr *, 32> BlockDeclRefs;139 140    // Block related declarations.141    llvm::SmallSetVector<ValueDecl *, 8> BlockByCopyDecls;142    llvm::SmallSetVector<ValueDecl *, 8> BlockByRefDecls;143    llvm::DenseMap<ValueDecl *, unsigned> BlockByRefDeclNo;144    llvm::SmallPtrSet<ValueDecl *, 8> ImportedBlockDecls;145    llvm::SmallPtrSet<VarDecl *, 8> ImportedLocalExternalDecls;146 147    llvm::DenseMap<BlockExpr *, std::string> RewrittenBlockExprs;148    llvm::DenseMap<ObjCInterfaceDecl *,149                    llvm::SmallSetVector<ObjCIvarDecl *, 8> > ReferencedIvars;150 151    // ivar bitfield grouping containers152    llvm::DenseSet<const ObjCInterfaceDecl *> ObjCInterefaceHasBitfieldGroups;153    llvm::DenseMap<const ObjCIvarDecl* , unsigned> IvarGroupNumber;154    // This container maps an <class, group number for ivar> tuple to the type155    // of the struct where the bitfield belongs.156    llvm::DenseMap<std::pair<const ObjCInterfaceDecl*, unsigned>, QualType> GroupRecordType;157    SmallVector<FunctionDecl*, 32> FunctionDefinitionsSeen;158 159    // This maps an original source AST to it's rewritten form. This allows160    // us to avoid rewriting the same node twice (which is very uncommon).161    // This is needed to support some of the exotic property rewriting.162    llvm::DenseMap<Stmt *, Stmt *> ReplacedNodes;163 164    // Needed for header files being rewritten165    bool IsHeader;166    bool SilenceRewriteMacroWarning;167    bool GenerateLineInfo;168    bool objc_impl_method;169 170    bool DisableReplaceStmt;171    class DisableReplaceStmtScope {172      RewriteModernObjC &R;173      bool SavedValue;174 175    public:176      DisableReplaceStmtScope(RewriteModernObjC &R)177        : R(R), SavedValue(R.DisableReplaceStmt) {178        R.DisableReplaceStmt = true;179      }180      ~DisableReplaceStmtScope() {181        R.DisableReplaceStmt = SavedValue;182      }183    };184    void InitializeCommon(ASTContext &context);185 186  public:187    llvm::DenseMap<ObjCMethodDecl*, std::string> MethodInternalNames;188 189    // Top Level Driver code.190    bool HandleTopLevelDecl(DeclGroupRef D) override {191      for (DeclGroupRef::iterator I = D.begin(), E = D.end(); I != E; ++I) {192        if (ObjCInterfaceDecl *Class = dyn_cast<ObjCInterfaceDecl>(*I)) {193          if (!Class->isThisDeclarationADefinition()) {194            RewriteForwardClassDecl(D);195            break;196          } else {197            // Keep track of all interface declarations seen.198            ObjCInterfacesSeen.push_back(Class);199            break;200          }201        }202 203        if (ObjCProtocolDecl *Proto = dyn_cast<ObjCProtocolDecl>(*I)) {204          if (!Proto->isThisDeclarationADefinition()) {205            RewriteForwardProtocolDecl(D);206            break;207          }208        }209 210        if (FunctionDecl *FDecl = dyn_cast<FunctionDecl>(*I)) {211          // Under modern abi, we cannot translate body of the function212          // yet until all class extensions and its implementation is seen.213          // This is because they may introduce new bitfields which must go214          // into their grouping struct.215          if (FDecl->isThisDeclarationADefinition() &&216              // Not c functions defined inside an objc container.217              !FDecl->isTopLevelDeclInObjCContainer()) {218            FunctionDefinitionsSeen.push_back(FDecl);219            break;220          }221        }222        HandleTopLevelSingleDecl(*I);223      }224      return true;225    }226 227    void HandleTopLevelDeclInObjCContainer(DeclGroupRef D) override {228      for (DeclGroupRef::iterator I = D.begin(), E = D.end(); I != E; ++I) {229        if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(*I)) {230          if (isTopLevelBlockPointerType(TD->getUnderlyingType()))231            RewriteBlockPointerDecl(TD);232          else if (TD->getUnderlyingType()->isFunctionPointerType())233            CheckFunctionPointerDecl(TD->getUnderlyingType(), TD);234          else235            RewriteObjCQualifiedInterfaceTypes(TD);236        }237      }238    }239 240    void HandleTopLevelSingleDecl(Decl *D);241    void HandleDeclInMainFile(Decl *D);242    RewriteModernObjC(std::string inFile, std::unique_ptr<raw_ostream> OS,243                      DiagnosticsEngine &D, const LangOptions &LOpts,244                      bool silenceMacroWarn, bool LineInfo);245 246    ~RewriteModernObjC() override {}247 248    void HandleTranslationUnit(ASTContext &C) override;249 250    void ReplaceStmt(Stmt *Old, Stmt *New) {251      ReplaceStmtWithRange(Old, New, Old->getSourceRange());252    }253 254    void ReplaceStmtWithRange(Stmt *Old, Stmt *New, SourceRange SrcRange) {255      assert(Old != nullptr && New != nullptr && "Expected non-null Stmt's");256 257      Stmt *ReplacingStmt = ReplacedNodes[Old];258      if (ReplacingStmt)259        return; // We can't rewrite the same node twice.260 261      if (DisableReplaceStmt)262        return;263 264      // Measure the old text.265      int Size = Rewrite.getRangeSize(SrcRange);266      if (Size == -1) {267        Diags.Report(Context->getFullLoc(Old->getBeginLoc()), RewriteFailedDiag)268            << Old->getSourceRange();269        return;270      }271      // Get the new text.272      std::string SStr;273      llvm::raw_string_ostream S(SStr);274      New->printPretty(S, nullptr, PrintingPolicy(LangOpts));275 276      // If replacement succeeded or warning disabled return with no warning.277      if (!Rewrite.ReplaceText(SrcRange.getBegin(), Size, SStr)) {278        ReplacedNodes[Old] = New;279        return;280      }281      if (SilenceRewriteMacroWarning)282        return;283      Diags.Report(Context->getFullLoc(Old->getBeginLoc()), RewriteFailedDiag)284          << Old->getSourceRange();285    }286 287    void InsertText(SourceLocation Loc, StringRef Str,288                    bool InsertAfter = true) {289      // If insertion succeeded or warning disabled return with no warning.290      if (!Rewrite.InsertText(Loc, Str, InsertAfter) ||291          SilenceRewriteMacroWarning)292        return;293 294      Diags.Report(Context->getFullLoc(Loc), RewriteFailedDiag);295    }296 297    void ReplaceText(SourceLocation Start, unsigned OrigLength,298                     StringRef Str) {299      // If removal succeeded or warning disabled return with no warning.300      if (!Rewrite.ReplaceText(Start, OrigLength, Str) ||301          SilenceRewriteMacroWarning)302        return;303 304      Diags.Report(Context->getFullLoc(Start), RewriteFailedDiag);305    }306 307    // Syntactic Rewriting.308    void RewriteRecordBody(RecordDecl *RD);309    void RewriteInclude();310    void RewriteLineDirective(const Decl *D);311    void ConvertSourceLocationToLineDirective(SourceLocation Loc,312                                              std::string &LineString);313    void RewriteForwardClassDecl(DeclGroupRef D);314    void RewriteForwardClassDecl(const SmallVectorImpl<Decl *> &DG);315    void RewriteForwardClassEpilogue(ObjCInterfaceDecl *ClassDecl,316                                     const std::string &typedefString);317    void RewriteImplementations();318    void RewritePropertyImplDecl(ObjCPropertyImplDecl *PID,319                                 ObjCImplementationDecl *IMD,320                                 ObjCCategoryImplDecl *CID);321    void RewriteInterfaceDecl(ObjCInterfaceDecl *Dcl);322    void RewriteImplementationDecl(Decl *Dcl);323    void RewriteObjCMethodDecl(const ObjCInterfaceDecl *IDecl,324                               ObjCMethodDecl *MDecl, std::string &ResultStr);325    void RewriteTypeIntoString(QualType T, std::string &ResultStr,326                               const FunctionType *&FPRetType);327    void RewriteByRefString(std::string &ResultStr, const std::string &Name,328                            ValueDecl *VD, bool def=false);329    void RewriteCategoryDecl(ObjCCategoryDecl *Dcl);330    void RewriteProtocolDecl(ObjCProtocolDecl *Dcl);331    void RewriteForwardProtocolDecl(DeclGroupRef D);332    void RewriteForwardProtocolDecl(const SmallVectorImpl<Decl *> &DG);333    void RewriteMethodDeclaration(ObjCMethodDecl *Method);334    void RewriteProperty(ObjCPropertyDecl *prop);335    void RewriteFunctionDecl(FunctionDecl *FD);336    void RewriteBlockPointerType(std::string& Str, QualType Type);337    void RewriteBlockPointerTypeVariable(std::string& Str, ValueDecl *VD);338    void RewriteBlockLiteralFunctionDecl(FunctionDecl *FD);339    void RewriteObjCQualifiedInterfaceTypes(Decl *Dcl);340    void RewriteTypeOfDecl(VarDecl *VD);341    void RewriteObjCQualifiedInterfaceTypes(Expr *E);342 343    std::string getIvarAccessString(ObjCIvarDecl *D);344 345    // Expression Rewriting.346    Stmt *RewriteFunctionBodyOrGlobalInitializer(Stmt *S);347    Stmt *RewriteAtEncode(ObjCEncodeExpr *Exp);348    Stmt *RewritePropertyOrImplicitGetter(PseudoObjectExpr *Pseudo);349    Stmt *RewritePropertyOrImplicitSetter(PseudoObjectExpr *Pseudo);350    Stmt *RewriteAtSelector(ObjCSelectorExpr *Exp);351    Stmt *RewriteMessageExpr(ObjCMessageExpr *Exp);352    Stmt *RewriteObjCStringLiteral(ObjCStringLiteral *Exp);353    Stmt *RewriteObjCBoolLiteralExpr(ObjCBoolLiteralExpr *Exp);354    Stmt *RewriteObjCBoxedExpr(ObjCBoxedExpr *Exp);355    Stmt *RewriteObjCArrayLiteralExpr(ObjCArrayLiteral *Exp);356    Stmt *RewriteObjCDictionaryLiteralExpr(ObjCDictionaryLiteral *Exp);357    Stmt *RewriteObjCProtocolExpr(ObjCProtocolExpr *Exp);358    Stmt *RewriteObjCTryStmt(ObjCAtTryStmt *S);359    Stmt *RewriteObjCAutoreleasePoolStmt(ObjCAutoreleasePoolStmt  *S);360    Stmt *RewriteObjCSynchronizedStmt(ObjCAtSynchronizedStmt *S);361    Stmt *RewriteObjCThrowStmt(ObjCAtThrowStmt *S);362    Stmt *RewriteObjCForCollectionStmt(ObjCForCollectionStmt *S,363                                       SourceLocation OrigEnd);364    Stmt *RewriteBreakStmt(BreakStmt *S);365    Stmt *RewriteContinueStmt(ContinueStmt *S);366    void RewriteCastExpr(CStyleCastExpr *CE);367    void RewriteImplicitCastObjCExpr(CastExpr *IE);368 369    // Computes ivar bitfield group no.370    unsigned ObjCIvarBitfieldGroupNo(ObjCIvarDecl *IV);371    // Names field decl. for ivar bitfield group.372    void ObjCIvarBitfieldGroupDecl(ObjCIvarDecl *IV, std::string &Result);373    // Names struct type for ivar bitfield group.374    void ObjCIvarBitfieldGroupType(ObjCIvarDecl *IV, std::string &Result);375    // Names symbol for ivar bitfield group field offset.376    void ObjCIvarBitfieldGroupOffset(ObjCIvarDecl *IV, std::string &Result);377    // Given an ivar bitfield, it builds (or finds) its group record type.378    QualType GetGroupRecordTypeForObjCIvarBitfield(ObjCIvarDecl *IV);379    QualType SynthesizeBitfieldGroupStructType(380                                    ObjCIvarDecl *IV,381                                    SmallVectorImpl<ObjCIvarDecl *> &IVars);382 383    // Block rewriting.384    void RewriteBlocksInFunctionProtoType(QualType funcType, NamedDecl *D);385 386    // Block specific rewrite rules.387    void RewriteBlockPointerDecl(NamedDecl *VD);388    void RewriteByRefVar(VarDecl *VD, bool firstDecl, bool lastDecl);389    Stmt *RewriteBlockDeclRefExpr(DeclRefExpr *VD);390    Stmt *RewriteLocalVariableExternalStorage(DeclRefExpr *DRE);391    void RewriteBlockPointerFunctionArgs(FunctionDecl *FD);392 393    void RewriteObjCInternalStruct(ObjCInterfaceDecl *CDecl,394                                      std::string &Result);395 396    void RewriteObjCFieldDecl(FieldDecl *fieldDecl, std::string &Result);397    bool IsTagDefinedInsideClass(ObjCContainerDecl *IDecl, TagDecl *Tag,398                                 bool &IsNamedDefinition);399    void RewriteLocallyDefinedNamedAggregates(FieldDecl *fieldDecl,400                                              std::string &Result);401 402    bool RewriteObjCFieldDeclType(QualType &Type, std::string &Result);403 404    void RewriteIvarOffsetSymbols(ObjCInterfaceDecl *CDecl,405                                  std::string &Result);406 407    void Initialize(ASTContext &context) override;408 409    // Misc. AST transformation routines. Sometimes they end up calling410    // rewriting routines on the new ASTs.411    CallExpr *SynthesizeCallToFunctionDecl(FunctionDecl *FD,412                                           ArrayRef<Expr *> Args,413                                           SourceLocation StartLoc=SourceLocation(),414                                           SourceLocation EndLoc=SourceLocation());415 416    Expr *SynthMsgSendStretCallExpr(FunctionDecl *MsgSendStretFlavor,417                                        QualType returnType,418                                        SmallVectorImpl<QualType> &ArgTypes,419                                        SmallVectorImpl<Expr*> &MsgExprs,420                                        ObjCMethodDecl *Method);421 422    Stmt *SynthMessageExpr(ObjCMessageExpr *Exp,423                           SourceLocation StartLoc=SourceLocation(),424                           SourceLocation EndLoc=SourceLocation());425 426    void SynthCountByEnumWithState(std::string &buf);427    void SynthMsgSendFunctionDecl();428    void SynthMsgSendSuperFunctionDecl();429    void SynthMsgSendStretFunctionDecl();430    void SynthMsgSendFpretFunctionDecl();431    void SynthMsgSendSuperStretFunctionDecl();432    void SynthGetClassFunctionDecl();433    void SynthGetMetaClassFunctionDecl();434    void SynthGetSuperClassFunctionDecl();435    void SynthSelGetUidFunctionDecl();436    void SynthSuperConstructorFunctionDecl();437 438    // Rewriting metadata439    template<typename MethodIterator>440    void RewriteObjCMethodsMetaData(MethodIterator MethodBegin,441                                    MethodIterator MethodEnd,442                                    bool IsInstanceMethod,443                                    StringRef prefix,444                                    StringRef ClassName,445                                    std::string &Result);446    void RewriteObjCProtocolMetaData(ObjCProtocolDecl *Protocol,447                                     std::string &Result);448    void RewriteObjCClassMetaData(ObjCImplementationDecl *IDecl,449                                          std::string &Result);450    void RewriteClassSetupInitHook(std::string &Result);451 452    void RewriteMetaDataIntoBuffer(std::string &Result);453    void WriteImageInfo(std::string &Result);454    void RewriteObjCCategoryImplDecl(ObjCCategoryImplDecl *CDecl,455                                             std::string &Result);456    void RewriteCategorySetupInitHook(std::string &Result);457 458    // Rewriting ivar459    void RewriteIvarOffsetComputation(ObjCIvarDecl *ivar,460                                              std::string &Result);461    Stmt *RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV);462 463 464    std::string SynthesizeByrefCopyDestroyHelper(VarDecl *VD, int flag);465    std::string SynthesizeBlockHelperFuncs(BlockExpr *CE, int i,466                                           StringRef funcName,467                                           const std::string &Tag);468    std::string SynthesizeBlockFunc(BlockExpr *CE, int i, StringRef funcName,469                                    const std::string &Tag);470    std::string SynthesizeBlockImpl(BlockExpr *CE, const std::string &Tag,471                                    const std::string &Desc);472    std::string SynthesizeBlockDescriptor(const std::string &DescTag,473                                          const std::string &ImplTag, int i,474                                          StringRef funcName, unsigned hasCopy);475    Stmt *SynthesizeBlockCall(CallExpr *Exp, const Expr* BlockExp);476    void SynthesizeBlockLiterals(SourceLocation FunLocStart,477                                 StringRef FunName);478    FunctionDecl *SynthBlockInitFunctionDecl(StringRef name);479    Stmt *SynthBlockInitExpr(BlockExpr *Exp,480                      const SmallVectorImpl<DeclRefExpr *> &InnerBlockDeclRefs);481 482    // Misc. helper routines.483    QualType getProtocolType();484    void WarnAboutReturnGotoStmts(Stmt *S);485    void CheckFunctionPointerDecl(QualType dType, NamedDecl *ND);486    void InsertBlockLiteralsWithinFunction(FunctionDecl *FD);487    void InsertBlockLiteralsWithinMethod(ObjCMethodDecl *MD);488 489    bool IsDeclStmtInForeachHeader(DeclStmt *DS);490    void CollectBlockDeclRefInfo(BlockExpr *Exp);491    void GetBlockDeclRefExprs(Stmt *S);492    void GetInnerBlockDeclRefExprs(Stmt *S,493                SmallVectorImpl<DeclRefExpr *> &InnerBlockDeclRefs,494                llvm::SmallPtrSetImpl<const DeclContext *> &InnerContexts);495 496    // We avoid calling Type::isBlockPointerType(), since it operates on the497    // canonical type. We only care if the top-level type is a closure pointer.498    bool isTopLevelBlockPointerType(QualType T) {499      return isa<BlockPointerType>(T);500    }501 502    /// convertBlockPointerToFunctionPointer - Converts a block-pointer type503    /// to a function pointer type and upon success, returns true; false504    /// otherwise.505    bool convertBlockPointerToFunctionPointer(QualType &T) {506      if (isTopLevelBlockPointerType(T)) {507        const auto *BPT = T->castAs<BlockPointerType>();508        T = Context->getPointerType(BPT->getPointeeType());509        return true;510      }511      return false;512    }513 514    bool convertObjCTypeToCStyleType(QualType &T);515 516    bool needToScanForQualifiers(QualType T);517    QualType getSuperStructType();518    QualType getConstantStringStructType();519    QualType convertFunctionTypeOfBlocks(const FunctionType *FT);520 521    void convertToUnqualifiedObjCType(QualType &T) {522      if (T->isObjCQualifiedIdType()) {523        bool isConst = T.isConstQualified();524        T = isConst ? Context->getObjCIdType().withConst()525                    : Context->getObjCIdType();526      }527      else if (T->isObjCQualifiedClassType())528        T = Context->getObjCClassType();529      else if (T->isObjCObjectPointerType() &&530               T->getPointeeType()->isObjCQualifiedInterfaceType()) {531        if (const ObjCObjectPointerType * OBJPT =532              T->getAsObjCInterfacePointerType()) {533          const ObjCInterfaceType *IFaceT = OBJPT->getInterfaceType();534          T = QualType(IFaceT, 0);535          T = Context->getPointerType(T);536        }537     }538    }539 540    // FIXME: This predicate seems like it would be useful to add to ASTContext.541    bool isObjCType(QualType T) {542      if (!LangOpts.ObjC)543        return false;544 545      QualType OCT = Context->getCanonicalType(T).getUnqualifiedType();546 547      if (OCT == Context->getCanonicalType(Context->getObjCIdType()) ||548          OCT == Context->getCanonicalType(Context->getObjCClassType()))549        return true;550 551      if (const PointerType *PT = OCT->getAs<PointerType>()) {552        if (isa<ObjCInterfaceType>(PT->getPointeeType()) ||553            PT->getPointeeType()->isObjCQualifiedIdType())554          return true;555      }556      return false;557    }558 559    bool PointerTypeTakesAnyBlockArguments(QualType QT);560    bool PointerTypeTakesAnyObjCQualifiedType(QualType QT);561    void GetExtentOfArgList(const char *Name, const char *&LParen,562                            const char *&RParen);563 564    void QuoteDoublequotes(std::string &From, std::string &To) {565      for (unsigned i = 0; i < From.length(); i++) {566        if (From[i] == '"')567          To += "\\\"";568        else569          To += From[i];570      }571    }572 573    QualType getSimpleFunctionType(QualType result,574                                   ArrayRef<QualType> args,575                                   bool variadic = false) {576      if (result == Context->getObjCInstanceType())577        result =  Context->getObjCIdType();578      FunctionProtoType::ExtProtoInfo fpi;579      fpi.Variadic = variadic;580      return Context->getFunctionType(result, args, fpi);581    }582 583    // Helper function: create a CStyleCastExpr with trivial type source info.584    CStyleCastExpr* NoTypeInfoCStyleCastExpr(ASTContext *Ctx, QualType Ty,585                                             CastKind Kind, Expr *E) {586      TypeSourceInfo *TInfo = Ctx->getTrivialTypeSourceInfo(Ty, SourceLocation());587      return CStyleCastExpr::Create(*Ctx, Ty, VK_PRValue, Kind, E, nullptr,588                                    FPOptionsOverride(), TInfo,589                                    SourceLocation(), SourceLocation());590    }591 592    bool ImplementationIsNonLazy(const ObjCImplDecl *OD) const {593      const IdentifierInfo *II = &Context->Idents.get("load");594      Selector LoadSel = Context->Selectors.getSelector(0, &II);595      return OD->getClassMethod(LoadSel) != nullptr;596    }597 598    StringLiteral *getStringLiteral(StringRef Str) {599      QualType StrType = Context->getConstantArrayType(600          Context->CharTy, llvm::APInt(32, Str.size() + 1), nullptr,601          ArraySizeModifier::Normal, 0);602      return StringLiteral::Create(*Context, Str, StringLiteralKind::Ordinary,603                                   /*Pascal=*/false, StrType, SourceLocation());604    }605  };606} // end anonymous namespace607 608void RewriteModernObjC::RewriteBlocksInFunctionProtoType(QualType funcType,609                                                   NamedDecl *D) {610  if (const FunctionProtoType *fproto611      = dyn_cast<FunctionProtoType>(funcType.IgnoreParens())) {612    for (const auto &I : fproto->param_types())613      if (isTopLevelBlockPointerType(I)) {614        // All the args are checked/rewritten. Don't call twice!615        RewriteBlockPointerDecl(D);616        break;617      }618  }619}620 621void RewriteModernObjC::CheckFunctionPointerDecl(QualType funcType, NamedDecl *ND) {622  const PointerType *PT = funcType->getAs<PointerType>();623  if (PT && PointerTypeTakesAnyBlockArguments(funcType))624    RewriteBlocksInFunctionProtoType(PT->getPointeeType(), ND);625}626 627static bool IsHeaderFile(const std::string &Filename) {628  std::string::size_type DotPos = Filename.rfind('.');629 630  if (DotPos == std::string::npos) {631    // no file extension632    return false;633  }634 635  std::string Ext = Filename.substr(DotPos + 1);636  // C header: .h637  // C++ header: .hh or .H;638  return Ext == "h" || Ext == "hh" || Ext == "H";639}640 641RewriteModernObjC::RewriteModernObjC(std::string inFile,642                                     std::unique_ptr<raw_ostream> OS,643                                     DiagnosticsEngine &D,644                                     const LangOptions &LOpts,645                                     bool silenceMacroWarn, bool LineInfo)646    : Diags(D), LangOpts(LOpts), InFileName(inFile), OutFile(std::move(OS)),647      SilenceRewriteMacroWarning(silenceMacroWarn), GenerateLineInfo(LineInfo) {648  IsHeader = IsHeaderFile(inFile);649  RewriteFailedDiag = Diags.getCustomDiagID(DiagnosticsEngine::Warning,650               "rewriting sub-expression within a macro (may not be correct)");651  // FIXME. This should be an error. But if block is not called, it is OK. And it652  // may break including some headers.653  GlobalBlockRewriteFailedDiag = Diags.getCustomDiagID(DiagnosticsEngine::Warning,654    "rewriting block literal declared in global scope is not implemented");655 656  TryFinallyContainsReturnDiag = Diags.getCustomDiagID(657               DiagnosticsEngine::Warning,658               "rewriter doesn't support user-specified control flow semantics "659               "for @try/@finally (code may not execute properly)");660}661 662std::unique_ptr<ASTConsumer> clang::CreateModernObjCRewriter(663    const std::string &InFile, std::unique_ptr<raw_ostream> OS,664    DiagnosticsEngine &Diags, const LangOptions &LOpts,665    bool SilenceRewriteMacroWarning, bool LineInfo) {666  return std::make_unique<RewriteModernObjC>(InFile, std::move(OS), Diags,667                                              LOpts, SilenceRewriteMacroWarning,668                                              LineInfo);669}670 671void RewriteModernObjC::InitializeCommon(ASTContext &context) {672  Context = &context;673  SM = &Context->getSourceManager();674  TUDecl = Context->getTranslationUnitDecl();675  MsgSendFunctionDecl = nullptr;676  MsgSendSuperFunctionDecl = nullptr;677  MsgSendStretFunctionDecl = nullptr;678  MsgSendSuperStretFunctionDecl = nullptr;679  MsgSendFpretFunctionDecl = nullptr;680  GetClassFunctionDecl = nullptr;681  GetMetaClassFunctionDecl = nullptr;682  GetSuperClassFunctionDecl = nullptr;683  SelGetUidFunctionDecl = nullptr;684  CFStringFunctionDecl = nullptr;685  ConstantStringClassReference = nullptr;686  NSStringRecord = nullptr;687  CurMethodDef = nullptr;688  CurFunctionDef = nullptr;689  GlobalVarDecl = nullptr;690  GlobalConstructionExp = nullptr;691  SuperStructDecl = nullptr;692  ProtocolTypeDecl = nullptr;693  ConstantStringDecl = nullptr;694  BcLabelCount = 0;695  SuperConstructorFunctionDecl = nullptr;696  NumObjCStringLiterals = 0;697  PropParentMap = nullptr;698  CurrentBody = nullptr;699  DisableReplaceStmt = false;700  objc_impl_method = false;701 702  // Get the ID and start/end of the main file.703  MainFileID = SM->getMainFileID();704  llvm::MemoryBufferRef MainBuf = SM->getBufferOrFake(MainFileID);705  MainFileStart = MainBuf.getBufferStart();706  MainFileEnd = MainBuf.getBufferEnd();707 708  Rewrite.setSourceMgr(Context->getSourceManager(), Context->getLangOpts());709}710 711//===----------------------------------------------------------------------===//712// Top Level Driver Code713//===----------------------------------------------------------------------===//714 715void RewriteModernObjC::HandleTopLevelSingleDecl(Decl *D) {716  if (Diags.hasErrorOccurred())717    return;718 719  // Two cases: either the decl could be in the main file, or it could be in a720  // #included file.  If the former, rewrite it now.  If the later, check to see721  // if we rewrote the #include/#import.722  SourceLocation Loc = D->getLocation();723  Loc = SM->getExpansionLoc(Loc);724 725  // If this is for a builtin, ignore it.726  if (Loc.isInvalid()) return;727 728  // Look for built-in declarations that we need to refer during the rewrite.729  if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {730    RewriteFunctionDecl(FD);731  } else if (VarDecl *FVD = dyn_cast<VarDecl>(D)) {732    // declared in <Foundation/NSString.h>733    if (FVD->getName() == "_NSConstantStringClassReference") {734      ConstantStringClassReference = FVD;735      return;736    }737  } else if (ObjCCategoryDecl *CD = dyn_cast<ObjCCategoryDecl>(D)) {738    RewriteCategoryDecl(CD);739  } else if (ObjCProtocolDecl *PD = dyn_cast<ObjCProtocolDecl>(D)) {740    if (PD->isThisDeclarationADefinition())741      RewriteProtocolDecl(PD);742  } else if (LinkageSpecDecl *LSD = dyn_cast<LinkageSpecDecl>(D)) {743    // Recurse into linkage specifications744    for (DeclContext::decl_iterator DI = LSD->decls_begin(),745                                 DIEnd = LSD->decls_end();746         DI != DIEnd; ) {747      if (ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>((*DI))) {748        if (!IFace->isThisDeclarationADefinition()) {749          SmallVector<Decl *, 8> DG;750          SourceLocation StartLoc = IFace->getBeginLoc();751          do {752            if (isa<ObjCInterfaceDecl>(*DI) &&753                !cast<ObjCInterfaceDecl>(*DI)->isThisDeclarationADefinition() &&754                StartLoc == (*DI)->getBeginLoc())755              DG.push_back(*DI);756            else757              break;758 759            ++DI;760          } while (DI != DIEnd);761          RewriteForwardClassDecl(DG);762          continue;763        }764        else {765          // Keep track of all interface declarations seen.766          ObjCInterfacesSeen.push_back(IFace);767          ++DI;768          continue;769        }770      }771 772      if (ObjCProtocolDecl *Proto = dyn_cast<ObjCProtocolDecl>((*DI))) {773        if (!Proto->isThisDeclarationADefinition()) {774          SmallVector<Decl *, 8> DG;775          SourceLocation StartLoc = Proto->getBeginLoc();776          do {777            if (isa<ObjCProtocolDecl>(*DI) &&778                !cast<ObjCProtocolDecl>(*DI)->isThisDeclarationADefinition() &&779                StartLoc == (*DI)->getBeginLoc())780              DG.push_back(*DI);781            else782              break;783 784            ++DI;785          } while (DI != DIEnd);786          RewriteForwardProtocolDecl(DG);787          continue;788        }789      }790 791      HandleTopLevelSingleDecl(*DI);792      ++DI;793    }794  }795  // If we have a decl in the main file, see if we should rewrite it.796  if (SM->isWrittenInMainFile(Loc))797    return HandleDeclInMainFile(D);798}799 800//===----------------------------------------------------------------------===//801// Syntactic (non-AST) Rewriting Code802//===----------------------------------------------------------------------===//803 804void RewriteModernObjC::RewriteInclude() {805  SourceLocation LocStart = SM->getLocForStartOfFile(MainFileID);806  StringRef MainBuf = SM->getBufferData(MainFileID);807  const char *MainBufStart = MainBuf.begin();808  const char *MainBufEnd = MainBuf.end();809  size_t ImportLen = strlen("import");810 811  // Loop over the whole file, looking for includes.812  for (const char *BufPtr = MainBufStart; BufPtr < MainBufEnd; ++BufPtr) {813    if (*BufPtr == '#') {814      if (++BufPtr == MainBufEnd)815        return;816      while (*BufPtr == ' ' || *BufPtr == '\t')817        if (++BufPtr == MainBufEnd)818          return;819      if (!strncmp(BufPtr, "import", ImportLen)) {820        // replace import with include821        SourceLocation ImportLoc =822          LocStart.getLocWithOffset(BufPtr-MainBufStart);823        ReplaceText(ImportLoc, ImportLen, "include");824        BufPtr += ImportLen;825      }826    }827  }828}829 830static void WriteInternalIvarName(const ObjCInterfaceDecl *IDecl,831                                  ObjCIvarDecl *IvarDecl, std::string &Result) {832  Result += "OBJC_IVAR_$_";833  Result += IDecl->getName();834  Result += "$";835  Result += IvarDecl->getName();836}837 838std::string839RewriteModernObjC::getIvarAccessString(ObjCIvarDecl *D) {840  const ObjCInterfaceDecl *ClassDecl = D->getContainingInterface();841 842  // Build name of symbol holding ivar offset.843  std::string IvarOffsetName;844  if (D->isBitField())845    ObjCIvarBitfieldGroupOffset(D, IvarOffsetName);846  else847    WriteInternalIvarName(ClassDecl, D, IvarOffsetName);848 849  std::string S = "(*(";850  QualType IvarT = D->getType();851  if (D->isBitField())852    IvarT = GetGroupRecordTypeForObjCIvarBitfield(D);853 854  if (!IvarT->getAs<TypedefType>() && IvarT->isRecordType()) {855    RecordDecl *RD = IvarT->castAsCanonical<RecordType>()->getDecl();856    RD = RD->getDefinition();857    if (RD && !RD->getDeclName().getAsIdentifierInfo()) {858      // decltype(((Foo_IMPL*)0)->bar) *859      auto *CDecl = cast<ObjCContainerDecl>(D->getDeclContext());860      // ivar in class extensions requires special treatment.861      if (ObjCCategoryDecl *CatDecl = dyn_cast<ObjCCategoryDecl>(CDecl))862        CDecl = CatDecl->getClassInterface();863      std::string RecName = std::string(CDecl->getName());864      RecName += "_IMPL";865      RecordDecl *RD = RecordDecl::Create(*Context, TagTypeKind::Struct, TUDecl,866                                          SourceLocation(), SourceLocation(),867                                          &Context->Idents.get(RecName));868      QualType PtrStructIMPL =869          Context->getPointerType(Context->getCanonicalTagType(RD));870      unsigned UnsignedIntSize =871      static_cast<unsigned>(Context->getTypeSize(Context->UnsignedIntTy));872      Expr *Zero = IntegerLiteral::Create(*Context,873                                          llvm::APInt(UnsignedIntSize, 0),874                                          Context->UnsignedIntTy, SourceLocation());875      Zero = NoTypeInfoCStyleCastExpr(Context, PtrStructIMPL, CK_BitCast, Zero);876      ParenExpr *PE = new (Context) ParenExpr(SourceLocation(), SourceLocation(),877                                              Zero);878      FieldDecl *FD = FieldDecl::Create(*Context, nullptr, SourceLocation(),879                                        SourceLocation(),880                                        &Context->Idents.get(D->getNameAsString()),881                                        IvarT, nullptr,882                                        /*BitWidth=*/nullptr, /*Mutable=*/true,883                                        ICIS_NoInit);884      MemberExpr *ME = MemberExpr::CreateImplicit(885          *Context, PE, true, FD, FD->getType(), VK_LValue, OK_Ordinary);886      IvarT = Context->getDecltypeType(ME, ME->getType());887    }888  }889  convertObjCTypeToCStyleType(IvarT);890  QualType castT = Context->getPointerType(IvarT);891  std::string TypeString(castT.getAsString(Context->getPrintingPolicy()));892  S += TypeString;893  S += ")";894 895  // ((char *)self + IVAR_OFFSET_SYMBOL_NAME)896  S += "((char *)self + ";897  S += IvarOffsetName;898  S += "))";899  if (D->isBitField()) {900    S += ".";901    S += D->getNameAsString();902  }903  ReferencedIvars[const_cast<ObjCInterfaceDecl *>(ClassDecl)].insert(D);904  return S;905}906 907/// mustSynthesizeSetterGetterMethod - returns true if setter or getter has not908/// been found in the class implementation. In this case, it must be synthesized.909static bool mustSynthesizeSetterGetterMethod(ObjCImplementationDecl *IMP,910                                             ObjCPropertyDecl *PD,911                                             bool getter) {912  auto *OMD = IMP->getInstanceMethod(getter ? PD->getGetterName()913                                            : PD->getSetterName());914  return !OMD || OMD->isSynthesizedAccessorStub();915}916 917void RewriteModernObjC::RewritePropertyImplDecl(ObjCPropertyImplDecl *PID,918                                          ObjCImplementationDecl *IMD,919                                          ObjCCategoryImplDecl *CID) {920  static bool objcGetPropertyDefined = false;921  static bool objcSetPropertyDefined = false;922  SourceLocation startGetterSetterLoc;923 924  if (PID->getBeginLoc().isValid()) {925    SourceLocation startLoc = PID->getBeginLoc();926    InsertText(startLoc, "// ");927    const char *startBuf = SM->getCharacterData(startLoc);928    assert((*startBuf == '@') && "bogus @synthesize location");929    const char *semiBuf = strchr(startBuf, ';');930    assert((*semiBuf == ';') && "@synthesize: can't find ';'");931    startGetterSetterLoc = startLoc.getLocWithOffset(semiBuf-startBuf+1);932  } else933    startGetterSetterLoc = IMD ? IMD->getEndLoc() : CID->getEndLoc();934 935  if (PID->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic)936    return; // FIXME: is this correct?937 938  // Generate the 'getter' function.939  ObjCPropertyDecl *PD = PID->getPropertyDecl();940  ObjCIvarDecl *OID = PID->getPropertyIvarDecl();941  assert(IMD && OID && "Synthesized ivars must be attached to @implementation");942 943  unsigned Attributes = PD->getPropertyAttributes();944  if (mustSynthesizeSetterGetterMethod(IMD, PD, true /*getter*/)) {945    bool GenGetProperty =946        !(Attributes & ObjCPropertyAttribute::kind_nonatomic) &&947        (Attributes & (ObjCPropertyAttribute::kind_retain |948                       ObjCPropertyAttribute::kind_copy));949    std::string Getr;950    if (GenGetProperty && !objcGetPropertyDefined) {951      objcGetPropertyDefined = true;952      // FIXME. Is this attribute correct in all cases?953      Getr = "\nextern \"C\" __declspec(dllimport) "954            "id objc_getProperty(id, SEL, long, bool);\n";955    }956    RewriteObjCMethodDecl(OID->getContainingInterface(),957                          PID->getGetterMethodDecl(), Getr);958    Getr += "{ ";959    // Synthesize an explicit cast to gain access to the ivar.960    // See objc-act.c:objc_synthesize_new_getter() for details.961    if (GenGetProperty) {962      // return objc_getProperty(self, _cmd, offsetof(ClassDecl, OID), 1)963      Getr += "typedef ";964      const FunctionType *FPRetType = nullptr;965      RewriteTypeIntoString(PID->getGetterMethodDecl()->getReturnType(), Getr,966                            FPRetType);967      Getr += " _TYPE";968      if (FPRetType) {969        Getr += ")"; // close the precedence "scope" for "*".970 971        // Now, emit the argument types (if any).972        if (const FunctionProtoType *FT = dyn_cast<FunctionProtoType>(FPRetType)){973          Getr += "(";974          for (unsigned i = 0, e = FT->getNumParams(); i != e; ++i) {975            if (i) Getr += ", ";976            std::string ParamStr =977                FT->getParamType(i).getAsString(Context->getPrintingPolicy());978            Getr += ParamStr;979          }980          if (FT->isVariadic()) {981            if (FT->getNumParams())982              Getr += ", ";983            Getr += "...";984          }985          Getr += ")";986        } else987          Getr += "()";988      }989      Getr += ";\n";990      Getr += "return (_TYPE)";991      Getr += "objc_getProperty(self, _cmd, ";992      RewriteIvarOffsetComputation(OID, Getr);993      Getr += ", 1)";994    }995    else996      Getr += "return " + getIvarAccessString(OID);997    Getr += "; }";998    InsertText(startGetterSetterLoc, Getr);999  }1000 1001  if (PD->isReadOnly() ||1002      !mustSynthesizeSetterGetterMethod(IMD, PD, false /*setter*/))1003    return;1004 1005  // Generate the 'setter' function.1006  std::string Setr;1007  bool GenSetProperty = Attributes & (ObjCPropertyAttribute::kind_retain |1008                                      ObjCPropertyAttribute::kind_copy);1009  if (GenSetProperty && !objcSetPropertyDefined) {1010    objcSetPropertyDefined = true;1011    // FIXME. Is this attribute correct in all cases?1012    Setr = "\nextern \"C\" __declspec(dllimport) "1013    "void objc_setProperty (id, SEL, long, id, bool, bool);\n";1014  }1015 1016  RewriteObjCMethodDecl(OID->getContainingInterface(),1017                        PID->getSetterMethodDecl(), Setr);1018  Setr += "{ ";1019  // Synthesize an explicit cast to initialize the ivar.1020  // See objc-act.c:objc_synthesize_new_setter() for details.1021  if (GenSetProperty) {1022    Setr += "objc_setProperty (self, _cmd, ";1023    RewriteIvarOffsetComputation(OID, Setr);1024    Setr += ", (id)";1025    Setr += PD->getName();1026    Setr += ", ";1027    if (Attributes & ObjCPropertyAttribute::kind_nonatomic)1028      Setr += "0, ";1029    else1030      Setr += "1, ";1031    if (Attributes & ObjCPropertyAttribute::kind_copy)1032      Setr += "1)";1033    else1034      Setr += "0)";1035  }1036  else {1037    Setr += getIvarAccessString(OID) + " = ";1038    Setr += PD->getName();1039  }1040  Setr += "; }\n";1041  InsertText(startGetterSetterLoc, Setr);1042}1043 1044static void RewriteOneForwardClassDecl(ObjCInterfaceDecl *ForwardDecl,1045                                       std::string &typedefString) {1046  typedefString += "\n#ifndef _REWRITER_typedef_";1047  typedefString += ForwardDecl->getNameAsString();1048  typedefString += "\n";1049  typedefString += "#define _REWRITER_typedef_";1050  typedefString += ForwardDecl->getNameAsString();1051  typedefString += "\n";1052  typedefString += "typedef struct objc_object ";1053  typedefString += ForwardDecl->getNameAsString();1054  // typedef struct { } _objc_exc_Classname;1055  typedefString += ";\ntypedef struct {} _objc_exc_";1056  typedefString += ForwardDecl->getNameAsString();1057  typedefString += ";\n#endif\n";1058}1059 1060void RewriteModernObjC::RewriteForwardClassEpilogue(ObjCInterfaceDecl *ClassDecl,1061                                              const std::string &typedefString) {1062  SourceLocation startLoc = ClassDecl->getBeginLoc();1063  const char *startBuf = SM->getCharacterData(startLoc);1064  const char *semiPtr = strchr(startBuf, ';');1065  // Replace the @class with typedefs corresponding to the classes.1066  ReplaceText(startLoc, semiPtr-startBuf+1, typedefString);1067}1068 1069void RewriteModernObjC::RewriteForwardClassDecl(DeclGroupRef D) {1070  std::string typedefString;1071  for (DeclGroupRef::iterator I = D.begin(), E = D.end(); I != E; ++I) {1072    if (ObjCInterfaceDecl *ForwardDecl = dyn_cast<ObjCInterfaceDecl>(*I)) {1073      if (I == D.begin()) {1074        // Translate to typedef's that forward reference structs with the same name1075        // as the class. As a convenience, we include the original declaration1076        // as a comment.1077        typedefString += "// @class ";1078        typedefString += ForwardDecl->getNameAsString();1079        typedefString += ";";1080      }1081      RewriteOneForwardClassDecl(ForwardDecl, typedefString);1082    }1083    else1084      HandleTopLevelSingleDecl(*I);1085  }1086  DeclGroupRef::iterator I = D.begin();1087  RewriteForwardClassEpilogue(cast<ObjCInterfaceDecl>(*I), typedefString);1088}1089 1090void RewriteModernObjC::RewriteForwardClassDecl(1091                                const SmallVectorImpl<Decl *> &D) {1092  std::string typedefString;1093  for (unsigned i = 0; i < D.size(); i++) {1094    ObjCInterfaceDecl *ForwardDecl = cast<ObjCInterfaceDecl>(D[i]);1095    if (i == 0) {1096      typedefString += "// @class ";1097      typedefString += ForwardDecl->getNameAsString();1098      typedefString += ";";1099    }1100    RewriteOneForwardClassDecl(ForwardDecl, typedefString);1101  }1102  RewriteForwardClassEpilogue(cast<ObjCInterfaceDecl>(D[0]), typedefString);1103}1104 1105void RewriteModernObjC::RewriteMethodDeclaration(ObjCMethodDecl *Method) {1106  // When method is a synthesized one, such as a getter/setter there is1107  // nothing to rewrite.1108  if (Method->isImplicit())1109    return;1110  SourceLocation LocStart = Method->getBeginLoc();1111  SourceLocation LocEnd = Method->getEndLoc();1112 1113  if (SM->getExpansionLineNumber(LocEnd) >1114      SM->getExpansionLineNumber(LocStart)) {1115    InsertText(LocStart, "#if 0\n");1116    ReplaceText(LocEnd, 1, ";\n#endif\n");1117  } else {1118    InsertText(LocStart, "// ");1119  }1120}1121 1122void RewriteModernObjC::RewriteProperty(ObjCPropertyDecl *prop) {1123  SourceLocation Loc = prop->getAtLoc();1124 1125  ReplaceText(Loc, 0, "// ");1126  // FIXME: handle properties that are declared across multiple lines.1127}1128 1129void RewriteModernObjC::RewriteCategoryDecl(ObjCCategoryDecl *CatDecl) {1130  SourceLocation LocStart = CatDecl->getBeginLoc();1131 1132  // FIXME: handle category headers that are declared across multiple lines.1133  if (CatDecl->getIvarRBraceLoc().isValid()) {1134    ReplaceText(LocStart, 1, "/** ");1135    ReplaceText(CatDecl->getIvarRBraceLoc(), 1, "**/ ");1136  }1137  else {1138    ReplaceText(LocStart, 0, "// ");1139  }1140 1141  for (auto *I : CatDecl->instance_properties())1142    RewriteProperty(I);1143 1144  for (auto *I : CatDecl->instance_methods())1145    RewriteMethodDeclaration(I);1146  for (auto *I : CatDecl->class_methods())1147    RewriteMethodDeclaration(I);1148 1149  // Lastly, comment out the @end.1150  ReplaceText(CatDecl->getAtEndRange().getBegin(),1151              strlen("@end"), "/* @end */\n");1152}1153 1154void RewriteModernObjC::RewriteProtocolDecl(ObjCProtocolDecl *PDecl) {1155  SourceLocation LocStart = PDecl->getBeginLoc();1156  assert(PDecl->isThisDeclarationADefinition());1157 1158  // FIXME: handle protocol headers that are declared across multiple lines.1159  ReplaceText(LocStart, 0, "// ");1160 1161  for (auto *I : PDecl->instance_methods())1162    RewriteMethodDeclaration(I);1163  for (auto *I : PDecl->class_methods())1164    RewriteMethodDeclaration(I);1165  for (auto *I : PDecl->instance_properties())1166    RewriteProperty(I);1167 1168  // Lastly, comment out the @end.1169  SourceLocation LocEnd = PDecl->getAtEndRange().getBegin();1170  ReplaceText(LocEnd, strlen("@end"), "/* @end */\n");1171 1172  // Must comment out @optional/@required1173  const char *startBuf = SM->getCharacterData(LocStart);1174  const char *endBuf = SM->getCharacterData(LocEnd);1175  for (const char *p = startBuf; p < endBuf; p++) {1176    if (*p == '@' && !strncmp(p+1, "optional", strlen("optional"))) {1177      SourceLocation OptionalLoc = LocStart.getLocWithOffset(p-startBuf);1178      ReplaceText(OptionalLoc, strlen("@optional"), "/* @optional */");1179 1180    }1181    else if (*p == '@' && !strncmp(p+1, "required", strlen("required"))) {1182      SourceLocation OptionalLoc = LocStart.getLocWithOffset(p-startBuf);1183      ReplaceText(OptionalLoc, strlen("@required"), "/* @required */");1184 1185    }1186  }1187}1188 1189void RewriteModernObjC::RewriteForwardProtocolDecl(DeclGroupRef D) {1190  SourceLocation LocStart = (*D.begin())->getBeginLoc();1191  if (LocStart.isInvalid())1192    llvm_unreachable("Invalid SourceLocation");1193  // FIXME: handle forward protocol that are declared across multiple lines.1194  ReplaceText(LocStart, 0, "// ");1195}1196 1197void1198RewriteModernObjC::RewriteForwardProtocolDecl(const SmallVectorImpl<Decl *> &DG) {1199  SourceLocation LocStart = DG[0]->getBeginLoc();1200  if (LocStart.isInvalid())1201    llvm_unreachable("Invalid SourceLocation");1202  // FIXME: handle forward protocol that are declared across multiple lines.1203  ReplaceText(LocStart, 0, "// ");1204}1205 1206void RewriteModernObjC::RewriteTypeIntoString(QualType T, std::string &ResultStr,1207                                        const FunctionType *&FPRetType) {1208  if (T->isObjCQualifiedIdType())1209    ResultStr += "id";1210  else if (T->isFunctionPointerType() ||1211           T->isBlockPointerType()) {1212    // needs special handling, since pointer-to-functions have special1213    // syntax (where a decaration models use).1214    QualType retType = T;1215    QualType PointeeTy;1216    if (const PointerType* PT = retType->getAs<PointerType>())1217      PointeeTy = PT->getPointeeType();1218    else if (const BlockPointerType *BPT = retType->getAs<BlockPointerType>())1219      PointeeTy = BPT->getPointeeType();1220    if ((FPRetType = PointeeTy->getAs<FunctionType>())) {1221      ResultStr +=1222          FPRetType->getReturnType().getAsString(Context->getPrintingPolicy());1223      ResultStr += "(*";1224    }1225  } else1226    ResultStr += T.getAsString(Context->getPrintingPolicy());1227}1228 1229void RewriteModernObjC::RewriteObjCMethodDecl(const ObjCInterfaceDecl *IDecl,1230                                        ObjCMethodDecl *OMD,1231                                        std::string &ResultStr) {1232  //fprintf(stderr,"In RewriteObjCMethodDecl\n");1233  const FunctionType *FPRetType = nullptr;1234  ResultStr += "\nstatic ";1235  RewriteTypeIntoString(OMD->getReturnType(), ResultStr, FPRetType);1236  ResultStr += " ";1237 1238  // Unique method name1239  std::string NameStr;1240 1241  if (OMD->isInstanceMethod())1242    NameStr += "_I_";1243  else1244    NameStr += "_C_";1245 1246  NameStr += IDecl->getNameAsString();1247  NameStr += "_";1248 1249  if (ObjCCategoryImplDecl *CID =1250      dyn_cast<ObjCCategoryImplDecl>(OMD->getDeclContext())) {1251    NameStr += CID->getNameAsString();1252    NameStr += "_";1253  }1254  // Append selector names, replacing ':' with '_'1255  {1256    std::string selString = OMD->getSelector().getAsString();1257    int len = selString.size();1258    for (int i = 0; i < len; i++)1259      if (selString[i] == ':')1260        selString[i] = '_';1261    NameStr += selString;1262  }1263  // Remember this name for metadata emission1264  MethodInternalNames[OMD] = NameStr;1265  ResultStr += NameStr;1266 1267  // Rewrite arguments1268  ResultStr += "(";1269 1270  // invisible arguments1271  if (OMD->isInstanceMethod()) {1272    QualType selfTy = Context->getObjCInterfaceType(IDecl);1273    selfTy = Context->getPointerType(selfTy);1274    if (!LangOpts.MicrosoftExt) {1275      if (ObjCSynthesizedStructs.count(const_cast<ObjCInterfaceDecl*>(IDecl)))1276        ResultStr += "struct ";1277    }1278    // When rewriting for Microsoft, explicitly omit the structure name.1279    ResultStr += IDecl->getNameAsString();1280    ResultStr += " *";1281  }1282  else1283    ResultStr += Context->getObjCClassType().getAsString(1284      Context->getPrintingPolicy());1285 1286  ResultStr += " self, ";1287  ResultStr += Context->getObjCSelType().getAsString(Context->getPrintingPolicy());1288  ResultStr += " _cmd";1289 1290  // Method arguments.1291  for (const auto *PDecl : OMD->parameters()) {1292    ResultStr += ", ";1293    if (PDecl->getType()->isObjCQualifiedIdType()) {1294      ResultStr += "id ";1295      ResultStr += PDecl->getNameAsString();1296    } else {1297      std::string Name = PDecl->getNameAsString();1298      QualType QT = PDecl->getType();1299      // Make sure we convert "t (^)(...)" to "t (*)(...)".1300      (void)convertBlockPointerToFunctionPointer(QT);1301      QT.getAsStringInternal(Name, Context->getPrintingPolicy());1302      ResultStr += Name;1303    }1304  }1305  if (OMD->isVariadic())1306    ResultStr += ", ...";1307  ResultStr += ") ";1308 1309  if (FPRetType) {1310    ResultStr += ")"; // close the precedence "scope" for "*".1311 1312    // Now, emit the argument types (if any).1313    if (const FunctionProtoType *FT = dyn_cast<FunctionProtoType>(FPRetType)) {1314      ResultStr += "(";1315      for (unsigned i = 0, e = FT->getNumParams(); i != e; ++i) {1316        if (i) ResultStr += ", ";1317        std::string ParamStr =1318            FT->getParamType(i).getAsString(Context->getPrintingPolicy());1319        ResultStr += ParamStr;1320      }1321      if (FT->isVariadic()) {1322        if (FT->getNumParams())1323          ResultStr += ", ";1324        ResultStr += "...";1325      }1326      ResultStr += ")";1327    } else {1328      ResultStr += "()";1329    }1330  }1331}1332 1333void RewriteModernObjC::RewriteImplementationDecl(Decl *OID) {1334  ObjCImplementationDecl *IMD = dyn_cast<ObjCImplementationDecl>(OID);1335  ObjCCategoryImplDecl *CID = dyn_cast<ObjCCategoryImplDecl>(OID);1336  assert((IMD || CID) && "Unknown implementation type");1337 1338  if (IMD) {1339    if (IMD->getIvarRBraceLoc().isValid()) {1340      ReplaceText(IMD->getBeginLoc(), 1, "/** ");1341      ReplaceText(IMD->getIvarRBraceLoc(), 1, "**/ ");1342    }1343    else {1344      InsertText(IMD->getBeginLoc(), "// ");1345    }1346  }1347  else1348    InsertText(CID->getBeginLoc(), "// ");1349 1350  for (auto *OMD : IMD ? IMD->instance_methods() : CID->instance_methods()) {1351    if (!OMD->getBody())1352      continue;1353    std::string ResultStr;1354    RewriteObjCMethodDecl(OMD->getClassInterface(), OMD, ResultStr);1355    SourceLocation LocStart = OMD->getBeginLoc();1356    SourceLocation LocEnd = OMD->getCompoundBody()->getBeginLoc();1357 1358    const char *startBuf = SM->getCharacterData(LocStart);1359    const char *endBuf = SM->getCharacterData(LocEnd);1360    ReplaceText(LocStart, endBuf-startBuf, ResultStr);1361  }1362 1363  for (auto *OMD : IMD ? IMD->class_methods() : CID->class_methods()) {1364    if (!OMD->getBody())1365      continue;1366    std::string ResultStr;1367    RewriteObjCMethodDecl(OMD->getClassInterface(), OMD, ResultStr);1368    SourceLocation LocStart = OMD->getBeginLoc();1369    SourceLocation LocEnd = OMD->getCompoundBody()->getBeginLoc();1370 1371    const char *startBuf = SM->getCharacterData(LocStart);1372    const char *endBuf = SM->getCharacterData(LocEnd);1373    ReplaceText(LocStart, endBuf-startBuf, ResultStr);1374  }1375  for (auto *I : IMD ? IMD->property_impls() : CID->property_impls())1376    RewritePropertyImplDecl(I, IMD, CID);1377 1378  InsertText(IMD ? IMD->getEndLoc() : CID->getEndLoc(), "// ");1379}1380 1381void RewriteModernObjC::RewriteInterfaceDecl(ObjCInterfaceDecl *ClassDecl) {1382  // Do not synthesize more than once.1383  if (ObjCSynthesizedStructs.count(ClassDecl))1384    return;1385  // Make sure super class's are written before current class is written.1386  ObjCInterfaceDecl *SuperClass = ClassDecl->getSuperClass();1387  while (SuperClass) {1388    RewriteInterfaceDecl(SuperClass);1389    SuperClass = SuperClass->getSuperClass();1390  }1391  std::string ResultStr;1392  if (!ObjCWrittenInterfaces.count(ClassDecl->getCanonicalDecl())) {1393    // we haven't seen a forward decl - generate a typedef.1394    RewriteOneForwardClassDecl(ClassDecl, ResultStr);1395    RewriteIvarOffsetSymbols(ClassDecl, ResultStr);1396 1397    RewriteObjCInternalStruct(ClassDecl, ResultStr);1398    // Mark this typedef as having been written into its c++ equivalent.1399    ObjCWrittenInterfaces.insert(ClassDecl->getCanonicalDecl());1400 1401    for (auto *I : ClassDecl->instance_properties())1402      RewriteProperty(I);1403    for (auto *I : ClassDecl->instance_methods())1404      RewriteMethodDeclaration(I);1405    for (auto *I : ClassDecl->class_methods())1406      RewriteMethodDeclaration(I);1407 1408    // Lastly, comment out the @end.1409    ReplaceText(ClassDecl->getAtEndRange().getBegin(), strlen("@end"),1410                "/* @end */\n");1411  }1412}1413 1414Stmt *RewriteModernObjC::RewritePropertyOrImplicitSetter(PseudoObjectExpr *PseudoOp) {1415  SourceRange OldRange = PseudoOp->getSourceRange();1416 1417  // We just magically know some things about the structure of this1418  // expression.1419  ObjCMessageExpr *OldMsg =1420    cast<ObjCMessageExpr>(PseudoOp->getSemanticExpr(1421                            PseudoOp->getNumSemanticExprs() - 1));1422 1423  // Because the rewriter doesn't allow us to rewrite rewritten code,1424  // we need to suppress rewriting the sub-statements.1425  Expr *Base;1426  SmallVector<Expr*, 2> Args;1427  {1428    DisableReplaceStmtScope S(*this);1429 1430    // Rebuild the base expression if we have one.1431    Base = nullptr;1432    if (OldMsg->getReceiverKind() == ObjCMessageExpr::Instance) {1433      Base = OldMsg->getInstanceReceiver();1434      Base = cast<OpaqueValueExpr>(Base)->getSourceExpr();1435      Base = cast<Expr>(RewriteFunctionBodyOrGlobalInitializer(Base));1436    }1437 1438    unsigned numArgs = OldMsg->getNumArgs();1439    for (unsigned i = 0; i < numArgs; i++) {1440      Expr *Arg = OldMsg->getArg(i);1441      if (isa<OpaqueValueExpr>(Arg))1442        Arg = cast<OpaqueValueExpr>(Arg)->getSourceExpr();1443      Arg = cast<Expr>(RewriteFunctionBodyOrGlobalInitializer(Arg));1444      Args.push_back(Arg);1445    }1446  }1447 1448  // TODO: avoid this copy.1449  SmallVector<SourceLocation, 1> SelLocs;1450  OldMsg->getSelectorLocs(SelLocs);1451 1452  ObjCMessageExpr *NewMsg = nullptr;1453  switch (OldMsg->getReceiverKind()) {1454  case ObjCMessageExpr::Class:1455    NewMsg = ObjCMessageExpr::Create(*Context, OldMsg->getType(),1456                                     OldMsg->getValueKind(),1457                                     OldMsg->getLeftLoc(),1458                                     OldMsg->getClassReceiverTypeInfo(),1459                                     OldMsg->getSelector(),1460                                     SelLocs,1461                                     OldMsg->getMethodDecl(),1462                                     Args,1463                                     OldMsg->getRightLoc(),1464                                     OldMsg->isImplicit());1465    break;1466 1467  case ObjCMessageExpr::Instance:1468    NewMsg = ObjCMessageExpr::Create(*Context, OldMsg->getType(),1469                                     OldMsg->getValueKind(),1470                                     OldMsg->getLeftLoc(),1471                                     Base,1472                                     OldMsg->getSelector(),1473                                     SelLocs,1474                                     OldMsg->getMethodDecl(),1475                                     Args,1476                                     OldMsg->getRightLoc(),1477                                     OldMsg->isImplicit());1478    break;1479 1480  case ObjCMessageExpr::SuperClass:1481  case ObjCMessageExpr::SuperInstance:1482    NewMsg = ObjCMessageExpr::Create(*Context, OldMsg->getType(),1483                                     OldMsg->getValueKind(),1484                                     OldMsg->getLeftLoc(),1485                                     OldMsg->getSuperLoc(),1486                 OldMsg->getReceiverKind() == ObjCMessageExpr::SuperInstance,1487                                     OldMsg->getSuperType(),1488                                     OldMsg->getSelector(),1489                                     SelLocs,1490                                     OldMsg->getMethodDecl(),1491                                     Args,1492                                     OldMsg->getRightLoc(),1493                                     OldMsg->isImplicit());1494    break;1495  }1496 1497  Stmt *Replacement = SynthMessageExpr(NewMsg);1498  ReplaceStmtWithRange(PseudoOp, Replacement, OldRange);1499  return Replacement;1500}1501 1502Stmt *RewriteModernObjC::RewritePropertyOrImplicitGetter(PseudoObjectExpr *PseudoOp) {1503  SourceRange OldRange = PseudoOp->getSourceRange();1504 1505  // We just magically know some things about the structure of this1506  // expression.1507  ObjCMessageExpr *OldMsg =1508    cast<ObjCMessageExpr>(PseudoOp->getResultExpr()->IgnoreImplicit());1509 1510  // Because the rewriter doesn't allow us to rewrite rewritten code,1511  // we need to suppress rewriting the sub-statements.1512  Expr *Base = nullptr;1513  SmallVector<Expr*, 1> Args;1514  {1515    DisableReplaceStmtScope S(*this);1516    // Rebuild the base expression if we have one.1517    if (OldMsg->getReceiverKind() == ObjCMessageExpr::Instance) {1518      Base = OldMsg->getInstanceReceiver();1519      Base = cast<OpaqueValueExpr>(Base)->getSourceExpr();1520      Base = cast<Expr>(RewriteFunctionBodyOrGlobalInitializer(Base));1521    }1522    unsigned numArgs = OldMsg->getNumArgs();1523    for (unsigned i = 0; i < numArgs; i++) {1524      Expr *Arg = OldMsg->getArg(i);1525      if (isa<OpaqueValueExpr>(Arg))1526        Arg = cast<OpaqueValueExpr>(Arg)->getSourceExpr();1527      Arg = cast<Expr>(RewriteFunctionBodyOrGlobalInitializer(Arg));1528      Args.push_back(Arg);1529    }1530  }1531 1532  // Intentionally empty.1533  SmallVector<SourceLocation, 1> SelLocs;1534 1535  ObjCMessageExpr *NewMsg = nullptr;1536  switch (OldMsg->getReceiverKind()) {1537  case ObjCMessageExpr::Class:1538    NewMsg = ObjCMessageExpr::Create(*Context, OldMsg->getType(),1539                                     OldMsg->getValueKind(),1540                                     OldMsg->getLeftLoc(),1541                                     OldMsg->getClassReceiverTypeInfo(),1542                                     OldMsg->getSelector(),1543                                     SelLocs,1544                                     OldMsg->getMethodDecl(),1545                                     Args,1546                                     OldMsg->getRightLoc(),1547                                     OldMsg->isImplicit());1548    break;1549 1550  case ObjCMessageExpr::Instance:1551    NewMsg = ObjCMessageExpr::Create(*Context, OldMsg->getType(),1552                                     OldMsg->getValueKind(),1553                                     OldMsg->getLeftLoc(),1554                                     Base,1555                                     OldMsg->getSelector(),1556                                     SelLocs,1557                                     OldMsg->getMethodDecl(),1558                                     Args,1559                                     OldMsg->getRightLoc(),1560                                     OldMsg->isImplicit());1561    break;1562 1563  case ObjCMessageExpr::SuperClass:1564  case ObjCMessageExpr::SuperInstance:1565    NewMsg = ObjCMessageExpr::Create(*Context, OldMsg->getType(),1566                                     OldMsg->getValueKind(),1567                                     OldMsg->getLeftLoc(),1568                                     OldMsg->getSuperLoc(),1569                 OldMsg->getReceiverKind() == ObjCMessageExpr::SuperInstance,1570                                     OldMsg->getSuperType(),1571                                     OldMsg->getSelector(),1572                                     SelLocs,1573                                     OldMsg->getMethodDecl(),1574                                     Args,1575                                     OldMsg->getRightLoc(),1576                                     OldMsg->isImplicit());1577    break;1578  }1579 1580  Stmt *Replacement = SynthMessageExpr(NewMsg);1581  ReplaceStmtWithRange(PseudoOp, Replacement, OldRange);1582  return Replacement;1583}1584 1585/// SynthCountByEnumWithState - To print:1586/// ((NSUInteger (*)1587///  (id, SEL, struct __objcFastEnumerationState *, id *, NSUInteger))1588///  (void *)objc_msgSend)((id)l_collection,1589///                        sel_registerName(1590///                          "countByEnumeratingWithState:objects:count:"),1591///                        &enumState,1592///                        (id *)__rw_items, (NSUInteger)16)1593///1594void RewriteModernObjC::SynthCountByEnumWithState(std::string &buf) {1595  buf += "((_WIN_NSUInteger (*) (id, SEL, struct __objcFastEnumerationState *, "1596  "id *, _WIN_NSUInteger))(void *)objc_msgSend)";1597  buf += "\n\t\t";1598  buf += "((id)l_collection,\n\t\t";1599  buf += "sel_registerName(\"countByEnumeratingWithState:objects:count:\"),";1600  buf += "\n\t\t";1601  buf += "&enumState, "1602         "(id *)__rw_items, (_WIN_NSUInteger)16)";1603}1604 1605/// RewriteBreakStmt - Rewrite for a break-stmt inside an ObjC2's foreach1606/// statement to exit to its outer synthesized loop.1607///1608Stmt *RewriteModernObjC::RewriteBreakStmt(BreakStmt *S) {1609  if (Stmts.empty() || !isa<ObjCForCollectionStmt>(Stmts.back()))1610    return S;1611  // replace break with goto __break_label1612  std::string buf;1613 1614  SourceLocation startLoc = S->getBeginLoc();1615  buf = "goto __break_label_";1616  buf += utostr(ObjCBcLabelNo.back());1617  ReplaceText(startLoc, strlen("break"), buf);1618 1619  return nullptr;1620}1621 1622void RewriteModernObjC::ConvertSourceLocationToLineDirective(1623                                          SourceLocation Loc,1624                                          std::string &LineString) {1625  if (Loc.isFileID() && GenerateLineInfo) {1626    LineString += "\n#line ";1627    PresumedLoc PLoc = SM->getPresumedLoc(Loc);1628    LineString += utostr(PLoc.getLine());1629    LineString += " \"";1630    LineString += Lexer::Stringify(PLoc.getFilename());1631    LineString += "\"\n";1632  }1633}1634 1635/// RewriteContinueStmt - Rewrite for a continue-stmt inside an ObjC2's foreach1636/// statement to continue with its inner synthesized loop.1637///1638Stmt *RewriteModernObjC::RewriteContinueStmt(ContinueStmt *S) {1639  if (Stmts.empty() || !isa<ObjCForCollectionStmt>(Stmts.back()))1640    return S;1641  // replace continue with goto __continue_label1642  std::string buf;1643 1644  SourceLocation startLoc = S->getBeginLoc();1645  buf = "goto __continue_label_";1646  buf += utostr(ObjCBcLabelNo.back());1647  ReplaceText(startLoc, strlen("continue"), buf);1648 1649  return nullptr;1650}1651 1652/// RewriteObjCForCollectionStmt - Rewriter for ObjC2's foreach statement.1653///  It rewrites:1654/// for ( type elem in collection) { stmts; }1655 1656/// Into:1657/// {1658///   type elem;1659///   struct __objcFastEnumerationState enumState = { 0 };1660///   id __rw_items[16];1661///   id l_collection = (id)collection;1662///   NSUInteger limit = [l_collection countByEnumeratingWithState:&enumState1663///                                       objects:__rw_items count:16];1664/// if (limit) {1665///   unsigned long startMutations = *enumState.mutationsPtr;1666///   do {1667///        unsigned long counter = 0;1668///        do {1669///             if (startMutations != *enumState.mutationsPtr)1670///               objc_enumerationMutation(l_collection);1671///             elem = (type)enumState.itemsPtr[counter++];1672///             stmts;1673///             __continue_label: ;1674///        } while (counter < limit);1675///   } while ((limit = [l_collection countByEnumeratingWithState:&enumState1676///                                  objects:__rw_items count:16]));1677///   elem = nil;1678///   __break_label: ;1679///  }1680///  else1681///       elem = nil;1682///  }1683///1684Stmt *RewriteModernObjC::RewriteObjCForCollectionStmt(ObjCForCollectionStmt *S,1685                                                SourceLocation OrigEnd) {1686  assert(!Stmts.empty() && "ObjCForCollectionStmt - Statement stack empty");1687  assert(isa<ObjCForCollectionStmt>(Stmts.back()) &&1688         "ObjCForCollectionStmt Statement stack mismatch");1689  assert(!ObjCBcLabelNo.empty() &&1690         "ObjCForCollectionStmt - Label No stack empty");1691 1692  SourceLocation startLoc = S->getBeginLoc();1693  const char *startBuf = SM->getCharacterData(startLoc);1694  StringRef elementName;1695  std::string elementTypeAsString;1696  std::string buf;1697  // line directive first.1698  SourceLocation ForEachLoc = S->getForLoc();1699  ConvertSourceLocationToLineDirective(ForEachLoc, buf);1700  buf += "{\n\t";1701  if (DeclStmt *DS = dyn_cast<DeclStmt>(S->getElement())) {1702    // type elem;1703    NamedDecl* D = cast<NamedDecl>(DS->getSingleDecl());1704    QualType ElementType = cast<ValueDecl>(D)->getType();1705    if (ElementType->isObjCQualifiedIdType() ||1706        ElementType->isObjCQualifiedInterfaceType())1707      // Simply use 'id' for all qualified types.1708      elementTypeAsString = "id";1709    else1710      elementTypeAsString = ElementType.getAsString(Context->getPrintingPolicy());1711    buf += elementTypeAsString;1712    buf += " ";1713    elementName = D->getName();1714    buf += elementName;1715    buf += ";\n\t";1716  }1717  else {1718    DeclRefExpr *DR = cast<DeclRefExpr>(S->getElement());1719    elementName = DR->getDecl()->getName();1720    ValueDecl *VD = DR->getDecl();1721    if (VD->getType()->isObjCQualifiedIdType() ||1722        VD->getType()->isObjCQualifiedInterfaceType())1723      // Simply use 'id' for all qualified types.1724      elementTypeAsString = "id";1725    else1726      elementTypeAsString = VD->getType().getAsString(Context->getPrintingPolicy());1727  }1728 1729  // struct __objcFastEnumerationState enumState = { 0 };1730  buf += "struct __objcFastEnumerationState enumState = { 0 };\n\t";1731  // id __rw_items[16];1732  buf += "id __rw_items[16];\n\t";1733  // id l_collection = (id)1734  buf += "id l_collection = (id)";1735  // Find start location of 'collection' the hard way!1736  const char *startCollectionBuf = startBuf;1737  startCollectionBuf += 3;  // skip 'for'1738  startCollectionBuf = strchr(startCollectionBuf, '(');1739  startCollectionBuf++; // skip '('1740  // find 'in' and skip it.1741  while (*startCollectionBuf != ' ' ||1742         *(startCollectionBuf+1) != 'i' || *(startCollectionBuf+2) != 'n' ||1743         (*(startCollectionBuf+3) != ' ' &&1744          *(startCollectionBuf+3) != '[' && *(startCollectionBuf+3) != '('))1745    startCollectionBuf++;1746  startCollectionBuf += 3;1747 1748  // Replace: "for (type element in" with string constructed thus far.1749  ReplaceText(startLoc, startCollectionBuf - startBuf, buf);1750  // Replace ')' in for '(' type elem in collection ')' with ';'1751  SourceLocation rightParenLoc = S->getRParenLoc();1752  const char *rparenBuf = SM->getCharacterData(rightParenLoc);1753  SourceLocation lparenLoc = startLoc.getLocWithOffset(rparenBuf-startBuf);1754  buf = ";\n\t";1755 1756  // unsigned long limit = [l_collection countByEnumeratingWithState:&enumState1757  //                                   objects:__rw_items count:16];1758  // which is synthesized into:1759  // NSUInteger limit =1760  // ((NSUInteger (*)1761  //  (id, SEL, struct __objcFastEnumerationState *, id *, NSUInteger))1762  //  (void *)objc_msgSend)((id)l_collection,1763  //                        sel_registerName(1764  //                          "countByEnumeratingWithState:objects:count:"),1765  //                        (struct __objcFastEnumerationState *)&state,1766  //                        (id *)__rw_items, (NSUInteger)16);1767  buf += "_WIN_NSUInteger limit =\n\t\t";1768  SynthCountByEnumWithState(buf);1769  buf += ";\n\t";1770  /// if (limit) {1771  ///   unsigned long startMutations = *enumState.mutationsPtr;1772  ///   do {1773  ///        unsigned long counter = 0;1774  ///        do {1775  ///             if (startMutations != *enumState.mutationsPtr)1776  ///               objc_enumerationMutation(l_collection);1777  ///             elem = (type)enumState.itemsPtr[counter++];1778  buf += "if (limit) {\n\t";1779  buf += "unsigned long startMutations = *enumState.mutationsPtr;\n\t";1780  buf += "do {\n\t\t";1781  buf += "unsigned long counter = 0;\n\t\t";1782  buf += "do {\n\t\t\t";1783  buf += "if (startMutations != *enumState.mutationsPtr)\n\t\t\t\t";1784  buf += "objc_enumerationMutation(l_collection);\n\t\t\t";1785  buf += elementName;1786  buf += " = (";1787  buf += elementTypeAsString;1788  buf += ")enumState.itemsPtr[counter++];";1789  // Replace ')' in for '(' type elem in collection ')' with all of these.1790  ReplaceText(lparenLoc, 1, buf);1791 1792  ///            __continue_label: ;1793  ///        } while (counter < limit);1794  ///   } while ((limit = [l_collection countByEnumeratingWithState:&enumState1795  ///                                  objects:__rw_items count:16]));1796  ///   elem = nil;1797  ///   __break_label: ;1798  ///  }1799  ///  else1800  ///       elem = nil;1801  ///  }1802  ///1803  buf = ";\n\t";1804  buf += "__continue_label_";1805  buf += utostr(ObjCBcLabelNo.back());1806  buf += ": ;";1807  buf += "\n\t\t";1808  buf += "} while (counter < limit);\n\t";1809  buf += "} while ((limit = ";1810  SynthCountByEnumWithState(buf);1811  buf += "));\n\t";1812  buf += elementName;1813  buf += " = ((";1814  buf += elementTypeAsString;1815  buf += ")0);\n\t";1816  buf += "__break_label_";1817  buf += utostr(ObjCBcLabelNo.back());1818  buf += ": ;\n\t";1819  buf += "}\n\t";1820  buf += "else\n\t\t";1821  buf += elementName;1822  buf += " = ((";1823  buf += elementTypeAsString;1824  buf += ")0);\n\t";1825  buf += "}\n";1826 1827  // Insert all these *after* the statement body.1828  // FIXME: If this should support Obj-C++, support CXXTryStmt1829  if (isa<CompoundStmt>(S->getBody())) {1830    SourceLocation endBodyLoc = OrigEnd.getLocWithOffset(1);1831    InsertText(endBodyLoc, buf);1832  } else {1833    /* Need to treat single statements specially. For example:1834     *1835     *     for (A *a in b) if (stuff()) break;1836     *     for (A *a in b) xxxyy;1837     *1838     * The following code simply scans ahead to the semi to find the actual end.1839     */1840    const char *stmtBuf = SM->getCharacterData(OrigEnd);1841    const char *semiBuf = strchr(stmtBuf, ';');1842    assert(semiBuf && "Can't find ';'");1843    SourceLocation endBodyLoc = OrigEnd.getLocWithOffset(semiBuf-stmtBuf+1);1844    InsertText(endBodyLoc, buf);1845  }1846  Stmts.pop_back();1847  ObjCBcLabelNo.pop_back();1848  return nullptr;1849}1850 1851static void Write_RethrowObject(std::string &buf) {1852  buf += "{ struct _FIN { _FIN(id reth) : rethrow(reth) {}\n";1853  buf += "\t~_FIN() { if (rethrow) objc_exception_throw(rethrow); }\n";1854  buf += "\tid rethrow;\n";1855  buf += "\t} _fin_force_rethow(_rethrow);";1856}1857 1858/// RewriteObjCSynchronizedStmt -1859/// This routine rewrites @synchronized(expr) stmt;1860/// into:1861/// objc_sync_enter(expr);1862/// @try stmt @finally { objc_sync_exit(expr); }1863///1864Stmt *RewriteModernObjC::RewriteObjCSynchronizedStmt(ObjCAtSynchronizedStmt *S) {1865  // Get the start location and compute the semi location.1866  SourceLocation startLoc = S->getBeginLoc();1867  const char *startBuf = SM->getCharacterData(startLoc);1868 1869  assert((*startBuf == '@') && "bogus @synchronized location");1870 1871  std::string buf;1872  SourceLocation SynchLoc = S->getAtSynchronizedLoc();1873  ConvertSourceLocationToLineDirective(SynchLoc, buf);1874  buf += "{ id _rethrow = 0; id _sync_obj = (id)";1875 1876  const char *lparenBuf = startBuf;1877  while (*lparenBuf != '(') lparenBuf++;1878  ReplaceText(startLoc, lparenBuf-startBuf+1, buf);1879 1880  buf = "; objc_sync_enter(_sync_obj);\n";1881  buf += "try {\n\tstruct _SYNC_EXIT { _SYNC_EXIT(id arg) : sync_exit(arg) {}";1882  buf += "\n\t~_SYNC_EXIT() {objc_sync_exit(sync_exit);}";1883  buf += "\n\tid sync_exit;";1884  buf += "\n\t} _sync_exit(_sync_obj);\n";1885 1886  // We can't use S->getSynchExpr()->getEndLoc() to find the end location, since1887  // the sync expression is typically a message expression that's already1888  // been rewritten! (which implies the SourceLocation's are invalid).1889  SourceLocation RParenExprLoc = S->getSynchBody()->getBeginLoc();1890  const char *RParenExprLocBuf = SM->getCharacterData(RParenExprLoc);1891  while (*RParenExprLocBuf != ')') RParenExprLocBuf--;1892  RParenExprLoc = startLoc.getLocWithOffset(RParenExprLocBuf-startBuf);1893 1894  SourceLocation LBranceLoc = S->getSynchBody()->getBeginLoc();1895  const char *LBraceLocBuf = SM->getCharacterData(LBranceLoc);1896  assert (*LBraceLocBuf == '{');1897  ReplaceText(RParenExprLoc, (LBraceLocBuf - SM->getCharacterData(RParenExprLoc) + 1), buf);1898 1899  SourceLocation startRBraceLoc = S->getSynchBody()->getEndLoc();1900  assert((*SM->getCharacterData(startRBraceLoc) == '}') &&1901         "bogus @synchronized block");1902 1903  buf = "} catch (id e) {_rethrow = e;}\n";1904  Write_RethrowObject(buf);1905  buf += "}\n";1906  buf += "}\n";1907 1908  ReplaceText(startRBraceLoc, 1, buf);1909 1910  return nullptr;1911}1912 1913void RewriteModernObjC::WarnAboutReturnGotoStmts(Stmt *S)1914{1915  // Perform a bottom up traversal of all children.1916  for (Stmt *SubStmt : S->children())1917    if (SubStmt)1918      WarnAboutReturnGotoStmts(SubStmt);1919 1920  if (isa<ReturnStmt>(S) || isa<GotoStmt>(S)) {1921    Diags.Report(Context->getFullLoc(S->getBeginLoc()),1922                 TryFinallyContainsReturnDiag);1923  }1924}1925 1926Stmt *RewriteModernObjC::RewriteObjCAutoreleasePoolStmt(ObjCAutoreleasePoolStmt  *S) {1927  SourceLocation startLoc = S->getAtLoc();1928  ReplaceText(startLoc, strlen("@autoreleasepool"), "/* @autoreleasepool */");1929  ReplaceText(S->getSubStmt()->getBeginLoc(), 1,1930              "{ __AtAutoreleasePool __autoreleasepool; ");1931 1932  return nullptr;1933}1934 1935Stmt *RewriteModernObjC::RewriteObjCTryStmt(ObjCAtTryStmt *S) {1936  ObjCAtFinallyStmt *finalStmt = S->getFinallyStmt();1937  bool noCatch = S->getNumCatchStmts() == 0;1938  std::string buf;1939  SourceLocation TryLocation = S->getAtTryLoc();1940  ConvertSourceLocationToLineDirective(TryLocation, buf);1941 1942  if (finalStmt) {1943    if (noCatch)1944      buf += "{ id volatile _rethrow = 0;\n";1945    else {1946      buf += "{ id volatile _rethrow = 0;\ntry {\n";1947    }1948  }1949  // Get the start location and compute the semi location.1950  SourceLocation startLoc = S->getBeginLoc();1951  const char *startBuf = SM->getCharacterData(startLoc);1952 1953  assert((*startBuf == '@') && "bogus @try location");1954  if (finalStmt)1955    ReplaceText(startLoc, 1, buf);1956  else1957    // @try -> try1958    ReplaceText(startLoc, 1, "");1959 1960  for (ObjCAtCatchStmt *Catch : S->catch_stmts()) {1961    VarDecl *catchDecl = Catch->getCatchParamDecl();1962 1963    startLoc = Catch->getBeginLoc();1964    bool AtRemoved = false;1965    if (catchDecl) {1966      QualType t = catchDecl->getType();1967      if (const ObjCObjectPointerType *Ptr =1968              t->getAs<ObjCObjectPointerType>()) {1969        // Should be a pointer to a class.1970        ObjCInterfaceDecl *IDecl = Ptr->getObjectType()->getInterface();1971        if (IDecl) {1972          std::string Result;1973          ConvertSourceLocationToLineDirective(Catch->getBeginLoc(), Result);1974 1975          startBuf = SM->getCharacterData(startLoc);1976          assert((*startBuf == '@') && "bogus @catch location");1977          SourceLocation rParenLoc = Catch->getRParenLoc();1978          const char *rParenBuf = SM->getCharacterData(rParenLoc);1979 1980          // _objc_exc_Foo *_e as argument to catch.1981          Result += "catch (_objc_exc_"; Result += IDecl->getNameAsString();1982          Result += " *_"; Result += catchDecl->getNameAsString();1983          Result += ")";1984          ReplaceText(startLoc, rParenBuf-startBuf+1, Result);1985          // Foo *e = (Foo *)_e;1986          Result.clear();1987          Result = "{ ";1988          Result += IDecl->getNameAsString();1989          Result += " *"; Result += catchDecl->getNameAsString();1990          Result += " = ("; Result += IDecl->getNameAsString(); Result += "*)";1991          Result += "_"; Result += catchDecl->getNameAsString();1992 1993          Result += "; ";1994          SourceLocation lBraceLoc = Catch->getCatchBody()->getBeginLoc();1995          ReplaceText(lBraceLoc, 1, Result);1996          AtRemoved = true;1997        }1998      }1999    }2000    if (!AtRemoved)2001      // @catch -> catch2002      ReplaceText(startLoc, 1, "");2003 2004  }2005  if (finalStmt) {2006    buf.clear();2007    SourceLocation FinallyLoc = finalStmt->getBeginLoc();2008 2009    if (noCatch) {2010      ConvertSourceLocationToLineDirective(FinallyLoc, buf);2011      buf += "catch (id e) {_rethrow = e;}\n";2012    }2013    else {2014      buf += "}\n";2015      ConvertSourceLocationToLineDirective(FinallyLoc, buf);2016      buf += "catch (id e) {_rethrow = e;}\n";2017    }2018 2019    SourceLocation startFinalLoc = finalStmt->getBeginLoc();2020    ReplaceText(startFinalLoc, 8, buf);2021    Stmt *body = finalStmt->getFinallyBody();2022    SourceLocation startFinalBodyLoc = body->getBeginLoc();2023    buf.clear();2024    Write_RethrowObject(buf);2025    ReplaceText(startFinalBodyLoc, 1, buf);2026 2027    SourceLocation endFinalBodyLoc = body->getEndLoc();2028    ReplaceText(endFinalBodyLoc, 1, "}\n}");2029    // Now check for any return/continue/go statements within the @try.2030    WarnAboutReturnGotoStmts(S->getTryBody());2031  }2032 2033  return nullptr;2034}2035 2036// This can't be done with ReplaceStmt(S, ThrowExpr), since2037// the throw expression is typically a message expression that's already2038// been rewritten! (which implies the SourceLocation's are invalid).2039Stmt *RewriteModernObjC::RewriteObjCThrowStmt(ObjCAtThrowStmt *S) {2040  // Get the start location and compute the semi location.2041  SourceLocation startLoc = S->getBeginLoc();2042  const char *startBuf = SM->getCharacterData(startLoc);2043 2044  assert((*startBuf == '@') && "bogus @throw location");2045 2046  std::string buf;2047  /* void objc_exception_throw(id) __attribute__((noreturn)); */2048  if (S->getThrowExpr())2049    buf = "objc_exception_throw(";2050  else2051    buf = "throw";2052 2053  // handle "@  throw" correctly.2054  const char *wBuf = strchr(startBuf, 'w');2055  assert((*wBuf == 'w') && "@throw: can't find 'w'");2056  ReplaceText(startLoc, wBuf-startBuf+1, buf);2057 2058  SourceLocation endLoc = S->getEndLoc();2059  const char *endBuf = SM->getCharacterData(endLoc);2060  const char *semiBuf = strchr(endBuf, ';');2061  assert((*semiBuf == ';') && "@throw: can't find ';'");2062  SourceLocation semiLoc = startLoc.getLocWithOffset(semiBuf-startBuf);2063  if (S->getThrowExpr())2064    ReplaceText(semiLoc, 1, ");");2065  return nullptr;2066}2067 2068Stmt *RewriteModernObjC::RewriteAtEncode(ObjCEncodeExpr *Exp) {2069  // Create a new string expression.2070  std::string StrEncoding;2071  Context->getObjCEncodingForType(Exp->getEncodedType(), StrEncoding);2072  Expr *Replacement = getStringLiteral(StrEncoding);2073  ReplaceStmt(Exp, Replacement);2074 2075  // Replace this subexpr in the parent.2076  // delete Exp; leak for now, see RewritePropertyOrImplicitSetter() usage for more info.2077  return Replacement;2078}2079 2080Stmt *RewriteModernObjC::RewriteAtSelector(ObjCSelectorExpr *Exp) {2081  if (!SelGetUidFunctionDecl)2082    SynthSelGetUidFunctionDecl();2083  assert(SelGetUidFunctionDecl && "Can't find sel_registerName() decl");2084  // Create a call to sel_registerName("selName").2085  SmallVector<Expr*, 8> SelExprs;2086  SelExprs.push_back(getStringLiteral(Exp->getSelector().getAsString()));2087  CallExpr *SelExp = SynthesizeCallToFunctionDecl(SelGetUidFunctionDecl,2088                                                  SelExprs);2089  ReplaceStmt(Exp, SelExp);2090  // delete Exp; leak for now, see RewritePropertyOrImplicitSetter() usage for more info.2091  return SelExp;2092}2093 2094CallExpr *2095RewriteModernObjC::SynthesizeCallToFunctionDecl(FunctionDecl *FD,2096                                                ArrayRef<Expr *> Args,2097                                                SourceLocation StartLoc,2098                                                SourceLocation EndLoc) {2099  // Get the type, we will need to reference it in a couple spots.2100  QualType msgSendType = FD->getType();2101 2102  // Create a reference to the objc_msgSend() declaration.2103  DeclRefExpr *DRE = new (Context) DeclRefExpr(*Context, FD, false, msgSendType,2104                                               VK_LValue, SourceLocation());2105 2106  // Now, we cast the reference to a pointer to the objc_msgSend type.2107  QualType pToFunc = Context->getPointerType(msgSendType);2108  ImplicitCastExpr *ICE =2109      ImplicitCastExpr::Create(*Context, pToFunc, CK_FunctionToPointerDecay,2110                               DRE, nullptr, VK_PRValue, FPOptionsOverride());2111 2112  const auto *FT = msgSendType->castAs<FunctionType>();2113  CallExpr *Exp =2114      CallExpr::Create(*Context, ICE, Args, FT->getCallResultType(*Context),2115                       VK_PRValue, EndLoc, FPOptionsOverride());2116  return Exp;2117}2118 2119static bool scanForProtocolRefs(const char *startBuf, const char *endBuf,2120                                const char *&startRef, const char *&endRef) {2121  while (startBuf < endBuf) {2122    if (*startBuf == '<')2123      startRef = startBuf; // mark the start.2124    if (*startBuf == '>') {2125      if (startRef && *startRef == '<') {2126        endRef = startBuf; // mark the end.2127        return true;2128      }2129      return false;2130    }2131    startBuf++;2132  }2133  return false;2134}2135 2136static void scanToNextArgument(const char *&argRef) {2137  int angle = 0;2138  while (*argRef != ')' && (*argRef != ',' || angle > 0)) {2139    if (*argRef == '<')2140      angle++;2141    else if (*argRef == '>')2142      angle--;2143    argRef++;2144  }2145  assert(angle == 0 && "scanToNextArgument - bad protocol type syntax");2146}2147 2148bool RewriteModernObjC::needToScanForQualifiers(QualType T) {2149  if (T->isObjCQualifiedIdType())2150    return true;2151  if (const PointerType *PT = T->getAs<PointerType>()) {2152    if (PT->getPointeeType()->isObjCQualifiedIdType())2153      return true;2154  }2155  if (T->isObjCObjectPointerType()) {2156    T = T->getPointeeType();2157    return T->isObjCQualifiedInterfaceType();2158  }2159  if (T->isArrayType()) {2160    QualType ElemTy = Context->getBaseElementType(T);2161    return needToScanForQualifiers(ElemTy);2162  }2163  return false;2164}2165 2166void RewriteModernObjC::RewriteObjCQualifiedInterfaceTypes(Expr *E) {2167  QualType Type = E->getType();2168  if (needToScanForQualifiers(Type)) {2169    SourceLocation Loc, EndLoc;2170 2171    if (const CStyleCastExpr *ECE = dyn_cast<CStyleCastExpr>(E)) {2172      Loc = ECE->getLParenLoc();2173      EndLoc = ECE->getRParenLoc();2174    } else {2175      Loc = E->getBeginLoc();2176      EndLoc = E->getEndLoc();2177    }2178    // This will defend against trying to rewrite synthesized expressions.2179    if (Loc.isInvalid() || EndLoc.isInvalid())2180      return;2181 2182    const char *startBuf = SM->getCharacterData(Loc);2183    const char *endBuf = SM->getCharacterData(EndLoc);2184    const char *startRef = nullptr, *endRef = nullptr;2185    if (scanForProtocolRefs(startBuf, endBuf, startRef, endRef)) {2186      // Get the locations of the startRef, endRef.2187      SourceLocation LessLoc = Loc.getLocWithOffset(startRef-startBuf);2188      SourceLocation GreaterLoc = Loc.getLocWithOffset(endRef-startBuf+1);2189      // Comment out the protocol references.2190      InsertText(LessLoc, "/*");2191      InsertText(GreaterLoc, "*/");2192    }2193  }2194}2195 2196void RewriteModernObjC::RewriteObjCQualifiedInterfaceTypes(Decl *Dcl) {2197  SourceLocation Loc;2198  QualType Type;2199  const FunctionProtoType *proto = nullptr;2200  if (VarDecl *VD = dyn_cast<VarDecl>(Dcl)) {2201    Loc = VD->getLocation();2202    Type = VD->getType();2203  }2204  else if (FunctionDecl *FD = dyn_cast<FunctionDecl>(Dcl)) {2205    Loc = FD->getLocation();2206    // Check for ObjC 'id' and class types that have been adorned with protocol2207    // information (id<p>, C<p>*). The protocol references need to be rewritten!2208    const FunctionType *funcType = FD->getType()->getAs<FunctionType>();2209    assert(funcType && "missing function type");2210    proto = dyn_cast<FunctionProtoType>(funcType);2211    if (!proto)2212      return;2213    Type = proto->getReturnType();2214  }2215  else if (FieldDecl *FD = dyn_cast<FieldDecl>(Dcl)) {2216    Loc = FD->getLocation();2217    Type = FD->getType();2218  }2219  else if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(Dcl)) {2220    Loc = TD->getLocation();2221    Type = TD->getUnderlyingType();2222  }2223  else2224    return;2225 2226  if (needToScanForQualifiers(Type)) {2227    // Since types are unique, we need to scan the buffer.2228 2229    const char *endBuf = SM->getCharacterData(Loc);2230    const char *startBuf = endBuf;2231    while (*startBuf != ';' && *startBuf != '<' && startBuf != MainFileStart)2232      startBuf--; // scan backward (from the decl location) for return type.2233    const char *startRef = nullptr, *endRef = nullptr;2234    if (scanForProtocolRefs(startBuf, endBuf, startRef, endRef)) {2235      // Get the locations of the startRef, endRef.2236      SourceLocation LessLoc = Loc.getLocWithOffset(startRef-endBuf);2237      SourceLocation GreaterLoc = Loc.getLocWithOffset(endRef-endBuf+1);2238      // Comment out the protocol references.2239      InsertText(LessLoc, "/*");2240      InsertText(GreaterLoc, "*/");2241    }2242  }2243  if (!proto)2244      return; // most likely, was a variable2245  // Now check arguments.2246  const char *startBuf = SM->getCharacterData(Loc);2247  const char *startFuncBuf = startBuf;2248  for (unsigned i = 0; i < proto->getNumParams(); i++) {2249    if (needToScanForQualifiers(proto->getParamType(i))) {2250      // Since types are unique, we need to scan the buffer.2251 2252      const char *endBuf = startBuf;2253      // scan forward (from the decl location) for argument types.2254      scanToNextArgument(endBuf);2255      const char *startRef = nullptr, *endRef = nullptr;2256      if (scanForProtocolRefs(startBuf, endBuf, startRef, endRef)) {2257        // Get the locations of the startRef, endRef.2258        SourceLocation LessLoc =2259          Loc.getLocWithOffset(startRef-startFuncBuf);2260        SourceLocation GreaterLoc =2261          Loc.getLocWithOffset(endRef-startFuncBuf+1);2262        // Comment out the protocol references.2263        InsertText(LessLoc, "/*");2264        InsertText(GreaterLoc, "*/");2265      }2266      startBuf = ++endBuf;2267    }2268    else {2269      // If the function name is derived from a macro expansion, then the2270      // argument buffer will not follow the name. Need to speak with Chris.2271      while (*startBuf && *startBuf != ')' && *startBuf != ',')2272        startBuf++; // scan forward (from the decl location) for argument types.2273      startBuf++;2274    }2275  }2276}2277 2278void RewriteModernObjC::RewriteTypeOfDecl(VarDecl *ND) {2279  QualType QT = ND->getType();2280  const Type* TypePtr = QT->getAs<Type>();2281  if (!isa<TypeOfExprType>(TypePtr))2282    return;2283  while (isa<TypeOfExprType>(TypePtr)) {2284    const TypeOfExprType *TypeOfExprTypePtr = cast<TypeOfExprType>(TypePtr);2285    QT = TypeOfExprTypePtr->getUnderlyingExpr()->getType();2286    TypePtr = QT->getAs<Type>();2287  }2288  // FIXME. This will not work for multiple declarators; as in:2289  // __typeof__(a) b,c,d;2290  std::string TypeAsString(QT.getAsString(Context->getPrintingPolicy()));2291  SourceLocation DeclLoc = ND->getTypeSpecStartLoc();2292  const char *startBuf = SM->getCharacterData(DeclLoc);2293  if (ND->getInit()) {2294    std::string Name(ND->getNameAsString());2295    TypeAsString += " " + Name + " = ";2296    Expr *E = ND->getInit();2297    SourceLocation startLoc;2298    if (const CStyleCastExpr *ECE = dyn_cast<CStyleCastExpr>(E))2299      startLoc = ECE->getLParenLoc();2300    else2301      startLoc = E->getBeginLoc();2302    startLoc = SM->getExpansionLoc(startLoc);2303    const char *endBuf = SM->getCharacterData(startLoc);2304    ReplaceText(DeclLoc, endBuf-startBuf-1, TypeAsString);2305  }2306  else {2307    SourceLocation X = ND->getEndLoc();2308    X = SM->getExpansionLoc(X);2309    const char *endBuf = SM->getCharacterData(X);2310    ReplaceText(DeclLoc, endBuf-startBuf-1, TypeAsString);2311  }2312}2313 2314// SynthSelGetUidFunctionDecl - SEL sel_registerName(const char *str);2315void RewriteModernObjC::SynthSelGetUidFunctionDecl() {2316  IdentifierInfo *SelGetUidIdent = &Context->Idents.get("sel_registerName");2317  SmallVector<QualType, 16> ArgTys;2318  ArgTys.push_back(Context->getPointerType(Context->CharTy.withConst()));2319  QualType getFuncType =2320    getSimpleFunctionType(Context->getObjCSelType(), ArgTys);2321  SelGetUidFunctionDecl = FunctionDecl::Create(*Context, TUDecl,2322                                               SourceLocation(),2323                                               SourceLocation(),2324                                               SelGetUidIdent, getFuncType,2325                                               nullptr, SC_Extern);2326}2327 2328void RewriteModernObjC::RewriteFunctionDecl(FunctionDecl *FD) {2329  // declared in <objc/objc.h>2330  if (FD->getIdentifier() &&2331      FD->getName() == "sel_registerName") {2332    SelGetUidFunctionDecl = FD;2333    return;2334  }2335  RewriteObjCQualifiedInterfaceTypes(FD);2336}2337 2338void RewriteModernObjC::RewriteBlockPointerType(std::string& Str, QualType Type) {2339  std::string TypeString(Type.getAsString(Context->getPrintingPolicy()));2340  const char *argPtr = TypeString.c_str();2341  if (!strchr(argPtr, '^')) {2342    Str += TypeString;2343    return;2344  }2345  while (*argPtr) {2346    Str += (*argPtr == '^' ? '*' : *argPtr);2347    argPtr++;2348  }2349}2350 2351// FIXME. Consolidate this routine with RewriteBlockPointerType.2352void RewriteModernObjC::RewriteBlockPointerTypeVariable(std::string& Str,2353                                                  ValueDecl *VD) {2354  QualType Type = VD->getType();2355  std::string TypeString(Type.getAsString(Context->getPrintingPolicy()));2356  const char *argPtr = TypeString.c_str();2357  int paren = 0;2358  while (*argPtr) {2359    switch (*argPtr) {2360      case '(':2361        Str += *argPtr;2362        paren++;2363        break;2364      case ')':2365        Str += *argPtr;2366        paren--;2367        break;2368      case '^':2369        Str += '*';2370        if (paren == 1)2371          Str += VD->getNameAsString();2372        break;2373      default:2374        Str += *argPtr;2375        break;2376    }2377    argPtr++;2378  }2379}2380 2381void RewriteModernObjC::RewriteBlockLiteralFunctionDecl(FunctionDecl *FD) {2382  SourceLocation FunLocStart = FD->getTypeSpecStartLoc();2383  const FunctionType *funcType = FD->getType()->getAs<FunctionType>();2384  const FunctionProtoType *proto = dyn_cast<FunctionProtoType>(funcType);2385  if (!proto)2386    return;2387  QualType Type = proto->getReturnType();2388  std::string FdStr = Type.getAsString(Context->getPrintingPolicy());2389  FdStr += " ";2390  FdStr += FD->getName();2391  FdStr +=  "(";2392  unsigned numArgs = proto->getNumParams();2393  for (unsigned i = 0; i < numArgs; i++) {2394    QualType ArgType = proto->getParamType(i);2395  RewriteBlockPointerType(FdStr, ArgType);2396  if (i+1 < numArgs)2397    FdStr += ", ";2398  }2399  if (FD->isVariadic()) {2400    FdStr +=  (numArgs > 0) ? ", ...);\n" : "...);\n";2401  }2402  else2403    FdStr +=  ");\n";2404  InsertText(FunLocStart, FdStr);2405}2406 2407// SynthSuperConstructorFunctionDecl - id __rw_objc_super(id obj, id super);2408void RewriteModernObjC::SynthSuperConstructorFunctionDecl() {2409  if (SuperConstructorFunctionDecl)2410    return;2411  IdentifierInfo *msgSendIdent = &Context->Idents.get("__rw_objc_super");2412  SmallVector<QualType, 16> ArgTys;2413  QualType argT = Context->getObjCIdType();2414  assert(!argT.isNull() && "Can't find 'id' type");2415  ArgTys.push_back(argT);2416  ArgTys.push_back(argT);2417  QualType msgSendType = getSimpleFunctionType(Context->getObjCIdType(),2418                                               ArgTys);2419  SuperConstructorFunctionDecl = FunctionDecl::Create(*Context, TUDecl,2420                                                     SourceLocation(),2421                                                     SourceLocation(),2422                                                     msgSendIdent, msgSendType,2423                                                     nullptr, SC_Extern);2424}2425 2426// SynthMsgSendFunctionDecl - id objc_msgSend(id self, SEL op, ...);2427void RewriteModernObjC::SynthMsgSendFunctionDecl() {2428  IdentifierInfo *msgSendIdent = &Context->Idents.get("objc_msgSend");2429  SmallVector<QualType, 16> ArgTys;2430  QualType argT = Context->getObjCIdType();2431  assert(!argT.isNull() && "Can't find 'id' type");2432  ArgTys.push_back(argT);2433  argT = Context->getObjCSelType();2434  assert(!argT.isNull() && "Can't find 'SEL' type");2435  ArgTys.push_back(argT);2436  QualType msgSendType = getSimpleFunctionType(Context->getObjCIdType(),2437                                               ArgTys, /*variadic=*/true);2438  MsgSendFunctionDecl = FunctionDecl::Create(*Context, TUDecl,2439                                             SourceLocation(),2440                                             SourceLocation(),2441                                             msgSendIdent, msgSendType, nullptr,2442                                             SC_Extern);2443}2444 2445// SynthMsgSendSuperFunctionDecl - id objc_msgSendSuper(void);2446void RewriteModernObjC::SynthMsgSendSuperFunctionDecl() {2447  IdentifierInfo *msgSendIdent = &Context->Idents.get("objc_msgSendSuper");2448  SmallVector<QualType, 2> ArgTys;2449  ArgTys.push_back(Context->VoidTy);2450  QualType msgSendType = getSimpleFunctionType(Context->getObjCIdType(),2451                                               ArgTys, /*variadic=*/true);2452  MsgSendSuperFunctionDecl = FunctionDecl::Create(*Context, TUDecl,2453                                                  SourceLocation(),2454                                                  SourceLocation(),2455                                                  msgSendIdent, msgSendType,2456                                                  nullptr, SC_Extern);2457}2458 2459// SynthMsgSendStretFunctionDecl - id objc_msgSend_stret(id self, SEL op, ...);2460void RewriteModernObjC::SynthMsgSendStretFunctionDecl() {2461  IdentifierInfo *msgSendIdent = &Context->Idents.get("objc_msgSend_stret");2462  SmallVector<QualType, 16> ArgTys;2463  QualType argT = Context->getObjCIdType();2464  assert(!argT.isNull() && "Can't find 'id' type");2465  ArgTys.push_back(argT);2466  argT = Context->getObjCSelType();2467  assert(!argT.isNull() && "Can't find 'SEL' type");2468  ArgTys.push_back(argT);2469  QualType msgSendType = getSimpleFunctionType(Context->getObjCIdType(),2470                                               ArgTys, /*variadic=*/true);2471  MsgSendStretFunctionDecl = FunctionDecl::Create(*Context, TUDecl,2472                                                  SourceLocation(),2473                                                  SourceLocation(),2474                                                  msgSendIdent, msgSendType,2475                                                  nullptr, SC_Extern);2476}2477 2478// SynthMsgSendSuperStretFunctionDecl -2479// id objc_msgSendSuper_stret(void);2480void RewriteModernObjC::SynthMsgSendSuperStretFunctionDecl() {2481  IdentifierInfo *msgSendIdent =2482    &Context->Idents.get("objc_msgSendSuper_stret");2483  SmallVector<QualType, 2> ArgTys;2484  ArgTys.push_back(Context->VoidTy);2485  QualType msgSendType = getSimpleFunctionType(Context->getObjCIdType(),2486                                               ArgTys, /*variadic=*/true);2487  MsgSendSuperStretFunctionDecl = FunctionDecl::Create(*Context, TUDecl,2488                                                       SourceLocation(),2489                                                       SourceLocation(),2490                                                       msgSendIdent,2491                                                       msgSendType, nullptr,2492                                                       SC_Extern);2493}2494 2495// SynthMsgSendFpretFunctionDecl - double objc_msgSend_fpret(id self, SEL op, ...);2496void RewriteModernObjC::SynthMsgSendFpretFunctionDecl() {2497  IdentifierInfo *msgSendIdent = &Context->Idents.get("objc_msgSend_fpret");2498  SmallVector<QualType, 16> ArgTys;2499  QualType argT = Context->getObjCIdType();2500  assert(!argT.isNull() && "Can't find 'id' type");2501  ArgTys.push_back(argT);2502  argT = Context->getObjCSelType();2503  assert(!argT.isNull() && "Can't find 'SEL' type");2504  ArgTys.push_back(argT);2505  QualType msgSendType = getSimpleFunctionType(Context->DoubleTy,2506                                               ArgTys, /*variadic=*/true);2507  MsgSendFpretFunctionDecl = FunctionDecl::Create(*Context, TUDecl,2508                                                  SourceLocation(),2509                                                  SourceLocation(),2510                                                  msgSendIdent, msgSendType,2511                                                  nullptr, SC_Extern);2512}2513 2514// SynthGetClassFunctionDecl - Class objc_getClass(const char *name);2515void RewriteModernObjC::SynthGetClassFunctionDecl() {2516  IdentifierInfo *getClassIdent = &Context->Idents.get("objc_getClass");2517  SmallVector<QualType, 16> ArgTys;2518  ArgTys.push_back(Context->getPointerType(Context->CharTy.withConst()));2519  QualType getClassType = getSimpleFunctionType(Context->getObjCClassType(),2520                                                ArgTys);2521  GetClassFunctionDecl = FunctionDecl::Create(*Context, TUDecl,2522                                              SourceLocation(),2523                                              SourceLocation(),2524                                              getClassIdent, getClassType,2525                                              nullptr, SC_Extern);2526}2527 2528// SynthGetSuperClassFunctionDecl - Class class_getSuperclass(Class cls);2529void RewriteModernObjC::SynthGetSuperClassFunctionDecl() {2530  IdentifierInfo *getSuperClassIdent =2531    &Context->Idents.get("class_getSuperclass");2532  SmallVector<QualType, 16> ArgTys;2533  ArgTys.push_back(Context->getObjCClassType());2534  QualType getClassType = getSimpleFunctionType(Context->getObjCClassType(),2535                                                ArgTys);2536  GetSuperClassFunctionDecl = FunctionDecl::Create(*Context, TUDecl,2537                                                   SourceLocation(),2538                                                   SourceLocation(),2539                                                   getSuperClassIdent,2540                                                   getClassType, nullptr,2541                                                   SC_Extern);2542}2543 2544// SynthGetMetaClassFunctionDecl - Class objc_getMetaClass(const char *name);2545void RewriteModernObjC::SynthGetMetaClassFunctionDecl() {2546  IdentifierInfo *getClassIdent = &Context->Idents.get("objc_getMetaClass");2547  SmallVector<QualType, 16> ArgTys;2548  ArgTys.push_back(Context->getPointerType(Context->CharTy.withConst()));2549  QualType getClassType = getSimpleFunctionType(Context->getObjCClassType(),2550                                                ArgTys);2551  GetMetaClassFunctionDecl = FunctionDecl::Create(*Context, TUDecl,2552                                                  SourceLocation(),2553                                                  SourceLocation(),2554                                                  getClassIdent, getClassType,2555                                                  nullptr, SC_Extern);2556}2557 2558Stmt *RewriteModernObjC::RewriteObjCStringLiteral(ObjCStringLiteral *Exp) {2559  assert (Exp != nullptr && "Expected non-null ObjCStringLiteral");2560  QualType strType = getConstantStringStructType();2561 2562  std::string S = "__NSConstantStringImpl_";2563 2564  std::string tmpName = InFileName;2565  unsigned i;2566  for (i=0; i < tmpName.length(); i++) {2567    char c = tmpName.at(i);2568    // replace any non-alphanumeric characters with '_'.2569    if (!isAlphanumeric(c))2570      tmpName[i] = '_';2571  }2572  S += tmpName;2573  S += "_";2574  S += utostr(NumObjCStringLiterals++);2575 2576  Preamble += "static __NSConstantStringImpl " + S;2577  Preamble += " __attribute__ ((section (\"__DATA, __cfstring\"))) = {__CFConstantStringClassReference,";2578  Preamble += "0x000007c8,"; // utf8_str2579  // The pretty printer for StringLiteral handles escape characters properly.2580  std::string prettyBufS;2581  llvm::raw_string_ostream prettyBuf(prettyBufS);2582  Exp->getString()->printPretty(prettyBuf, nullptr, PrintingPolicy(LangOpts));2583  Preamble += prettyBufS;2584  Preamble += ",";2585  Preamble += utostr(Exp->getString()->getByteLength()) + "};\n";2586 2587  VarDecl *NewVD = VarDecl::Create(*Context, TUDecl, SourceLocation(),2588                                   SourceLocation(), &Context->Idents.get(S),2589                                   strType, nullptr, SC_Static);2590  DeclRefExpr *DRE = new (Context)2591      DeclRefExpr(*Context, NewVD, false, strType, VK_LValue, SourceLocation());2592  Expr *Unop = UnaryOperator::Create(2593      const_cast<ASTContext &>(*Context), DRE, UO_AddrOf,2594      Context->getPointerType(DRE->getType()), VK_PRValue, OK_Ordinary,2595      SourceLocation(), false, FPOptionsOverride());2596  // cast to NSConstantString *2597  CastExpr *cast = NoTypeInfoCStyleCastExpr(Context, Exp->getType(),2598                                            CK_CPointerToObjCPointerCast, Unop);2599  ReplaceStmt(Exp, cast);2600  // delete Exp; leak for now, see RewritePropertyOrImplicitSetter() usage for more info.2601  return cast;2602}2603 2604Stmt *RewriteModernObjC::RewriteObjCBoolLiteralExpr(ObjCBoolLiteralExpr *Exp) {2605  unsigned IntSize =2606    static_cast<unsigned>(Context->getTypeSize(Context->IntTy));2607 2608  Expr *FlagExp = IntegerLiteral::Create(*Context,2609                                         llvm::APInt(IntSize, Exp->getValue()),2610                                         Context->IntTy, Exp->getLocation());2611  CastExpr *cast = NoTypeInfoCStyleCastExpr(Context, Context->ObjCBuiltinBoolTy,2612                                            CK_BitCast, FlagExp);2613  ParenExpr *PE = new (Context) ParenExpr(Exp->getLocation(), Exp->getExprLoc(),2614                                          cast);2615  ReplaceStmt(Exp, PE);2616  return PE;2617}2618 2619Stmt *RewriteModernObjC::RewriteObjCBoxedExpr(ObjCBoxedExpr *Exp) {2620  // synthesize declaration of helper functions needed in this routine.2621  if (!SelGetUidFunctionDecl)2622    SynthSelGetUidFunctionDecl();2623  // use objc_msgSend() for all.2624  if (!MsgSendFunctionDecl)2625    SynthMsgSendFunctionDecl();2626  if (!GetClassFunctionDecl)2627    SynthGetClassFunctionDecl();2628 2629  FunctionDecl *MsgSendFlavor = MsgSendFunctionDecl;2630  SourceLocation StartLoc = Exp->getBeginLoc();2631  SourceLocation EndLoc = Exp->getEndLoc();2632 2633  // Synthesize a call to objc_msgSend().2634  SmallVector<Expr*, 4> MsgExprs;2635  SmallVector<Expr*, 4> ClsExprs;2636 2637  // Create a call to objc_getClass("<BoxingClass>"). It will be the 1st argument.2638  ObjCMethodDecl *BoxingMethod = Exp->getBoxingMethod();2639  ObjCInterfaceDecl *BoxingClass = BoxingMethod->getClassInterface();2640 2641  IdentifierInfo *clsName = BoxingClass->getIdentifier();2642  ClsExprs.push_back(getStringLiteral(clsName->getName()));2643  CallExpr *Cls = SynthesizeCallToFunctionDecl(GetClassFunctionDecl, ClsExprs,2644                                               StartLoc, EndLoc);2645  MsgExprs.push_back(Cls);2646 2647  // Create a call to sel_registerName("<BoxingMethod>:"), etc.2648  // it will be the 2nd argument.2649  SmallVector<Expr*, 4> SelExprs;2650  SelExprs.push_back(2651      getStringLiteral(BoxingMethod->getSelector().getAsString()));2652  CallExpr *SelExp = SynthesizeCallToFunctionDecl(SelGetUidFunctionDecl,2653                                                  SelExprs, StartLoc, EndLoc);2654  MsgExprs.push_back(SelExp);2655 2656  // User provided sub-expression is the 3rd, and last, argument.2657  Expr *subExpr  = Exp->getSubExpr();2658  if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(subExpr)) {2659    QualType type = ICE->getType();2660    const Expr *SubExpr = ICE->IgnoreParenImpCasts();2661    CastKind CK = CK_BitCast;2662    if (SubExpr->getType()->isIntegralType(*Context) && type->isBooleanType())2663      CK = CK_IntegralToBoolean;2664    subExpr = NoTypeInfoCStyleCastExpr(Context, type, CK, subExpr);2665  }2666  MsgExprs.push_back(subExpr);2667 2668  SmallVector<QualType, 4> ArgTypes;2669  ArgTypes.push_back(Context->getObjCClassType());2670  ArgTypes.push_back(Context->getObjCSelType());2671  for (const auto PI : BoxingMethod->parameters())2672    ArgTypes.push_back(PI->getType());2673 2674  QualType returnType = Exp->getType();2675  // Get the type, we will need to reference it in a couple spots.2676  QualType msgSendType = MsgSendFlavor->getType();2677 2678  // Create a reference to the objc_msgSend() declaration.2679  DeclRefExpr *DRE = new (Context) DeclRefExpr(2680      *Context, MsgSendFlavor, false, msgSendType, VK_LValue, SourceLocation());2681 2682  CastExpr *cast = NoTypeInfoCStyleCastExpr(2683      Context, Context->getPointerType(Context->VoidTy), CK_BitCast, DRE);2684 2685  // Now do the "normal" pointer to function cast.2686  QualType castType =2687    getSimpleFunctionType(returnType, ArgTypes, BoxingMethod->isVariadic());2688  castType = Context->getPointerType(castType);2689  cast = NoTypeInfoCStyleCastExpr(Context, castType, CK_BitCast,2690                                  cast);2691 2692  // Don't forget the parens to enforce the proper binding.2693  ParenExpr *PE = new (Context) ParenExpr(StartLoc, EndLoc, cast);2694 2695  auto *FT = msgSendType->castAs<FunctionType>();2696  CallExpr *CE = CallExpr::Create(*Context, PE, MsgExprs, FT->getReturnType(),2697                                  VK_PRValue, EndLoc, FPOptionsOverride());2698  ReplaceStmt(Exp, CE);2699  return CE;2700}2701 2702Stmt *RewriteModernObjC::RewriteObjCArrayLiteralExpr(ObjCArrayLiteral *Exp) {2703  // synthesize declaration of helper functions needed in this routine.2704  if (!SelGetUidFunctionDecl)2705    SynthSelGetUidFunctionDecl();2706  // use objc_msgSend() for all.2707  if (!MsgSendFunctionDecl)2708    SynthMsgSendFunctionDecl();2709  if (!GetClassFunctionDecl)2710    SynthGetClassFunctionDecl();2711 2712  FunctionDecl *MsgSendFlavor = MsgSendFunctionDecl;2713  SourceLocation StartLoc = Exp->getBeginLoc();2714  SourceLocation EndLoc = Exp->getEndLoc();2715 2716  // Build the expression: __NSContainer_literal(int, ...).arr2717  QualType IntQT = Context->IntTy;2718  QualType NSArrayFType =2719    getSimpleFunctionType(Context->VoidTy, IntQT, true);2720  std::string NSArrayFName("__NSContainer_literal");2721  FunctionDecl *NSArrayFD = SynthBlockInitFunctionDecl(NSArrayFName);2722  DeclRefExpr *NSArrayDRE = new (Context) DeclRefExpr(2723      *Context, NSArrayFD, false, NSArrayFType, VK_PRValue, SourceLocation());2724 2725  SmallVector<Expr*, 16> InitExprs;2726  unsigned NumElements = Exp->getNumElements();2727  unsigned UnsignedIntSize =2728    static_cast<unsigned>(Context->getTypeSize(Context->UnsignedIntTy));2729  Expr *count = IntegerLiteral::Create(*Context,2730                                       llvm::APInt(UnsignedIntSize, NumElements),2731                                       Context->UnsignedIntTy, SourceLocation());2732  InitExprs.push_back(count);2733  for (unsigned i = 0; i < NumElements; i++)2734    InitExprs.push_back(Exp->getElement(i));2735  Expr *NSArrayCallExpr =2736      CallExpr::Create(*Context, NSArrayDRE, InitExprs, NSArrayFType, VK_LValue,2737                       SourceLocation(), FPOptionsOverride());2738 2739  FieldDecl *ARRFD = FieldDecl::Create(*Context, nullptr, SourceLocation(),2740                                    SourceLocation(),2741                                    &Context->Idents.get("arr"),2742                                    Context->getPointerType(Context->VoidPtrTy),2743                                    nullptr, /*BitWidth=*/nullptr,2744                                    /*Mutable=*/true, ICIS_NoInit);2745  MemberExpr *ArrayLiteralME =2746      MemberExpr::CreateImplicit(*Context, NSArrayCallExpr, false, ARRFD,2747                                 ARRFD->getType(), VK_LValue, OK_Ordinary);2748  QualType ConstIdT = Context->getObjCIdType().withConst();2749  CStyleCastExpr * ArrayLiteralObjects =2750    NoTypeInfoCStyleCastExpr(Context,2751                             Context->getPointerType(ConstIdT),2752                             CK_BitCast,2753                             ArrayLiteralME);2754 2755  // Synthesize a call to objc_msgSend().2756  SmallVector<Expr*, 32> MsgExprs;2757  SmallVector<Expr*, 4> ClsExprs;2758  QualType expType = Exp->getType();2759 2760  // Create a call to objc_getClass("NSArray"). It will be th 1st argument.2761  ObjCInterfaceDecl *Class =2762    expType->getPointeeType()->castAs<ObjCObjectType>()->getInterface();2763 2764  IdentifierInfo *clsName = Class->getIdentifier();2765  ClsExprs.push_back(getStringLiteral(clsName->getName()));2766  CallExpr *Cls = SynthesizeCallToFunctionDecl(GetClassFunctionDecl, ClsExprs,2767                                               StartLoc, EndLoc);2768  MsgExprs.push_back(Cls);2769 2770  // Create a call to sel_registerName("arrayWithObjects:count:").2771  // it will be the 2nd argument.2772  SmallVector<Expr*, 4> SelExprs;2773  ObjCMethodDecl *ArrayMethod = Exp->getArrayWithObjectsMethod();2774  SelExprs.push_back(2775      getStringLiteral(ArrayMethod->getSelector().getAsString()));2776  CallExpr *SelExp = SynthesizeCallToFunctionDecl(SelGetUidFunctionDecl,2777                                                  SelExprs, StartLoc, EndLoc);2778  MsgExprs.push_back(SelExp);2779 2780  // (const id [])objects2781  MsgExprs.push_back(ArrayLiteralObjects);2782 2783  // (NSUInteger)cnt2784  Expr *cnt = IntegerLiteral::Create(*Context,2785                                     llvm::APInt(UnsignedIntSize, NumElements),2786                                     Context->UnsignedIntTy, SourceLocation());2787  MsgExprs.push_back(cnt);2788 2789  SmallVector<QualType, 4> ArgTypes;2790  ArgTypes.push_back(Context->getObjCClassType());2791  ArgTypes.push_back(Context->getObjCSelType());2792  for (const auto *PI : ArrayMethod->parameters())2793    ArgTypes.push_back(PI->getType());2794 2795  QualType returnType = Exp->getType();2796  // Get the type, we will need to reference it in a couple spots.2797  QualType msgSendType = MsgSendFlavor->getType();2798 2799  // Create a reference to the objc_msgSend() declaration.2800  DeclRefExpr *DRE = new (Context) DeclRefExpr(2801      *Context, MsgSendFlavor, false, msgSendType, VK_LValue, SourceLocation());2802 2803  CastExpr *cast = NoTypeInfoCStyleCastExpr(2804      Context, Context->getPointerType(Context->VoidTy), CK_BitCast, DRE);2805 2806  // Now do the "normal" pointer to function cast.2807  QualType castType =2808  getSimpleFunctionType(returnType, ArgTypes, ArrayMethod->isVariadic());2809  castType = Context->getPointerType(castType);2810  cast = NoTypeInfoCStyleCastExpr(Context, castType, CK_BitCast,2811                                  cast);2812 2813  // Don't forget the parens to enforce the proper binding.2814  ParenExpr *PE = new (Context) ParenExpr(StartLoc, EndLoc, cast);2815 2816  const FunctionType *FT = msgSendType->castAs<FunctionType>();2817  CallExpr *CE = CallExpr::Create(*Context, PE, MsgExprs, FT->getReturnType(),2818                                  VK_PRValue, EndLoc, FPOptionsOverride());2819  ReplaceStmt(Exp, CE);2820  return CE;2821}2822 2823Stmt *RewriteModernObjC::RewriteObjCDictionaryLiteralExpr(ObjCDictionaryLiteral *Exp) {2824  // synthesize declaration of helper functions needed in this routine.2825  if (!SelGetUidFunctionDecl)2826    SynthSelGetUidFunctionDecl();2827  // use objc_msgSend() for all.2828  if (!MsgSendFunctionDecl)2829    SynthMsgSendFunctionDecl();2830  if (!GetClassFunctionDecl)2831    SynthGetClassFunctionDecl();2832 2833  FunctionDecl *MsgSendFlavor = MsgSendFunctionDecl;2834  SourceLocation StartLoc = Exp->getBeginLoc();2835  SourceLocation EndLoc = Exp->getEndLoc();2836 2837  // Build the expression: __NSContainer_literal(int, ...).arr2838  QualType IntQT = Context->IntTy;2839  QualType NSDictFType =2840    getSimpleFunctionType(Context->VoidTy, IntQT, true);2841  std::string NSDictFName("__NSContainer_literal");2842  FunctionDecl *NSDictFD = SynthBlockInitFunctionDecl(NSDictFName);2843  DeclRefExpr *NSDictDRE = new (Context) DeclRefExpr(2844      *Context, NSDictFD, false, NSDictFType, VK_PRValue, SourceLocation());2845 2846  SmallVector<Expr*, 16> KeyExprs;2847  SmallVector<Expr*, 16> ValueExprs;2848 2849  unsigned NumElements = Exp->getNumElements();2850  unsigned UnsignedIntSize =2851    static_cast<unsigned>(Context->getTypeSize(Context->UnsignedIntTy));2852  Expr *count = IntegerLiteral::Create(*Context,2853                                       llvm::APInt(UnsignedIntSize, NumElements),2854                                       Context->UnsignedIntTy, SourceLocation());2855  KeyExprs.push_back(count);2856  ValueExprs.push_back(count);2857  for (unsigned i = 0; i < NumElements; i++) {2858    ObjCDictionaryElement Element = Exp->getKeyValueElement(i);2859    KeyExprs.push_back(Element.Key);2860    ValueExprs.push_back(Element.Value);2861  }2862 2863  // (const id [])objects2864  Expr *NSValueCallExpr =2865      CallExpr::Create(*Context, NSDictDRE, ValueExprs, NSDictFType, VK_LValue,2866                       SourceLocation(), FPOptionsOverride());2867 2868  FieldDecl *ARRFD = FieldDecl::Create(*Context, nullptr, SourceLocation(),2869                                       SourceLocation(),2870                                       &Context->Idents.get("arr"),2871                                       Context->getPointerType(Context->VoidPtrTy),2872                                       nullptr, /*BitWidth=*/nullptr,2873                                       /*Mutable=*/true, ICIS_NoInit);2874  MemberExpr *DictLiteralValueME =2875      MemberExpr::CreateImplicit(*Context, NSValueCallExpr, false, ARRFD,2876                                 ARRFD->getType(), VK_LValue, OK_Ordinary);2877  QualType ConstIdT = Context->getObjCIdType().withConst();2878  CStyleCastExpr * DictValueObjects =2879    NoTypeInfoCStyleCastExpr(Context,2880                             Context->getPointerType(ConstIdT),2881                             CK_BitCast,2882                             DictLiteralValueME);2883  // (const id <NSCopying> [])keys2884  Expr *NSKeyCallExpr =2885      CallExpr::Create(*Context, NSDictDRE, KeyExprs, NSDictFType, VK_LValue,2886                       SourceLocation(), FPOptionsOverride());2887 2888  MemberExpr *DictLiteralKeyME =2889      MemberExpr::CreateImplicit(*Context, NSKeyCallExpr, false, ARRFD,2890                                 ARRFD->getType(), VK_LValue, OK_Ordinary);2891 2892  CStyleCastExpr * DictKeyObjects =2893    NoTypeInfoCStyleCastExpr(Context,2894                             Context->getPointerType(ConstIdT),2895                             CK_BitCast,2896                             DictLiteralKeyME);2897 2898  // Synthesize a call to objc_msgSend().2899  SmallVector<Expr*, 32> MsgExprs;2900  SmallVector<Expr*, 4> ClsExprs;2901  QualType expType = Exp->getType();2902 2903  // Create a call to objc_getClass("NSArray"). It will be th 1st argument.2904  ObjCInterfaceDecl *Class =2905  expType->getPointeeType()->castAs<ObjCObjectType>()->getInterface();2906 2907  IdentifierInfo *clsName = Class->getIdentifier();2908  ClsExprs.push_back(getStringLiteral(clsName->getName()));2909  CallExpr *Cls = SynthesizeCallToFunctionDecl(GetClassFunctionDecl, ClsExprs,2910                                               StartLoc, EndLoc);2911  MsgExprs.push_back(Cls);2912 2913  // Create a call to sel_registerName("arrayWithObjects:count:").2914  // it will be the 2nd argument.2915  SmallVector<Expr*, 4> SelExprs;2916  ObjCMethodDecl *DictMethod = Exp->getDictWithObjectsMethod();2917  SelExprs.push_back(getStringLiteral(DictMethod->getSelector().getAsString()));2918  CallExpr *SelExp = SynthesizeCallToFunctionDecl(SelGetUidFunctionDecl,2919                                                  SelExprs, StartLoc, EndLoc);2920  MsgExprs.push_back(SelExp);2921 2922  // (const id [])objects2923  MsgExprs.push_back(DictValueObjects);2924 2925  // (const id <NSCopying> [])keys2926  MsgExprs.push_back(DictKeyObjects);2927 2928  // (NSUInteger)cnt2929  Expr *cnt = IntegerLiteral::Create(*Context,2930                                     llvm::APInt(UnsignedIntSize, NumElements),2931                                     Context->UnsignedIntTy, SourceLocation());2932  MsgExprs.push_back(cnt);2933 2934  SmallVector<QualType, 8> ArgTypes;2935  ArgTypes.push_back(Context->getObjCClassType());2936  ArgTypes.push_back(Context->getObjCSelType());2937  for (const auto *PI : DictMethod->parameters()) {2938    QualType T = PI->getType();2939    if (const PointerType* PT = T->getAs<PointerType>()) {2940      QualType PointeeTy = PT->getPointeeType();2941      convertToUnqualifiedObjCType(PointeeTy);2942      T = Context->getPointerType(PointeeTy);2943    }2944    ArgTypes.push_back(T);2945  }2946 2947  QualType returnType = Exp->getType();2948  // Get the type, we will need to reference it in a couple spots.2949  QualType msgSendType = MsgSendFlavor->getType();2950 2951  // Create a reference to the objc_msgSend() declaration.2952  DeclRefExpr *DRE = new (Context) DeclRefExpr(2953      *Context, MsgSendFlavor, false, msgSendType, VK_LValue, SourceLocation());2954 2955  CastExpr *cast = NoTypeInfoCStyleCastExpr(2956      Context, Context->getPointerType(Context->VoidTy), CK_BitCast, DRE);2957 2958  // Now do the "normal" pointer to function cast.2959  QualType castType =2960  getSimpleFunctionType(returnType, ArgTypes, DictMethod->isVariadic());2961  castType = Context->getPointerType(castType);2962  cast = NoTypeInfoCStyleCastExpr(Context, castType, CK_BitCast,2963                                  cast);2964 2965  // Don't forget the parens to enforce the proper binding.2966  ParenExpr *PE = new (Context) ParenExpr(StartLoc, EndLoc, cast);2967 2968  const FunctionType *FT = msgSendType->castAs<FunctionType>();2969  CallExpr *CE = CallExpr::Create(*Context, PE, MsgExprs, FT->getReturnType(),2970                                  VK_PRValue, EndLoc, FPOptionsOverride());2971  ReplaceStmt(Exp, CE);2972  return CE;2973}2974 2975// struct __rw_objc_super {2976//   struct objc_object *object; struct objc_object *superClass;2977// };2978QualType RewriteModernObjC::getSuperStructType() {2979  if (!SuperStructDecl) {2980    SuperStructDecl = RecordDecl::Create(2981        *Context, TagTypeKind::Struct, TUDecl, SourceLocation(),2982        SourceLocation(), &Context->Idents.get("__rw_objc_super"));2983    QualType FieldTypes[2];2984 2985    // struct objc_object *object;2986    FieldTypes[0] = Context->getObjCIdType();2987    // struct objc_object *superClass;2988    FieldTypes[1] = Context->getObjCIdType();2989 2990    // Create fields2991    for (unsigned i = 0; i < 2; ++i) {2992      SuperStructDecl->addDecl(FieldDecl::Create(*Context, SuperStructDecl,2993                                                 SourceLocation(),2994                                                 SourceLocation(), nullptr,2995                                                 FieldTypes[i], nullptr,2996                                                 /*BitWidth=*/nullptr,2997                                                 /*Mutable=*/false,2998                                                 ICIS_NoInit));2999    }3000 3001    SuperStructDecl->completeDefinition();3002  }3003  return Context->getCanonicalTagType(SuperStructDecl);3004}3005 3006QualType RewriteModernObjC::getConstantStringStructType() {3007  if (!ConstantStringDecl) {3008    ConstantStringDecl = RecordDecl::Create(3009        *Context, TagTypeKind::Struct, TUDecl, SourceLocation(),3010        SourceLocation(), &Context->Idents.get("__NSConstantStringImpl"));3011    QualType FieldTypes[4];3012 3013    // struct objc_object *receiver;3014    FieldTypes[0] = Context->getObjCIdType();3015    // int flags;3016    FieldTypes[1] = Context->IntTy;3017    // char *str;3018    FieldTypes[2] = Context->getPointerType(Context->CharTy);3019    // long length;3020    FieldTypes[3] = Context->LongTy;3021 3022    // Create fields3023    for (unsigned i = 0; i < 4; ++i) {3024      ConstantStringDecl->addDecl(FieldDecl::Create(*Context,3025                                                    ConstantStringDecl,3026                                                    SourceLocation(),3027                                                    SourceLocation(), nullptr,3028                                                    FieldTypes[i], nullptr,3029                                                    /*BitWidth=*/nullptr,3030                                                    /*Mutable=*/true,3031                                                    ICIS_NoInit));3032    }3033 3034    ConstantStringDecl->completeDefinition();3035  }3036  return Context->getCanonicalTagType(ConstantStringDecl);3037}3038 3039/// getFunctionSourceLocation - returns start location of a function3040/// definition. Complication arises when function has declared as3041/// extern "C" or extern "C" {...}3042static SourceLocation getFunctionSourceLocation (RewriteModernObjC &R,3043                                                 FunctionDecl *FD) {3044  if (FD->isExternC()  && !FD->isMain()) {3045    const DeclContext *DC = FD->getDeclContext();3046    if (const LinkageSpecDecl *LSD = dyn_cast<LinkageSpecDecl>(DC))3047      // if it is extern "C" {...}, return function decl's own location.3048      if (!LSD->getRBraceLoc().isValid())3049        return LSD->getExternLoc();3050  }3051  if (FD->getStorageClass() != SC_None)3052    R.RewriteBlockLiteralFunctionDecl(FD);3053  return FD->getTypeSpecStartLoc();3054}3055 3056void RewriteModernObjC::RewriteLineDirective(const Decl *D) {3057 3058  SourceLocation Location = D->getLocation();3059 3060  if (Location.isFileID() && GenerateLineInfo) {3061    std::string LineString("\n#line ");3062    PresumedLoc PLoc = SM->getPresumedLoc(Location);3063    LineString += utostr(PLoc.getLine());3064    LineString += " \"";3065    LineString += Lexer::Stringify(PLoc.getFilename());3066    if (isa<ObjCMethodDecl>(D))3067      LineString += "\"";3068    else LineString += "\"\n";3069 3070    Location = D->getBeginLoc();3071    if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {3072      if (FD->isExternC()  && !FD->isMain()) {3073        const DeclContext *DC = FD->getDeclContext();3074        if (const LinkageSpecDecl *LSD = dyn_cast<LinkageSpecDecl>(DC))3075          // if it is extern "C" {...}, return function decl's own location.3076          if (!LSD->getRBraceLoc().isValid())3077            Location = LSD->getExternLoc();3078      }3079    }3080    InsertText(Location, LineString);3081  }3082}3083 3084/// SynthMsgSendStretCallExpr - This routine translates message expression3085/// into a call to objc_msgSend_stret() entry point. Tricky part is that3086/// nil check on receiver must be performed before calling objc_msgSend_stret.3087/// MsgSendStretFlavor - function declaration objc_msgSend_stret(...)3088/// msgSendType - function type of objc_msgSend_stret(...)3089/// returnType - Result type of the method being synthesized.3090/// ArgTypes - type of the arguments passed to objc_msgSend_stret, starting with receiver type.3091/// MsgExprs - list of argument expressions being passed to objc_msgSend_stret,3092/// starting with receiver.3093/// Method - Method being rewritten.3094Expr *RewriteModernObjC::SynthMsgSendStretCallExpr(FunctionDecl *MsgSendStretFlavor,3095                                                 QualType returnType,3096                                                 SmallVectorImpl<QualType> &ArgTypes,3097                                                 SmallVectorImpl<Expr*> &MsgExprs,3098                                                 ObjCMethodDecl *Method) {3099  // Now do the "normal" pointer to function cast.3100  QualType FuncType = getSimpleFunctionType(3101      returnType, ArgTypes, Method ? Method->isVariadic() : false);3102  QualType castType = Context->getPointerType(FuncType);3103 3104  // build type for containing the objc_msgSend_stret object.3105  static unsigned stretCount=0;3106  std::string name = "__Stret"; name += utostr(stretCount);3107  std::string str =3108    "extern \"C\" void * __cdecl memset(void *_Dst, int _Val, size_t _Size);\n";3109  str += "namespace {\n";3110  str += "struct "; str += name;3111  str += " {\n\t";3112  str += name;3113  str += "(id receiver, SEL sel";3114  for (unsigned i = 2; i < ArgTypes.size(); i++) {3115    std::string ArgName = "arg"; ArgName += utostr(i);3116    ArgTypes[i].getAsStringInternal(ArgName, Context->getPrintingPolicy());3117    str += ", "; str += ArgName;3118  }3119  // could be vararg.3120  for (unsigned i = ArgTypes.size(); i < MsgExprs.size(); i++) {3121    std::string ArgName = "arg"; ArgName += utostr(i);3122    MsgExprs[i]->getType().getAsStringInternal(ArgName,3123                                               Context->getPrintingPolicy());3124    str += ", "; str += ArgName;3125  }3126 3127  str += ") {\n";3128  str += "\t  unsigned size = sizeof(";3129  str += returnType.getAsString(Context->getPrintingPolicy()); str += ");\n";3130 3131  str += "\t  if (size == 1 || size == 2 || size == 4 || size == 8)\n";3132 3133  str += "\t    s = (("; str += castType.getAsString(Context->getPrintingPolicy());3134  str += ")(void *)objc_msgSend)(receiver, sel";3135  for (unsigned i = 2; i < ArgTypes.size(); i++) {3136    str += ", arg"; str += utostr(i);3137  }3138  // could be vararg.3139  for (unsigned i = ArgTypes.size(); i < MsgExprs.size(); i++) {3140    str += ", arg"; str += utostr(i);3141  }3142  str+= ");\n";3143 3144  str += "\t  else if (receiver == 0)\n";3145  str += "\t    memset((void*)&s, 0, sizeof(s));\n";3146  str += "\t  else\n";3147 3148  str += "\t    s = (("; str += castType.getAsString(Context->getPrintingPolicy());3149  str += ")(void *)objc_msgSend_stret)(receiver, sel";3150  for (unsigned i = 2; i < ArgTypes.size(); i++) {3151    str += ", arg"; str += utostr(i);3152  }3153  // could be vararg.3154  for (unsigned i = ArgTypes.size(); i < MsgExprs.size(); i++) {3155    str += ", arg"; str += utostr(i);3156  }3157  str += ");\n";3158 3159  str += "\t}\n";3160  str += "\t"; str += returnType.getAsString(Context->getPrintingPolicy());3161  str += " s;\n";3162  str += "};\n};\n\n";3163  SourceLocation FunLocStart;3164  if (CurFunctionDef)3165    FunLocStart = getFunctionSourceLocation(*this, CurFunctionDef);3166  else {3167    assert(CurMethodDef && "SynthMsgSendStretCallExpr - CurMethodDef is null");3168    FunLocStart = CurMethodDef->getBeginLoc();3169  }3170 3171  InsertText(FunLocStart, str);3172  ++stretCount;3173 3174  // AST for __Stretn(receiver, args).s;3175  IdentifierInfo *ID = &Context->Idents.get(name);3176  FunctionDecl *FD =3177      FunctionDecl::Create(*Context, TUDecl, SourceLocation(), SourceLocation(),3178                           ID, FuncType, nullptr, SC_Extern, false, false);3179  DeclRefExpr *DRE = new (Context)3180      DeclRefExpr(*Context, FD, false, castType, VK_PRValue, SourceLocation());3181  CallExpr *STCE =3182      CallExpr::Create(*Context, DRE, MsgExprs, castType, VK_LValue,3183                       SourceLocation(), FPOptionsOverride());3184 3185  FieldDecl *FieldD = FieldDecl::Create(*Context, nullptr, SourceLocation(),3186                                    SourceLocation(),3187                                    &Context->Idents.get("s"),3188                                    returnType, nullptr,3189                                    /*BitWidth=*/nullptr,3190                                    /*Mutable=*/true, ICIS_NoInit);3191  MemberExpr *ME = MemberExpr::CreateImplicit(3192      *Context, STCE, false, FieldD, FieldD->getType(), VK_LValue, OK_Ordinary);3193 3194  return ME;3195}3196 3197Stmt *RewriteModernObjC::SynthMessageExpr(ObjCMessageExpr *Exp,3198                                    SourceLocation StartLoc,3199                                    SourceLocation EndLoc) {3200  if (!SelGetUidFunctionDecl)3201    SynthSelGetUidFunctionDecl();3202  if (!MsgSendFunctionDecl)3203    SynthMsgSendFunctionDecl();3204  if (!MsgSendSuperFunctionDecl)3205    SynthMsgSendSuperFunctionDecl();3206  if (!MsgSendStretFunctionDecl)3207    SynthMsgSendStretFunctionDecl();3208  if (!MsgSendSuperStretFunctionDecl)3209    SynthMsgSendSuperStretFunctionDecl();3210  if (!MsgSendFpretFunctionDecl)3211    SynthMsgSendFpretFunctionDecl();3212  if (!GetClassFunctionDecl)3213    SynthGetClassFunctionDecl();3214  if (!GetSuperClassFunctionDecl)3215    SynthGetSuperClassFunctionDecl();3216  if (!GetMetaClassFunctionDecl)3217    SynthGetMetaClassFunctionDecl();3218 3219  // default to objc_msgSend().3220  FunctionDecl *MsgSendFlavor = MsgSendFunctionDecl;3221  // May need to use objc_msgSend_stret() as well.3222  FunctionDecl *MsgSendStretFlavor = nullptr;3223  if (ObjCMethodDecl *mDecl = Exp->getMethodDecl()) {3224    QualType resultType = mDecl->getReturnType();3225    if (resultType->isRecordType())3226      MsgSendStretFlavor = MsgSendStretFunctionDecl;3227    else if (resultType->isRealFloatingType())3228      MsgSendFlavor = MsgSendFpretFunctionDecl;3229  }3230 3231  // Synthesize a call to objc_msgSend().3232  SmallVector<Expr*, 8> MsgExprs;3233  switch (Exp->getReceiverKind()) {3234  case ObjCMessageExpr::SuperClass: {3235    MsgSendFlavor = MsgSendSuperFunctionDecl;3236    if (MsgSendStretFlavor)3237      MsgSendStretFlavor = MsgSendSuperStretFunctionDecl;3238    assert(MsgSendFlavor && "MsgSendFlavor is NULL!");3239 3240    ObjCInterfaceDecl *ClassDecl = CurMethodDef->getClassInterface();3241 3242    SmallVector<Expr*, 4> InitExprs;3243 3244    // set the receiver to self, the first argument to all methods.3245    InitExprs.push_back(NoTypeInfoCStyleCastExpr(3246        Context, Context->getObjCIdType(), CK_BitCast,3247        new (Context) DeclRefExpr(*Context, CurMethodDef->getSelfDecl(), false,3248                                  Context->getObjCIdType(), VK_PRValue,3249                                  SourceLocation()))); // set the 'receiver'.3250 3251    // (id)class_getSuperclass((Class)objc_getClass("CurrentClass"))3252    SmallVector<Expr*, 8> ClsExprs;3253    ClsExprs.push_back(getStringLiteral(ClassDecl->getIdentifier()->getName()));3254    // (Class)objc_getClass("CurrentClass")3255    CallExpr *Cls = SynthesizeCallToFunctionDecl(GetMetaClassFunctionDecl,3256                                                 ClsExprs, StartLoc, EndLoc);3257    ClsExprs.clear();3258    ClsExprs.push_back(Cls);3259    Cls = SynthesizeCallToFunctionDecl(GetSuperClassFunctionDecl, ClsExprs,3260                                       StartLoc, EndLoc);3261 3262    // (id)class_getSuperclass((Class)objc_getClass("CurrentClass"))3263    // To turn off a warning, type-cast to 'id'3264    InitExprs.push_back( // set 'super class', using class_getSuperclass().3265                        NoTypeInfoCStyleCastExpr(Context,3266                                                 Context->getObjCIdType(),3267                                                 CK_BitCast, Cls));3268    // struct __rw_objc_super3269    QualType superType = getSuperStructType();3270    Expr *SuperRep;3271 3272    if (LangOpts.MicrosoftExt) {3273      SynthSuperConstructorFunctionDecl();3274      // Simulate a constructor call...3275      DeclRefExpr *DRE = new (Context)3276          DeclRefExpr(*Context, SuperConstructorFunctionDecl, false, superType,3277                      VK_LValue, SourceLocation());3278      SuperRep =3279          CallExpr::Create(*Context, DRE, InitExprs, superType, VK_LValue,3280                           SourceLocation(), FPOptionsOverride());3281      // The code for super is a little tricky to prevent collision with3282      // the structure definition in the header. The rewriter has it's own3283      // internal definition (__rw_objc_super) that is uses. This is why3284      // we need the cast below. For example:3285      // (struct __rw_objc_super *)&__rw_objc_super((id)self, (id)objc_getClass("SUPER"))3286      //3287      SuperRep = UnaryOperator::Create(3288          const_cast<ASTContext &>(*Context), SuperRep, UO_AddrOf,3289          Context->getPointerType(SuperRep->getType()), VK_PRValue, OK_Ordinary,3290          SourceLocation(), false, FPOptionsOverride());3291      SuperRep = NoTypeInfoCStyleCastExpr(Context,3292                                          Context->getPointerType(superType),3293                                          CK_BitCast, SuperRep);3294    } else {3295      // (struct __rw_objc_super) { <exprs from above> }3296      InitListExpr *ILE =3297        new (Context) InitListExpr(*Context, SourceLocation(), InitExprs,3298                                   SourceLocation());3299      TypeSourceInfo *superTInfo3300        = Context->getTrivialTypeSourceInfo(superType);3301      SuperRep = new (Context) CompoundLiteralExpr(SourceLocation(), superTInfo,3302                                                   superType, VK_LValue,3303                                                   ILE, false);3304      // struct __rw_objc_super *3305      SuperRep = UnaryOperator::Create(3306          const_cast<ASTContext &>(*Context), SuperRep, UO_AddrOf,3307          Context->getPointerType(SuperRep->getType()), VK_PRValue, OK_Ordinary,3308          SourceLocation(), false, FPOptionsOverride());3309    }3310    MsgExprs.push_back(SuperRep);3311    break;3312  }3313 3314  case ObjCMessageExpr::Class: {3315    SmallVector<Expr*, 8> ClsExprs;3316    ObjCInterfaceDecl *Class3317      = Exp->getClassReceiver()->castAs<ObjCObjectType>()->getInterface();3318    IdentifierInfo *clsName = Class->getIdentifier();3319    ClsExprs.push_back(getStringLiteral(clsName->getName()));3320    CallExpr *Cls = SynthesizeCallToFunctionDecl(GetClassFunctionDecl, ClsExprs,3321                                                 StartLoc, EndLoc);3322    CastExpr *ArgExpr = NoTypeInfoCStyleCastExpr(Context,3323                                                 Context->getObjCIdType(),3324                                                 CK_BitCast, Cls);3325    MsgExprs.push_back(ArgExpr);3326    break;3327  }3328 3329  case ObjCMessageExpr::SuperInstance:{3330    MsgSendFlavor = MsgSendSuperFunctionDecl;3331    if (MsgSendStretFlavor)3332      MsgSendStretFlavor = MsgSendSuperStretFunctionDecl;3333    assert(MsgSendFlavor && "MsgSendFlavor is NULL!");3334    ObjCInterfaceDecl *ClassDecl = CurMethodDef->getClassInterface();3335    SmallVector<Expr*, 4> InitExprs;3336 3337    InitExprs.push_back(NoTypeInfoCStyleCastExpr(3338        Context, Context->getObjCIdType(), CK_BitCast,3339        new (Context) DeclRefExpr(*Context, CurMethodDef->getSelfDecl(), false,3340                                  Context->getObjCIdType(), VK_PRValue,3341                                  SourceLocation()))); // set the 'receiver'.3342 3343    // (id)class_getSuperclass((Class)objc_getClass("CurrentClass"))3344    SmallVector<Expr*, 8> ClsExprs;3345    ClsExprs.push_back(getStringLiteral(ClassDecl->getIdentifier()->getName()));3346    // (Class)objc_getClass("CurrentClass")3347    CallExpr *Cls = SynthesizeCallToFunctionDecl(GetClassFunctionDecl, ClsExprs,3348                                                 StartLoc, EndLoc);3349    ClsExprs.clear();3350    ClsExprs.push_back(Cls);3351    Cls = SynthesizeCallToFunctionDecl(GetSuperClassFunctionDecl, ClsExprs,3352                                       StartLoc, EndLoc);3353 3354    // (id)class_getSuperclass((Class)objc_getClass("CurrentClass"))3355    // To turn off a warning, type-cast to 'id'3356    InitExprs.push_back(3357      // set 'super class', using class_getSuperclass().3358      NoTypeInfoCStyleCastExpr(Context, Context->getObjCIdType(),3359                               CK_BitCast, Cls));3360    // struct __rw_objc_super3361    QualType superType = getSuperStructType();3362    Expr *SuperRep;3363 3364    if (LangOpts.MicrosoftExt) {3365      SynthSuperConstructorFunctionDecl();3366      // Simulate a constructor call...3367      DeclRefExpr *DRE = new (Context)3368          DeclRefExpr(*Context, SuperConstructorFunctionDecl, false, superType,3369                      VK_LValue, SourceLocation());3370      SuperRep =3371          CallExpr::Create(*Context, DRE, InitExprs, superType, VK_LValue,3372                           SourceLocation(), FPOptionsOverride());3373      // The code for super is a little tricky to prevent collision with3374      // the structure definition in the header. The rewriter has it's own3375      // internal definition (__rw_objc_super) that is uses. This is why3376      // we need the cast below. For example:3377      // (struct __rw_objc_super *)&__rw_objc_super((id)self, (id)objc_getClass("SUPER"))3378      //3379      SuperRep = UnaryOperator::Create(3380          const_cast<ASTContext &>(*Context), SuperRep, UO_AddrOf,3381          Context->getPointerType(SuperRep->getType()), VK_PRValue, OK_Ordinary,3382          SourceLocation(), false, FPOptionsOverride());3383      SuperRep = NoTypeInfoCStyleCastExpr(Context,3384                               Context->getPointerType(superType),3385                               CK_BitCast, SuperRep);3386    } else {3387      // (struct __rw_objc_super) { <exprs from above> }3388      InitListExpr *ILE =3389        new (Context) InitListExpr(*Context, SourceLocation(), InitExprs,3390                                   SourceLocation());3391      TypeSourceInfo *superTInfo3392        = Context->getTrivialTypeSourceInfo(superType);3393      SuperRep = new (Context) CompoundLiteralExpr(3394          SourceLocation(), superTInfo, superType, VK_PRValue, ILE, false);3395    }3396    MsgExprs.push_back(SuperRep);3397    break;3398  }3399 3400  case ObjCMessageExpr::Instance: {3401    // Remove all type-casts because it may contain objc-style types; e.g.3402    // Foo<Proto> *.3403    Expr *recExpr = Exp->getInstanceReceiver();3404    while (CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(recExpr))3405      recExpr = CE->getSubExpr();3406    CastKind CK = recExpr->getType()->isObjCObjectPointerType()3407                    ? CK_BitCast : recExpr->getType()->isBlockPointerType()3408                                     ? CK_BlockPointerToObjCPointerCast3409                                     : CK_CPointerToObjCPointerCast;3410 3411    recExpr = NoTypeInfoCStyleCastExpr(Context, Context->getObjCIdType(),3412                                       CK, recExpr);3413    MsgExprs.push_back(recExpr);3414    break;3415  }3416  }3417 3418  // Create a call to sel_registerName("selName"), it will be the 2nd argument.3419  SmallVector<Expr*, 8> SelExprs;3420  SelExprs.push_back(getStringLiteral(Exp->getSelector().getAsString()));3421  CallExpr *SelExp = SynthesizeCallToFunctionDecl(SelGetUidFunctionDecl,3422                                                  SelExprs, StartLoc, EndLoc);3423  MsgExprs.push_back(SelExp);3424 3425  // Now push any user supplied arguments.3426  for (unsigned i = 0; i < Exp->getNumArgs(); i++) {3427    Expr *userExpr = Exp->getArg(i);3428    // Make all implicit casts explicit...ICE comes in handy:-)3429    if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(userExpr)) {3430      // Reuse the ICE type, it is exactly what the doctor ordered.3431      QualType type = ICE->getType();3432      if (needToScanForQualifiers(type))3433        type = Context->getObjCIdType();3434      // Make sure we convert "type (^)(...)" to "type (*)(...)".3435      (void)convertBlockPointerToFunctionPointer(type);3436      const Expr *SubExpr = ICE->IgnoreParenImpCasts();3437      CastKind CK;3438      if (SubExpr->getType()->isIntegralType(*Context) &&3439          type->isBooleanType()) {3440        CK = CK_IntegralToBoolean;3441      } else if (type->isObjCObjectPointerType()) {3442        if (SubExpr->getType()->isBlockPointerType()) {3443          CK = CK_BlockPointerToObjCPointerCast;3444        } else if (SubExpr->getType()->isPointerType()) {3445          CK = CK_CPointerToObjCPointerCast;3446        } else {3447          CK = CK_BitCast;3448        }3449      } else {3450        CK = CK_BitCast;3451      }3452 3453      userExpr = NoTypeInfoCStyleCastExpr(Context, type, CK, userExpr);3454    }3455    // Make id<P...> cast into an 'id' cast.3456    else if (CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(userExpr)) {3457      if (CE->getType()->isObjCQualifiedIdType()) {3458        while ((CE = dyn_cast<CStyleCastExpr>(userExpr)))3459          userExpr = CE->getSubExpr();3460        CastKind CK;3461        if (userExpr->getType()->isIntegralType(*Context)) {3462          CK = CK_IntegralToPointer;3463        } else if (userExpr->getType()->isBlockPointerType()) {3464          CK = CK_BlockPointerToObjCPointerCast;3465        } else if (userExpr->getType()->isPointerType()) {3466          CK = CK_CPointerToObjCPointerCast;3467        } else {3468          CK = CK_BitCast;3469        }3470        userExpr = NoTypeInfoCStyleCastExpr(Context, Context->getObjCIdType(),3471                                            CK, userExpr);3472      }3473    }3474    MsgExprs.push_back(userExpr);3475    // We've transferred the ownership to MsgExprs. For now, we *don't* null3476    // out the argument in the original expression (since we aren't deleting3477    // the ObjCMessageExpr). See RewritePropertyOrImplicitSetter() usage for more info.3478    //Exp->setArg(i, 0);3479  }3480  // Generate the funky cast.3481  CastExpr *cast;3482  SmallVector<QualType, 8> ArgTypes;3483  QualType returnType;3484 3485  // Push 'id' and 'SEL', the 2 implicit arguments.3486  if (MsgSendFlavor == MsgSendSuperFunctionDecl)3487    ArgTypes.push_back(Context->getPointerType(getSuperStructType()));3488  else3489    ArgTypes.push_back(Context->getObjCIdType());3490  ArgTypes.push_back(Context->getObjCSelType());3491  if (ObjCMethodDecl *OMD = Exp->getMethodDecl()) {3492    // Push any user argument types.3493    for (const auto *PI : OMD->parameters()) {3494      QualType t = PI->getType()->isObjCQualifiedIdType()3495                     ? Context->getObjCIdType()3496                     : PI->getType();3497      // Make sure we convert "t (^)(...)" to "t (*)(...)".3498      (void)convertBlockPointerToFunctionPointer(t);3499      ArgTypes.push_back(t);3500    }3501    returnType = Exp->getType();3502    convertToUnqualifiedObjCType(returnType);3503    (void)convertBlockPointerToFunctionPointer(returnType);3504  } else {3505    returnType = Context->getObjCIdType();3506  }3507  // Get the type, we will need to reference it in a couple spots.3508  QualType msgSendType = MsgSendFlavor->getType();3509 3510  // Create a reference to the objc_msgSend() declaration.3511  DeclRefExpr *DRE = new (Context) DeclRefExpr(3512      *Context, MsgSendFlavor, false, msgSendType, VK_LValue, SourceLocation());3513 3514  // Need to cast objc_msgSend to "void *" (to workaround a GCC bandaid).3515  // If we don't do this cast, we get the following bizarre warning/note:3516  // xx.m:13: warning: function called through a non-compatible type3517  // xx.m:13: note: if this code is reached, the program will abort3518  cast = NoTypeInfoCStyleCastExpr(Context,3519                                  Context->getPointerType(Context->VoidTy),3520                                  CK_BitCast, DRE);3521 3522  // Now do the "normal" pointer to function cast.3523  // If we don't have a method decl, force a variadic cast.3524  const ObjCMethodDecl *MD = Exp->getMethodDecl();3525  QualType castType =3526    getSimpleFunctionType(returnType, ArgTypes, MD ? MD->isVariadic() : true);3527  castType = Context->getPointerType(castType);3528  cast = NoTypeInfoCStyleCastExpr(Context, castType, CK_BitCast,3529                                  cast);3530 3531  // Don't forget the parens to enforce the proper binding.3532  ParenExpr *PE = new (Context) ParenExpr(StartLoc, EndLoc, cast);3533 3534  const FunctionType *FT = msgSendType->castAs<FunctionType>();3535  CallExpr *CE = CallExpr::Create(*Context, PE, MsgExprs, FT->getReturnType(),3536                                  VK_PRValue, EndLoc, FPOptionsOverride());3537  Stmt *ReplacingStmt = CE;3538  if (MsgSendStretFlavor) {3539    // We have the method which returns a struct/union. Must also generate3540    // call to objc_msgSend_stret and hang both varieties on a conditional3541    // expression which dictate which one to envoke depending on size of3542    // method's return type.3543 3544    Expr *STCE = SynthMsgSendStretCallExpr(MsgSendStretFlavor,3545                                           returnType,3546                                           ArgTypes, MsgExprs,3547                                           Exp->getMethodDecl());3548    ReplacingStmt = STCE;3549  }3550  // delete Exp; leak for now, see RewritePropertyOrImplicitSetter() usage for more info.3551  return ReplacingStmt;3552}3553 3554Stmt *RewriteModernObjC::RewriteMessageExpr(ObjCMessageExpr *Exp) {3555  Stmt *ReplacingStmt =3556      SynthMessageExpr(Exp, Exp->getBeginLoc(), Exp->getEndLoc());3557 3558  // Now do the actual rewrite.3559  ReplaceStmt(Exp, ReplacingStmt);3560 3561  // delete Exp; leak for now, see RewritePropertyOrImplicitSetter() usage for more info.3562  return ReplacingStmt;3563}3564 3565// typedef struct objc_object Protocol;3566QualType RewriteModernObjC::getProtocolType() {3567  if (!ProtocolTypeDecl) {3568    TypeSourceInfo *TInfo3569      = Context->getTrivialTypeSourceInfo(Context->getObjCIdType());3570    ProtocolTypeDecl = TypedefDecl::Create(*Context, TUDecl,3571                                           SourceLocation(), SourceLocation(),3572                                           &Context->Idents.get("Protocol"),3573                                           TInfo);3574  }3575  return Context->getTypeDeclType(ProtocolTypeDecl);3576}3577 3578/// RewriteObjCProtocolExpr - Rewrite a protocol expression into3579/// a synthesized/forward data reference (to the protocol's metadata).3580/// The forward references (and metadata) are generated in3581/// RewriteModernObjC::HandleTranslationUnit().3582Stmt *RewriteModernObjC::RewriteObjCProtocolExpr(ObjCProtocolExpr *Exp) {3583  std::string Name = "_OBJC_PROTOCOL_REFERENCE_$_" +3584                      Exp->getProtocol()->getNameAsString();3585  IdentifierInfo *ID = &Context->Idents.get(Name);3586  VarDecl *VD = VarDecl::Create(*Context, TUDecl, SourceLocation(),3587                                SourceLocation(), ID, getProtocolType(),3588                                nullptr, SC_Extern);3589  DeclRefExpr *DRE = new (Context) DeclRefExpr(3590      *Context, VD, false, getProtocolType(), VK_LValue, SourceLocation());3591  CastExpr *castExpr = NoTypeInfoCStyleCastExpr(3592      Context, Context->getPointerType(DRE->getType()), CK_BitCast, DRE);3593  ReplaceStmt(Exp, castExpr);3594  ProtocolExprDecls.insert(Exp->getProtocol()->getCanonicalDecl());3595  // delete Exp; leak for now, see RewritePropertyOrImplicitSetter() usage for more info.3596  return castExpr;3597}3598 3599/// IsTagDefinedInsideClass - This routine checks that a named tagged type3600/// is defined inside an objective-c class. If so, it returns true.3601bool RewriteModernObjC::IsTagDefinedInsideClass(ObjCContainerDecl *IDecl,3602                                                TagDecl *Tag,3603                                                bool &IsNamedDefinition) {3604  if (!IDecl)3605    return false;3606  SourceLocation TagLocation;3607  if (RecordDecl *RD = dyn_cast<RecordDecl>(Tag)) {3608    RD = RD->getDefinition();3609    if (!RD || !RD->getDeclName().getAsIdentifierInfo())3610      return false;3611    IsNamedDefinition = true;3612    TagLocation = RD->getLocation();3613    return Context->getSourceManager().isBeforeInTranslationUnit(3614                                          IDecl->getLocation(), TagLocation);3615  }3616  if (EnumDecl *ED = dyn_cast<EnumDecl>(Tag)) {3617    if (!ED || !ED->getDeclName().getAsIdentifierInfo())3618      return false;3619    IsNamedDefinition = true;3620    TagLocation = ED->getLocation();3621    return Context->getSourceManager().isBeforeInTranslationUnit(3622                                          IDecl->getLocation(), TagLocation);3623  }3624  return false;3625}3626 3627/// RewriteObjCFieldDeclType - This routine rewrites a type into the buffer.3628/// It handles elaborated types, as well as enum types in the process.3629bool RewriteModernObjC::RewriteObjCFieldDeclType(QualType &Type,3630                                                 std::string &Result) {3631  if (Type->getAs<TypedefType>()) {3632    Result += "\t";3633    return false;3634  }3635 3636  if (Type->isArrayType()) {3637    QualType ElemTy = Context->getBaseElementType(Type);3638    return RewriteObjCFieldDeclType(ElemTy, Result);3639  }3640  else if (Type->isRecordType()) {3641    auto *RD = Type->castAsRecordDecl();3642    if (RD->isCompleteDefinition()) {3643      if (RD->isStruct())3644        Result += "\n\tstruct ";3645      else if (RD->isUnion())3646        Result += "\n\tunion ";3647      else3648        assert(false && "class not allowed as an ivar type");3649 3650      Result += RD->getName();3651      if (GlobalDefinedTags.count(RD)) {3652        // struct/union is defined globally, use it.3653        Result += " ";3654        return true;3655      }3656      Result += " {\n";3657      for (auto *FD : RD->fields())3658        RewriteObjCFieldDecl(FD, Result);3659      Result += "\t} ";3660      return true;3661    }3662  } else if (auto *ED = Type->getAsEnumDecl();3663             ED && ED->isCompleteDefinition()) {3664    Result += "\n\tenum ";3665    Result += ED->getName();3666    if (GlobalDefinedTags.count(ED)) {3667      // Enum is globall defined, use it.3668      Result += " ";3669      return true;3670    }3671 3672    Result += " {\n";3673    for (const auto *EC : ED->enumerators()) {3674      Result += "\t";3675      Result += EC->getName();3676      Result += " = ";3677      Result += toString(EC->getInitVal(), 10);3678      Result += ",\n";3679    }3680    Result += "\t} ";3681    return true;3682  }3683 3684  Result += "\t";3685  convertObjCTypeToCStyleType(Type);3686  return false;3687}3688 3689 3690/// RewriteObjCFieldDecl - This routine rewrites a field into the buffer.3691/// It handles elaborated types, as well as enum types in the process.3692void RewriteModernObjC::RewriteObjCFieldDecl(FieldDecl *fieldDecl,3693                                             std::string &Result) {3694  QualType Type = fieldDecl->getType();3695  std::string Name = fieldDecl->getNameAsString();3696 3697  bool EleboratedType = RewriteObjCFieldDeclType(Type, Result);3698  if (!EleboratedType)3699    Type.getAsStringInternal(Name, Context->getPrintingPolicy());3700  Result += Name;3701  if (fieldDecl->isBitField()) {3702    Result += " : ";3703    Result += utostr(fieldDecl->getBitWidthValue());3704  }3705  else if (EleboratedType && Type->isArrayType()) {3706    const ArrayType *AT = Context->getAsArrayType(Type);3707    do {3708      if (const ConstantArrayType *CAT = dyn_cast<ConstantArrayType>(AT)) {3709        Result += "[";3710        llvm::APInt Dim = CAT->getSize();3711        Result += utostr(Dim.getZExtValue());3712        Result += "]";3713      }3714      AT = Context->getAsArrayType(AT->getElementType());3715    } while (AT);3716  }3717 3718  Result += ";\n";3719}3720 3721/// RewriteLocallyDefinedNamedAggregates - This routine rewrites locally defined3722/// named aggregate types into the input buffer.3723void RewriteModernObjC::RewriteLocallyDefinedNamedAggregates(FieldDecl *fieldDecl,3724                                             std::string &Result) {3725  QualType Type = fieldDecl->getType();3726  if (Type->getAs<TypedefType>())3727    return;3728  if (Type->isArrayType())3729    Type = Context->getBaseElementType(Type);3730 3731  auto *IDecl = dyn_cast<ObjCContainerDecl>(fieldDecl->getDeclContext());3732 3733  if (auto *TD = Type->getAsTagDecl()) {3734    if (GlobalDefinedTags.count(TD))3735      return;3736 3737    bool IsNamedDefinition = false;3738    if (IsTagDefinedInsideClass(IDecl, TD, IsNamedDefinition)) {3739      RewriteObjCFieldDeclType(Type, Result);3740      Result += ";";3741    }3742    if (IsNamedDefinition)3743      GlobalDefinedTags.insert(TD);3744  }3745}3746 3747unsigned RewriteModernObjC::ObjCIvarBitfieldGroupNo(ObjCIvarDecl *IV) {3748  const ObjCInterfaceDecl *CDecl = IV->getContainingInterface();3749  if (ObjCInterefaceHasBitfieldGroups.count(CDecl)) {3750    return IvarGroupNumber[IV];3751  }3752  unsigned GroupNo = 0;3753  SmallVector<const ObjCIvarDecl *, 8> IVars;3754  for (const ObjCIvarDecl *IVD = CDecl->all_declared_ivar_begin();3755       IVD; IVD = IVD->getNextIvar())3756    IVars.push_back(IVD);3757 3758  for (unsigned i = 0, e = IVars.size(); i < e; i++)3759    if (IVars[i]->isBitField()) {3760      IvarGroupNumber[IVars[i++]] = ++GroupNo;3761      while (i < e && IVars[i]->isBitField())3762        IvarGroupNumber[IVars[i++]] = GroupNo;3763      if (i < e)3764        --i;3765    }3766 3767  ObjCInterefaceHasBitfieldGroups.insert(CDecl);3768  return IvarGroupNumber[IV];3769}3770 3771QualType RewriteModernObjC::SynthesizeBitfieldGroupStructType(3772                              ObjCIvarDecl *IV,3773                              SmallVectorImpl<ObjCIvarDecl *> &IVars) {3774  std::string StructTagName;3775  ObjCIvarBitfieldGroupType(IV, StructTagName);3776  RecordDecl *RD = RecordDecl::Create(3777      *Context, TagTypeKind::Struct, Context->getTranslationUnitDecl(),3778      SourceLocation(), SourceLocation(), &Context->Idents.get(StructTagName));3779  for (unsigned i=0, e = IVars.size(); i < e; i++) {3780    ObjCIvarDecl *Ivar = IVars[i];3781    RD->addDecl(FieldDecl::Create(*Context, RD, SourceLocation(), SourceLocation(),3782                                  &Context->Idents.get(Ivar->getName()),3783                                  Ivar->getType(),3784                                  nullptr, /*Expr *BW */Ivar->getBitWidth(),3785                                  false, ICIS_NoInit));3786  }3787  RD->completeDefinition();3788  return Context->getCanonicalTagType(RD);3789}3790 3791QualType RewriteModernObjC::GetGroupRecordTypeForObjCIvarBitfield(ObjCIvarDecl *IV) {3792  const ObjCInterfaceDecl *CDecl = IV->getContainingInterface();3793  unsigned GroupNo = ObjCIvarBitfieldGroupNo(IV);3794  std::pair<const ObjCInterfaceDecl*, unsigned> tuple = std::make_pair(CDecl, GroupNo);3795  if (auto It = GroupRecordType.find(tuple); It != GroupRecordType.end())3796    return It->second;3797 3798  SmallVector<ObjCIvarDecl *, 8> IVars;3799  for (const ObjCIvarDecl *IVD = CDecl->all_declared_ivar_begin();3800       IVD; IVD = IVD->getNextIvar()) {3801    if (IVD->isBitField())3802      IVars.push_back(const_cast<ObjCIvarDecl *>(IVD));3803    else {3804      if (!IVars.empty()) {3805        unsigned GroupNo = ObjCIvarBitfieldGroupNo(IVars[0]);3806        // Generate the struct type for this group of bitfield ivars.3807        GroupRecordType[std::make_pair(CDecl, GroupNo)] =3808          SynthesizeBitfieldGroupStructType(IVars[0], IVars);3809        IVars.clear();3810      }3811    }3812  }3813  if (!IVars.empty()) {3814    // Do the last one.3815    unsigned GroupNo = ObjCIvarBitfieldGroupNo(IVars[0]);3816    GroupRecordType[std::make_pair(CDecl, GroupNo)] =3817      SynthesizeBitfieldGroupStructType(IVars[0], IVars);3818  }3819  QualType RetQT = GroupRecordType[tuple];3820  assert(!RetQT.isNull() && "GetGroupRecordTypeForObjCIvarBitfield struct type is NULL");3821 3822  return RetQT;3823}3824 3825/// ObjCIvarBitfieldGroupDecl - Names field decl. for ivar bitfield group.3826/// Name would be: classname__GRBF_n where n is the group number for this ivar.3827void RewriteModernObjC::ObjCIvarBitfieldGroupDecl(ObjCIvarDecl *IV,3828                                                  std::string &Result) {3829  const ObjCInterfaceDecl *CDecl = IV->getContainingInterface();3830  Result += CDecl->getName();3831  Result += "__GRBF_";3832  unsigned GroupNo = ObjCIvarBitfieldGroupNo(IV);3833  Result += utostr(GroupNo);3834}3835 3836/// ObjCIvarBitfieldGroupType - Names struct type for ivar bitfield group.3837/// Name of the struct would be: classname__T_n where n is the group number for3838/// this ivar.3839void RewriteModernObjC::ObjCIvarBitfieldGroupType(ObjCIvarDecl *IV,3840                                                  std::string &Result) {3841  const ObjCInterfaceDecl *CDecl = IV->getContainingInterface();3842  Result += CDecl->getName();3843  Result += "__T_";3844  unsigned GroupNo = ObjCIvarBitfieldGroupNo(IV);3845  Result += utostr(GroupNo);3846}3847 3848/// ObjCIvarBitfieldGroupOffset - Names symbol for ivar bitfield group field offset.3849/// Name would be: OBJC_IVAR_$_classname__GRBF_n where n is the group number for3850/// this ivar.3851void RewriteModernObjC::ObjCIvarBitfieldGroupOffset(ObjCIvarDecl *IV,3852                                                    std::string &Result) {3853  Result += "OBJC_IVAR_$_";3854  ObjCIvarBitfieldGroupDecl(IV, Result);3855}3856 3857#define SKIP_BITFIELDS(IX, ENDIX, VEC) { \3858      while ((IX < ENDIX) && VEC[IX]->isBitField()) \3859        ++IX; \3860      if (IX < ENDIX) \3861        --IX; \3862}3863 3864/// RewriteObjCInternalStruct - Rewrite one internal struct corresponding to3865/// an objective-c class with ivars.3866void RewriteModernObjC::RewriteObjCInternalStruct(ObjCInterfaceDecl *CDecl,3867                                               std::string &Result) {3868  assert(CDecl && "Class missing in SynthesizeObjCInternalStruct");3869  assert(CDecl->getName() != "" &&3870         "Name missing in SynthesizeObjCInternalStruct");3871  ObjCInterfaceDecl *RCDecl = CDecl->getSuperClass();3872  SmallVector<ObjCIvarDecl *, 8> IVars;3873  for (ObjCIvarDecl *IVD = CDecl->all_declared_ivar_begin();3874       IVD; IVD = IVD->getNextIvar())3875    IVars.push_back(IVD);3876 3877  SourceLocation LocStart = CDecl->getBeginLoc();3878  SourceLocation LocEnd = CDecl->getEndOfDefinitionLoc();3879 3880  const char *startBuf = SM->getCharacterData(LocStart);3881  const char *endBuf = SM->getCharacterData(LocEnd);3882 3883  // If no ivars and no root or if its root, directly or indirectly,3884  // have no ivars (thus not synthesized) then no need to synthesize this class.3885  if ((!CDecl->isThisDeclarationADefinition() || IVars.size() == 0) &&3886      (!RCDecl || !ObjCSynthesizedStructs.count(RCDecl))) {3887    endBuf += Lexer::MeasureTokenLength(LocEnd, *SM, LangOpts);3888    ReplaceText(LocStart, endBuf-startBuf, Result);3889    return;3890  }3891 3892  // Insert named struct/union definitions inside class to3893  // outer scope. This follows semantics of locally defined3894  // struct/unions in objective-c classes.3895  for (unsigned i = 0, e = IVars.size(); i < e; i++)3896    RewriteLocallyDefinedNamedAggregates(IVars[i], Result);3897 3898  // Insert named structs which are syntheized to group ivar bitfields3899  // to outer scope as well.3900  for (unsigned i = 0, e = IVars.size(); i < e; i++)3901    if (IVars[i]->isBitField()) {3902      ObjCIvarDecl *IV = IVars[i];3903      QualType QT = GetGroupRecordTypeForObjCIvarBitfield(IV);3904      RewriteObjCFieldDeclType(QT, Result);3905      Result += ";";3906      // skip over ivar bitfields in this group.3907      SKIP_BITFIELDS(i , e, IVars);3908    }3909 3910  Result += "\nstruct ";3911  Result += CDecl->getNameAsString();3912  Result += "_IMPL {\n";3913 3914  if (RCDecl && ObjCSynthesizedStructs.count(RCDecl)) {3915    Result += "\tstruct "; Result += RCDecl->getNameAsString();3916    Result += "_IMPL "; Result += RCDecl->getNameAsString();3917    Result += "_IVARS;\n";3918  }3919 3920  for (unsigned i = 0, e = IVars.size(); i < e; i++) {3921    if (IVars[i]->isBitField()) {3922      ObjCIvarDecl *IV = IVars[i];3923      Result += "\tstruct ";3924      ObjCIvarBitfieldGroupType(IV, Result); Result += " ";3925      ObjCIvarBitfieldGroupDecl(IV, Result); Result += ";\n";3926      // skip over ivar bitfields in this group.3927      SKIP_BITFIELDS(i , e, IVars);3928    }3929    else3930      RewriteObjCFieldDecl(IVars[i], Result);3931  }3932 3933  Result += "};\n";3934  endBuf += Lexer::MeasureTokenLength(LocEnd, *SM, LangOpts);3935  ReplaceText(LocStart, endBuf-startBuf, Result);3936  // Mark this struct as having been generated.3937  if (!ObjCSynthesizedStructs.insert(CDecl).second)3938    llvm_unreachable("struct already synthesize- RewriteObjCInternalStruct");3939}3940 3941/// RewriteIvarOffsetSymbols - Rewrite ivar offset symbols of those ivars which3942/// have been referenced in an ivar access expression.3943void RewriteModernObjC::RewriteIvarOffsetSymbols(ObjCInterfaceDecl *CDecl,3944                                                  std::string &Result) {3945  // write out ivar offset symbols which have been referenced in an ivar3946  // access expression.3947  llvm::SmallSetVector<ObjCIvarDecl *, 8> Ivars = ReferencedIvars[CDecl];3948 3949  if (Ivars.empty())3950    return;3951 3952  llvm::DenseSet<std::pair<const ObjCInterfaceDecl*, unsigned> > GroupSymbolOutput;3953  for (ObjCIvarDecl *IvarDecl : Ivars) {3954    const ObjCInterfaceDecl *IDecl = IvarDecl->getContainingInterface();3955    unsigned GroupNo = 0;3956    if (IvarDecl->isBitField()) {3957      GroupNo = ObjCIvarBitfieldGroupNo(IvarDecl);3958      if (GroupSymbolOutput.count(std::make_pair(IDecl, GroupNo)))3959        continue;3960    }3961    Result += "\n";3962    if (LangOpts.MicrosoftExt)3963      Result += "__declspec(allocate(\".objc_ivar$B\")) ";3964    Result += "extern \"C\" ";3965    if (LangOpts.MicrosoftExt &&3966        IvarDecl->getAccessControl() != ObjCIvarDecl::Private &&3967        IvarDecl->getAccessControl() != ObjCIvarDecl::Package)3968        Result += "__declspec(dllimport) ";3969 3970    Result += "unsigned long ";3971    if (IvarDecl->isBitField()) {3972      ObjCIvarBitfieldGroupOffset(IvarDecl, Result);3973      GroupSymbolOutput.insert(std::make_pair(IDecl, GroupNo));3974    }3975    else3976      WriteInternalIvarName(CDecl, IvarDecl, Result);3977    Result += ";";3978  }3979}3980 3981//===----------------------------------------------------------------------===//3982// Meta Data Emission3983//===----------------------------------------------------------------------===//3984 3985/// RewriteImplementations - This routine rewrites all method implementations3986/// and emits meta-data.3987 3988void RewriteModernObjC::RewriteImplementations() {3989  int ClsDefCount = ClassImplementation.size();3990  int CatDefCount = CategoryImplementation.size();3991 3992  // Rewrite implemented methods3993  for (int i = 0; i < ClsDefCount; i++) {3994    ObjCImplementationDecl *OIMP = ClassImplementation[i];3995    ObjCInterfaceDecl *CDecl = OIMP->getClassInterface();3996    if (CDecl->isImplicitInterfaceDecl())3997      assert(false &&3998             "Legacy implicit interface rewriting not supported in moder abi");3999    RewriteImplementationDecl(OIMP);4000  }4001 4002  for (int i = 0; i < CatDefCount; i++) {4003    ObjCCategoryImplDecl *CIMP = CategoryImplementation[i];4004    ObjCInterfaceDecl *CDecl = CIMP->getClassInterface();4005    if (CDecl->isImplicitInterfaceDecl())4006      assert(false &&4007             "Legacy implicit interface rewriting not supported in moder abi");4008    RewriteImplementationDecl(CIMP);4009  }4010}4011 4012void RewriteModernObjC::RewriteByRefString(std::string &ResultStr,4013                                     const std::string &Name,4014                                     ValueDecl *VD, bool def) {4015  assert(BlockByRefDeclNo.count(VD) &&4016         "RewriteByRefString: ByRef decl missing");4017  if (def)4018    ResultStr += "struct ";4019  ResultStr += "__Block_byref_" + Name +4020    "_" + utostr(BlockByRefDeclNo[VD]) ;4021}4022 4023static bool HasLocalVariableExternalStorage(ValueDecl *VD) {4024  if (VarDecl *Var = dyn_cast<VarDecl>(VD))4025    return (Var->isFunctionOrMethodVarDecl() && !Var->hasLocalStorage());4026  return false;4027}4028 4029std::string RewriteModernObjC::SynthesizeBlockFunc(BlockExpr *CE, int i,4030                                                   StringRef funcName,4031                                                   const std::string &Tag) {4032  const FunctionType *AFT = CE->getFunctionType();4033  QualType RT = AFT->getReturnType();4034  std::string StructRef = "struct " + Tag;4035  SourceLocation BlockLoc = CE->getExprLoc();4036  std::string S;4037  ConvertSourceLocationToLineDirective(BlockLoc, S);4038 4039  S += "static " + RT.getAsString(Context->getPrintingPolicy()) + " __" +4040         funcName.str() + "_block_func_" + utostr(i);4041 4042  BlockDecl *BD = CE->getBlockDecl();4043 4044  if (isa<FunctionNoProtoType>(AFT)) {4045    // No user-supplied arguments. Still need to pass in a pointer to the4046    // block (to reference imported block decl refs).4047    S += "(" + StructRef + " *__cself)";4048  } else if (BD->param_empty()) {4049    S += "(" + StructRef + " *__cself)";4050  } else {4051    const FunctionProtoType *FT = cast<FunctionProtoType>(AFT);4052    assert(FT && "SynthesizeBlockFunc: No function proto");4053    S += '(';4054    // first add the implicit argument.4055    S += StructRef + " *__cself, ";4056    std::string ParamStr;4057    for (BlockDecl::param_iterator AI = BD->param_begin(),4058         E = BD->param_end(); AI != E; ++AI) {4059      if (AI != BD->param_begin()) S += ", ";4060      ParamStr = (*AI)->getNameAsString();4061      QualType QT = (*AI)->getType();4062      (void)convertBlockPointerToFunctionPointer(QT);4063      QT.getAsStringInternal(ParamStr, Context->getPrintingPolicy());4064      S += ParamStr;4065    }4066    if (FT->isVariadic()) {4067      if (!BD->param_empty()) S += ", ";4068      S += "...";4069    }4070    S += ')';4071  }4072  S += " {\n";4073 4074  // Create local declarations to avoid rewriting all closure decl ref exprs.4075  // First, emit a declaration for all "by ref" decls.4076  for (ValueDecl *VD : BlockByRefDecls) {4077    S += "  ";4078    std::string Name = VD->getNameAsString();4079    std::string TypeString;4080    RewriteByRefString(TypeString, Name, VD);4081    TypeString += " *";4082    Name = TypeString + Name;4083    S += Name + " = __cself->" + VD->getNameAsString() + "; // bound by ref\n";4084  }4085  // Next, emit a declaration for all "by copy" declarations.4086  for (ValueDecl *VD : BlockByCopyDecls) {4087    S += "  ";4088    // Handle nested closure invocation. For example:4089    //4090    //   void (^myImportedClosure)(void);4091    //   myImportedClosure  = ^(void) { setGlobalInt(x + y); };4092    //4093    //   void (^anotherClosure)(void);4094    //   anotherClosure = ^(void) {4095    //     myImportedClosure(); // import and invoke the closure4096    //   };4097    //4098    if (isTopLevelBlockPointerType(VD->getType())) {4099      RewriteBlockPointerTypeVariable(S, VD);4100      S += " = (";4101      RewriteBlockPointerType(S, VD->getType());4102      S += ")";4103      S += "__cself->" + VD->getNameAsString() + "; // bound by copy\n";4104    } else {4105      std::string Name = VD->getNameAsString();4106      QualType QT = VD->getType();4107      if (HasLocalVariableExternalStorage(VD))4108        QT = Context->getPointerType(QT);4109      QT.getAsStringInternal(Name, Context->getPrintingPolicy());4110      S += Name + " = __cself->" + VD->getNameAsString() +4111           "; // bound by copy\n";4112    }4113  }4114  std::string RewrittenStr = RewrittenBlockExprs[CE];4115  const char *cstr = RewrittenStr.c_str();4116  while (*cstr++ != '{') ;4117  S += cstr;4118  S += "\n";4119  return S;4120}4121 4122std::string RewriteModernObjC::SynthesizeBlockHelperFuncs(4123    BlockExpr *CE, int i, StringRef funcName, const std::string &Tag) {4124  std::string StructRef = "struct " + Tag;4125  std::string S = "static void __";4126 4127  S += funcName;4128  S += "_block_copy_" + utostr(i);4129  S += "(" + StructRef;4130  S += "*dst, " + StructRef;4131  S += "*src) {";4132  for (ValueDecl *VD : ImportedBlockDecls) {4133    S += "_Block_object_assign((void*)&dst->";4134    S += VD->getNameAsString();4135    S += ", (void*)src->";4136    S += VD->getNameAsString();4137    if (BlockByRefDecls.count(VD))4138      S += ", " + utostr(BLOCK_FIELD_IS_BYREF) + "/*BLOCK_FIELD_IS_BYREF*/);";4139    else if (VD->getType()->isBlockPointerType())4140      S += ", " + utostr(BLOCK_FIELD_IS_BLOCK) + "/*BLOCK_FIELD_IS_BLOCK*/);";4141    else4142      S += ", " + utostr(BLOCK_FIELD_IS_OBJECT) + "/*BLOCK_FIELD_IS_OBJECT*/);";4143  }4144  S += "}\n";4145 4146  S += "\nstatic void __";4147  S += funcName;4148  S += "_block_dispose_" + utostr(i);4149  S += "(" + StructRef;4150  S += "*src) {";4151  for (ValueDecl *VD : ImportedBlockDecls) {4152    S += "_Block_object_dispose((void*)src->";4153    S += VD->getNameAsString();4154    if (BlockByRefDecls.count(VD))4155      S += ", " + utostr(BLOCK_FIELD_IS_BYREF) + "/*BLOCK_FIELD_IS_BYREF*/);";4156    else if (VD->getType()->isBlockPointerType())4157      S += ", " + utostr(BLOCK_FIELD_IS_BLOCK) + "/*BLOCK_FIELD_IS_BLOCK*/);";4158    else4159      S += ", " + utostr(BLOCK_FIELD_IS_OBJECT) + "/*BLOCK_FIELD_IS_OBJECT*/);";4160  }4161  S += "}\n";4162  return S;4163}4164 4165std::string RewriteModernObjC::SynthesizeBlockImpl(BlockExpr *CE,4166                                                   const std::string &Tag,4167                                                   const std::string &Desc) {4168  std::string S = "\nstruct " + Tag;4169  std::string Constructor = "  " + Tag;4170 4171  S += " {\n  struct __block_impl impl;\n";4172  S += "  struct " + Desc;4173  S += "* Desc;\n";4174 4175  Constructor += "(void *fp, "; // Invoke function pointer.4176  Constructor += "struct " + Desc; // Descriptor pointer.4177  Constructor += " *desc";4178 4179  if (BlockDeclRefs.size()) {4180    // Output all "by copy" declarations.4181    for (ValueDecl *VD : BlockByCopyDecls) {4182      S += "  ";4183      std::string FieldName = VD->getNameAsString();4184      std::string ArgName = "_" + FieldName;4185      // Handle nested closure invocation. For example:4186      //4187      //   void (^myImportedBlock)(void);4188      //   myImportedBlock  = ^(void) { setGlobalInt(x + y); };4189      //4190      //   void (^anotherBlock)(void);4191      //   anotherBlock = ^(void) {4192      //     myImportedBlock(); // import and invoke the closure4193      //   };4194      //4195      if (isTopLevelBlockPointerType(VD->getType())) {4196        S += "struct __block_impl *";4197        Constructor += ", void *" + ArgName;4198      } else {4199        QualType QT = VD->getType();4200        if (HasLocalVariableExternalStorage(VD))4201          QT = Context->getPointerType(QT);4202        QT.getAsStringInternal(FieldName, Context->getPrintingPolicy());4203        QT.getAsStringInternal(ArgName, Context->getPrintingPolicy());4204        Constructor += ", " + ArgName;4205      }4206      S += FieldName + ";\n";4207    }4208    // Output all "by ref" declarations.4209    for (ValueDecl *VD : BlockByRefDecls) {4210      S += "  ";4211      std::string FieldName = VD->getNameAsString();4212      std::string ArgName = "_" + FieldName;4213      {4214        std::string TypeString;4215        RewriteByRefString(TypeString, FieldName, VD);4216        TypeString += " *";4217        FieldName = TypeString + FieldName;4218        ArgName = TypeString + ArgName;4219        Constructor += ", " + ArgName;4220      }4221      S += FieldName + "; // by ref\n";4222    }4223    // Finish writing the constructor.4224    Constructor += ", int flags=0)";4225    // Initialize all "by copy" arguments.4226    bool firsTime = true;4227    for (const ValueDecl *VD : BlockByCopyDecls) {4228      std::string Name = VD->getNameAsString();4229      if (firsTime) {4230        Constructor += " : ";4231        firsTime = false;4232      } else4233        Constructor += ", ";4234      if (isTopLevelBlockPointerType(VD->getType()))4235        Constructor += Name + "((struct __block_impl *)_" + Name + ")";4236      else4237        Constructor += Name + "(_" + Name + ")";4238    }4239    // Initialize all "by ref" arguments.4240    for (const ValueDecl *VD : BlockByRefDecls) {4241      std::string Name = VD->getNameAsString();4242      if (firsTime) {4243        Constructor += " : ";4244        firsTime = false;4245      }4246      else4247        Constructor += ", ";4248      Constructor += Name + "(_" + Name + "->__forwarding)";4249    }4250 4251    Constructor += " {\n";4252    if (GlobalVarDecl)4253      Constructor += "    impl.isa = &_NSConcreteGlobalBlock;\n";4254    else4255      Constructor += "    impl.isa = &_NSConcreteStackBlock;\n";4256    Constructor += "    impl.Flags = flags;\n    impl.FuncPtr = fp;\n";4257 4258    Constructor += "    Desc = desc;\n";4259  } else {4260    // Finish writing the constructor.4261    Constructor += ", int flags=0) {\n";4262    if (GlobalVarDecl)4263      Constructor += "    impl.isa = &_NSConcreteGlobalBlock;\n";4264    else4265      Constructor += "    impl.isa = &_NSConcreteStackBlock;\n";4266    Constructor += "    impl.Flags = flags;\n    impl.FuncPtr = fp;\n";4267    Constructor += "    Desc = desc;\n";4268  }4269  Constructor += "  ";4270  Constructor += "}\n";4271  S += Constructor;4272  S += "};\n";4273  return S;4274}4275 4276std::string RewriteModernObjC::SynthesizeBlockDescriptor(4277    const std::string &DescTag, const std::string &ImplTag, int i,4278    StringRef FunName, unsigned hasCopy) {4279  std::string S = "\nstatic struct " + DescTag;4280 4281  S += " {\n  size_t reserved;\n";4282  S += "  size_t Block_size;\n";4283  if (hasCopy) {4284    S += "  void (*copy)(struct ";4285    S += ImplTag; S += "*, struct ";4286    S += ImplTag; S += "*);\n";4287 4288    S += "  void (*dispose)(struct ";4289    S += ImplTag; S += "*);\n";4290  }4291  S += "} ";4292 4293  S += DescTag + "_DATA = { 0, sizeof(struct ";4294  S += ImplTag + ")";4295  if (hasCopy) {4296    S += ", __" + FunName.str() + "_block_copy_" + utostr(i);4297    S += ", __" + FunName.str() + "_block_dispose_" + utostr(i);4298  }4299  S += "};\n";4300  return S;4301}4302 4303void RewriteModernObjC::SynthesizeBlockLiterals(SourceLocation FunLocStart,4304                                          StringRef FunName) {4305  bool RewriteSC = (GlobalVarDecl &&4306                    !Blocks.empty() &&4307                    GlobalVarDecl->getStorageClass() == SC_Static &&4308                    GlobalVarDecl->getType().getCVRQualifiers());4309  if (RewriteSC) {4310    std::string SC(" void __");4311    SC += GlobalVarDecl->getNameAsString();4312    SC += "() {}";4313    InsertText(FunLocStart, SC);4314  }4315 4316  // Insert closures that were part of the function.4317  for (unsigned i = 0, count=0; i < Blocks.size(); i++) {4318    CollectBlockDeclRefInfo(Blocks[i]);4319    // Need to copy-in the inner copied-in variables not actually used in this4320    // block.4321    for (int j = 0; j < InnerDeclRefsCount[i]; j++) {4322      DeclRefExpr *Exp = InnerDeclRefs[count++];4323      ValueDecl *VD = Exp->getDecl();4324      BlockDeclRefs.push_back(Exp);4325      if (!VD->hasAttr<BlocksAttr>()) {4326        BlockByCopyDecls.insert(VD);4327        continue;4328      }4329 4330      BlockByRefDecls.insert(VD);4331 4332      // imported objects in the inner blocks not used in the outer4333      // blocks must be copied/disposed in the outer block as well.4334      if (VD->getType()->isObjCObjectPointerType() ||4335          VD->getType()->isBlockPointerType())4336        ImportedBlockDecls.insert(VD);4337    }4338 4339    std::string ImplTag = "__" + FunName.str() + "_block_impl_" + utostr(i);4340    std::string DescTag = "__" + FunName.str() + "_block_desc_" + utostr(i);4341 4342    std::string CI = SynthesizeBlockImpl(Blocks[i], ImplTag, DescTag);4343 4344    InsertText(FunLocStart, CI);4345 4346    std::string CF = SynthesizeBlockFunc(Blocks[i], i, FunName, ImplTag);4347 4348    InsertText(FunLocStart, CF);4349 4350    if (ImportedBlockDecls.size()) {4351      std::string HF = SynthesizeBlockHelperFuncs(Blocks[i], i, FunName, ImplTag);4352      InsertText(FunLocStart, HF);4353    }4354    std::string BD = SynthesizeBlockDescriptor(DescTag, ImplTag, i, FunName,4355                                               ImportedBlockDecls.size() > 0);4356    InsertText(FunLocStart, BD);4357 4358    BlockDeclRefs.clear();4359    BlockByRefDecls.clear();4360    BlockByCopyDecls.clear();4361    ImportedBlockDecls.clear();4362  }4363  if (RewriteSC) {4364    // Must insert any 'const/volatile/static here. Since it has been4365    // removed as result of rewriting of block literals.4366    std::string SC;4367    if (GlobalVarDecl->getStorageClass() == SC_Static)4368      SC = "static ";4369    if (GlobalVarDecl->getType().isConstQualified())4370      SC += "const ";4371    if (GlobalVarDecl->getType().isVolatileQualified())4372      SC += "volatile ";4373    if (GlobalVarDecl->getType().isRestrictQualified())4374      SC += "restrict ";4375    InsertText(FunLocStart, SC);4376  }4377  if (GlobalConstructionExp) {4378    // extra fancy dance for global literal expression.4379 4380    // Always the latest block expression on the block stack.4381    std::string Tag = "__";4382    Tag += FunName;4383    Tag += "_block_impl_";4384    Tag += utostr(Blocks.size()-1);4385    std::string globalBuf = "static ";4386    globalBuf += Tag; globalBuf += " ";4387    std::string SStr;4388 4389    llvm::raw_string_ostream constructorExprBuf(SStr);4390    GlobalConstructionExp->printPretty(constructorExprBuf, nullptr,4391                                       PrintingPolicy(LangOpts));4392    globalBuf += SStr;4393    globalBuf += ";\n";4394    InsertText(FunLocStart, globalBuf);4395    GlobalConstructionExp = nullptr;4396  }4397 4398  Blocks.clear();4399  InnerDeclRefsCount.clear();4400  InnerDeclRefs.clear();4401  RewrittenBlockExprs.clear();4402}4403 4404void RewriteModernObjC::InsertBlockLiteralsWithinFunction(FunctionDecl *FD) {4405  SourceLocation FunLocStart =4406    (!Blocks.empty()) ? getFunctionSourceLocation(*this, FD)4407                      : FD->getTypeSpecStartLoc();4408  StringRef FuncName = FD->getName();4409 4410  SynthesizeBlockLiterals(FunLocStart, FuncName);4411}4412 4413static void BuildUniqueMethodName(std::string &Name,4414                                  ObjCMethodDecl *MD) {4415  ObjCInterfaceDecl *IFace = MD->getClassInterface();4416  Name = std::string(IFace->getName());4417  Name += "__" + MD->getSelector().getAsString();4418  // Convert colons to underscores.4419  std::string::size_type loc = 0;4420  while ((loc = Name.find(':', loc)) != std::string::npos)4421    Name.replace(loc, 1, "_");4422}4423 4424void RewriteModernObjC::InsertBlockLiteralsWithinMethod(ObjCMethodDecl *MD) {4425  // fprintf(stderr,"In InsertBlockLiteralsWitinMethod\n");4426  // SourceLocation FunLocStart = MD->getBeginLoc();4427  SourceLocation FunLocStart = MD->getBeginLoc();4428  std::string FuncName;4429  BuildUniqueMethodName(FuncName, MD);4430  SynthesizeBlockLiterals(FunLocStart, FuncName);4431}4432 4433void RewriteModernObjC::GetBlockDeclRefExprs(Stmt *S) {4434  for (Stmt *SubStmt : S->children())4435    if (SubStmt) {4436      if (BlockExpr *CBE = dyn_cast<BlockExpr>(SubStmt))4437        GetBlockDeclRefExprs(CBE->getBody());4438      else4439        GetBlockDeclRefExprs(SubStmt);4440    }4441  // Handle specific things.4442  if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(S))4443    if (DRE->refersToEnclosingVariableOrCapture() ||4444        HasLocalVariableExternalStorage(DRE->getDecl()))4445      // FIXME: Handle enums.4446      BlockDeclRefs.push_back(DRE);4447}4448 4449void RewriteModernObjC::GetInnerBlockDeclRefExprs(Stmt *S,4450                SmallVectorImpl<DeclRefExpr *> &InnerBlockDeclRefs,4451                llvm::SmallPtrSetImpl<const DeclContext *> &InnerContexts) {4452  for (Stmt *SubStmt : S->children())4453    if (SubStmt) {4454      if (BlockExpr *CBE = dyn_cast<BlockExpr>(SubStmt)) {4455        InnerContexts.insert(cast<DeclContext>(CBE->getBlockDecl()));4456        GetInnerBlockDeclRefExprs(CBE->getBody(),4457                                  InnerBlockDeclRefs,4458                                  InnerContexts);4459      }4460      else4461        GetInnerBlockDeclRefExprs(SubStmt, InnerBlockDeclRefs, InnerContexts);4462    }4463  // Handle specific things.4464  if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(S)) {4465    if (DRE->refersToEnclosingVariableOrCapture() ||4466        HasLocalVariableExternalStorage(DRE->getDecl())) {4467      if (!InnerContexts.count(DRE->getDecl()->getDeclContext()))4468        InnerBlockDeclRefs.push_back(DRE);4469      if (VarDecl *Var = cast<VarDecl>(DRE->getDecl()))4470        if (Var->isFunctionOrMethodVarDecl())4471          ImportedLocalExternalDecls.insert(Var);4472    }4473  }4474}4475 4476/// convertObjCTypeToCStyleType - This routine converts such objc types4477/// as qualified objects, and blocks to their closest c/c++ types that4478/// it can. It returns true if input type was modified.4479bool RewriteModernObjC::convertObjCTypeToCStyleType(QualType &T) {4480  QualType oldT = T;4481  convertBlockPointerToFunctionPointer(T);4482  if (T->isFunctionPointerType()) {4483    QualType PointeeTy;4484    if (const PointerType* PT = T->getAs<PointerType>()) {4485      PointeeTy = PT->getPointeeType();4486      if (const FunctionType *FT = PointeeTy->getAs<FunctionType>()) {4487        T = convertFunctionTypeOfBlocks(FT);4488        T = Context->getPointerType(T);4489      }4490    }4491  }4492 4493  convertToUnqualifiedObjCType(T);4494  return T != oldT;4495}4496 4497/// convertFunctionTypeOfBlocks - This routine converts a function type4498/// whose result type may be a block pointer or whose argument type(s)4499/// might be block pointers to an equivalent function type replacing4500/// all block pointers to function pointers.4501QualType RewriteModernObjC::convertFunctionTypeOfBlocks(const FunctionType *FT) {4502  const FunctionProtoType *FTP = dyn_cast<FunctionProtoType>(FT);4503  // FTP will be null for closures that don't take arguments.4504  // Generate a funky cast.4505  SmallVector<QualType, 8> ArgTypes;4506  QualType Res = FT->getReturnType();4507  bool modified = convertObjCTypeToCStyleType(Res);4508 4509  if (FTP) {4510    for (auto &I : FTP->param_types()) {4511      QualType t = I;4512      // Make sure we convert "t (^)(...)" to "t (*)(...)".4513      if (convertObjCTypeToCStyleType(t))4514        modified = true;4515      ArgTypes.push_back(t);4516    }4517  }4518  QualType FuncType;4519  if (modified)4520    FuncType = getSimpleFunctionType(Res, ArgTypes);4521  else FuncType = QualType(FT, 0);4522  return FuncType;4523}4524 4525Stmt *RewriteModernObjC::SynthesizeBlockCall(CallExpr *Exp, const Expr *BlockExp) {4526  // Navigate to relevant type information.4527  const BlockPointerType *CPT = nullptr;4528 4529  if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(BlockExp)) {4530    CPT = DRE->getType()->getAs<BlockPointerType>();4531  } else if (const MemberExpr *MExpr = dyn_cast<MemberExpr>(BlockExp)) {4532    CPT = MExpr->getType()->getAs<BlockPointerType>();4533  }4534  else if (const ParenExpr *PRE = dyn_cast<ParenExpr>(BlockExp)) {4535    return SynthesizeBlockCall(Exp, PRE->getSubExpr());4536  }4537  else if (const ImplicitCastExpr *IEXPR = dyn_cast<ImplicitCastExpr>(BlockExp))4538    CPT = IEXPR->getType()->getAs<BlockPointerType>();4539  else if (const ConditionalOperator *CEXPR =4540            dyn_cast<ConditionalOperator>(BlockExp)) {4541    Expr *LHSExp = CEXPR->getLHS();4542    Stmt *LHSStmt = SynthesizeBlockCall(Exp, LHSExp);4543    Expr *RHSExp = CEXPR->getRHS();4544    Stmt *RHSStmt = SynthesizeBlockCall(Exp, RHSExp);4545    Expr *CONDExp = CEXPR->getCond();4546    ConditionalOperator *CondExpr = new (Context) ConditionalOperator(4547        CONDExp, SourceLocation(), cast<Expr>(LHSStmt), SourceLocation(),4548        cast<Expr>(RHSStmt), Exp->getType(), VK_PRValue, OK_Ordinary);4549    return CondExpr;4550  } else if (const ObjCIvarRefExpr *IRE = dyn_cast<ObjCIvarRefExpr>(BlockExp)) {4551    CPT = IRE->getType()->getAs<BlockPointerType>();4552  } else if (const PseudoObjectExpr *POE4553               = dyn_cast<PseudoObjectExpr>(BlockExp)) {4554    CPT = POE->getType()->castAs<BlockPointerType>();4555  } else {4556    assert(false && "RewriteBlockClass: Bad type");4557  }4558  assert(CPT && "RewriteBlockClass: Bad type");4559  const FunctionType *FT = CPT->getPointeeType()->getAs<FunctionType>();4560  assert(FT && "RewriteBlockClass: Bad type");4561  const FunctionProtoType *FTP = dyn_cast<FunctionProtoType>(FT);4562  // FTP will be null for closures that don't take arguments.4563 4564  RecordDecl *RD = RecordDecl::Create(*Context, TagTypeKind::Struct, TUDecl,4565                                      SourceLocation(), SourceLocation(),4566                                      &Context->Idents.get("__block_impl"));4567  QualType PtrBlock = Context->getPointerType(Context->getCanonicalTagType(RD));4568 4569  // Generate a funky cast.4570  SmallVector<QualType, 8> ArgTypes;4571 4572  // Push the block argument type.4573  ArgTypes.push_back(PtrBlock);4574  if (FTP) {4575    for (auto &I : FTP->param_types()) {4576      QualType t = I;4577      // Make sure we convert "t (^)(...)" to "t (*)(...)".4578      if (!convertBlockPointerToFunctionPointer(t))4579        convertToUnqualifiedObjCType(t);4580      ArgTypes.push_back(t);4581    }4582  }4583  // Now do the pointer to function cast.4584  QualType PtrToFuncCastType = getSimpleFunctionType(Exp->getType(), ArgTypes);4585 4586  PtrToFuncCastType = Context->getPointerType(PtrToFuncCastType);4587 4588  CastExpr *BlkCast = NoTypeInfoCStyleCastExpr(Context, PtrBlock,4589                                               CK_BitCast,4590                                               const_cast<Expr*>(BlockExp));4591  // Don't forget the parens to enforce the proper binding.4592  ParenExpr *PE = new (Context) ParenExpr(SourceLocation(), SourceLocation(),4593                                          BlkCast);4594  //PE->dump();4595 4596  FieldDecl *FD = FieldDecl::Create(*Context, nullptr, SourceLocation(),4597                                    SourceLocation(),4598                                    &Context->Idents.get("FuncPtr"),4599                                    Context->VoidPtrTy, nullptr,4600                                    /*BitWidth=*/nullptr, /*Mutable=*/true,4601                                    ICIS_NoInit);4602  MemberExpr *ME = MemberExpr::CreateImplicit(4603      *Context, PE, true, FD, FD->getType(), VK_LValue, OK_Ordinary);4604 4605  CastExpr *FunkCast = NoTypeInfoCStyleCastExpr(Context, PtrToFuncCastType,4606                                                CK_BitCast, ME);4607  PE = new (Context) ParenExpr(SourceLocation(), SourceLocation(), FunkCast);4608 4609  SmallVector<Expr*, 8> BlkExprs;4610  // Add the implicit argument.4611  BlkExprs.push_back(BlkCast);4612  // Add the user arguments.4613  for (CallExpr::arg_iterator I = Exp->arg_begin(),4614       E = Exp->arg_end(); I != E; ++I) {4615    BlkExprs.push_back(*I);4616  }4617  CallExpr *CE =4618      CallExpr::Create(*Context, PE, BlkExprs, Exp->getType(), VK_PRValue,4619                       SourceLocation(), FPOptionsOverride());4620  return CE;4621}4622 4623// We need to return the rewritten expression to handle cases where the4624// DeclRefExpr is embedded in another expression being rewritten.4625// For example:4626//4627// int main() {4628//    __block Foo *f;4629//    __block int i;4630//4631//    void (^myblock)() = ^() {4632//        [f test]; // f is a DeclRefExpr embedded in a message (which is being rewritten).4633//        i = 77;4634//    };4635//}4636Stmt *RewriteModernObjC::RewriteBlockDeclRefExpr(DeclRefExpr *DeclRefExp) {4637  // Rewrite the byref variable into BYREFVAR->__forwarding->BYREFVAR4638  // for each DeclRefExp where BYREFVAR is name of the variable.4639  ValueDecl *VD = DeclRefExp->getDecl();4640  bool isArrow = DeclRefExp->refersToEnclosingVariableOrCapture() ||4641                 HasLocalVariableExternalStorage(DeclRefExp->getDecl());4642 4643  FieldDecl *FD = FieldDecl::Create(*Context, nullptr, SourceLocation(),4644                                    SourceLocation(),4645                                    &Context->Idents.get("__forwarding"),4646                                    Context->VoidPtrTy, nullptr,4647                                    /*BitWidth=*/nullptr, /*Mutable=*/true,4648                                    ICIS_NoInit);4649  MemberExpr *ME = MemberExpr::CreateImplicit(4650      *Context, DeclRefExp, isArrow, FD, FD->getType(), VK_LValue, OK_Ordinary);4651 4652  StringRef Name = VD->getName();4653  FD = FieldDecl::Create(*Context, nullptr, SourceLocation(), SourceLocation(),4654                         &Context->Idents.get(Name),4655                         Context->VoidPtrTy, nullptr,4656                         /*BitWidth=*/nullptr, /*Mutable=*/true,4657                         ICIS_NoInit);4658  ME = MemberExpr::CreateImplicit(*Context, ME, true, FD, DeclRefExp->getType(),4659                                  VK_LValue, OK_Ordinary);4660 4661  // Need parens to enforce precedence.4662  ParenExpr *PE = new (Context) ParenExpr(DeclRefExp->getExprLoc(),4663                                          DeclRefExp->getExprLoc(),4664                                          ME);4665  ReplaceStmt(DeclRefExp, PE);4666  return PE;4667}4668 4669// Rewrites the imported local variable V with external storage4670// (static, extern, etc.) as *V4671//4672Stmt *RewriteModernObjC::RewriteLocalVariableExternalStorage(DeclRefExpr *DRE) {4673  ValueDecl *VD = DRE->getDecl();4674  if (VarDecl *Var = dyn_cast<VarDecl>(VD))4675    if (!ImportedLocalExternalDecls.count(Var))4676      return DRE;4677  Expr *Exp = UnaryOperator::Create(4678      const_cast<ASTContext &>(*Context), DRE, UO_Deref, DRE->getType(),4679      VK_LValue, OK_Ordinary, DRE->getLocation(), false, FPOptionsOverride());4680  // Need parens to enforce precedence.4681  ParenExpr *PE = new (Context) ParenExpr(SourceLocation(), SourceLocation(),4682                                          Exp);4683  ReplaceStmt(DRE, PE);4684  return PE;4685}4686 4687void RewriteModernObjC::RewriteCastExpr(CStyleCastExpr *CE) {4688  SourceLocation LocStart = CE->getLParenLoc();4689  SourceLocation LocEnd = CE->getRParenLoc();4690 4691  // Need to avoid trying to rewrite synthesized casts.4692  if (LocStart.isInvalid())4693    return;4694  // Need to avoid trying to rewrite casts contained in macros.4695  if (!Rewriter::isRewritable(LocStart) || !Rewriter::isRewritable(LocEnd))4696    return;4697 4698  const char *startBuf = SM->getCharacterData(LocStart);4699  const char *endBuf = SM->getCharacterData(LocEnd);4700  QualType QT = CE->getType();4701  const Type* TypePtr = QT->getAs<Type>();4702  if (isa<TypeOfExprType>(TypePtr)) {4703    const TypeOfExprType *TypeOfExprTypePtr = cast<TypeOfExprType>(TypePtr);4704    QT = TypeOfExprTypePtr->getUnderlyingExpr()->getType();4705    std::string TypeAsString = "(";4706    RewriteBlockPointerType(TypeAsString, QT);4707    TypeAsString += ")";4708    ReplaceText(LocStart, endBuf-startBuf+1, TypeAsString);4709    return;4710  }4711  // advance the location to startArgList.4712  const char *argPtr = startBuf;4713 4714  while (*argPtr++ && (argPtr < endBuf)) {4715    switch (*argPtr) {4716    case '^':4717      // Replace the '^' with '*'.4718      LocStart = LocStart.getLocWithOffset(argPtr-startBuf);4719      ReplaceText(LocStart, 1, "*");4720      break;4721    }4722  }4723}4724 4725void RewriteModernObjC::RewriteImplicitCastObjCExpr(CastExpr *IC) {4726  CastKind CastKind = IC->getCastKind();4727  if (CastKind != CK_BlockPointerToObjCPointerCast &&4728      CastKind != CK_AnyPointerToBlockPointerCast)4729    return;4730 4731  QualType QT = IC->getType();4732  (void)convertBlockPointerToFunctionPointer(QT);4733  std::string TypeString(QT.getAsString(Context->getPrintingPolicy()));4734  std::string Str = "(";4735  Str += TypeString;4736  Str += ")";4737  InsertText(IC->getSubExpr()->getBeginLoc(), Str);4738}4739 4740void RewriteModernObjC::RewriteBlockPointerFunctionArgs(FunctionDecl *FD) {4741  SourceLocation DeclLoc = FD->getLocation();4742  unsigned parenCount = 0;4743 4744  // We have 1 or more arguments that have closure pointers.4745  const char *startBuf = SM->getCharacterData(DeclLoc);4746  const char *startArgList = strchr(startBuf, '(');4747 4748  assert((*startArgList == '(') && "Rewriter fuzzy parser confused");4749 4750  parenCount++;4751  // advance the location to startArgList.4752  DeclLoc = DeclLoc.getLocWithOffset(startArgList-startBuf);4753  assert((DeclLoc.isValid()) && "Invalid DeclLoc");4754 4755  const char *argPtr = startArgList;4756 4757  while (*argPtr++ && parenCount) {4758    switch (*argPtr) {4759    case '^':4760      // Replace the '^' with '*'.4761      DeclLoc = DeclLoc.getLocWithOffset(argPtr-startArgList);4762      ReplaceText(DeclLoc, 1, "*");4763      break;4764    case '(':4765      parenCount++;4766      break;4767    case ')':4768      parenCount--;4769      break;4770    }4771  }4772}4773 4774bool RewriteModernObjC::PointerTypeTakesAnyBlockArguments(QualType QT) {4775  const FunctionProtoType *FTP;4776  const PointerType *PT = QT->getAs<PointerType>();4777  if (PT) {4778    FTP = PT->getPointeeType()->getAs<FunctionProtoType>();4779  } else {4780    const BlockPointerType *BPT = QT->getAs<BlockPointerType>();4781    assert(BPT && "BlockPointerTypeTakeAnyBlockArguments(): not a block pointer type");4782    FTP = BPT->getPointeeType()->getAs<FunctionProtoType>();4783  }4784  if (FTP) {4785    for (const auto &I : FTP->param_types())4786      if (isTopLevelBlockPointerType(I))4787        return true;4788  }4789  return false;4790}4791 4792bool RewriteModernObjC::PointerTypeTakesAnyObjCQualifiedType(QualType QT) {4793  const FunctionProtoType *FTP;4794  const PointerType *PT = QT->getAs<PointerType>();4795  if (PT) {4796    FTP = PT->getPointeeType()->getAs<FunctionProtoType>();4797  } else {4798    const BlockPointerType *BPT = QT->getAs<BlockPointerType>();4799    assert(BPT && "BlockPointerTypeTakeAnyBlockArguments(): not a block pointer type");4800    FTP = BPT->getPointeeType()->getAs<FunctionProtoType>();4801  }4802  if (FTP) {4803    for (const auto &I : FTP->param_types()) {4804      if (I->isObjCQualifiedIdType())4805        return true;4806      if (I->isObjCObjectPointerType() &&4807          I->getPointeeType()->isObjCQualifiedInterfaceType())4808        return true;4809    }4810 4811  }4812  return false;4813}4814 4815void RewriteModernObjC::GetExtentOfArgList(const char *Name, const char *&LParen,4816                                     const char *&RParen) {4817  const char *argPtr = strchr(Name, '(');4818  assert((*argPtr == '(') && "Rewriter fuzzy parser confused");4819 4820  LParen = argPtr; // output the start.4821  argPtr++; // skip past the left paren.4822  unsigned parenCount = 1;4823 4824  while (*argPtr && parenCount) {4825    switch (*argPtr) {4826    case '(': parenCount++; break;4827    case ')': parenCount--; break;4828    default: break;4829    }4830    if (parenCount) argPtr++;4831  }4832  assert((*argPtr == ')') && "Rewriter fuzzy parser confused");4833  RParen = argPtr; // output the end4834}4835 4836void RewriteModernObjC::RewriteBlockPointerDecl(NamedDecl *ND) {4837  if (FunctionDecl *FD = dyn_cast<FunctionDecl>(ND)) {4838    RewriteBlockPointerFunctionArgs(FD);4839    return;4840  }4841  // Handle Variables and Typedefs.4842  SourceLocation DeclLoc = ND->getLocation();4843  QualType DeclT;4844  if (VarDecl *VD = dyn_cast<VarDecl>(ND))4845    DeclT = VD->getType();4846  else if (TypedefNameDecl *TDD = dyn_cast<TypedefNameDecl>(ND))4847    DeclT = TDD->getUnderlyingType();4848  else if (FieldDecl *FD = dyn_cast<FieldDecl>(ND))4849    DeclT = FD->getType();4850  else4851    llvm_unreachable("RewriteBlockPointerDecl(): Decl type not yet handled");4852 4853  const char *startBuf = SM->getCharacterData(DeclLoc);4854  const char *endBuf = startBuf;4855  // scan backward (from the decl location) for the end of the previous decl.4856  while (*startBuf != '^' && *startBuf != ';' && startBuf != MainFileStart)4857    startBuf--;4858  SourceLocation Start = DeclLoc.getLocWithOffset(startBuf-endBuf);4859  std::string buf;4860  unsigned OrigLength=0;4861  // *startBuf != '^' if we are dealing with a pointer to function that4862  // may take block argument types (which will be handled below).4863  if (*startBuf == '^') {4864    // Replace the '^' with '*', computing a negative offset.4865    buf = '*';4866    startBuf++;4867    OrigLength++;4868  }4869  while (*startBuf != ')') {4870    buf += *startBuf;4871    startBuf++;4872    OrigLength++;4873  }4874  buf += ')';4875  OrigLength++;4876 4877  if (PointerTypeTakesAnyBlockArguments(DeclT) ||4878      PointerTypeTakesAnyObjCQualifiedType(DeclT)) {4879    // Replace the '^' with '*' for arguments.4880    // Replace id<P> with id/*<>*/4881    DeclLoc = ND->getLocation();4882    startBuf = SM->getCharacterData(DeclLoc);4883    const char *argListBegin, *argListEnd;4884    GetExtentOfArgList(startBuf, argListBegin, argListEnd);4885    while (argListBegin < argListEnd) {4886      if (*argListBegin == '^')4887        buf += '*';4888      else if (*argListBegin ==  '<') {4889        buf += "/*";4890        buf += *argListBegin++;4891        OrigLength++;4892        while (*argListBegin != '>') {4893          buf += *argListBegin++;4894          OrigLength++;4895        }4896        buf += *argListBegin;4897        buf += "*/";4898      }4899      else4900        buf += *argListBegin;4901      argListBegin++;4902      OrigLength++;4903    }4904    buf += ')';4905    OrigLength++;4906  }4907  ReplaceText(Start, OrigLength, buf);4908}4909 4910/// SynthesizeByrefCopyDestroyHelper - This routine synthesizes:4911/// void __Block_byref_id_object_copy(struct Block_byref_id_object *dst,4912///                    struct Block_byref_id_object *src) {4913///  _Block_object_assign (&_dest->object, _src->object,4914///                        BLOCK_BYREF_CALLER | BLOCK_FIELD_IS_OBJECT4915///                        [|BLOCK_FIELD_IS_WEAK]) // object4916///  _Block_object_assign(&_dest->object, _src->object,4917///                       BLOCK_BYREF_CALLER | BLOCK_FIELD_IS_BLOCK4918///                       [|BLOCK_FIELD_IS_WEAK]) // block4919/// }4920/// And:4921/// void __Block_byref_id_object_dispose(struct Block_byref_id_object *_src) {4922///  _Block_object_dispose(_src->object,4923///                        BLOCK_BYREF_CALLER | BLOCK_FIELD_IS_OBJECT4924///                        [|BLOCK_FIELD_IS_WEAK]) // object4925///  _Block_object_dispose(_src->object,4926///                         BLOCK_BYREF_CALLER | BLOCK_FIELD_IS_BLOCK4927///                         [|BLOCK_FIELD_IS_WEAK]) // block4928/// }4929 4930std::string RewriteModernObjC::SynthesizeByrefCopyDestroyHelper(VarDecl *VD,4931                                                          int flag) {4932  std::string S;4933  if (CopyDestroyCache.count(flag))4934    return S;4935  CopyDestroyCache.insert(flag);4936  S = "static void __Block_byref_id_object_copy_";4937  S += utostr(flag);4938  S += "(void *dst, void *src) {\n";4939 4940  // offset into the object pointer is computed as:4941  // void * + void* + int + int + void* + void *4942  unsigned IntSize =4943  static_cast<unsigned>(Context->getTypeSize(Context->IntTy));4944  unsigned VoidPtrSize =4945  static_cast<unsigned>(Context->getTypeSize(Context->VoidPtrTy));4946 4947  unsigned offset = (VoidPtrSize*4 + IntSize + IntSize)/Context->getCharWidth();4948  S += " _Block_object_assign((char*)dst + ";4949  S += utostr(offset);4950  S += ", *(void * *) ((char*)src + ";4951  S += utostr(offset);4952  S += "), ";4953  S += utostr(flag);4954  S += ");\n}\n";4955 4956  S += "static void __Block_byref_id_object_dispose_";4957  S += utostr(flag);4958  S += "(void *src) {\n";4959  S += " _Block_object_dispose(*(void * *) ((char*)src + ";4960  S += utostr(offset);4961  S += "), ";4962  S += utostr(flag);4963  S += ");\n}\n";4964  return S;4965}4966 4967/// RewriteByRefVar - For each __block typex ND variable this routine transforms4968/// the declaration into:4969/// struct __Block_byref_ND {4970/// void *__isa;                  // NULL for everything except __weak pointers4971/// struct __Block_byref_ND *__forwarding;4972/// int32_t __flags;4973/// int32_t __size;4974/// void *__Block_byref_id_object_copy; // If variable is __block ObjC object4975/// void *__Block_byref_id_object_dispose; // If variable is __block ObjC object4976/// typex ND;4977/// };4978///4979/// It then replaces declaration of ND variable with:4980/// struct __Block_byref_ND ND = {__isa=0B, __forwarding=&ND, __flags=some_flag,4981///                               __size=sizeof(struct __Block_byref_ND),4982///                               ND=initializer-if-any};4983///4984///4985void RewriteModernObjC::RewriteByRefVar(VarDecl *ND, bool firstDecl,4986                                        bool lastDecl) {4987  int flag = 0;4988  int isa = 0;4989  SourceLocation DeclLoc = ND->getTypeSpecStartLoc();4990  if (DeclLoc.isInvalid())4991    // If type location is missing, it is because of missing type (a warning).4992    // Use variable's location which is good for this case.4993    DeclLoc = ND->getLocation();4994  const char *startBuf = SM->getCharacterData(DeclLoc);4995  SourceLocation X = ND->getEndLoc();4996  X = SM->getExpansionLoc(X);4997  const char *endBuf = SM->getCharacterData(X);4998  std::string Name(ND->getNameAsString());4999  std::string ByrefType;5000  RewriteByRefString(ByrefType, Name, ND, true);5001  ByrefType += " {\n";5002  ByrefType += "  void *__isa;\n";5003  RewriteByRefString(ByrefType, Name, ND);5004  ByrefType += " *__forwarding;\n";5005  ByrefType += " int __flags;\n";5006  ByrefType += " int __size;\n";5007  // Add void *__Block_byref_id_object_copy;5008  // void *__Block_byref_id_object_dispose; if needed.5009  QualType Ty = ND->getType();5010  bool HasCopyAndDispose = Context->BlockRequiresCopying(Ty, ND);5011  if (HasCopyAndDispose) {5012    ByrefType += " void (*__Block_byref_id_object_copy)(void*, void*);\n";5013    ByrefType += " void (*__Block_byref_id_object_dispose)(void*);\n";5014  }5015 5016  QualType T = Ty;5017  (void)convertBlockPointerToFunctionPointer(T);5018  T.getAsStringInternal(Name, Context->getPrintingPolicy());5019 5020  ByrefType += " " + Name + ";\n";5021  ByrefType += "};\n";5022  // Insert this type in global scope. It is needed by helper function.5023  SourceLocation FunLocStart;5024  if (CurFunctionDef)5025     FunLocStart = getFunctionSourceLocation(*this, CurFunctionDef);5026  else {5027    assert(CurMethodDef && "RewriteByRefVar - CurMethodDef is null");5028    FunLocStart = CurMethodDef->getBeginLoc();5029  }5030  InsertText(FunLocStart, ByrefType);5031 5032  if (Ty.isObjCGCWeak()) {5033    flag |= BLOCK_FIELD_IS_WEAK;5034    isa = 1;5035  }5036  if (HasCopyAndDispose) {5037    flag = BLOCK_BYREF_CALLER;5038    QualType Ty = ND->getType();5039    // FIXME. Handle __weak variable (BLOCK_FIELD_IS_WEAK) as well.5040    if (Ty->isBlockPointerType())5041      flag |= BLOCK_FIELD_IS_BLOCK;5042    else5043      flag |= BLOCK_FIELD_IS_OBJECT;5044    std::string HF = SynthesizeByrefCopyDestroyHelper(ND, flag);5045    if (!HF.empty())5046      Preamble += HF;5047  }5048 5049  // struct __Block_byref_ND ND =5050  // {0, &ND, some_flag, __size=sizeof(struct __Block_byref_ND),5051  //  initializer-if-any};5052  bool hasInit = (ND->getInit() != nullptr);5053  // FIXME. rewriter does not support __block c++ objects which5054  // require construction.5055  if (hasInit)5056    if (CXXConstructExpr *CExp = dyn_cast<CXXConstructExpr>(ND->getInit())) {5057      CXXConstructorDecl *CXXDecl = CExp->getConstructor();5058      if (CXXDecl && CXXDecl->isDefaultConstructor())5059        hasInit = false;5060    }5061 5062  unsigned flags = 0;5063  if (HasCopyAndDispose)5064    flags |= BLOCK_HAS_COPY_DISPOSE;5065  Name = ND->getNameAsString();5066  ByrefType.clear();5067  RewriteByRefString(ByrefType, Name, ND);5068  std::string ForwardingCastType("(");5069  ForwardingCastType += ByrefType + " *)";5070  ByrefType += " " + Name + " = {(void*)";5071  ByrefType += utostr(isa);5072  ByrefType += "," +  ForwardingCastType + "&" + Name + ", ";5073  ByrefType += utostr(flags);5074  ByrefType += ", ";5075  ByrefType += "sizeof(";5076  RewriteByRefString(ByrefType, Name, ND);5077  ByrefType += ")";5078  if (HasCopyAndDispose) {5079    ByrefType += ", __Block_byref_id_object_copy_";5080    ByrefType += utostr(flag);5081    ByrefType += ", __Block_byref_id_object_dispose_";5082    ByrefType += utostr(flag);5083  }5084 5085  if (!firstDecl) {5086    // In multiple __block declarations, and for all but 1st declaration,5087    // find location of the separating comma. This would be start location5088    // where new text is to be inserted.5089    DeclLoc = ND->getLocation();5090    const char *startDeclBuf = SM->getCharacterData(DeclLoc);5091    const char *commaBuf = startDeclBuf;5092    while (*commaBuf != ',')5093      commaBuf--;5094    assert((*commaBuf == ',') && "RewriteByRefVar: can't find ','");5095    DeclLoc = DeclLoc.getLocWithOffset(commaBuf - startDeclBuf);5096    startBuf = commaBuf;5097  }5098 5099  if (!hasInit) {5100    ByrefType += "};\n";5101    unsigned nameSize = Name.size();5102    // for block or function pointer declaration. Name is already5103    // part of the declaration.5104    if (Ty->isBlockPointerType() || Ty->isFunctionPointerType())5105      nameSize = 1;5106    ReplaceText(DeclLoc, endBuf-startBuf+nameSize, ByrefType);5107  }5108  else {5109    ByrefType += ", ";5110    SourceLocation startLoc;5111    Expr *E = ND->getInit();5112    if (const CStyleCastExpr *ECE = dyn_cast<CStyleCastExpr>(E))5113      startLoc = ECE->getLParenLoc();5114    else5115      startLoc = E->getBeginLoc();5116    startLoc = SM->getExpansionLoc(startLoc);5117    endBuf = SM->getCharacterData(startLoc);5118    ReplaceText(DeclLoc, endBuf-startBuf, ByrefType);5119 5120    const char separator = lastDecl ? ';' : ',';5121    const char *startInitializerBuf = SM->getCharacterData(startLoc);5122    const char *separatorBuf = strchr(startInitializerBuf, separator);5123    assert((*separatorBuf == separator) &&5124           "RewriteByRefVar: can't find ';' or ','");5125    SourceLocation separatorLoc =5126      startLoc.getLocWithOffset(separatorBuf-startInitializerBuf);5127 5128    InsertText(separatorLoc, lastDecl ? "}" : "};\n");5129  }5130}5131 5132void RewriteModernObjC::CollectBlockDeclRefInfo(BlockExpr *Exp) {5133  // Add initializers for any closure decl refs.5134  GetBlockDeclRefExprs(Exp->getBody());5135  if (BlockDeclRefs.size()) {5136    // Unique all "by copy" declarations.5137    for (unsigned i = 0; i < BlockDeclRefs.size(); i++)5138      if (!BlockDeclRefs[i]->getDecl()->hasAttr<BlocksAttr>())5139        BlockByCopyDecls.insert(BlockDeclRefs[i]->getDecl());5140    // Unique all "by ref" declarations.5141    for (unsigned i = 0; i < BlockDeclRefs.size(); i++)5142      if (BlockDeclRefs[i]->getDecl()->hasAttr<BlocksAttr>())5143        BlockByRefDecls.insert(BlockDeclRefs[i]->getDecl());5144    // Find any imported blocks...they will need special attention.5145    for (unsigned i = 0; i < BlockDeclRefs.size(); i++)5146      if (BlockDeclRefs[i]->getDecl()->hasAttr<BlocksAttr>() ||5147          BlockDeclRefs[i]->getType()->isObjCObjectPointerType() ||5148          BlockDeclRefs[i]->getType()->isBlockPointerType())5149        ImportedBlockDecls.insert(BlockDeclRefs[i]->getDecl());5150  }5151}5152 5153FunctionDecl *RewriteModernObjC::SynthBlockInitFunctionDecl(StringRef name) {5154  IdentifierInfo *ID = &Context->Idents.get(name);5155  QualType FType = Context->getFunctionNoProtoType(Context->VoidPtrTy);5156  return FunctionDecl::Create(*Context, TUDecl, SourceLocation(),5157                              SourceLocation(), ID, FType, nullptr, SC_Extern,5158                              false, false);5159}5160 5161Stmt *RewriteModernObjC::SynthBlockInitExpr(BlockExpr *Exp,5162                     const SmallVectorImpl<DeclRefExpr *> &InnerBlockDeclRefs) {5163  const BlockDecl *block = Exp->getBlockDecl();5164 5165  Blocks.push_back(Exp);5166 5167  CollectBlockDeclRefInfo(Exp);5168 5169  // Add inner imported variables now used in current block.5170  int countOfInnerDecls = 0;5171  if (!InnerBlockDeclRefs.empty()) {5172    for (unsigned i = 0; i < InnerBlockDeclRefs.size(); i++) {5173      DeclRefExpr *Exp = InnerBlockDeclRefs[i];5174      ValueDecl *VD = Exp->getDecl();5175      if (!VD->hasAttr<BlocksAttr>() && BlockByCopyDecls.insert(VD)) {5176        // We need to save the copied-in variables in nested5177        // blocks because it is needed at the end for some of the API5178        // generations. See SynthesizeBlockLiterals routine.5179        InnerDeclRefs.push_back(Exp); countOfInnerDecls++;5180        BlockDeclRefs.push_back(Exp);5181      }5182      if (VD->hasAttr<BlocksAttr>() && BlockByRefDecls.insert(VD)) {5183        InnerDeclRefs.push_back(Exp); countOfInnerDecls++;5184        BlockDeclRefs.push_back(Exp);5185      }5186    }5187    // Find any imported blocks...they will need special attention.5188    for (unsigned i = 0; i < InnerBlockDeclRefs.size(); i++)5189      if (InnerBlockDeclRefs[i]->getDecl()->hasAttr<BlocksAttr>() ||5190          InnerBlockDeclRefs[i]->getType()->isObjCObjectPointerType() ||5191          InnerBlockDeclRefs[i]->getType()->isBlockPointerType())5192        ImportedBlockDecls.insert(InnerBlockDeclRefs[i]->getDecl());5193  }5194  InnerDeclRefsCount.push_back(countOfInnerDecls);5195 5196  std::string FuncName;5197 5198  if (CurFunctionDef)5199    FuncName = CurFunctionDef->getNameAsString();5200  else if (CurMethodDef)5201    BuildUniqueMethodName(FuncName, CurMethodDef);5202  else if (GlobalVarDecl)5203    FuncName = std::string(GlobalVarDecl->getNameAsString());5204 5205  bool GlobalBlockExpr =5206    block->getDeclContext()->getRedeclContext()->isFileContext();5207 5208  if (GlobalBlockExpr && !GlobalVarDecl) {5209    Diags.Report(block->getLocation(), GlobalBlockRewriteFailedDiag);5210    GlobalBlockExpr = false;5211  }5212 5213  std::string BlockNumber = utostr(Blocks.size()-1);5214 5215  std::string Func = "__" + FuncName + "_block_func_" + BlockNumber;5216 5217  // Get a pointer to the function type so we can cast appropriately.5218  QualType BFT = convertFunctionTypeOfBlocks(Exp->getFunctionType());5219  QualType FType = Context->getPointerType(BFT);5220 5221  FunctionDecl *FD;5222  Expr *NewRep;5223 5224  // Simulate a constructor call...5225  std::string Tag;5226 5227  if (GlobalBlockExpr)5228    Tag = "__global_";5229  else5230    Tag = "__";5231  Tag += FuncName + "_block_impl_" + BlockNumber;5232 5233  FD = SynthBlockInitFunctionDecl(Tag);5234  DeclRefExpr *DRE = new (Context)5235      DeclRefExpr(*Context, FD, false, FType, VK_PRValue, SourceLocation());5236 5237  SmallVector<Expr*, 4> InitExprs;5238 5239  // Initialize the block function.5240  FD = SynthBlockInitFunctionDecl(Func);5241  DeclRefExpr *Arg = new (Context) DeclRefExpr(5242      *Context, FD, false, FD->getType(), VK_LValue, SourceLocation());5243  CastExpr *castExpr = NoTypeInfoCStyleCastExpr(Context, Context->VoidPtrTy,5244                                                CK_BitCast, Arg);5245  InitExprs.push_back(castExpr);5246 5247  // Initialize the block descriptor.5248  std::string DescData = "__" + FuncName + "_block_desc_" + BlockNumber + "_DATA";5249 5250  VarDecl *NewVD = VarDecl::Create(5251      *Context, TUDecl, SourceLocation(), SourceLocation(),5252      &Context->Idents.get(DescData), Context->VoidPtrTy, nullptr, SC_Static);5253  UnaryOperator *DescRefExpr = UnaryOperator::Create(5254      const_cast<ASTContext &>(*Context),5255      new (Context) DeclRefExpr(*Context, NewVD, false, Context->VoidPtrTy,5256                                VK_LValue, SourceLocation()),5257      UO_AddrOf, Context->getPointerType(Context->VoidPtrTy), VK_PRValue,5258      OK_Ordinary, SourceLocation(), false, FPOptionsOverride());5259  InitExprs.push_back(DescRefExpr);5260 5261  // Add initializers for any closure decl refs.5262  if (BlockDeclRefs.size()) {5263    Expr *Exp;5264    // Output all "by copy" declarations.5265    for (ValueDecl *VD : BlockByCopyDecls) {5266      if (isObjCType(VD->getType())) {5267        // FIXME: Conform to ABI ([[obj retain] autorelease]).5268        FD = SynthBlockInitFunctionDecl(VD->getName());5269        Exp = new (Context) DeclRefExpr(*Context, FD, false, FD->getType(),5270                                        VK_LValue, SourceLocation());5271        if (HasLocalVariableExternalStorage(VD)) {5272          QualType QT = VD->getType();5273          QT = Context->getPointerType(QT);5274          Exp = UnaryOperator::Create(const_cast<ASTContext &>(*Context), Exp,5275                                      UO_AddrOf, QT, VK_PRValue, OK_Ordinary,5276                                      SourceLocation(), false,5277                                      FPOptionsOverride());5278        }5279      } else if (isTopLevelBlockPointerType(VD->getType())) {5280        FD = SynthBlockInitFunctionDecl(VD->getName());5281        Arg = new (Context) DeclRefExpr(*Context, FD, false, FD->getType(),5282                                        VK_LValue, SourceLocation());5283        Exp = NoTypeInfoCStyleCastExpr(Context, Context->VoidPtrTy,5284                                       CK_BitCast, Arg);5285      } else {5286        FD = SynthBlockInitFunctionDecl(VD->getName());5287        Exp = new (Context) DeclRefExpr(*Context, FD, false, FD->getType(),5288                                        VK_LValue, SourceLocation());5289        if (HasLocalVariableExternalStorage(VD)) {5290          QualType QT = VD->getType();5291          QT = Context->getPointerType(QT);5292          Exp = UnaryOperator::Create(const_cast<ASTContext &>(*Context), Exp,5293                                      UO_AddrOf, QT, VK_PRValue, OK_Ordinary,5294                                      SourceLocation(), false,5295                                      FPOptionsOverride());5296        }5297      }5298      InitExprs.push_back(Exp);5299    }5300    // Output all "by ref" declarations.5301    for (ValueDecl *ND : BlockByRefDecls) {5302      std::string Name(ND->getNameAsString());5303      std::string RecName;5304      RewriteByRefString(RecName, Name, ND, true);5305      IdentifierInfo *II = &Context->Idents.get(RecName.c_str()5306                                                + sizeof("struct"));5307      RecordDecl *RD =5308          RecordDecl::Create(*Context, TagTypeKind::Struct, TUDecl,5309                             SourceLocation(), SourceLocation(), II);5310      assert(RD && "SynthBlockInitExpr(): Can't find RecordDecl");5311      QualType castT =5312          Context->getPointerType(Context->getCanonicalTagType(RD));5313 5314      FD = SynthBlockInitFunctionDecl(ND->getName());5315      Exp = new (Context) DeclRefExpr(*Context, FD, false, FD->getType(),5316                                      VK_LValue, SourceLocation());5317      bool isNestedCapturedVar = false;5318      for (const auto &CI : block->captures()) {5319        const VarDecl *variable = CI.getVariable();5320        if (variable == ND && CI.isNested()) {5321          assert(CI.isByRef() &&5322                 "SynthBlockInitExpr - captured block variable is not byref");5323          isNestedCapturedVar = true;5324          break;5325        }5326      }5327      // captured nested byref variable has its address passed. Do not take5328      // its address again.5329      if (!isNestedCapturedVar)5330        Exp = UnaryOperator::Create(5331            const_cast<ASTContext &>(*Context), Exp, UO_AddrOf,5332            Context->getPointerType(Exp->getType()), VK_PRValue, OK_Ordinary,5333            SourceLocation(), false, FPOptionsOverride());5334      Exp = NoTypeInfoCStyleCastExpr(Context, castT, CK_BitCast, Exp);5335      InitExprs.push_back(Exp);5336    }5337  }5338  if (ImportedBlockDecls.size()) {5339    // generate BLOCK_HAS_COPY_DISPOSE(have helper funcs) | BLOCK_HAS_DESCRIPTOR5340    int flag = (BLOCK_HAS_COPY_DISPOSE | BLOCK_HAS_DESCRIPTOR);5341    unsigned IntSize =5342      static_cast<unsigned>(Context->getTypeSize(Context->IntTy));5343    Expr *FlagExp = IntegerLiteral::Create(*Context, llvm::APInt(IntSize, flag),5344                                           Context->IntTy, SourceLocation());5345    InitExprs.push_back(FlagExp);5346  }5347  NewRep = CallExpr::Create(*Context, DRE, InitExprs, FType, VK_LValue,5348                            SourceLocation(), FPOptionsOverride());5349 5350  if (GlobalBlockExpr) {5351    assert (!GlobalConstructionExp &&5352            "SynthBlockInitExpr - GlobalConstructionExp must be null");5353    GlobalConstructionExp = NewRep;5354    NewRep = DRE;5355  }5356 5357  NewRep = UnaryOperator::Create(5358      const_cast<ASTContext &>(*Context), NewRep, UO_AddrOf,5359      Context->getPointerType(NewRep->getType()), VK_PRValue, OK_Ordinary,5360      SourceLocation(), false, FPOptionsOverride());5361  NewRep = NoTypeInfoCStyleCastExpr(Context, FType, CK_BitCast,5362                                    NewRep);5363  // Put Paren around the call.5364  NewRep = new (Context) ParenExpr(SourceLocation(), SourceLocation(),5365                                   NewRep);5366 5367  BlockDeclRefs.clear();5368  BlockByRefDecls.clear();5369  BlockByCopyDecls.clear();5370  ImportedBlockDecls.clear();5371  return NewRep;5372}5373 5374bool RewriteModernObjC::IsDeclStmtInForeachHeader(DeclStmt *DS) {5375  if (const ObjCForCollectionStmt * CS =5376      dyn_cast<ObjCForCollectionStmt>(Stmts.back()))5377        return CS->getElement() == DS;5378  return false;5379}5380 5381//===----------------------------------------------------------------------===//5382// Function Body / Expression rewriting5383//===----------------------------------------------------------------------===//5384 5385Stmt *RewriteModernObjC::RewriteFunctionBodyOrGlobalInitializer(Stmt *S) {5386  if (isa<SwitchStmt>(S) || isa<WhileStmt>(S) ||5387      isa<DoStmt>(S) || isa<ForStmt>(S))5388    Stmts.push_back(S);5389  else if (isa<ObjCForCollectionStmt>(S)) {5390    Stmts.push_back(S);5391    ObjCBcLabelNo.push_back(++BcLabelCount);5392  }5393 5394  // Pseudo-object operations and ivar references need special5395  // treatment because we're going to recursively rewrite them.5396  if (PseudoObjectExpr *PseudoOp = dyn_cast<PseudoObjectExpr>(S)) {5397    if (isa<BinaryOperator>(PseudoOp->getSyntacticForm())) {5398      return RewritePropertyOrImplicitSetter(PseudoOp);5399    } else {5400      return RewritePropertyOrImplicitGetter(PseudoOp);5401    }5402  } else if (ObjCIvarRefExpr *IvarRefExpr = dyn_cast<ObjCIvarRefExpr>(S)) {5403    return RewriteObjCIvarRefExpr(IvarRefExpr);5404  }5405  else if (isa<OpaqueValueExpr>(S))5406    S = cast<OpaqueValueExpr>(S)->getSourceExpr();5407 5408  SourceRange OrigStmtRange = S->getSourceRange();5409 5410  // Perform a bottom up rewrite of all children.5411  for (Stmt *&childStmt : S->children())5412    if (childStmt) {5413      Stmt *newStmt = RewriteFunctionBodyOrGlobalInitializer(childStmt);5414      if (newStmt) {5415        childStmt = newStmt;5416      }5417    }5418 5419  if (BlockExpr *BE = dyn_cast<BlockExpr>(S)) {5420    SmallVector<DeclRefExpr *, 8> InnerBlockDeclRefs;5421    llvm::SmallPtrSet<const DeclContext *, 8> InnerContexts;5422    InnerContexts.insert(BE->getBlockDecl());5423    ImportedLocalExternalDecls.clear();5424    GetInnerBlockDeclRefExprs(BE->getBody(),5425                              InnerBlockDeclRefs, InnerContexts);5426    // Rewrite the block body in place.5427    Stmt *SaveCurrentBody = CurrentBody;5428    CurrentBody = BE->getBody();5429    PropParentMap = nullptr;5430    // block literal on rhs of a property-dot-sytax assignment5431    // must be replaced by its synthesize ast so getRewrittenText5432    // works as expected. In this case, what actually ends up on RHS5433    // is the blockTranscribed which is the helper function for the5434    // block literal; as in: self.c = ^() {[ace ARR];};5435    bool saveDisableReplaceStmt = DisableReplaceStmt;5436    DisableReplaceStmt = false;5437    RewriteFunctionBodyOrGlobalInitializer(BE->getBody());5438    DisableReplaceStmt = saveDisableReplaceStmt;5439    CurrentBody = SaveCurrentBody;5440    PropParentMap = nullptr;5441    ImportedLocalExternalDecls.clear();5442    // Now we snarf the rewritten text and stash it away for later use.5443    std::string Str = Rewrite.getRewrittenText(BE->getSourceRange());5444    RewrittenBlockExprs[BE] = Str;5445 5446    Stmt *blockTranscribed = SynthBlockInitExpr(BE, InnerBlockDeclRefs);5447 5448    //blockTranscribed->dump();5449    ReplaceStmt(S, blockTranscribed);5450    return blockTranscribed;5451  }5452  // Handle specific things.5453  if (ObjCEncodeExpr *AtEncode = dyn_cast<ObjCEncodeExpr>(S))5454    return RewriteAtEncode(AtEncode);5455 5456  if (ObjCSelectorExpr *AtSelector = dyn_cast<ObjCSelectorExpr>(S))5457    return RewriteAtSelector(AtSelector);5458 5459  if (ObjCStringLiteral *AtString = dyn_cast<ObjCStringLiteral>(S))5460    return RewriteObjCStringLiteral(AtString);5461 5462  if (ObjCBoolLiteralExpr *BoolLitExpr = dyn_cast<ObjCBoolLiteralExpr>(S))5463    return RewriteObjCBoolLiteralExpr(BoolLitExpr);5464 5465  if (ObjCBoxedExpr *BoxedExpr = dyn_cast<ObjCBoxedExpr>(S))5466    return RewriteObjCBoxedExpr(BoxedExpr);5467 5468  if (ObjCArrayLiteral *ArrayLitExpr = dyn_cast<ObjCArrayLiteral>(S))5469    return RewriteObjCArrayLiteralExpr(ArrayLitExpr);5470 5471  if (ObjCDictionaryLiteral *DictionaryLitExpr =5472        dyn_cast<ObjCDictionaryLiteral>(S))5473    return RewriteObjCDictionaryLiteralExpr(DictionaryLitExpr);5474 5475  if (ObjCMessageExpr *MessExpr = dyn_cast<ObjCMessageExpr>(S)) {5476#if 05477    // Before we rewrite it, put the original message expression in a comment.5478    SourceLocation startLoc = MessExpr->getBeginLoc();5479    SourceLocation endLoc = MessExpr->getEndLoc();5480 5481    const char *startBuf = SM->getCharacterData(startLoc);5482    const char *endBuf = SM->getCharacterData(endLoc);5483 5484    std::string messString;5485    messString += "// ";5486    messString.append(startBuf, endBuf-startBuf+1);5487    messString += "\n";5488 5489    // FIXME: Missing definition of5490    // InsertText(clang::SourceLocation, char const*, unsigned int).5491    // InsertText(startLoc, messString);5492    // Tried this, but it didn't work either...5493    // ReplaceText(startLoc, 0, messString.c_str(), messString.size());5494#endif5495    return RewriteMessageExpr(MessExpr);5496  }5497 5498  if (ObjCAutoreleasePoolStmt *StmtAutoRelease =5499        dyn_cast<ObjCAutoreleasePoolStmt>(S)) {5500    return RewriteObjCAutoreleasePoolStmt(StmtAutoRelease);5501  }5502 5503  if (ObjCAtTryStmt *StmtTry = dyn_cast<ObjCAtTryStmt>(S))5504    return RewriteObjCTryStmt(StmtTry);5505 5506  if (ObjCAtSynchronizedStmt *StmtTry = dyn_cast<ObjCAtSynchronizedStmt>(S))5507    return RewriteObjCSynchronizedStmt(StmtTry);5508 5509  if (ObjCAtThrowStmt *StmtThrow = dyn_cast<ObjCAtThrowStmt>(S))5510    return RewriteObjCThrowStmt(StmtThrow);5511 5512  if (ObjCProtocolExpr *ProtocolExp = dyn_cast<ObjCProtocolExpr>(S))5513    return RewriteObjCProtocolExpr(ProtocolExp);5514 5515  if (ObjCForCollectionStmt *StmtForCollection =5516        dyn_cast<ObjCForCollectionStmt>(S))5517    return RewriteObjCForCollectionStmt(StmtForCollection,5518                                        OrigStmtRange.getEnd());5519  if (BreakStmt *StmtBreakStmt =5520      dyn_cast<BreakStmt>(S))5521    return RewriteBreakStmt(StmtBreakStmt);5522  if (ContinueStmt *StmtContinueStmt =5523      dyn_cast<ContinueStmt>(S))5524    return RewriteContinueStmt(StmtContinueStmt);5525 5526  // Need to check for protocol refs (id <P>, Foo <P> *) in variable decls5527  // and cast exprs.5528  if (DeclStmt *DS = dyn_cast<DeclStmt>(S)) {5529    // FIXME: What we're doing here is modifying the type-specifier that5530    // precedes the first Decl.  In the future the DeclGroup should have5531    // a separate type-specifier that we can rewrite.5532    // NOTE: We need to avoid rewriting the DeclStmt if it is within5533    // the context of an ObjCForCollectionStmt. For example:5534    //   NSArray *someArray;5535    //   for (id <FooProtocol> index in someArray) ;5536    // This is because RewriteObjCForCollectionStmt() does textual rewriting5537    // and it depends on the original text locations/positions.5538    if (Stmts.empty() || !IsDeclStmtInForeachHeader(DS))5539      RewriteObjCQualifiedInterfaceTypes(*DS->decl_begin());5540 5541    // Blocks rewrite rules.5542    for (DeclStmt::decl_iterator DI = DS->decl_begin(), DE = DS->decl_end();5543         DI != DE; ++DI) {5544      Decl *SD = *DI;5545      if (ValueDecl *ND = dyn_cast<ValueDecl>(SD)) {5546        if (isTopLevelBlockPointerType(ND->getType()))5547          RewriteBlockPointerDecl(ND);5548        else if (ND->getType()->isFunctionPointerType())5549          CheckFunctionPointerDecl(ND->getType(), ND);5550        if (VarDecl *VD = dyn_cast<VarDecl>(SD)) {5551          if (VD->hasAttr<BlocksAttr>()) {5552            static unsigned uniqueByrefDeclCount = 0;5553            assert(!BlockByRefDeclNo.count(ND) &&5554              "RewriteFunctionBodyOrGlobalInitializer: Duplicate byref decl");5555            BlockByRefDeclNo[ND] = uniqueByrefDeclCount++;5556            RewriteByRefVar(VD, (DI == DS->decl_begin()), ((DI+1) == DE));5557          }5558          else5559            RewriteTypeOfDecl(VD);5560        }5561      }5562      if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(SD)) {5563        if (isTopLevelBlockPointerType(TD->getUnderlyingType()))5564          RewriteBlockPointerDecl(TD);5565        else if (TD->getUnderlyingType()->isFunctionPointerType())5566          CheckFunctionPointerDecl(TD->getUnderlyingType(), TD);5567      }5568    }5569  }5570 5571  if (CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(S))5572    RewriteObjCQualifiedInterfaceTypes(CE);5573 5574  if (isa<SwitchStmt>(S) || isa<WhileStmt>(S) ||5575      isa<DoStmt>(S) || isa<ForStmt>(S)) {5576    assert(!Stmts.empty() && "Statement stack is empty");5577    assert ((isa<SwitchStmt>(Stmts.back()) || isa<WhileStmt>(Stmts.back()) ||5578             isa<DoStmt>(Stmts.back()) || isa<ForStmt>(Stmts.back()))5579            && "Statement stack mismatch");5580    Stmts.pop_back();5581  }5582  // Handle blocks rewriting.5583  if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(S)) {5584    ValueDecl *VD = DRE->getDecl();5585    if (VD->hasAttr<BlocksAttr>())5586      return RewriteBlockDeclRefExpr(DRE);5587    if (HasLocalVariableExternalStorage(VD))5588      return RewriteLocalVariableExternalStorage(DRE);5589  }5590 5591  if (CallExpr *CE = dyn_cast<CallExpr>(S)) {5592    if (CE->getCallee()->getType()->isBlockPointerType()) {5593      Stmt *BlockCall = SynthesizeBlockCall(CE, CE->getCallee());5594      ReplaceStmt(S, BlockCall);5595      return BlockCall;5596    }5597  }5598  if (CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(S)) {5599    RewriteCastExpr(CE);5600  }5601  if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(S)) {5602    RewriteImplicitCastObjCExpr(ICE);5603  }5604#if 05605 5606  if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(S)) {5607    CastExpr *Replacement = new (Context) CastExpr(ICE->getType(),5608                                                   ICE->getSubExpr(),5609                                                   SourceLocation());5610    // Get the new text.5611    std::string SStr;5612    llvm::raw_string_ostream Buf(SStr);5613    Replacement->printPretty(Buf);5614    const std::string &Str = Buf.str();5615 5616    printf("CAST = %s\n", &Str[0]);5617    InsertText(ICE->getSubExpr()->getBeginLoc(), Str);5618    delete S;5619    return Replacement;5620  }5621#endif5622  // Return this stmt unmodified.5623  return S;5624}5625 5626void RewriteModernObjC::RewriteRecordBody(RecordDecl *RD) {5627  for (auto *FD : RD->fields()) {5628    if (isTopLevelBlockPointerType(FD->getType()))5629      RewriteBlockPointerDecl(FD);5630    if (FD->getType()->isObjCQualifiedIdType() ||5631        FD->getType()->isObjCQualifiedInterfaceType())5632      RewriteObjCQualifiedInterfaceTypes(FD);5633  }5634}5635 5636/// HandleDeclInMainFile - This is called for each top-level decl defined in the5637/// main file of the input.5638void RewriteModernObjC::HandleDeclInMainFile(Decl *D) {5639  switch (D->getKind()) {5640    case Decl::Function: {5641      FunctionDecl *FD = cast<FunctionDecl>(D);5642      if (FD->isOverloadedOperator())5643        return;5644 5645      // Since function prototypes don't have ParmDecl's, we check the function5646      // prototype. This enables us to rewrite function declarations and5647      // definitions using the same code.5648      RewriteBlocksInFunctionProtoType(FD->getType(), FD);5649 5650      if (!FD->isThisDeclarationADefinition())5651        break;5652 5653      // FIXME: If this should support Obj-C++, support CXXTryStmt5654      if (CompoundStmt *Body = dyn_cast_or_null<CompoundStmt>(FD->getBody())) {5655        CurFunctionDef = FD;5656        CurrentBody = Body;5657        Body =5658        cast_or_null<CompoundStmt>(RewriteFunctionBodyOrGlobalInitializer(Body));5659        FD->setBody(Body);5660        CurrentBody = nullptr;5661        if (PropParentMap) {5662          delete PropParentMap;5663          PropParentMap = nullptr;5664        }5665        // This synthesizes and inserts the block "impl" struct, invoke function,5666        // and any copy/dispose helper functions.5667        InsertBlockLiteralsWithinFunction(FD);5668        RewriteLineDirective(D);5669        CurFunctionDef = nullptr;5670      }5671      break;5672    }5673    case Decl::ObjCMethod: {5674      ObjCMethodDecl *MD = cast<ObjCMethodDecl>(D);5675      if (CompoundStmt *Body = MD->getCompoundBody()) {5676        CurMethodDef = MD;5677        CurrentBody = Body;5678        Body =5679          cast_or_null<CompoundStmt>(RewriteFunctionBodyOrGlobalInitializer(Body));5680        MD->setBody(Body);5681        CurrentBody = nullptr;5682        if (PropParentMap) {5683          delete PropParentMap;5684          PropParentMap = nullptr;5685        }5686        InsertBlockLiteralsWithinMethod(MD);5687        RewriteLineDirective(D);5688        CurMethodDef = nullptr;5689      }5690      break;5691    }5692    case Decl::ObjCImplementation: {5693      ObjCImplementationDecl *CI = cast<ObjCImplementationDecl>(D);5694      ClassImplementation.push_back(CI);5695      break;5696    }5697    case Decl::ObjCCategoryImpl: {5698      ObjCCategoryImplDecl *CI = cast<ObjCCategoryImplDecl>(D);5699      CategoryImplementation.push_back(CI);5700      break;5701    }5702    case Decl::Var: {5703      VarDecl *VD = cast<VarDecl>(D);5704      RewriteObjCQualifiedInterfaceTypes(VD);5705      if (isTopLevelBlockPointerType(VD->getType()))5706        RewriteBlockPointerDecl(VD);5707      else if (VD->getType()->isFunctionPointerType()) {5708        CheckFunctionPointerDecl(VD->getType(), VD);5709        if (VD->getInit()) {5710          if (CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(VD->getInit())) {5711            RewriteCastExpr(CE);5712          }5713        }5714      } else if (VD->getType()->isRecordType()) {5715        auto *RD = VD->getType()->castAsRecordDecl();5716        if (RD->isCompleteDefinition())5717          RewriteRecordBody(RD);5718      }5719      if (VD->getInit()) {5720        GlobalVarDecl = VD;5721        CurrentBody = VD->getInit();5722        RewriteFunctionBodyOrGlobalInitializer(VD->getInit());5723        CurrentBody = nullptr;5724        if (PropParentMap) {5725          delete PropParentMap;5726          PropParentMap = nullptr;5727        }5728        SynthesizeBlockLiterals(VD->getTypeSpecStartLoc(), VD->getName());5729        GlobalVarDecl = nullptr;5730 5731        // This is needed for blocks.5732        if (CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(VD->getInit())) {5733            RewriteCastExpr(CE);5734        }5735      }5736      break;5737    }5738    case Decl::TypeAlias:5739    case Decl::Typedef: {5740      if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(D)) {5741        if (isTopLevelBlockPointerType(TD->getUnderlyingType()))5742          RewriteBlockPointerDecl(TD);5743        else if (TD->getUnderlyingType()->isFunctionPointerType())5744          CheckFunctionPointerDecl(TD->getUnderlyingType(), TD);5745        else5746          RewriteObjCQualifiedInterfaceTypes(TD);5747      }5748      break;5749    }5750    case Decl::CXXRecord:5751    case Decl::Record: {5752      RecordDecl *RD = cast<RecordDecl>(D);5753      if (RD->isCompleteDefinition())5754        RewriteRecordBody(RD);5755      break;5756    }5757    default:5758      break;5759  }5760  // Nothing yet.5761}5762 5763/// Write_ProtocolExprReferencedMetadata - This routine writer out the5764/// protocol reference symbols in the for of:5765/// struct _protocol_t *PROTOCOL_REF = &PROTOCOL_METADATA.5766static void Write_ProtocolExprReferencedMetadata(ASTContext *Context,5767                                                 ObjCProtocolDecl *PDecl,5768                                                 std::string &Result) {5769  // Also output .objc_protorefs$B section and its meta-data.5770  if (Context->getLangOpts().MicrosoftExt)5771    Result += "static ";5772  Result += "struct _protocol_t *";5773  Result += "_OBJC_PROTOCOL_REFERENCE_$_";5774  Result += PDecl->getNameAsString();5775  Result += " = &";5776  Result += "_OBJC_PROTOCOL_"; Result += PDecl->getNameAsString();5777  Result += ";\n";5778}5779 5780void RewriteModernObjC::HandleTranslationUnit(ASTContext &C) {5781  if (Diags.hasErrorOccurred())5782    return;5783 5784  RewriteInclude();5785 5786  for (unsigned i = 0, e = FunctionDefinitionsSeen.size(); i < e; i++) {5787    // translation of function bodies were postponed until all class and5788    // their extensions and implementations are seen. This is because, we5789    // cannot build grouping structs for bitfields until they are all seen.5790    FunctionDecl *FDecl = FunctionDefinitionsSeen[i];5791    HandleTopLevelSingleDecl(FDecl);5792  }5793 5794  // Here's a great place to add any extra declarations that may be needed.5795  // Write out meta data for each @protocol(<expr>).5796  for (ObjCProtocolDecl *ProtDecl : ProtocolExprDecls) {5797    RewriteObjCProtocolMetaData(ProtDecl, Preamble);5798    Write_ProtocolExprReferencedMetadata(Context, ProtDecl, Preamble);5799  }5800 5801  InsertText(SM->getLocForStartOfFile(MainFileID), Preamble, false);5802 5803  if (ClassImplementation.size() || CategoryImplementation.size())5804    RewriteImplementations();5805 5806  for (unsigned i = 0, e = ObjCInterfacesSeen.size(); i < e; i++) {5807    ObjCInterfaceDecl *CDecl = ObjCInterfacesSeen[i];5808    // Write struct declaration for the class matching its ivar declarations.5809    // Note that for modern abi, this is postponed until the end of TU5810    // because class extensions and the implementation might declare their own5811    // private ivars.5812    RewriteInterfaceDecl(CDecl);5813  }5814 5815  // Get the buffer corresponding to MainFileID.  If we haven't changed it, then5816  // we are done.5817  if (const RewriteBuffer *RewriteBuf =5818      Rewrite.getRewriteBufferFor(MainFileID)) {5819    //printf("Changed:\n");5820    *OutFile << std::string(RewriteBuf->begin(), RewriteBuf->end());5821  } else {5822    llvm::errs() << "No changes\n";5823  }5824 5825  if (ClassImplementation.size() || CategoryImplementation.size() ||5826      ProtocolExprDecls.size()) {5827    // Rewrite Objective-c meta data*5828    std::string ResultStr;5829    RewriteMetaDataIntoBuffer(ResultStr);5830    // Emit metadata.5831    *OutFile << ResultStr;5832  }5833  // Emit ImageInfo;5834  {5835    std::string ResultStr;5836    WriteImageInfo(ResultStr);5837    *OutFile << ResultStr;5838  }5839  OutFile->flush();5840}5841 5842void RewriteModernObjC::Initialize(ASTContext &context) {5843  InitializeCommon(context);5844 5845  Preamble += "#ifndef __OBJC2__\n";5846  Preamble += "#define __OBJC2__\n";5847  Preamble += "#endif\n";5848 5849  // declaring objc_selector outside the parameter list removes a silly5850  // scope related warning...5851  if (IsHeader)5852    Preamble = "#pragma once\n";5853  Preamble += "struct objc_selector; struct objc_class;\n";5854  Preamble += "struct __rw_objc_super { \n\tstruct objc_object *object; ";5855  Preamble += "\n\tstruct objc_object *superClass; ";5856  // Add a constructor for creating temporary objects.5857  Preamble += "\n\t__rw_objc_super(struct objc_object *o, struct objc_object *s) ";5858  Preamble += ": object(o), superClass(s) {} ";5859  Preamble += "\n};\n";5860 5861  if (LangOpts.MicrosoftExt) {5862    // Define all sections using syntax that makes sense.5863    // These are currently generated.5864    Preamble += "\n#pragma section(\".objc_classlist$B\", long, read, write)\n";5865    Preamble += "#pragma section(\".objc_catlist$B\", long, read, write)\n";5866    Preamble += "#pragma section(\".objc_imageinfo$B\", long, read, write)\n";5867    Preamble += "#pragma section(\".objc_nlclslist$B\", long, read, write)\n";5868    Preamble += "#pragma section(\".objc_nlcatlist$B\", long, read, write)\n";5869    // These are generated but not necessary for functionality.5870    Preamble += "#pragma section(\".cat_cls_meth$B\", long, read, write)\n";5871    Preamble += "#pragma section(\".inst_meth$B\", long, read, write)\n";5872    Preamble += "#pragma section(\".cls_meth$B\", long, read, write)\n";5873    Preamble += "#pragma section(\".objc_ivar$B\", long, read, write)\n";5874 5875    // These need be generated for performance. Currently they are not,5876    // using API calls instead.5877    Preamble += "#pragma section(\".objc_selrefs$B\", long, read, write)\n";5878    Preamble += "#pragma section(\".objc_classrefs$B\", long, read, write)\n";5879    Preamble += "#pragma section(\".objc_superrefs$B\", long, read, write)\n";5880 5881  }5882  Preamble += "#ifndef _REWRITER_typedef_Protocol\n";5883  Preamble += "typedef struct objc_object Protocol;\n";5884  Preamble += "#define _REWRITER_typedef_Protocol\n";5885  Preamble += "#endif\n";5886  if (LangOpts.MicrosoftExt) {5887    Preamble += "#define __OBJC_RW_DLLIMPORT extern \"C\" __declspec(dllimport)\n";5888    Preamble += "#define __OBJC_RW_STATICIMPORT extern \"C\"\n";5889  }5890  else5891    Preamble += "#define __OBJC_RW_DLLIMPORT extern\n";5892 5893  Preamble += "__OBJC_RW_DLLIMPORT void objc_msgSend(void);\n";5894  Preamble += "__OBJC_RW_DLLIMPORT void objc_msgSendSuper(void);\n";5895  Preamble += "__OBJC_RW_DLLIMPORT void objc_msgSend_stret(void);\n";5896  Preamble += "__OBJC_RW_DLLIMPORT void objc_msgSendSuper_stret(void);\n";5897  Preamble += "__OBJC_RW_DLLIMPORT void objc_msgSend_fpret(void);\n";5898 5899  Preamble += "__OBJC_RW_DLLIMPORT struct objc_class *objc_getClass";5900  Preamble += "(const char *);\n";5901  Preamble += "__OBJC_RW_DLLIMPORT struct objc_class *class_getSuperclass";5902  Preamble += "(struct objc_class *);\n";5903  Preamble += "__OBJC_RW_DLLIMPORT struct objc_class *objc_getMetaClass";5904  Preamble += "(const char *);\n";5905  Preamble += "__OBJC_RW_DLLIMPORT void objc_exception_throw( struct objc_object *);\n";5906  // @synchronized hooks.5907  Preamble += "__OBJC_RW_DLLIMPORT int objc_sync_enter( struct objc_object *);\n";5908  Preamble += "__OBJC_RW_DLLIMPORT int objc_sync_exit( struct objc_object *);\n";5909  Preamble += "__OBJC_RW_DLLIMPORT Protocol *objc_getProtocol(const char *);\n";5910  Preamble += "#ifdef _WIN64\n";5911  Preamble += "typedef unsigned long long  _WIN_NSUInteger;\n";5912  Preamble += "#else\n";5913  Preamble += "typedef unsigned int _WIN_NSUInteger;\n";5914  Preamble += "#endif\n";5915  Preamble += "#ifndef __FASTENUMERATIONSTATE\n";5916  Preamble += "struct __objcFastEnumerationState {\n\t";5917  Preamble += "unsigned long state;\n\t";5918  Preamble += "void **itemsPtr;\n\t";5919  Preamble += "unsigned long *mutationsPtr;\n\t";5920  Preamble += "unsigned long extra[5];\n};\n";5921  Preamble += "__OBJC_RW_DLLIMPORT void objc_enumerationMutation(struct objc_object *);\n";5922  Preamble += "#define __FASTENUMERATIONSTATE\n";5923  Preamble += "#endif\n";5924  Preamble += "#ifndef __NSCONSTANTSTRINGIMPL\n";5925  Preamble += "struct __NSConstantStringImpl {\n";5926  Preamble += "  int *isa;\n";5927  Preamble += "  int flags;\n";5928  Preamble += "  char *str;\n";5929  Preamble += "#if _WIN64\n";5930  Preamble += "  long long length;\n";5931  Preamble += "#else\n";5932  Preamble += "  long length;\n";5933  Preamble += "#endif\n";5934  Preamble += "};\n";5935  Preamble += "#ifdef CF_EXPORT_CONSTANT_STRING\n";5936  Preamble += "extern \"C\" __declspec(dllexport) int __CFConstantStringClassReference[];\n";5937  Preamble += "#else\n";5938  Preamble += "__OBJC_RW_DLLIMPORT int __CFConstantStringClassReference[];\n";5939  Preamble += "#endif\n";5940  Preamble += "#define __NSCONSTANTSTRINGIMPL\n";5941  Preamble += "#endif\n";5942  // Blocks preamble.5943  Preamble += "#ifndef BLOCK_IMPL\n";5944  Preamble += "#define BLOCK_IMPL\n";5945  Preamble += "struct __block_impl {\n";5946  Preamble += "  void *isa;\n";5947  Preamble += "  int Flags;\n";5948  Preamble += "  int Reserved;\n";5949  Preamble += "  void *FuncPtr;\n";5950  Preamble += "};\n";5951  Preamble += "// Runtime copy/destroy helper functions (from Block_private.h)\n";5952  Preamble += "#ifdef __OBJC_EXPORT_BLOCKS\n";5953  Preamble += "extern \"C\" __declspec(dllexport) "5954  "void _Block_object_assign(void *, const void *, const int);\n";5955  Preamble += "extern \"C\" __declspec(dllexport) void _Block_object_dispose(const void *, const int);\n";5956  Preamble += "extern \"C\" __declspec(dllexport) void *_NSConcreteGlobalBlock[32];\n";5957  Preamble += "extern \"C\" __declspec(dllexport) void *_NSConcreteStackBlock[32];\n";5958  Preamble += "#else\n";5959  Preamble += "__OBJC_RW_DLLIMPORT void _Block_object_assign(void *, const void *, const int);\n";5960  Preamble += "__OBJC_RW_DLLIMPORT void _Block_object_dispose(const void *, const int);\n";5961  Preamble += "__OBJC_RW_DLLIMPORT void *_NSConcreteGlobalBlock[32];\n";5962  Preamble += "__OBJC_RW_DLLIMPORT void *_NSConcreteStackBlock[32];\n";5963  Preamble += "#endif\n";5964  Preamble += "#endif\n";5965  if (LangOpts.MicrosoftExt) {5966    Preamble += "#undef __OBJC_RW_DLLIMPORT\n";5967    Preamble += "#undef __OBJC_RW_STATICIMPORT\n";5968    Preamble += "#ifndef KEEP_ATTRIBUTES\n";  // We use this for clang tests.5969    Preamble += "#define __attribute__(X)\n";5970    Preamble += "#endif\n";5971    Preamble += "#ifndef __weak\n";5972    Preamble += "#define __weak\n";5973    Preamble += "#endif\n";5974    Preamble += "#ifndef __block\n";5975    Preamble += "#define __block\n";5976    Preamble += "#endif\n";5977  }5978  else {5979    Preamble += "#define __block\n";5980    Preamble += "#define __weak\n";5981  }5982 5983  // Declarations required for modern objective-c array and dictionary literals.5984  Preamble += "\n#include <stdarg.h>\n";5985  Preamble += "struct __NSContainer_literal {\n";5986  Preamble += "  void * *arr;\n";5987  Preamble += "  __NSContainer_literal (unsigned int count, ...) {\n";5988  Preamble += "\tva_list marker;\n";5989  Preamble += "\tva_start(marker, count);\n";5990  Preamble += "\tarr = new void *[count];\n";5991  Preamble += "\tfor (unsigned i = 0; i < count; i++)\n";5992  Preamble += "\t  arr[i] = va_arg(marker, void *);\n";5993  Preamble += "\tva_end( marker );\n";5994  Preamble += "  };\n";5995  Preamble += "  ~__NSContainer_literal() {\n";5996  Preamble += "\tdelete[] arr;\n";5997  Preamble += "  }\n";5998  Preamble += "};\n";5999 6000  // Declaration required for implementation of @autoreleasepool statement.6001  Preamble += "extern \"C\" __declspec(dllimport) void * objc_autoreleasePoolPush(void);\n";6002  Preamble += "extern \"C\" __declspec(dllimport) void objc_autoreleasePoolPop(void *);\n\n";6003  Preamble += "struct __AtAutoreleasePool {\n";6004  Preamble += "  __AtAutoreleasePool() {atautoreleasepoolobj = objc_autoreleasePoolPush();}\n";6005  Preamble += "  ~__AtAutoreleasePool() {objc_autoreleasePoolPop(atautoreleasepoolobj);}\n";6006  Preamble += "  void * atautoreleasepoolobj;\n";6007  Preamble += "};\n";6008 6009  // NOTE! Windows uses LLP64 for 64bit mode. So, cast pointer to long long6010  // as this avoids warning in any 64bit/32bit compilation model.6011  Preamble += "\n#define __OFFSETOFIVAR__(TYPE, MEMBER) ((long long) &((TYPE *)0)->MEMBER)\n";6012}6013 6014/// RewriteIvarOffsetComputation - This routine synthesizes computation of6015/// ivar offset.6016void RewriteModernObjC::RewriteIvarOffsetComputation(ObjCIvarDecl *ivar,6017                                                         std::string &Result) {6018  Result += "__OFFSETOFIVAR__(struct ";6019  Result += ivar->getContainingInterface()->getNameAsString();6020  if (LangOpts.MicrosoftExt)6021    Result += "_IMPL";6022  Result += ", ";6023  if (ivar->isBitField())6024    ObjCIvarBitfieldGroupDecl(ivar, Result);6025  else6026    Result += ivar->getNameAsString();6027  Result += ")";6028}6029 6030/// WriteModernMetadataDeclarations - Writes out metadata declarations for modern ABI.6031/// struct _prop_t {6032///   const char *name;6033///   char *attributes;6034/// }6035 6036/// struct _prop_list_t {6037///   uint32_t entsize;      // sizeof(struct _prop_t)6038///   uint32_t count_of_properties;6039///   struct _prop_t prop_list[count_of_properties];6040/// }6041 6042/// struct _protocol_t;6043 6044/// struct _protocol_list_t {6045///   long protocol_count;   // Note, this is 32/64 bit6046///   struct _protocol_t * protocol_list[protocol_count];6047/// }6048 6049/// struct _objc_method {6050///   SEL _cmd;6051///   const char *method_type;6052///   char *_imp;6053/// }6054 6055/// struct _method_list_t {6056///   uint32_t entsize;  // sizeof(struct _objc_method)6057///   uint32_t method_count;6058///   struct _objc_method method_list[method_count];6059/// }6060 6061/// struct _protocol_t {6062///   id isa;  // NULL6063///   const char *protocol_name;6064///   const struct _protocol_list_t * protocol_list; // super protocols6065///   const struct method_list_t *instance_methods;6066///   const struct method_list_t *class_methods;6067///   const struct method_list_t *optionalInstanceMethods;6068///   const struct method_list_t *optionalClassMethods;6069///   const struct _prop_list_t * properties;6070///   const uint32_t size;  // sizeof(struct _protocol_t)6071///   const uint32_t flags;  // = 06072///   const char ** extendedMethodTypes;6073/// }6074 6075/// struct _ivar_t {6076///   unsigned long int *offset;  // pointer to ivar offset location6077///   const char *name;6078///   const char *type;6079///   uint32_t alignment;6080///   uint32_t size;6081/// }6082 6083/// struct _ivar_list_t {6084///   uint32 entsize;  // sizeof(struct _ivar_t)6085///   uint32 count;6086///   struct _ivar_t list[count];6087/// }6088 6089/// struct _class_ro_t {6090///   uint32_t flags;6091///   uint32_t instanceStart;6092///   uint32_t instanceSize;6093///   uint32_t reserved;  // only when building for 64bit targets6094///   const uint8_t *ivarLayout;6095///   const char *name;6096///   const struct _method_list_t *baseMethods;6097///   const struct _protocol_list_t *baseProtocols;6098///   const struct _ivar_list_t *ivars;6099///   const uint8_t *weakIvarLayout;6100///   const struct _prop_list_t *properties;6101/// }6102 6103/// struct _class_t {6104///   struct _class_t *isa;6105///   struct _class_t *superclass;6106///   void *cache;6107///   IMP *vtable;6108///   struct _class_ro_t *ro;6109/// }6110 6111/// struct _category_t {6112///   const char *name;6113///   struct _class_t *cls;6114///   const struct _method_list_t *instance_methods;6115///   const struct _method_list_t *class_methods;6116///   const struct _protocol_list_t *protocols;6117///   const struct _prop_list_t *properties;6118/// }6119 6120/// MessageRefTy - LLVM for:6121/// struct _message_ref_t {6122///   IMP messenger;6123///   SEL name;6124/// };6125 6126/// SuperMessageRefTy - LLVM for:6127/// struct _super_message_ref_t {6128///   SUPER_IMP messenger;6129///   SEL name;6130/// };6131 6132static void WriteModernMetadataDeclarations(ASTContext *Context, std::string &Result) {6133  static bool meta_data_declared = false;6134  if (meta_data_declared)6135    return;6136 6137  Result += "\nstruct _prop_t {\n";6138  Result += "\tconst char *name;\n";6139  Result += "\tconst char *attributes;\n";6140  Result += "};\n";6141 6142  Result += "\nstruct _protocol_t;\n";6143 6144  Result += "\nstruct _objc_method {\n";6145  Result += "\tstruct objc_selector * _cmd;\n";6146  Result += "\tconst char *method_type;\n";6147  Result += "\tvoid  *_imp;\n";6148  Result += "};\n";6149 6150  Result += "\nstruct _protocol_t {\n";6151  Result += "\tvoid * isa;  // NULL\n";6152  Result += "\tconst char *protocol_name;\n";6153  Result += "\tconst struct _protocol_list_t * protocol_list; // super protocols\n";6154  Result += "\tconst struct method_list_t *instance_methods;\n";6155  Result += "\tconst struct method_list_t *class_methods;\n";6156  Result += "\tconst struct method_list_t *optionalInstanceMethods;\n";6157  Result += "\tconst struct method_list_t *optionalClassMethods;\n";6158  Result += "\tconst struct _prop_list_t * properties;\n";6159  Result += "\tconst unsigned int size;  // sizeof(struct _protocol_t)\n";6160  Result += "\tconst unsigned int flags;  // = 0\n";6161  Result += "\tconst char ** extendedMethodTypes;\n";6162  Result += "};\n";6163 6164  Result += "\nstruct _ivar_t {\n";6165  Result += "\tunsigned long int *offset;  // pointer to ivar offset location\n";6166  Result += "\tconst char *name;\n";6167  Result += "\tconst char *type;\n";6168  Result += "\tunsigned int alignment;\n";6169  Result += "\tunsigned int  size;\n";6170  Result += "};\n";6171 6172  Result += "\nstruct _class_ro_t {\n";6173  Result += "\tunsigned int flags;\n";6174  Result += "\tunsigned int instanceStart;\n";6175  Result += "\tunsigned int instanceSize;\n";6176  const llvm::Triple &Triple(Context->getTargetInfo().getTriple());6177  if (Triple.getArch() == llvm::Triple::x86_64)6178    Result += "\tunsigned int reserved;\n";6179  Result += "\tconst unsigned char *ivarLayout;\n";6180  Result += "\tconst char *name;\n";6181  Result += "\tconst struct _method_list_t *baseMethods;\n";6182  Result += "\tconst struct _objc_protocol_list *baseProtocols;\n";6183  Result += "\tconst struct _ivar_list_t *ivars;\n";6184  Result += "\tconst unsigned char *weakIvarLayout;\n";6185  Result += "\tconst struct _prop_list_t *properties;\n";6186  Result += "};\n";6187 6188  Result += "\nstruct _class_t {\n";6189  Result += "\tstruct _class_t *isa;\n";6190  Result += "\tstruct _class_t *superclass;\n";6191  Result += "\tvoid *cache;\n";6192  Result += "\tvoid *vtable;\n";6193  Result += "\tstruct _class_ro_t *ro;\n";6194  Result += "};\n";6195 6196  Result += "\nstruct _category_t {\n";6197  Result += "\tconst char *name;\n";6198  Result += "\tstruct _class_t *cls;\n";6199  Result += "\tconst struct _method_list_t *instance_methods;\n";6200  Result += "\tconst struct _method_list_t *class_methods;\n";6201  Result += "\tconst struct _protocol_list_t *protocols;\n";6202  Result += "\tconst struct _prop_list_t *properties;\n";6203  Result += "};\n";6204 6205  Result += "extern \"C\" __declspec(dllimport) struct objc_cache _objc_empty_cache;\n";6206  Result += "#pragma warning(disable:4273)\n";6207  meta_data_declared = true;6208}6209 6210static void Write_protocol_list_t_TypeDecl(std::string &Result,6211                                           long super_protocol_count) {6212  Result += "struct /*_protocol_list_t*/"; Result += " {\n";6213  Result += "\tlong protocol_count;  // Note, this is 32/64 bit\n";6214  Result += "\tstruct _protocol_t *super_protocols[";6215  Result += utostr(super_protocol_count); Result += "];\n";6216  Result += "}";6217}6218 6219static void Write_method_list_t_TypeDecl(std::string &Result,6220                                         unsigned int method_count) {6221  Result += "struct /*_method_list_t*/"; Result += " {\n";6222  Result += "\tunsigned int entsize;  // sizeof(struct _objc_method)\n";6223  Result += "\tunsigned int method_count;\n";6224  Result += "\tstruct _objc_method method_list[";6225  Result += utostr(method_count); Result += "];\n";6226  Result += "}";6227}6228 6229static void Write__prop_list_t_TypeDecl(std::string &Result,6230                                        unsigned int property_count) {6231  Result += "struct /*_prop_list_t*/"; Result += " {\n";6232  Result += "\tunsigned int entsize;  // sizeof(struct _prop_t)\n";6233  Result += "\tunsigned int count_of_properties;\n";6234  Result += "\tstruct _prop_t prop_list[";6235  Result += utostr(property_count); Result += "];\n";6236  Result += "}";6237}6238 6239static void Write__ivar_list_t_TypeDecl(std::string &Result,6240                                        unsigned int ivar_count) {6241  Result += "struct /*_ivar_list_t*/"; Result += " {\n";6242  Result += "\tunsigned int entsize;  // sizeof(struct _prop_t)\n";6243  Result += "\tunsigned int count;\n";6244  Result += "\tstruct _ivar_t ivar_list[";6245  Result += utostr(ivar_count); Result += "];\n";6246  Result += "}";6247}6248 6249static void Write_protocol_list_initializer(ASTContext *Context, std::string &Result,6250                                            ArrayRef<ObjCProtocolDecl *> SuperProtocols,6251                                            StringRef VarName,6252                                            StringRef ProtocolName) {6253  if (SuperProtocols.size() > 0) {6254    Result += "\nstatic ";6255    Write_protocol_list_t_TypeDecl(Result, SuperProtocols.size());6256    Result += " "; Result += VarName;6257    Result += ProtocolName;6258    Result += " __attribute__ ((used, section (\"__DATA,__objc_const\"))) = {\n";6259    Result += "\t"; Result += utostr(SuperProtocols.size()); Result += ",\n";6260    for (unsigned i = 0, e = SuperProtocols.size(); i < e; i++) {6261      ObjCProtocolDecl *SuperPD = SuperProtocols[i];6262      Result += "\t&"; Result += "_OBJC_PROTOCOL_";6263      Result += SuperPD->getNameAsString();6264      if (i == e-1)6265        Result += "\n};\n";6266      else6267        Result += ",\n";6268    }6269  }6270}6271 6272static void Write_method_list_t_initializer(RewriteModernObjC &RewriteObj,6273                                            ASTContext *Context, std::string &Result,6274                                            ArrayRef<ObjCMethodDecl *> Methods,6275                                            StringRef VarName,6276                                            StringRef TopLevelDeclName,6277                                            bool MethodImpl) {6278  if (Methods.size() > 0) {6279    Result += "\nstatic ";6280    Write_method_list_t_TypeDecl(Result, Methods.size());6281    Result += " "; Result += VarName;6282    Result += TopLevelDeclName;6283    Result += " __attribute__ ((used, section (\"__DATA,__objc_const\"))) = {\n";6284    Result += "\t"; Result += "sizeof(_objc_method)"; Result += ",\n";6285    Result += "\t"; Result += utostr(Methods.size()); Result += ",\n";6286    for (unsigned i = 0, e = Methods.size(); i < e; i++) {6287      ObjCMethodDecl *MD = Methods[i];6288      if (i == 0)6289        Result += "\t{{(struct objc_selector *)\"";6290      else6291        Result += "\t{(struct objc_selector *)\"";6292      Result += (MD)->getSelector().getAsString(); Result += "\"";6293      Result += ", ";6294      std::string MethodTypeString = Context->getObjCEncodingForMethodDecl(MD);6295      Result += "\""; Result += MethodTypeString; Result += "\"";6296      Result += ", ";6297      if (!MethodImpl)6298        Result += "0";6299      else {6300        Result += "(void *)";6301        Result += RewriteObj.MethodInternalNames[MD];6302      }6303      if (i  == e-1)6304        Result += "}}\n";6305      else6306        Result += "},\n";6307    }6308    Result += "};\n";6309  }6310}6311 6312static void Write_prop_list_t_initializer(RewriteModernObjC &RewriteObj,6313                                           ASTContext *Context, std::string &Result,6314                                           ArrayRef<ObjCPropertyDecl *> Properties,6315                                           const Decl *Container,6316                                           StringRef VarName,6317                                           StringRef ProtocolName) {6318  if (Properties.size() > 0) {6319    Result += "\nstatic ";6320    Write__prop_list_t_TypeDecl(Result, Properties.size());6321    Result += " "; Result += VarName;6322    Result += ProtocolName;6323    Result += " __attribute__ ((used, section (\"__DATA,__objc_const\"))) = {\n";6324    Result += "\t"; Result += "sizeof(_prop_t)"; Result += ",\n";6325    Result += "\t"; Result += utostr(Properties.size()); Result += ",\n";6326    for (unsigned i = 0, e = Properties.size(); i < e; i++) {6327      ObjCPropertyDecl *PropDecl = Properties[i];6328      if (i == 0)6329        Result += "\t{{\"";6330      else6331        Result += "\t{\"";6332      Result += PropDecl->getName(); Result += "\",";6333      std::string PropertyTypeString =6334        Context->getObjCEncodingForPropertyDecl(PropDecl, Container);6335      std::string QuotePropertyTypeString;6336      RewriteObj.QuoteDoublequotes(PropertyTypeString, QuotePropertyTypeString);6337      Result += "\""; Result += QuotePropertyTypeString; Result += "\"";6338      if (i  == e-1)6339        Result += "}}\n";6340      else6341        Result += "},\n";6342    }6343    Result += "};\n";6344  }6345}6346 6347// Metadata flags6348enum MetaDataDlags {6349  CLS = 0x0,6350  CLS_META = 0x1,6351  CLS_ROOT = 0x2,6352  OBJC2_CLS_HIDDEN = 0x10,6353  CLS_EXCEPTION = 0x20,6354 6355  /// (Obsolete) ARC-specific: this class has a .release_ivars method6356  CLS_HAS_IVAR_RELEASER = 0x40,6357  /// class was compiled with -fobjc-arr6358  CLS_COMPILED_BY_ARC = 0x80  // (1<<7)6359};6360 6361static void Write__class_ro_t_initializer(ASTContext *Context, std::string &Result,6362                                          unsigned int flags,6363                                          const std::string &InstanceStart,6364                                          const std::string &InstanceSize,6365                                          ArrayRef<ObjCMethodDecl *>baseMethods,6366                                          ArrayRef<ObjCProtocolDecl *>baseProtocols,6367                                          ArrayRef<ObjCIvarDecl *>ivars,6368                                          ArrayRef<ObjCPropertyDecl *>Properties,6369                                          StringRef VarName,6370                                          StringRef ClassName) {6371  Result += "\nstatic struct _class_ro_t ";6372  Result += VarName; Result += ClassName;6373  Result += " __attribute__ ((used, section (\"__DATA,__objc_const\"))) = {\n";6374  Result += "\t";6375  Result += llvm::utostr(flags); Result += ", ";6376  Result += InstanceStart; Result += ", ";6377  Result += InstanceSize; Result += ", \n";6378  Result += "\t";6379  const llvm::Triple &Triple(Context->getTargetInfo().getTriple());6380  if (Triple.getArch() == llvm::Triple::x86_64)6381    // uint32_t const reserved; // only when building for 64bit targets6382    Result += "(unsigned int)0, \n\t";6383  // const uint8_t * const ivarLayout;6384  Result += "0, \n\t";6385  Result += "\""; Result += ClassName; Result += "\",\n\t";6386  bool metaclass = ((flags & CLS_META) != 0);6387  if (baseMethods.size() > 0) {6388    Result += "(const struct _method_list_t *)&";6389    if (metaclass)6390      Result += "_OBJC_$_CLASS_METHODS_";6391    else6392      Result += "_OBJC_$_INSTANCE_METHODS_";6393    Result += ClassName;6394    Result += ",\n\t";6395  }6396  else6397    Result += "0, \n\t";6398 6399  if (!metaclass && baseProtocols.size() > 0) {6400    Result += "(const struct _objc_protocol_list *)&";6401    Result += "_OBJC_CLASS_PROTOCOLS_$_"; Result += ClassName;6402    Result += ",\n\t";6403  }6404  else6405    Result += "0, \n\t";6406 6407  if (!metaclass && ivars.size() > 0) {6408    Result += "(const struct _ivar_list_t *)&";6409    Result += "_OBJC_$_INSTANCE_VARIABLES_"; Result += ClassName;6410    Result += ",\n\t";6411  }6412  else6413    Result += "0, \n\t";6414 6415  // weakIvarLayout6416  Result += "0, \n\t";6417  if (!metaclass && Properties.size() > 0) {6418    Result += "(const struct _prop_list_t *)&";6419    Result += "_OBJC_$_PROP_LIST_"; Result += ClassName;6420    Result += ",\n";6421  }6422  else6423    Result += "0, \n";6424 6425  Result += "};\n";6426}6427 6428static void Write_class_t(ASTContext *Context, std::string &Result,6429                          StringRef VarName,6430                          const ObjCInterfaceDecl *CDecl, bool metaclass) {6431  bool rootClass = (!CDecl->getSuperClass());6432  const ObjCInterfaceDecl *RootClass = CDecl;6433 6434  if (!rootClass) {6435    // Find the Root class6436    RootClass = CDecl->getSuperClass();6437    while (RootClass->getSuperClass()) {6438      RootClass = RootClass->getSuperClass();6439    }6440  }6441 6442  if (metaclass && rootClass) {6443    // Need to handle a case of use of forward declaration.6444    Result += "\n";6445    Result += "extern \"C\" ";6446    if (CDecl->getImplementation())6447      Result += "__declspec(dllexport) ";6448    else6449      Result += "__declspec(dllimport) ";6450 6451    Result += "struct _class_t OBJC_CLASS_$_";6452    Result += CDecl->getNameAsString();6453    Result += ";\n";6454  }6455  // Also, for possibility of 'super' metadata class not having been defined yet.6456  if (!rootClass) {6457    ObjCInterfaceDecl *SuperClass = CDecl->getSuperClass();6458    Result += "\n";6459    Result += "extern \"C\" ";6460    if (SuperClass->getImplementation())6461      Result += "__declspec(dllexport) ";6462    else6463      Result += "__declspec(dllimport) ";6464 6465    Result += "struct _class_t ";6466    Result += VarName;6467    Result += SuperClass->getNameAsString();6468    Result += ";\n";6469 6470    if (metaclass && RootClass != SuperClass) {6471      Result += "extern \"C\" ";6472      if (RootClass->getImplementation())6473        Result += "__declspec(dllexport) ";6474      else6475        Result += "__declspec(dllimport) ";6476 6477      Result += "struct _class_t ";6478      Result += VarName;6479      Result += RootClass->getNameAsString();6480      Result += ";\n";6481    }6482  }6483 6484  Result += "\nextern \"C\" __declspec(dllexport) struct _class_t ";6485  Result += VarName; Result += CDecl->getNameAsString();6486  Result += " __attribute__ ((used, section (\"__DATA,__objc_data\"))) = {\n";6487  Result += "\t";6488  if (metaclass) {6489    if (!rootClass) {6490      Result += "0, // &"; Result += VarName;6491      Result += RootClass->getNameAsString();6492      Result += ",\n\t";6493      Result += "0, // &"; Result += VarName;6494      Result += CDecl->getSuperClass()->getNameAsString();6495      Result += ",\n\t";6496    }6497    else {6498      Result += "0, // &"; Result += VarName;6499      Result += CDecl->getNameAsString();6500      Result += ",\n\t";6501      Result += "0, // &OBJC_CLASS_$_"; Result += CDecl->getNameAsString();6502      Result += ",\n\t";6503    }6504  }6505  else {6506    Result += "0, // &OBJC_METACLASS_$_";6507    Result += CDecl->getNameAsString();6508    Result += ",\n\t";6509    if (!rootClass) {6510      Result += "0, // &"; Result += VarName;6511      Result += CDecl->getSuperClass()->getNameAsString();6512      Result += ",\n\t";6513    }6514    else6515      Result += "0,\n\t";6516  }6517  Result += "0, // (void *)&_objc_empty_cache,\n\t";6518  Result += "0, // unused, was (void *)&_objc_empty_vtable,\n\t";6519  if (metaclass)6520    Result += "&_OBJC_METACLASS_RO_$_";6521  else6522    Result += "&_OBJC_CLASS_RO_$_";6523  Result += CDecl->getNameAsString();6524  Result += ",\n};\n";6525 6526  // Add static function to initialize some of the meta-data fields.6527  // avoid doing it twice.6528  if (metaclass)6529    return;6530 6531  const ObjCInterfaceDecl *SuperClass =6532    rootClass ? CDecl : CDecl->getSuperClass();6533 6534  Result += "static void OBJC_CLASS_SETUP_$_";6535  Result += CDecl->getNameAsString();6536  Result += "(void ) {\n";6537  Result += "\tOBJC_METACLASS_$_"; Result += CDecl->getNameAsString();6538  Result += ".isa = "; Result += "&OBJC_METACLASS_$_";6539  Result += RootClass->getNameAsString(); Result += ";\n";6540 6541  Result += "\tOBJC_METACLASS_$_"; Result += CDecl->getNameAsString();6542  Result += ".superclass = ";6543  if (rootClass)6544    Result += "&OBJC_CLASS_$_";6545  else6546     Result += "&OBJC_METACLASS_$_";6547 6548  Result += SuperClass->getNameAsString(); Result += ";\n";6549 6550  Result += "\tOBJC_METACLASS_$_"; Result += CDecl->getNameAsString();6551  Result += ".cache = "; Result += "&_objc_empty_cache"; Result += ";\n";6552 6553  Result += "\tOBJC_CLASS_$_"; Result += CDecl->getNameAsString();6554  Result += ".isa = "; Result += "&OBJC_METACLASS_$_";6555  Result += CDecl->getNameAsString(); Result += ";\n";6556 6557  if (!rootClass) {6558    Result += "\tOBJC_CLASS_$_"; Result += CDecl->getNameAsString();6559    Result += ".superclass = "; Result += "&OBJC_CLASS_$_";6560    Result += SuperClass->getNameAsString(); Result += ";\n";6561  }6562 6563  Result += "\tOBJC_CLASS_$_"; Result += CDecl->getNameAsString();6564  Result += ".cache = "; Result += "&_objc_empty_cache"; Result += ";\n";6565  Result += "}\n";6566}6567 6568static void Write_category_t(RewriteModernObjC &RewriteObj, ASTContext *Context,6569                             std::string &Result,6570                             ObjCCategoryDecl *CatDecl,6571                             ObjCInterfaceDecl *ClassDecl,6572                             ArrayRef<ObjCMethodDecl *> InstanceMethods,6573                             ArrayRef<ObjCMethodDecl *> ClassMethods,6574                             ArrayRef<ObjCProtocolDecl *> RefedProtocols,6575                             ArrayRef<ObjCPropertyDecl *> ClassProperties) {6576  StringRef CatName = CatDecl->getName();6577  StringRef ClassName = ClassDecl->getName();6578  // must declare an extern class object in case this class is not implemented6579  // in this TU.6580  Result += "\n";6581  Result += "extern \"C\" ";6582  if (ClassDecl->getImplementation())6583    Result += "__declspec(dllexport) ";6584  else6585    Result += "__declspec(dllimport) ";6586 6587  Result += "struct _class_t ";6588  Result += "OBJC_CLASS_$_"; Result += ClassName;6589  Result += ";\n";6590 6591  Result += "\nstatic struct _category_t ";6592  Result += "_OBJC_$_CATEGORY_";6593  Result += ClassName; Result += "_$_"; Result += CatName;6594  Result += " __attribute__ ((used, section (\"__DATA,__objc_const\"))) = \n";6595  Result += "{\n";6596  Result += "\t\""; Result += ClassName; Result += "\",\n";6597  Result += "\t0, // &"; Result += "OBJC_CLASS_$_"; Result += ClassName;6598  Result += ",\n";6599  if (InstanceMethods.size() > 0) {6600    Result += "\t(const struct _method_list_t *)&";6601    Result += "_OBJC_$_CATEGORY_INSTANCE_METHODS_";6602    Result += ClassName; Result += "_$_"; Result += CatName;6603    Result += ",\n";6604  }6605  else6606    Result += "\t0,\n";6607 6608  if (ClassMethods.size() > 0) {6609    Result += "\t(const struct _method_list_t *)&";6610    Result += "_OBJC_$_CATEGORY_CLASS_METHODS_";6611    Result += ClassName; Result += "_$_"; Result += CatName;6612    Result += ",\n";6613  }6614  else6615    Result += "\t0,\n";6616 6617  if (RefedProtocols.size() > 0) {6618    Result += "\t(const struct _protocol_list_t *)&";6619    Result += "_OBJC_CATEGORY_PROTOCOLS_$_";6620    Result += ClassName; Result += "_$_"; Result += CatName;6621    Result += ",\n";6622  }6623  else6624    Result += "\t0,\n";6625 6626  if (ClassProperties.size() > 0) {6627    Result += "\t(const struct _prop_list_t *)&";  Result += "_OBJC_$_PROP_LIST_";6628    Result += ClassName; Result += "_$_"; Result += CatName;6629    Result += ",\n";6630  }6631  else6632    Result += "\t0,\n";6633 6634  Result += "};\n";6635 6636  // Add static function to initialize the class pointer in the category structure.6637  Result += "static void OBJC_CATEGORY_SETUP_$_";6638  Result += ClassDecl->getNameAsString();6639  Result += "_$_";6640  Result += CatName;6641  Result += "(void ) {\n";6642  Result += "\t_OBJC_$_CATEGORY_";6643  Result += ClassDecl->getNameAsString();6644  Result += "_$_";6645  Result += CatName;6646  Result += ".cls = "; Result += "&OBJC_CLASS_$_"; Result += ClassName;6647  Result += ";\n}\n";6648}6649 6650static void Write__extendedMethodTypes_initializer(RewriteModernObjC &RewriteObj,6651                                           ASTContext *Context, std::string &Result,6652                                           ArrayRef<ObjCMethodDecl *> Methods,6653                                           StringRef VarName,6654                                           StringRef ProtocolName) {6655  if (Methods.size() == 0)6656    return;6657 6658  Result += "\nstatic const char *";6659  Result += VarName; Result += ProtocolName;6660  Result += " [] __attribute__ ((used, section (\"__DATA,__objc_const\"))) = \n";6661  Result += "{\n";6662  for (unsigned i = 0, e = Methods.size(); i < e; i++) {6663    ObjCMethodDecl *MD = Methods[i];6664    std::string MethodTypeString =6665      Context->getObjCEncodingForMethodDecl(MD, true);6666    std::string QuoteMethodTypeString;6667    RewriteObj.QuoteDoublequotes(MethodTypeString, QuoteMethodTypeString);6668    Result += "\t\""; Result += QuoteMethodTypeString; Result += "\"";6669    if (i == e-1)6670      Result += "\n};\n";6671    else {6672      Result += ",\n";6673    }6674  }6675}6676 6677static void Write_IvarOffsetVar(RewriteModernObjC &RewriteObj,6678                                ASTContext *Context,6679                                std::string &Result,6680                                ArrayRef<ObjCIvarDecl *> Ivars,6681                                ObjCInterfaceDecl *CDecl) {6682  // FIXME. visibility of offset symbols may have to be set; for Darwin6683  // this is what happens:6684  /**6685   if (Ivar->getAccessControl() == ObjCIvarDecl::Private ||6686       Ivar->getAccessControl() == ObjCIvarDecl::Package ||6687       Class->getVisibility() == HiddenVisibility)6688     Visibility should be: HiddenVisibility;6689   else6690     Visibility should be: DefaultVisibility;6691  */6692 6693  Result += "\n";6694  for (unsigned i =0, e = Ivars.size(); i < e; i++) {6695    ObjCIvarDecl *IvarDecl = Ivars[i];6696    if (Context->getLangOpts().MicrosoftExt)6697      Result += "__declspec(allocate(\".objc_ivar$B\")) ";6698 6699    if (!Context->getLangOpts().MicrosoftExt ||6700        IvarDecl->getAccessControl() == ObjCIvarDecl::Private ||6701        IvarDecl->getAccessControl() == ObjCIvarDecl::Package)6702      Result += "extern \"C\" unsigned long int ";6703    else6704      Result += "extern \"C\" __declspec(dllexport) unsigned long int ";6705    if (Ivars[i]->isBitField())6706      RewriteObj.ObjCIvarBitfieldGroupOffset(IvarDecl, Result);6707    else6708      WriteInternalIvarName(CDecl, IvarDecl, Result);6709    Result += " __attribute__ ((used, section (\"__DATA,__objc_ivar\")))";6710    Result += " = ";6711    RewriteObj.RewriteIvarOffsetComputation(IvarDecl, Result);6712    Result += ";\n";6713    if (Ivars[i]->isBitField()) {6714      // skip over rest of the ivar bitfields.6715      SKIP_BITFIELDS(i , e, Ivars);6716    }6717  }6718}6719 6720static void Write__ivar_list_t_initializer(RewriteModernObjC &RewriteObj,6721                                           ASTContext *Context, std::string &Result,6722                                           ArrayRef<ObjCIvarDecl *> OriginalIvars,6723                                           StringRef VarName,6724                                           ObjCInterfaceDecl *CDecl) {6725  if (OriginalIvars.size() > 0) {6726    Write_IvarOffsetVar(RewriteObj, Context, Result, OriginalIvars, CDecl);6727    SmallVector<ObjCIvarDecl *, 8> Ivars;6728    // strip off all but the first ivar bitfield from each group of ivars.6729    // Such ivars in the ivar list table will be replaced by their grouping struct6730    // 'ivar'.6731    for (unsigned i = 0, e = OriginalIvars.size(); i < e; i++) {6732      if (OriginalIvars[i]->isBitField()) {6733        Ivars.push_back(OriginalIvars[i]);6734        // skip over rest of the ivar bitfields.6735        SKIP_BITFIELDS(i , e, OriginalIvars);6736      }6737      else6738        Ivars.push_back(OriginalIvars[i]);6739    }6740 6741    Result += "\nstatic ";6742    Write__ivar_list_t_TypeDecl(Result, Ivars.size());6743    Result += " "; Result += VarName;6744    Result += CDecl->getNameAsString();6745    Result += " __attribute__ ((used, section (\"__DATA,__objc_const\"))) = {\n";6746    Result += "\t"; Result += "sizeof(_ivar_t)"; Result += ",\n";6747    Result += "\t"; Result += utostr(Ivars.size()); Result += ",\n";6748    for (unsigned i =0, e = Ivars.size(); i < e; i++) {6749      ObjCIvarDecl *IvarDecl = Ivars[i];6750      if (i == 0)6751        Result += "\t{{";6752      else6753        Result += "\t {";6754      Result += "(unsigned long int *)&";6755      if (Ivars[i]->isBitField())6756        RewriteObj.ObjCIvarBitfieldGroupOffset(IvarDecl, Result);6757      else6758        WriteInternalIvarName(CDecl, IvarDecl, Result);6759      Result += ", ";6760 6761      Result += "\"";6762      if (Ivars[i]->isBitField())6763        RewriteObj.ObjCIvarBitfieldGroupDecl(Ivars[i], Result);6764      else6765        Result += IvarDecl->getName();6766      Result += "\", ";6767 6768      QualType IVQT = IvarDecl->getType();6769      if (IvarDecl->isBitField())6770        IVQT = RewriteObj.GetGroupRecordTypeForObjCIvarBitfield(IvarDecl);6771 6772      std::string IvarTypeString, QuoteIvarTypeString;6773      Context->getObjCEncodingForType(IVQT, IvarTypeString,6774                                      IvarDecl);6775      RewriteObj.QuoteDoublequotes(IvarTypeString, QuoteIvarTypeString);6776      Result += "\""; Result += QuoteIvarTypeString; Result += "\", ";6777 6778      // FIXME. this alignment represents the host alignment and need be changed to6779      // represent the target alignment.6780      unsigned Align = Context->getTypeAlign(IVQT)/8;6781      Align = llvm::Log2_32(Align);6782      Result += llvm::utostr(Align); Result += ", ";6783      CharUnits Size = Context->getTypeSizeInChars(IVQT);6784      Result += llvm::utostr(Size.getQuantity());6785      if (i  == e-1)6786        Result += "}}\n";6787      else6788        Result += "},\n";6789    }6790    Result += "};\n";6791  }6792}6793 6794/// RewriteObjCProtocolMetaData - Rewrite protocols meta-data.6795void RewriteModernObjC::RewriteObjCProtocolMetaData(ObjCProtocolDecl *PDecl,6796                                                    std::string &Result) {6797 6798  // Do not synthesize the protocol more than once.6799  if (ObjCSynthesizedProtocols.count(PDecl->getCanonicalDecl()))6800    return;6801  WriteModernMetadataDeclarations(Context, Result);6802 6803  if (ObjCProtocolDecl *Def = PDecl->getDefinition())6804    PDecl = Def;6805  // Must write out all protocol definitions in current qualifier list,6806  // and in their nested qualifiers before writing out current definition.6807  for (auto *I : PDecl->protocols())6808    RewriteObjCProtocolMetaData(I, Result);6809 6810  // Construct method lists.6811  std::vector<ObjCMethodDecl *> InstanceMethods, ClassMethods;6812  std::vector<ObjCMethodDecl *> OptInstanceMethods, OptClassMethods;6813  for (auto *MD : PDecl->instance_methods()) {6814    if (MD->getImplementationControl() == ObjCImplementationControl::Optional) {6815      OptInstanceMethods.push_back(MD);6816    } else {6817      InstanceMethods.push_back(MD);6818    }6819  }6820 6821  for (auto *MD : PDecl->class_methods()) {6822    if (MD->getImplementationControl() == ObjCImplementationControl::Optional) {6823      OptClassMethods.push_back(MD);6824    } else {6825      ClassMethods.push_back(MD);6826    }6827  }6828  std::vector<ObjCMethodDecl *> AllMethods;6829  for (unsigned i = 0, e = InstanceMethods.size(); i < e; i++)6830    AllMethods.push_back(InstanceMethods[i]);6831  for (unsigned i = 0, e = ClassMethods.size(); i < e; i++)6832    AllMethods.push_back(ClassMethods[i]);6833  for (unsigned i = 0, e = OptInstanceMethods.size(); i < e; i++)6834    AllMethods.push_back(OptInstanceMethods[i]);6835  for (unsigned i = 0, e = OptClassMethods.size(); i < e; i++)6836    AllMethods.push_back(OptClassMethods[i]);6837 6838  Write__extendedMethodTypes_initializer(*this, Context, Result,6839                                         AllMethods,6840                                         "_OBJC_PROTOCOL_METHOD_TYPES_",6841                                         PDecl->getNameAsString());6842  // Protocol's super protocol list6843  SmallVector<ObjCProtocolDecl *, 8> SuperProtocols(PDecl->protocols());6844  Write_protocol_list_initializer(Context, Result, SuperProtocols,6845                                  "_OBJC_PROTOCOL_REFS_",6846                                  PDecl->getNameAsString());6847 6848  Write_method_list_t_initializer(*this, Context, Result, InstanceMethods,6849                                  "_OBJC_PROTOCOL_INSTANCE_METHODS_",6850                                  PDecl->getNameAsString(), false);6851 6852  Write_method_list_t_initializer(*this, Context, Result, ClassMethods,6853                                  "_OBJC_PROTOCOL_CLASS_METHODS_",6854                                  PDecl->getNameAsString(), false);6855 6856  Write_method_list_t_initializer(*this, Context, Result, OptInstanceMethods,6857                                  "_OBJC_PROTOCOL_OPT_INSTANCE_METHODS_",6858                                  PDecl->getNameAsString(), false);6859 6860  Write_method_list_t_initializer(*this, Context, Result, OptClassMethods,6861                                  "_OBJC_PROTOCOL_OPT_CLASS_METHODS_",6862                                  PDecl->getNameAsString(), false);6863 6864  // Protocol's property metadata.6865  SmallVector<ObjCPropertyDecl *, 8> ProtocolProperties(6866      PDecl->instance_properties());6867  Write_prop_list_t_initializer(*this, Context, Result, ProtocolProperties,6868                                 /* Container */nullptr,6869                                 "_OBJC_PROTOCOL_PROPERTIES_",6870                                 PDecl->getNameAsString());6871 6872  // Writer out root metadata for current protocol: struct _protocol_t6873  Result += "\n";6874  if (LangOpts.MicrosoftExt)6875    Result += "static ";6876  Result += "struct _protocol_t _OBJC_PROTOCOL_";6877  Result += PDecl->getNameAsString();6878  Result += " __attribute__ ((used)) = {\n";6879  Result += "\t0,\n"; // id is; is null6880  Result += "\t\""; Result += PDecl->getNameAsString(); Result += "\",\n";6881  if (SuperProtocols.size() > 0) {6882    Result += "\t(const struct _protocol_list_t *)&"; Result += "_OBJC_PROTOCOL_REFS_";6883    Result += PDecl->getNameAsString(); Result += ",\n";6884  }6885  else6886    Result += "\t0,\n";6887  if (InstanceMethods.size() > 0) {6888    Result += "\t(const struct method_list_t *)&_OBJC_PROTOCOL_INSTANCE_METHODS_";6889    Result += PDecl->getNameAsString(); Result += ",\n";6890  }6891  else6892    Result += "\t0,\n";6893 6894  if (ClassMethods.size() > 0) {6895    Result += "\t(const struct method_list_t *)&_OBJC_PROTOCOL_CLASS_METHODS_";6896    Result += PDecl->getNameAsString(); Result += ",\n";6897  }6898  else6899    Result += "\t0,\n";6900 6901  if (OptInstanceMethods.size() > 0) {6902    Result += "\t(const struct method_list_t *)&_OBJC_PROTOCOL_OPT_INSTANCE_METHODS_";6903    Result += PDecl->getNameAsString(); Result += ",\n";6904  }6905  else6906    Result += "\t0,\n";6907 6908  if (OptClassMethods.size() > 0) {6909    Result += "\t(const struct method_list_t *)&_OBJC_PROTOCOL_OPT_CLASS_METHODS_";6910    Result += PDecl->getNameAsString(); Result += ",\n";6911  }6912  else6913    Result += "\t0,\n";6914 6915  if (ProtocolProperties.size() > 0) {6916    Result += "\t(const struct _prop_list_t *)&_OBJC_PROTOCOL_PROPERTIES_";6917    Result += PDecl->getNameAsString(); Result += ",\n";6918  }6919  else6920    Result += "\t0,\n";6921 6922  Result += "\t"; Result += "sizeof(_protocol_t)"; Result += ",\n";6923  Result += "\t0,\n";6924 6925  if (AllMethods.size() > 0) {6926    Result += "\t(const char **)&"; Result += "_OBJC_PROTOCOL_METHOD_TYPES_";6927    Result += PDecl->getNameAsString();6928    Result += "\n};\n";6929  }6930  else6931    Result += "\t0\n};\n";6932 6933  if (LangOpts.MicrosoftExt)6934    Result += "static ";6935  Result += "struct _protocol_t *";6936  Result += "_OBJC_LABEL_PROTOCOL_$_"; Result += PDecl->getNameAsString();6937  Result += " = &_OBJC_PROTOCOL_"; Result += PDecl->getNameAsString();6938  Result += ";\n";6939 6940  // Mark this protocol as having been generated.6941  if (!ObjCSynthesizedProtocols.insert(PDecl->getCanonicalDecl()).second)6942    llvm_unreachable("protocol already synthesized");6943}6944 6945/// hasObjCExceptionAttribute - Return true if this class or any super6946/// class has the __objc_exception__ attribute.6947/// FIXME. Move this to ASTContext.cpp as it is also used for IRGen.6948static bool hasObjCExceptionAttribute(ASTContext &Context,6949                                      const ObjCInterfaceDecl *OID) {6950  if (OID->hasAttr<ObjCExceptionAttr>())6951    return true;6952  if (const ObjCInterfaceDecl *Super = OID->getSuperClass())6953    return hasObjCExceptionAttribute(Context, Super);6954  return false;6955}6956 6957void RewriteModernObjC::RewriteObjCClassMetaData(ObjCImplementationDecl *IDecl,6958                                           std::string &Result) {6959  ObjCInterfaceDecl *CDecl = IDecl->getClassInterface();6960 6961  // Explicitly declared @interface's are already synthesized.6962  if (CDecl->isImplicitInterfaceDecl())6963    assert(false &&6964           "Legacy implicit interface rewriting not supported in moder abi");6965 6966  WriteModernMetadataDeclarations(Context, Result);6967  SmallVector<ObjCIvarDecl *, 8> IVars;6968 6969  for (ObjCIvarDecl *IVD = CDecl->all_declared_ivar_begin();6970      IVD; IVD = IVD->getNextIvar()) {6971    // Ignore unnamed bit-fields.6972    if (!IVD->getDeclName())6973      continue;6974    IVars.push_back(IVD);6975  }6976 6977  Write__ivar_list_t_initializer(*this, Context, Result, IVars,6978                                 "_OBJC_$_INSTANCE_VARIABLES_",6979                                 CDecl);6980 6981  // Build _objc_method_list for class's instance methods if needed6982  SmallVector<ObjCMethodDecl *, 32> InstanceMethods(IDecl->instance_methods());6983 6984  // If any of our property implementations have associated getters or6985  // setters, produce metadata for them as well.6986  for (const auto *Prop : IDecl->property_impls()) {6987    if (Prop->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic)6988      continue;6989    if (!Prop->getPropertyIvarDecl())6990      continue;6991    ObjCPropertyDecl *PD = Prop->getPropertyDecl();6992    if (!PD)6993      continue;6994    if (ObjCMethodDecl *Getter = Prop->getGetterMethodDecl())6995      if (mustSynthesizeSetterGetterMethod(IDecl, PD, true /*getter*/))6996        InstanceMethods.push_back(Getter);6997    if (PD->isReadOnly())6998      continue;6999    if (ObjCMethodDecl *Setter = Prop->getSetterMethodDecl())7000      if (mustSynthesizeSetterGetterMethod(IDecl, PD, false /*setter*/))7001        InstanceMethods.push_back(Setter);7002  }7003 7004  Write_method_list_t_initializer(*this, Context, Result, InstanceMethods,7005                                  "_OBJC_$_INSTANCE_METHODS_",7006                                  IDecl->getNameAsString(), true);7007 7008  SmallVector<ObjCMethodDecl *, 32> ClassMethods(IDecl->class_methods());7009 7010  Write_method_list_t_initializer(*this, Context, Result, ClassMethods,7011                                  "_OBJC_$_CLASS_METHODS_",7012                                  IDecl->getNameAsString(), true);7013 7014  // Protocols referenced in class declaration?7015  // Protocol's super protocol list7016  std::vector<ObjCProtocolDecl *> RefedProtocols;7017  const ObjCList<ObjCProtocolDecl> &Protocols = CDecl->getReferencedProtocols();7018  for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),7019       E = Protocols.end();7020       I != E; ++I) {7021    RefedProtocols.push_back(*I);7022    // Must write out all protocol definitions in current qualifier list,7023    // and in their nested qualifiers before writing out current definition.7024    RewriteObjCProtocolMetaData(*I, Result);7025  }7026 7027  Write_protocol_list_initializer(Context, Result,7028                                  RefedProtocols,7029                                  "_OBJC_CLASS_PROTOCOLS_$_",7030                                  IDecl->getNameAsString());7031 7032  // Protocol's property metadata.7033  SmallVector<ObjCPropertyDecl *, 8> ClassProperties(7034      CDecl->instance_properties());7035  Write_prop_list_t_initializer(*this, Context, Result, ClassProperties,7036                                 /* Container */IDecl,7037                                 "_OBJC_$_PROP_LIST_",7038                                 CDecl->getNameAsString());7039 7040  // Data for initializing _class_ro_t  metaclass meta-data7041  uint32_t flags = CLS_META;7042  std::string InstanceSize;7043  std::string InstanceStart;7044 7045  bool classIsHidden = CDecl->getVisibility() == HiddenVisibility;7046  if (classIsHidden)7047    flags |= OBJC2_CLS_HIDDEN;7048 7049  if (!CDecl->getSuperClass())7050    // class is root7051    flags |= CLS_ROOT;7052  InstanceSize = "sizeof(struct _class_t)";7053  InstanceStart = InstanceSize;7054  Write__class_ro_t_initializer(Context, Result, flags,7055                                InstanceStart, InstanceSize,7056                                ClassMethods,7057                                nullptr,7058                                nullptr,7059                                nullptr,7060                                "_OBJC_METACLASS_RO_$_",7061                                CDecl->getNameAsString());7062 7063  // Data for initializing _class_ro_t meta-data7064  flags = CLS;7065  if (classIsHidden)7066    flags |= OBJC2_CLS_HIDDEN;7067 7068  if (hasObjCExceptionAttribute(*Context, CDecl))7069    flags |= CLS_EXCEPTION;7070 7071  if (!CDecl->getSuperClass())7072    // class is root7073    flags |= CLS_ROOT;7074 7075  InstanceSize.clear();7076  InstanceStart.clear();7077  if (!ObjCSynthesizedStructs.count(CDecl)) {7078    InstanceSize = "0";7079    InstanceStart = "0";7080  }7081  else {7082    InstanceSize = "sizeof(struct ";7083    InstanceSize += CDecl->getNameAsString();7084    InstanceSize += "_IMPL)";7085 7086    ObjCIvarDecl *IVD = CDecl->all_declared_ivar_begin();7087    if (IVD) {7088      RewriteIvarOffsetComputation(IVD, InstanceStart);7089    }7090    else7091      InstanceStart = InstanceSize;7092  }7093  Write__class_ro_t_initializer(Context, Result, flags,7094                                InstanceStart, InstanceSize,7095                                InstanceMethods,7096                                RefedProtocols,7097                                IVars,7098                                ClassProperties,7099                                "_OBJC_CLASS_RO_$_",7100                                CDecl->getNameAsString());7101 7102  Write_class_t(Context, Result,7103                "OBJC_METACLASS_$_",7104                CDecl, /*metaclass*/true);7105 7106  Write_class_t(Context, Result,7107                "OBJC_CLASS_$_",7108                CDecl, /*metaclass*/false);7109 7110  if (ImplementationIsNonLazy(IDecl))7111    DefinedNonLazyClasses.push_back(CDecl);7112}7113 7114void RewriteModernObjC::RewriteClassSetupInitHook(std::string &Result) {7115  int ClsDefCount = ClassImplementation.size();7116  if (!ClsDefCount)7117    return;7118  Result += "#pragma section(\".objc_inithooks$B\", long, read, write)\n";7119  Result += "__declspec(allocate(\".objc_inithooks$B\")) ";7120  Result += "static void *OBJC_CLASS_SETUP[] = {\n";7121  for (int i = 0; i < ClsDefCount; i++) {7122    ObjCImplementationDecl *IDecl = ClassImplementation[i];7123    ObjCInterfaceDecl *CDecl = IDecl->getClassInterface();7124    Result += "\t(void *)&OBJC_CLASS_SETUP_$_";7125    Result  += CDecl->getName(); Result += ",\n";7126  }7127  Result += "};\n";7128}7129 7130void RewriteModernObjC::RewriteMetaDataIntoBuffer(std::string &Result) {7131  int ClsDefCount = ClassImplementation.size();7132  int CatDefCount = CategoryImplementation.size();7133 7134  // For each implemented class, write out all its meta data.7135  for (int i = 0; i < ClsDefCount; i++)7136    RewriteObjCClassMetaData(ClassImplementation[i], Result);7137 7138  RewriteClassSetupInitHook(Result);7139 7140  // For each implemented category, write out all its meta data.7141  for (int i = 0; i < CatDefCount; i++)7142    RewriteObjCCategoryImplDecl(CategoryImplementation[i], Result);7143 7144  RewriteCategorySetupInitHook(Result);7145 7146  if (ClsDefCount > 0) {7147    if (LangOpts.MicrosoftExt)7148      Result += "__declspec(allocate(\".objc_classlist$B\")) ";7149    Result += "static struct _class_t *L_OBJC_LABEL_CLASS_$ [";7150    Result += llvm::utostr(ClsDefCount); Result += "]";7151    Result +=7152      " __attribute__((used, section (\"__DATA, __objc_classlist,"7153      "regular,no_dead_strip\")))= {\n";7154    for (int i = 0; i < ClsDefCount; i++) {7155      Result += "\t&OBJC_CLASS_$_";7156      Result += ClassImplementation[i]->getNameAsString();7157      Result += ",\n";7158    }7159    Result += "};\n";7160 7161    if (!DefinedNonLazyClasses.empty()) {7162      if (LangOpts.MicrosoftExt)7163        Result += "__declspec(allocate(\".objc_nlclslist$B\")) \n";7164      Result += "static struct _class_t *_OBJC_LABEL_NONLAZY_CLASS_$[] = {\n\t";7165      for (unsigned i = 0, e = DefinedNonLazyClasses.size(); i < e; i++) {7166        Result += "\t&OBJC_CLASS_$_"; Result += DefinedNonLazyClasses[i]->getNameAsString();7167        Result += ",\n";7168      }7169      Result += "};\n";7170    }7171  }7172 7173  if (CatDefCount > 0) {7174    if (LangOpts.MicrosoftExt)7175      Result += "__declspec(allocate(\".objc_catlist$B\")) ";7176    Result += "static struct _category_t *L_OBJC_LABEL_CATEGORY_$ [";7177    Result += llvm::utostr(CatDefCount); Result += "]";7178    Result +=7179    " __attribute__((used, section (\"__DATA, __objc_catlist,"7180    "regular,no_dead_strip\")))= {\n";7181    for (int i = 0; i < CatDefCount; i++) {7182      Result += "\t&_OBJC_$_CATEGORY_";7183      Result +=7184        CategoryImplementation[i]->getClassInterface()->getNameAsString();7185      Result += "_$_";7186      Result += CategoryImplementation[i]->getNameAsString();7187      Result += ",\n";7188    }7189    Result += "};\n";7190  }7191 7192  if (!DefinedNonLazyCategories.empty()) {7193    if (LangOpts.MicrosoftExt)7194      Result += "__declspec(allocate(\".objc_nlcatlist$B\")) \n";7195    Result += "static struct _category_t *_OBJC_LABEL_NONLAZY_CATEGORY_$[] = {\n\t";7196    for (unsigned i = 0, e = DefinedNonLazyCategories.size(); i < e; i++) {7197      Result += "\t&_OBJC_$_CATEGORY_";7198      Result +=7199        DefinedNonLazyCategories[i]->getClassInterface()->getNameAsString();7200      Result += "_$_";7201      Result += DefinedNonLazyCategories[i]->getNameAsString();7202      Result += ",\n";7203    }7204    Result += "};\n";7205  }7206}7207 7208void RewriteModernObjC::WriteImageInfo(std::string &Result) {7209  if (LangOpts.MicrosoftExt)7210    Result += "__declspec(allocate(\".objc_imageinfo$B\")) \n";7211 7212  Result += "static struct IMAGE_INFO { unsigned version; unsigned flag; } ";7213  // version 0, ObjCABI is 27214  Result += "_OBJC_IMAGE_INFO = { 0, 2 };\n";7215}7216 7217/// RewriteObjCCategoryImplDecl - Rewrite metadata for each category7218/// implementation.7219void RewriteModernObjC::RewriteObjCCategoryImplDecl(ObjCCategoryImplDecl *IDecl,7220                                              std::string &Result) {7221  WriteModernMetadataDeclarations(Context, Result);7222  ObjCInterfaceDecl *ClassDecl = IDecl->getClassInterface();7223  // Find category declaration for this implementation.7224  ObjCCategoryDecl *CDecl7225    = ClassDecl->FindCategoryDeclaration(IDecl->getIdentifier());7226 7227  std::string FullCategoryName = ClassDecl->getNameAsString();7228  FullCategoryName += "_$_";7229  FullCategoryName += CDecl->getNameAsString();7230 7231  // Build _objc_method_list for class's instance methods if needed7232  SmallVector<ObjCMethodDecl *, 32> InstanceMethods(IDecl->instance_methods());7233 7234  // If any of our property implementations have associated getters or7235  // setters, produce metadata for them as well.7236  for (const auto *Prop : IDecl->property_impls()) {7237    if (Prop->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic)7238      continue;7239    if (!Prop->getPropertyIvarDecl())7240      continue;7241    ObjCPropertyDecl *PD = Prop->getPropertyDecl();7242    if (!PD)7243      continue;7244    if (ObjCMethodDecl *Getter = Prop->getGetterMethodDecl())7245      InstanceMethods.push_back(Getter);7246    if (PD->isReadOnly())7247      continue;7248    if (ObjCMethodDecl *Setter = Prop->getSetterMethodDecl())7249      InstanceMethods.push_back(Setter);7250  }7251 7252  Write_method_list_t_initializer(*this, Context, Result, InstanceMethods,7253                                  "_OBJC_$_CATEGORY_INSTANCE_METHODS_",7254                                  FullCategoryName, true);7255 7256  SmallVector<ObjCMethodDecl *, 32> ClassMethods(IDecl->class_methods());7257 7258  Write_method_list_t_initializer(*this, Context, Result, ClassMethods,7259                                  "_OBJC_$_CATEGORY_CLASS_METHODS_",7260                                  FullCategoryName, true);7261 7262  // Protocols referenced in class declaration?7263  // Protocol's super protocol list7264  SmallVector<ObjCProtocolDecl *, 8> RefedProtocols(CDecl->protocols());7265  for (auto *I : CDecl->protocols())7266    // Must write out all protocol definitions in current qualifier list,7267    // and in their nested qualifiers before writing out current definition.7268    RewriteObjCProtocolMetaData(I, Result);7269 7270  Write_protocol_list_initializer(Context, Result,7271                                  RefedProtocols,7272                                  "_OBJC_CATEGORY_PROTOCOLS_$_",7273                                  FullCategoryName);7274 7275  // Protocol's property metadata.7276  SmallVector<ObjCPropertyDecl *, 8> ClassProperties(7277      CDecl->instance_properties());7278  Write_prop_list_t_initializer(*this, Context, Result, ClassProperties,7279                                /* Container */IDecl,7280                                "_OBJC_$_PROP_LIST_",7281                                FullCategoryName);7282 7283  Write_category_t(*this, Context, Result,7284                   CDecl,7285                   ClassDecl,7286                   InstanceMethods,7287                   ClassMethods,7288                   RefedProtocols,7289                   ClassProperties);7290 7291  // Determine if this category is also "non-lazy".7292  if (ImplementationIsNonLazy(IDecl))7293    DefinedNonLazyCategories.push_back(CDecl);7294}7295 7296void RewriteModernObjC::RewriteCategorySetupInitHook(std::string &Result) {7297  int CatDefCount = CategoryImplementation.size();7298  if (!CatDefCount)7299    return;7300  Result += "#pragma section(\".objc_inithooks$B\", long, read, write)\n";7301  Result += "__declspec(allocate(\".objc_inithooks$B\")) ";7302  Result += "static void *OBJC_CATEGORY_SETUP[] = {\n";7303  for (int i = 0; i < CatDefCount; i++) {7304    ObjCCategoryImplDecl *IDecl = CategoryImplementation[i];7305    ObjCCategoryDecl *CatDecl= IDecl->getCategoryDecl();7306    ObjCInterfaceDecl *ClassDecl = IDecl->getClassInterface();7307    Result += "\t(void *)&OBJC_CATEGORY_SETUP_$_";7308    Result += ClassDecl->getName();7309    Result += "_$_";7310    Result += CatDecl->getName();7311    Result += ",\n";7312  }7313  Result += "};\n";7314}7315 7316// RewriteObjCMethodsMetaData - Rewrite methods metadata for instance or7317/// class methods.7318template<typename MethodIterator>7319void RewriteModernObjC::RewriteObjCMethodsMetaData(MethodIterator MethodBegin,7320                                             MethodIterator MethodEnd,7321                                             bool IsInstanceMethod,7322                                             StringRef prefix,7323                                             StringRef ClassName,7324                                             std::string &Result) {7325  if (MethodBegin == MethodEnd) return;7326 7327  if (!objc_impl_method) {7328    /* struct _objc_method {7329     SEL _cmd;7330     char *method_types;7331     void *_imp;7332     }7333     */7334    Result += "\nstruct _objc_method {\n";7335    Result += "\tSEL _cmd;\n";7336    Result += "\tchar *method_types;\n";7337    Result += "\tvoid *_imp;\n";7338    Result += "};\n";7339 7340    objc_impl_method = true;7341  }7342 7343  // Build _objc_method_list for class's methods if needed7344 7345  /* struct  {7346   struct _objc_method_list *next_method;7347   int method_count;7348   struct _objc_method method_list[];7349   }7350   */7351  unsigned NumMethods = std::distance(MethodBegin, MethodEnd);7352  Result += "\n";7353  if (LangOpts.MicrosoftExt) {7354    if (IsInstanceMethod)7355      Result += "__declspec(allocate(\".inst_meth$B\")) ";7356    else7357      Result += "__declspec(allocate(\".cls_meth$B\")) ";7358  }7359  Result += "static struct {\n";7360  Result += "\tstruct _objc_method_list *next_method;\n";7361  Result += "\tint method_count;\n";7362  Result += "\tstruct _objc_method method_list[";7363  Result += utostr(NumMethods);7364  Result += "];\n} _OBJC_";7365  Result += prefix;7366  Result += IsInstanceMethod ? "INSTANCE" : "CLASS";7367  Result += "_METHODS_";7368  Result += ClassName;7369  Result += " __attribute__ ((used, section (\"__OBJC, __";7370  Result += IsInstanceMethod ? "inst" : "cls";7371  Result += "_meth\")))= ";7372  Result += "{\n\t0, " + utostr(NumMethods) + "\n";7373 7374  Result += "\t,{{(SEL)\"";7375  Result += (*MethodBegin)->getSelector().getAsString().c_str();7376  std::string MethodTypeString;7377  Context->getObjCEncodingForMethodDecl(*MethodBegin, MethodTypeString);7378  Result += "\", \"";7379  Result += MethodTypeString;7380  Result += "\", (void *)";7381  Result += MethodInternalNames[*MethodBegin];7382  Result += "}\n";7383  for (++MethodBegin; MethodBegin != MethodEnd; ++MethodBegin) {7384    Result += "\t  ,{(SEL)\"";7385    Result += (*MethodBegin)->getSelector().getAsString().c_str();7386    std::string MethodTypeString;7387    Context->getObjCEncodingForMethodDecl(*MethodBegin, MethodTypeString);7388    Result += "\", \"";7389    Result += MethodTypeString;7390    Result += "\", (void *)";7391    Result += MethodInternalNames[*MethodBegin];7392    Result += "}\n";7393  }7394  Result += "\t }\n};\n";7395}7396 7397Stmt *RewriteModernObjC::RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV) {7398  SourceRange OldRange = IV->getSourceRange();7399  Expr *BaseExpr = IV->getBase();7400 7401  // Rewrite the base, but without actually doing replaces.7402  {7403    DisableReplaceStmtScope S(*this);7404    BaseExpr = cast<Expr>(RewriteFunctionBodyOrGlobalInitializer(BaseExpr));7405    IV->setBase(BaseExpr);7406  }7407 7408  ObjCIvarDecl *D = IV->getDecl();7409 7410  Expr *Replacement = IV;7411 7412    if (BaseExpr->getType()->isObjCObjectPointerType()) {7413      const ObjCInterfaceType *iFaceDecl =7414        dyn_cast<ObjCInterfaceType>(BaseExpr->getType()->getPointeeType());7415      assert(iFaceDecl && "RewriteObjCIvarRefExpr - iFaceDecl is null");7416      // lookup which class implements the instance variable.7417      ObjCInterfaceDecl *clsDeclared = nullptr;7418      iFaceDecl->getDecl()->lookupInstanceVariable(D->getIdentifier(),7419                                                   clsDeclared);7420      assert(clsDeclared && "RewriteObjCIvarRefExpr(): Can't find class");7421 7422      // Build name of symbol holding ivar offset.7423      std::string IvarOffsetName;7424      if (D->isBitField())7425        ObjCIvarBitfieldGroupOffset(D, IvarOffsetName);7426      else7427        WriteInternalIvarName(clsDeclared, D, IvarOffsetName);7428 7429      ReferencedIvars[clsDeclared].insert(D);7430 7431      // cast offset to "char *".7432      CastExpr *castExpr = NoTypeInfoCStyleCastExpr(Context,7433                                                    Context->getPointerType(Context->CharTy),7434                                                    CK_BitCast,7435                                                    BaseExpr);7436      VarDecl *NewVD = VarDecl::Create(*Context, TUDecl, SourceLocation(),7437                                       SourceLocation(), &Context->Idents.get(IvarOffsetName),7438                                       Context->UnsignedLongTy, nullptr,7439                                       SC_Extern);7440      DeclRefExpr *DRE = new (Context)7441          DeclRefExpr(*Context, NewVD, false, Context->UnsignedLongTy,7442                      VK_LValue, SourceLocation());7443      BinaryOperator *addExpr = BinaryOperator::Create(7444          *Context, castExpr, DRE, BO_Add,7445          Context->getPointerType(Context->CharTy), VK_PRValue, OK_Ordinary,7446          SourceLocation(), FPOptionsOverride());7447      // Don't forget the parens to enforce the proper binding.7448      ParenExpr *PE = new (Context) ParenExpr(SourceLocation(),7449                                              SourceLocation(),7450                                              addExpr);7451      QualType IvarT = D->getType();7452      if (D->isBitField())7453        IvarT = GetGroupRecordTypeForObjCIvarBitfield(D);7454 7455      if (!IvarT->getAs<TypedefType>() && IvarT->isRecordType()) {7456        RecordDecl *RD = IvarT->castAsCanonical<RecordType>()->getDecl();7457        RD = RD->getDefinition();7458        if (RD && !RD->getDeclName().getAsIdentifierInfo()) {7459          // decltype(((Foo_IMPL*)0)->bar) *7460          auto *CDecl = cast<ObjCContainerDecl>(D->getDeclContext());7461          // ivar in class extensions requires special treatment.7462          if (ObjCCategoryDecl *CatDecl = dyn_cast<ObjCCategoryDecl>(CDecl))7463            CDecl = CatDecl->getClassInterface();7464          std::string RecName = std::string(CDecl->getName());7465          RecName += "_IMPL";7466          RecordDecl *RD = RecordDecl::Create(7467              *Context, TagTypeKind::Struct, TUDecl, SourceLocation(),7468              SourceLocation(), &Context->Idents.get(RecName));7469          QualType PtrStructIMPL =7470              Context->getPointerType(Context->getCanonicalTagType(RD));7471          unsigned UnsignedIntSize =7472            static_cast<unsigned>(Context->getTypeSize(Context->UnsignedIntTy));7473          Expr *Zero = IntegerLiteral::Create(*Context,7474                                              llvm::APInt(UnsignedIntSize, 0),7475                                              Context->UnsignedIntTy, SourceLocation());7476          Zero = NoTypeInfoCStyleCastExpr(Context, PtrStructIMPL, CK_BitCast, Zero);7477          ParenExpr *PE = new (Context) ParenExpr(SourceLocation(), SourceLocation(),7478                                                  Zero);7479          FieldDecl *FD = FieldDecl::Create(*Context, nullptr, SourceLocation(),7480                                            SourceLocation(),7481                                            &Context->Idents.get(D->getNameAsString()),7482                                            IvarT, nullptr,7483                                            /*BitWidth=*/nullptr,7484                                            /*Mutable=*/true, ICIS_NoInit);7485          MemberExpr *ME = MemberExpr::CreateImplicit(7486              *Context, PE, true, FD, FD->getType(), VK_LValue, OK_Ordinary);7487          IvarT = Context->getDecltypeType(ME, ME->getType());7488        }7489      }7490      convertObjCTypeToCStyleType(IvarT);7491      QualType castT = Context->getPointerType(IvarT);7492 7493      castExpr = NoTypeInfoCStyleCastExpr(Context,7494                                          castT,7495                                          CK_BitCast,7496                                          PE);7497 7498      Expr *Exp = UnaryOperator::Create(7499          const_cast<ASTContext &>(*Context), castExpr, UO_Deref, IvarT,7500          VK_LValue, OK_Ordinary, SourceLocation(), false, FPOptionsOverride());7501      PE = new (Context) ParenExpr(OldRange.getBegin(),7502                                   OldRange.getEnd(),7503                                   Exp);7504 7505      if (D->isBitField()) {7506        FieldDecl *FD = FieldDecl::Create(*Context, nullptr, SourceLocation(),7507                                          SourceLocation(),7508                                          &Context->Idents.get(D->getNameAsString()),7509                                          D->getType(), nullptr,7510                                          /*BitWidth=*/D->getBitWidth(),7511                                          /*Mutable=*/true, ICIS_NoInit);7512        MemberExpr *ME =7513            MemberExpr::CreateImplicit(*Context, PE, /*isArrow*/ false, FD,7514                                       FD->getType(), VK_LValue, OK_Ordinary);7515        Replacement = ME;7516 7517      }7518      else7519        Replacement = PE;7520    }7521 7522    ReplaceStmtWithRange(IV, Replacement, OldRange);7523    return Replacement;7524}7525 7526#endif // CLANG_ENABLE_OBJC_REWRITER7527