Path: blob/main/contrib/llvm-project/clang/lib/Frontend/Rewrite/RewriteModernObjC.cpp
35266 views
//===-- RewriteModernObjC.cpp - Playground for the code rewriter ----------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// Hacks and fun related to the code rewriter.9//10//===----------------------------------------------------------------------===//1112#include "clang/Rewrite/Frontend/ASTConsumers.h"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 "llvm/ADT/DenseSet.h"26#include "llvm/ADT/SetVector.h"27#include "llvm/ADT/SmallPtrSet.h"28#include "llvm/ADT/StringExtras.h"29#include "llvm/Support/MemoryBuffer.h"30#include "llvm/Support/raw_ostream.h"31#include <memory>3233#if CLANG_ENABLE_OBJC_REWRITER3435using namespace clang;36using llvm::utostr;3738namespace {39class RewriteModernObjC : public ASTConsumer {40protected:4142enum {43BLOCK_FIELD_IS_OBJECT = 3, /* id, NSObject, __attribute__((NSObject)),44block, ... */45BLOCK_FIELD_IS_BLOCK = 7, /* a block variable */46BLOCK_FIELD_IS_BYREF = 8, /* the on stack structure holding the47__block variable */48BLOCK_FIELD_IS_WEAK = 16, /* declared __weak, only used in byref copy49helpers */50BLOCK_BYREF_CALLER = 128, /* called from __block (byref) copy/dispose51support routines */52BLOCK_BYREF_CURRENT_MAX = 25653};5455enum {56BLOCK_NEEDS_FREE = (1 << 24),57BLOCK_HAS_COPY_DISPOSE = (1 << 25),58BLOCK_HAS_CXX_OBJ = (1 << 26),59BLOCK_IS_GC = (1 << 27),60BLOCK_IS_GLOBAL = (1 << 28),61BLOCK_HAS_DESCRIPTOR = (1 << 29)62};6364Rewriter Rewrite;65DiagnosticsEngine &Diags;66const LangOptions &LangOpts;67ASTContext *Context;68SourceManager *SM;69TranslationUnitDecl *TUDecl;70FileID MainFileID;71const char *MainFileStart, *MainFileEnd;72Stmt *CurrentBody;73ParentMap *PropParentMap; // created lazily.74std::string InFileName;75std::unique_ptr<raw_ostream> OutFile;76std::string Preamble;7778TypeDecl *ProtocolTypeDecl;79VarDecl *GlobalVarDecl;80Expr *GlobalConstructionExp;81unsigned RewriteFailedDiag;82unsigned GlobalBlockRewriteFailedDiag;83// ObjC string constant support.84unsigned NumObjCStringLiterals;85VarDecl *ConstantStringClassReference;86RecordDecl *NSStringRecord;8788// ObjC foreach break/continue generation support.89int BcLabelCount;9091unsigned TryFinallyContainsReturnDiag;92// Needed for super.93ObjCMethodDecl *CurMethodDef;94RecordDecl *SuperStructDecl;95RecordDecl *ConstantStringDecl;9697FunctionDecl *MsgSendFunctionDecl;98FunctionDecl *MsgSendSuperFunctionDecl;99FunctionDecl *MsgSendStretFunctionDecl;100FunctionDecl *MsgSendSuperStretFunctionDecl;101FunctionDecl *MsgSendFpretFunctionDecl;102FunctionDecl *GetClassFunctionDecl;103FunctionDecl *GetMetaClassFunctionDecl;104FunctionDecl *GetSuperClassFunctionDecl;105FunctionDecl *SelGetUidFunctionDecl;106FunctionDecl *CFStringFunctionDecl;107FunctionDecl *SuperConstructorFunctionDecl;108FunctionDecl *CurFunctionDef;109110/* Misc. containers needed for meta-data rewrite. */111SmallVector<ObjCImplementationDecl *, 8> ClassImplementation;112SmallVector<ObjCCategoryImplDecl *, 8> CategoryImplementation;113llvm::SmallPtrSet<ObjCInterfaceDecl*, 8> ObjCSynthesizedStructs;114llvm::SmallPtrSet<ObjCProtocolDecl*, 8> ObjCSynthesizedProtocols;115llvm::SmallPtrSet<ObjCInterfaceDecl*, 8> ObjCWrittenInterfaces;116llvm::SmallPtrSet<TagDecl*, 32> GlobalDefinedTags;117SmallVector<ObjCInterfaceDecl*, 32> ObjCInterfacesSeen;118/// DefinedNonLazyClasses - List of defined "non-lazy" classes.119SmallVector<ObjCInterfaceDecl*, 8> DefinedNonLazyClasses;120121/// DefinedNonLazyCategories - List of defined "non-lazy" categories.122SmallVector<ObjCCategoryDecl *, 8> DefinedNonLazyCategories;123124SmallVector<Stmt *, 32> Stmts;125SmallVector<int, 8> ObjCBcLabelNo;126// Remember all the @protocol(<expr>) expressions.127llvm::SmallPtrSet<ObjCProtocolDecl *, 32> ProtocolExprDecls;128129llvm::DenseSet<uint64_t> CopyDestroyCache;130131// Block expressions.132SmallVector<BlockExpr *, 32> Blocks;133SmallVector<int, 32> InnerDeclRefsCount;134SmallVector<DeclRefExpr *, 32> InnerDeclRefs;135136SmallVector<DeclRefExpr *, 32> BlockDeclRefs;137138// Block related declarations.139SmallVector<ValueDecl *, 8> BlockByCopyDecls;140llvm::SmallPtrSet<ValueDecl *, 8> BlockByCopyDeclsPtrSet;141SmallVector<ValueDecl *, 8> BlockByRefDecls;142llvm::SmallPtrSet<ValueDecl *, 8> BlockByRefDeclsPtrSet;143llvm::DenseMap<ValueDecl *, unsigned> BlockByRefDeclNo;144llvm::SmallPtrSet<ValueDecl *, 8> ImportedBlockDecls;145llvm::SmallPtrSet<VarDecl *, 8> ImportedLocalExternalDecls;146147llvm::DenseMap<BlockExpr *, std::string> RewrittenBlockExprs;148llvm::DenseMap<ObjCInterfaceDecl *,149llvm::SmallSetVector<ObjCIvarDecl *, 8> > ReferencedIvars;150151// ivar bitfield grouping containers152llvm::DenseSet<const ObjCInterfaceDecl *> ObjCInterefaceHasBitfieldGroups;153llvm::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.156llvm::DenseMap<std::pair<const ObjCInterfaceDecl*, unsigned>, QualType> GroupRecordType;157SmallVector<FunctionDecl*, 32> FunctionDefinitionsSeen;158159// 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.162llvm::DenseMap<Stmt *, Stmt *> ReplacedNodes;163164// Needed for header files being rewritten165bool IsHeader;166bool SilenceRewriteMacroWarning;167bool GenerateLineInfo;168bool objc_impl_method;169170bool DisableReplaceStmt;171class DisableReplaceStmtScope {172RewriteModernObjC &R;173bool SavedValue;174175public:176DisableReplaceStmtScope(RewriteModernObjC &R)177: R(R), SavedValue(R.DisableReplaceStmt) {178R.DisableReplaceStmt = true;179}180~DisableReplaceStmtScope() {181R.DisableReplaceStmt = SavedValue;182}183};184void InitializeCommon(ASTContext &context);185186public:187llvm::DenseMap<ObjCMethodDecl*, std::string> MethodInternalNames;188189// Top Level Driver code.190bool HandleTopLevelDecl(DeclGroupRef D) override {191for (DeclGroupRef::iterator I = D.begin(), E = D.end(); I != E; ++I) {192if (ObjCInterfaceDecl *Class = dyn_cast<ObjCInterfaceDecl>(*I)) {193if (!Class->isThisDeclarationADefinition()) {194RewriteForwardClassDecl(D);195break;196} else {197// Keep track of all interface declarations seen.198ObjCInterfacesSeen.push_back(Class);199break;200}201}202203if (ObjCProtocolDecl *Proto = dyn_cast<ObjCProtocolDecl>(*I)) {204if (!Proto->isThisDeclarationADefinition()) {205RewriteForwardProtocolDecl(D);206break;207}208}209210if (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.215if (FDecl->isThisDeclarationADefinition() &&216// Not c functions defined inside an objc container.217!FDecl->isTopLevelDeclInObjCContainer()) {218FunctionDefinitionsSeen.push_back(FDecl);219break;220}221}222HandleTopLevelSingleDecl(*I);223}224return true;225}226227void HandleTopLevelDeclInObjCContainer(DeclGroupRef D) override {228for (DeclGroupRef::iterator I = D.begin(), E = D.end(); I != E; ++I) {229if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(*I)) {230if (isTopLevelBlockPointerType(TD->getUnderlyingType()))231RewriteBlockPointerDecl(TD);232else if (TD->getUnderlyingType()->isFunctionPointerType())233CheckFunctionPointerDecl(TD->getUnderlyingType(), TD);234else235RewriteObjCQualifiedInterfaceTypes(TD);236}237}238}239240void HandleTopLevelSingleDecl(Decl *D);241void HandleDeclInMainFile(Decl *D);242RewriteModernObjC(std::string inFile, std::unique_ptr<raw_ostream> OS,243DiagnosticsEngine &D, const LangOptions &LOpts,244bool silenceMacroWarn, bool LineInfo);245246~RewriteModernObjC() override {}247248void HandleTranslationUnit(ASTContext &C) override;249250void ReplaceStmt(Stmt *Old, Stmt *New) {251ReplaceStmtWithRange(Old, New, Old->getSourceRange());252}253254void ReplaceStmtWithRange(Stmt *Old, Stmt *New, SourceRange SrcRange) {255assert(Old != nullptr && New != nullptr && "Expected non-null Stmt's");256257Stmt *ReplacingStmt = ReplacedNodes[Old];258if (ReplacingStmt)259return; // We can't rewrite the same node twice.260261if (DisableReplaceStmt)262return;263264// Measure the old text.265int Size = Rewrite.getRangeSize(SrcRange);266if (Size == -1) {267Diags.Report(Context->getFullLoc(Old->getBeginLoc()), RewriteFailedDiag)268<< Old->getSourceRange();269return;270}271// Get the new text.272std::string SStr;273llvm::raw_string_ostream S(SStr);274New->printPretty(S, nullptr, PrintingPolicy(LangOpts));275276// If replacement succeeded or warning disabled return with no warning.277if (!Rewrite.ReplaceText(SrcRange.getBegin(), Size, SStr)) {278ReplacedNodes[Old] = New;279return;280}281if (SilenceRewriteMacroWarning)282return;283Diags.Report(Context->getFullLoc(Old->getBeginLoc()), RewriteFailedDiag)284<< Old->getSourceRange();285}286287void InsertText(SourceLocation Loc, StringRef Str,288bool InsertAfter = true) {289// If insertion succeeded or warning disabled return with no warning.290if (!Rewrite.InsertText(Loc, Str, InsertAfter) ||291SilenceRewriteMacroWarning)292return;293294Diags.Report(Context->getFullLoc(Loc), RewriteFailedDiag);295}296297void ReplaceText(SourceLocation Start, unsigned OrigLength,298StringRef Str) {299// If removal succeeded or warning disabled return with no warning.300if (!Rewrite.ReplaceText(Start, OrigLength, Str) ||301SilenceRewriteMacroWarning)302return;303304Diags.Report(Context->getFullLoc(Start), RewriteFailedDiag);305}306307// Syntactic Rewriting.308void RewriteRecordBody(RecordDecl *RD);309void RewriteInclude();310void RewriteLineDirective(const Decl *D);311void ConvertSourceLocationToLineDirective(SourceLocation Loc,312std::string &LineString);313void RewriteForwardClassDecl(DeclGroupRef D);314void RewriteForwardClassDecl(const SmallVectorImpl<Decl *> &DG);315void RewriteForwardClassEpilogue(ObjCInterfaceDecl *ClassDecl,316const std::string &typedefString);317void RewriteImplementations();318void RewritePropertyImplDecl(ObjCPropertyImplDecl *PID,319ObjCImplementationDecl *IMD,320ObjCCategoryImplDecl *CID);321void RewriteInterfaceDecl(ObjCInterfaceDecl *Dcl);322void RewriteImplementationDecl(Decl *Dcl);323void RewriteObjCMethodDecl(const ObjCInterfaceDecl *IDecl,324ObjCMethodDecl *MDecl, std::string &ResultStr);325void RewriteTypeIntoString(QualType T, std::string &ResultStr,326const FunctionType *&FPRetType);327void RewriteByRefString(std::string &ResultStr, const std::string &Name,328ValueDecl *VD, bool def=false);329void RewriteCategoryDecl(ObjCCategoryDecl *Dcl);330void RewriteProtocolDecl(ObjCProtocolDecl *Dcl);331void RewriteForwardProtocolDecl(DeclGroupRef D);332void RewriteForwardProtocolDecl(const SmallVectorImpl<Decl *> &DG);333void RewriteMethodDeclaration(ObjCMethodDecl *Method);334void RewriteProperty(ObjCPropertyDecl *prop);335void RewriteFunctionDecl(FunctionDecl *FD);336void RewriteBlockPointerType(std::string& Str, QualType Type);337void RewriteBlockPointerTypeVariable(std::string& Str, ValueDecl *VD);338void RewriteBlockLiteralFunctionDecl(FunctionDecl *FD);339void RewriteObjCQualifiedInterfaceTypes(Decl *Dcl);340void RewriteTypeOfDecl(VarDecl *VD);341void RewriteObjCQualifiedInterfaceTypes(Expr *E);342343std::string getIvarAccessString(ObjCIvarDecl *D);344345// Expression Rewriting.346Stmt *RewriteFunctionBodyOrGlobalInitializer(Stmt *S);347Stmt *RewriteAtEncode(ObjCEncodeExpr *Exp);348Stmt *RewritePropertyOrImplicitGetter(PseudoObjectExpr *Pseudo);349Stmt *RewritePropertyOrImplicitSetter(PseudoObjectExpr *Pseudo);350Stmt *RewriteAtSelector(ObjCSelectorExpr *Exp);351Stmt *RewriteMessageExpr(ObjCMessageExpr *Exp);352Stmt *RewriteObjCStringLiteral(ObjCStringLiteral *Exp);353Stmt *RewriteObjCBoolLiteralExpr(ObjCBoolLiteralExpr *Exp);354Stmt *RewriteObjCBoxedExpr(ObjCBoxedExpr *Exp);355Stmt *RewriteObjCArrayLiteralExpr(ObjCArrayLiteral *Exp);356Stmt *RewriteObjCDictionaryLiteralExpr(ObjCDictionaryLiteral *Exp);357Stmt *RewriteObjCProtocolExpr(ObjCProtocolExpr *Exp);358Stmt *RewriteObjCTryStmt(ObjCAtTryStmt *S);359Stmt *RewriteObjCAutoreleasePoolStmt(ObjCAutoreleasePoolStmt *S);360Stmt *RewriteObjCSynchronizedStmt(ObjCAtSynchronizedStmt *S);361Stmt *RewriteObjCThrowStmt(ObjCAtThrowStmt *S);362Stmt *RewriteObjCForCollectionStmt(ObjCForCollectionStmt *S,363SourceLocation OrigEnd);364Stmt *RewriteBreakStmt(BreakStmt *S);365Stmt *RewriteContinueStmt(ContinueStmt *S);366void RewriteCastExpr(CStyleCastExpr *CE);367void RewriteImplicitCastObjCExpr(CastExpr *IE);368369// Computes ivar bitfield group no.370unsigned ObjCIvarBitfieldGroupNo(ObjCIvarDecl *IV);371// Names field decl. for ivar bitfield group.372void ObjCIvarBitfieldGroupDecl(ObjCIvarDecl *IV, std::string &Result);373// Names struct type for ivar bitfield group.374void ObjCIvarBitfieldGroupType(ObjCIvarDecl *IV, std::string &Result);375// Names symbol for ivar bitfield group field offset.376void ObjCIvarBitfieldGroupOffset(ObjCIvarDecl *IV, std::string &Result);377// Given an ivar bitfield, it builds (or finds) its group record type.378QualType GetGroupRecordTypeForObjCIvarBitfield(ObjCIvarDecl *IV);379QualType SynthesizeBitfieldGroupStructType(380ObjCIvarDecl *IV,381SmallVectorImpl<ObjCIvarDecl *> &IVars);382383// Block rewriting.384void RewriteBlocksInFunctionProtoType(QualType funcType, NamedDecl *D);385386// Block specific rewrite rules.387void RewriteBlockPointerDecl(NamedDecl *VD);388void RewriteByRefVar(VarDecl *VD, bool firstDecl, bool lastDecl);389Stmt *RewriteBlockDeclRefExpr(DeclRefExpr *VD);390Stmt *RewriteLocalVariableExternalStorage(DeclRefExpr *DRE);391void RewriteBlockPointerFunctionArgs(FunctionDecl *FD);392393void RewriteObjCInternalStruct(ObjCInterfaceDecl *CDecl,394std::string &Result);395396void RewriteObjCFieldDecl(FieldDecl *fieldDecl, std::string &Result);397bool IsTagDefinedInsideClass(ObjCContainerDecl *IDecl, TagDecl *Tag,398bool &IsNamedDefinition);399void RewriteLocallyDefinedNamedAggregates(FieldDecl *fieldDecl,400std::string &Result);401402bool RewriteObjCFieldDeclType(QualType &Type, std::string &Result);403404void RewriteIvarOffsetSymbols(ObjCInterfaceDecl *CDecl,405std::string &Result);406407void Initialize(ASTContext &context) override;408409// Misc. AST transformation routines. Sometimes they end up calling410// rewriting routines on the new ASTs.411CallExpr *SynthesizeCallToFunctionDecl(FunctionDecl *FD,412ArrayRef<Expr *> Args,413SourceLocation StartLoc=SourceLocation(),414SourceLocation EndLoc=SourceLocation());415416Expr *SynthMsgSendStretCallExpr(FunctionDecl *MsgSendStretFlavor,417QualType returnType,418SmallVectorImpl<QualType> &ArgTypes,419SmallVectorImpl<Expr*> &MsgExprs,420ObjCMethodDecl *Method);421422Stmt *SynthMessageExpr(ObjCMessageExpr *Exp,423SourceLocation StartLoc=SourceLocation(),424SourceLocation EndLoc=SourceLocation());425426void SynthCountByEnumWithState(std::string &buf);427void SynthMsgSendFunctionDecl();428void SynthMsgSendSuperFunctionDecl();429void SynthMsgSendStretFunctionDecl();430void SynthMsgSendFpretFunctionDecl();431void SynthMsgSendSuperStretFunctionDecl();432void SynthGetClassFunctionDecl();433void SynthGetMetaClassFunctionDecl();434void SynthGetSuperClassFunctionDecl();435void SynthSelGetUidFunctionDecl();436void SynthSuperConstructorFunctionDecl();437438// Rewriting metadata439template<typename MethodIterator>440void RewriteObjCMethodsMetaData(MethodIterator MethodBegin,441MethodIterator MethodEnd,442bool IsInstanceMethod,443StringRef prefix,444StringRef ClassName,445std::string &Result);446void RewriteObjCProtocolMetaData(ObjCProtocolDecl *Protocol,447std::string &Result);448void RewriteObjCClassMetaData(ObjCImplementationDecl *IDecl,449std::string &Result);450void RewriteClassSetupInitHook(std::string &Result);451452void RewriteMetaDataIntoBuffer(std::string &Result);453void WriteImageInfo(std::string &Result);454void RewriteObjCCategoryImplDecl(ObjCCategoryImplDecl *CDecl,455std::string &Result);456void RewriteCategorySetupInitHook(std::string &Result);457458// Rewriting ivar459void RewriteIvarOffsetComputation(ObjCIvarDecl *ivar,460std::string &Result);461Stmt *RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV);462463464std::string SynthesizeByrefCopyDestroyHelper(VarDecl *VD, int flag);465std::string SynthesizeBlockHelperFuncs(BlockExpr *CE, int i,466StringRef funcName,467const std::string &Tag);468std::string SynthesizeBlockFunc(BlockExpr *CE, int i, StringRef funcName,469const std::string &Tag);470std::string SynthesizeBlockImpl(BlockExpr *CE, const std::string &Tag,471const std::string &Desc);472std::string SynthesizeBlockDescriptor(const std::string &DescTag,473const std::string &ImplTag, int i,474StringRef funcName, unsigned hasCopy);475Stmt *SynthesizeBlockCall(CallExpr *Exp, const Expr* BlockExp);476void SynthesizeBlockLiterals(SourceLocation FunLocStart,477StringRef FunName);478FunctionDecl *SynthBlockInitFunctionDecl(StringRef name);479Stmt *SynthBlockInitExpr(BlockExpr *Exp,480const SmallVectorImpl<DeclRefExpr *> &InnerBlockDeclRefs);481482// Misc. helper routines.483QualType getProtocolType();484void WarnAboutReturnGotoStmts(Stmt *S);485void CheckFunctionPointerDecl(QualType dType, NamedDecl *ND);486void InsertBlockLiteralsWithinFunction(FunctionDecl *FD);487void InsertBlockLiteralsWithinMethod(ObjCMethodDecl *MD);488489bool IsDeclStmtInForeachHeader(DeclStmt *DS);490void CollectBlockDeclRefInfo(BlockExpr *Exp);491void GetBlockDeclRefExprs(Stmt *S);492void GetInnerBlockDeclRefExprs(Stmt *S,493SmallVectorImpl<DeclRefExpr *> &InnerBlockDeclRefs,494llvm::SmallPtrSetImpl<const DeclContext *> &InnerContexts);495496// We avoid calling Type::isBlockPointerType(), since it operates on the497// canonical type. We only care if the top-level type is a closure pointer.498bool isTopLevelBlockPointerType(QualType T) {499return isa<BlockPointerType>(T);500}501502/// convertBlockPointerToFunctionPointer - Converts a block-pointer type503/// to a function pointer type and upon success, returns true; false504/// otherwise.505bool convertBlockPointerToFunctionPointer(QualType &T) {506if (isTopLevelBlockPointerType(T)) {507const auto *BPT = T->castAs<BlockPointerType>();508T = Context->getPointerType(BPT->getPointeeType());509return true;510}511return false;512}513514bool convertObjCTypeToCStyleType(QualType &T);515516bool needToScanForQualifiers(QualType T);517QualType getSuperStructType();518QualType getConstantStringStructType();519QualType convertFunctionTypeOfBlocks(const FunctionType *FT);520521void convertToUnqualifiedObjCType(QualType &T) {522if (T->isObjCQualifiedIdType()) {523bool isConst = T.isConstQualified();524T = isConst ? Context->getObjCIdType().withConst()525: Context->getObjCIdType();526}527else if (T->isObjCQualifiedClassType())528T = Context->getObjCClassType();529else if (T->isObjCObjectPointerType() &&530T->getPointeeType()->isObjCQualifiedInterfaceType()) {531if (const ObjCObjectPointerType * OBJPT =532T->getAsObjCInterfacePointerType()) {533const ObjCInterfaceType *IFaceT = OBJPT->getInterfaceType();534T = QualType(IFaceT, 0);535T = Context->getPointerType(T);536}537}538}539540// FIXME: This predicate seems like it would be useful to add to ASTContext.541bool isObjCType(QualType T) {542if (!LangOpts.ObjC)543return false;544545QualType OCT = Context->getCanonicalType(T).getUnqualifiedType();546547if (OCT == Context->getCanonicalType(Context->getObjCIdType()) ||548OCT == Context->getCanonicalType(Context->getObjCClassType()))549return true;550551if (const PointerType *PT = OCT->getAs<PointerType>()) {552if (isa<ObjCInterfaceType>(PT->getPointeeType()) ||553PT->getPointeeType()->isObjCQualifiedIdType())554return true;555}556return false;557}558559bool PointerTypeTakesAnyBlockArguments(QualType QT);560bool PointerTypeTakesAnyObjCQualifiedType(QualType QT);561void GetExtentOfArgList(const char *Name, const char *&LParen,562const char *&RParen);563564void QuoteDoublequotes(std::string &From, std::string &To) {565for (unsigned i = 0; i < From.length(); i++) {566if (From[i] == '"')567To += "\\\"";568else569To += From[i];570}571}572573QualType getSimpleFunctionType(QualType result,574ArrayRef<QualType> args,575bool variadic = false) {576if (result == Context->getObjCInstanceType())577result = Context->getObjCIdType();578FunctionProtoType::ExtProtoInfo fpi;579fpi.Variadic = variadic;580return Context->getFunctionType(result, args, fpi);581}582583// Helper function: create a CStyleCastExpr with trivial type source info.584CStyleCastExpr* NoTypeInfoCStyleCastExpr(ASTContext *Ctx, QualType Ty,585CastKind Kind, Expr *E) {586TypeSourceInfo *TInfo = Ctx->getTrivialTypeSourceInfo(Ty, SourceLocation());587return CStyleCastExpr::Create(*Ctx, Ty, VK_PRValue, Kind, E, nullptr,588FPOptionsOverride(), TInfo,589SourceLocation(), SourceLocation());590}591592bool ImplementationIsNonLazy(const ObjCImplDecl *OD) const {593const IdentifierInfo *II = &Context->Idents.get("load");594Selector LoadSel = Context->Selectors.getSelector(0, &II);595return OD->getClassMethod(LoadSel) != nullptr;596}597598StringLiteral *getStringLiteral(StringRef Str) {599QualType StrType = Context->getConstantArrayType(600Context->CharTy, llvm::APInt(32, Str.size() + 1), nullptr,601ArraySizeModifier::Normal, 0);602return StringLiteral::Create(*Context, Str, StringLiteralKind::Ordinary,603/*Pascal=*/false, StrType, SourceLocation());604}605};606} // end anonymous namespace607608void RewriteModernObjC::RewriteBlocksInFunctionProtoType(QualType funcType,609NamedDecl *D) {610if (const FunctionProtoType *fproto611= dyn_cast<FunctionProtoType>(funcType.IgnoreParens())) {612for (const auto &I : fproto->param_types())613if (isTopLevelBlockPointerType(I)) {614// All the args are checked/rewritten. Don't call twice!615RewriteBlockPointerDecl(D);616break;617}618}619}620621void RewriteModernObjC::CheckFunctionPointerDecl(QualType funcType, NamedDecl *ND) {622const PointerType *PT = funcType->getAs<PointerType>();623if (PT && PointerTypeTakesAnyBlockArguments(funcType))624RewriteBlocksInFunctionProtoType(PT->getPointeeType(), ND);625}626627static bool IsHeaderFile(const std::string &Filename) {628std::string::size_type DotPos = Filename.rfind('.');629630if (DotPos == std::string::npos) {631// no file extension632return false;633}634635std::string Ext = Filename.substr(DotPos + 1);636// C header: .h637// C++ header: .hh or .H;638return Ext == "h" || Ext == "hh" || Ext == "H";639}640641RewriteModernObjC::RewriteModernObjC(std::string inFile,642std::unique_ptr<raw_ostream> OS,643DiagnosticsEngine &D,644const LangOptions &LOpts,645bool silenceMacroWarn, bool LineInfo)646: Diags(D), LangOpts(LOpts), InFileName(inFile), OutFile(std::move(OS)),647SilenceRewriteMacroWarning(silenceMacroWarn), GenerateLineInfo(LineInfo) {648IsHeader = IsHeaderFile(inFile);649RewriteFailedDiag = 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.653GlobalBlockRewriteFailedDiag = Diags.getCustomDiagID(DiagnosticsEngine::Warning,654"rewriting block literal declared in global scope is not implemented");655656TryFinallyContainsReturnDiag = Diags.getCustomDiagID(657DiagnosticsEngine::Warning,658"rewriter doesn't support user-specified control flow semantics "659"for @try/@finally (code may not execute properly)");660}661662std::unique_ptr<ASTConsumer> clang::CreateModernObjCRewriter(663const std::string &InFile, std::unique_ptr<raw_ostream> OS,664DiagnosticsEngine &Diags, const LangOptions &LOpts,665bool SilenceRewriteMacroWarning, bool LineInfo) {666return std::make_unique<RewriteModernObjC>(InFile, std::move(OS), Diags,667LOpts, SilenceRewriteMacroWarning,668LineInfo);669}670671void RewriteModernObjC::InitializeCommon(ASTContext &context) {672Context = &context;673SM = &Context->getSourceManager();674TUDecl = Context->getTranslationUnitDecl();675MsgSendFunctionDecl = nullptr;676MsgSendSuperFunctionDecl = nullptr;677MsgSendStretFunctionDecl = nullptr;678MsgSendSuperStretFunctionDecl = nullptr;679MsgSendFpretFunctionDecl = nullptr;680GetClassFunctionDecl = nullptr;681GetMetaClassFunctionDecl = nullptr;682GetSuperClassFunctionDecl = nullptr;683SelGetUidFunctionDecl = nullptr;684CFStringFunctionDecl = nullptr;685ConstantStringClassReference = nullptr;686NSStringRecord = nullptr;687CurMethodDef = nullptr;688CurFunctionDef = nullptr;689GlobalVarDecl = nullptr;690GlobalConstructionExp = nullptr;691SuperStructDecl = nullptr;692ProtocolTypeDecl = nullptr;693ConstantStringDecl = nullptr;694BcLabelCount = 0;695SuperConstructorFunctionDecl = nullptr;696NumObjCStringLiterals = 0;697PropParentMap = nullptr;698CurrentBody = nullptr;699DisableReplaceStmt = false;700objc_impl_method = false;701702// Get the ID and start/end of the main file.703MainFileID = SM->getMainFileID();704llvm::MemoryBufferRef MainBuf = SM->getBufferOrFake(MainFileID);705MainFileStart = MainBuf.getBufferStart();706MainFileEnd = MainBuf.getBufferEnd();707708Rewrite.setSourceMgr(Context->getSourceManager(), Context->getLangOpts());709}710711//===----------------------------------------------------------------------===//712// Top Level Driver Code713//===----------------------------------------------------------------------===//714715void RewriteModernObjC::HandleTopLevelSingleDecl(Decl *D) {716if (Diags.hasErrorOccurred())717return;718719// 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.722SourceLocation Loc = D->getLocation();723Loc = SM->getExpansionLoc(Loc);724725// If this is for a builtin, ignore it.726if (Loc.isInvalid()) return;727728// Look for built-in declarations that we need to refer during the rewrite.729if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {730RewriteFunctionDecl(FD);731} else if (VarDecl *FVD = dyn_cast<VarDecl>(D)) {732// declared in <Foundation/NSString.h>733if (FVD->getName() == "_NSConstantStringClassReference") {734ConstantStringClassReference = FVD;735return;736}737} else if (ObjCCategoryDecl *CD = dyn_cast<ObjCCategoryDecl>(D)) {738RewriteCategoryDecl(CD);739} else if (ObjCProtocolDecl *PD = dyn_cast<ObjCProtocolDecl>(D)) {740if (PD->isThisDeclarationADefinition())741RewriteProtocolDecl(PD);742} else if (LinkageSpecDecl *LSD = dyn_cast<LinkageSpecDecl>(D)) {743// Recurse into linkage specifications744for (DeclContext::decl_iterator DI = LSD->decls_begin(),745DIEnd = LSD->decls_end();746DI != DIEnd; ) {747if (ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>((*DI))) {748if (!IFace->isThisDeclarationADefinition()) {749SmallVector<Decl *, 8> DG;750SourceLocation StartLoc = IFace->getBeginLoc();751do {752if (isa<ObjCInterfaceDecl>(*DI) &&753!cast<ObjCInterfaceDecl>(*DI)->isThisDeclarationADefinition() &&754StartLoc == (*DI)->getBeginLoc())755DG.push_back(*DI);756else757break;758759++DI;760} while (DI != DIEnd);761RewriteForwardClassDecl(DG);762continue;763}764else {765// Keep track of all interface declarations seen.766ObjCInterfacesSeen.push_back(IFace);767++DI;768continue;769}770}771772if (ObjCProtocolDecl *Proto = dyn_cast<ObjCProtocolDecl>((*DI))) {773if (!Proto->isThisDeclarationADefinition()) {774SmallVector<Decl *, 8> DG;775SourceLocation StartLoc = Proto->getBeginLoc();776do {777if (isa<ObjCProtocolDecl>(*DI) &&778!cast<ObjCProtocolDecl>(*DI)->isThisDeclarationADefinition() &&779StartLoc == (*DI)->getBeginLoc())780DG.push_back(*DI);781else782break;783784++DI;785} while (DI != DIEnd);786RewriteForwardProtocolDecl(DG);787continue;788}789}790791HandleTopLevelSingleDecl(*DI);792++DI;793}794}795// If we have a decl in the main file, see if we should rewrite it.796if (SM->isWrittenInMainFile(Loc))797return HandleDeclInMainFile(D);798}799800//===----------------------------------------------------------------------===//801// Syntactic (non-AST) Rewriting Code802//===----------------------------------------------------------------------===//803804void RewriteModernObjC::RewriteInclude() {805SourceLocation LocStart = SM->getLocForStartOfFile(MainFileID);806StringRef MainBuf = SM->getBufferData(MainFileID);807const char *MainBufStart = MainBuf.begin();808const char *MainBufEnd = MainBuf.end();809size_t ImportLen = strlen("import");810811// Loop over the whole file, looking for includes.812for (const char *BufPtr = MainBufStart; BufPtr < MainBufEnd; ++BufPtr) {813if (*BufPtr == '#') {814if (++BufPtr == MainBufEnd)815return;816while (*BufPtr == ' ' || *BufPtr == '\t')817if (++BufPtr == MainBufEnd)818return;819if (!strncmp(BufPtr, "import", ImportLen)) {820// replace import with include821SourceLocation ImportLoc =822LocStart.getLocWithOffset(BufPtr-MainBufStart);823ReplaceText(ImportLoc, ImportLen, "include");824BufPtr += ImportLen;825}826}827}828}829830static void WriteInternalIvarName(const ObjCInterfaceDecl *IDecl,831ObjCIvarDecl *IvarDecl, std::string &Result) {832Result += "OBJC_IVAR_$_";833Result += IDecl->getName();834Result += "$";835Result += IvarDecl->getName();836}837838std::string839RewriteModernObjC::getIvarAccessString(ObjCIvarDecl *D) {840const ObjCInterfaceDecl *ClassDecl = D->getContainingInterface();841842// Build name of symbol holding ivar offset.843std::string IvarOffsetName;844if (D->isBitField())845ObjCIvarBitfieldGroupOffset(D, IvarOffsetName);846else847WriteInternalIvarName(ClassDecl, D, IvarOffsetName);848849std::string S = "(*(";850QualType IvarT = D->getType();851if (D->isBitField())852IvarT = GetGroupRecordTypeForObjCIvarBitfield(D);853854if (!IvarT->getAs<TypedefType>() && IvarT->isRecordType()) {855RecordDecl *RD = IvarT->castAs<RecordType>()->getDecl();856RD = RD->getDefinition();857if (RD && !RD->getDeclName().getAsIdentifierInfo()) {858// decltype(((Foo_IMPL*)0)->bar) *859auto *CDecl = cast<ObjCContainerDecl>(D->getDeclContext());860// ivar in class extensions requires special treatment.861if (ObjCCategoryDecl *CatDecl = dyn_cast<ObjCCategoryDecl>(CDecl))862CDecl = CatDecl->getClassInterface();863std::string RecName = std::string(CDecl->getName());864RecName += "_IMPL";865RecordDecl *RD = RecordDecl::Create(*Context, TagTypeKind::Struct, TUDecl,866SourceLocation(), SourceLocation(),867&Context->Idents.get(RecName));868QualType PtrStructIMPL = Context->getPointerType(Context->getTagDeclType(RD));869unsigned UnsignedIntSize =870static_cast<unsigned>(Context->getTypeSize(Context->UnsignedIntTy));871Expr *Zero = IntegerLiteral::Create(*Context,872llvm::APInt(UnsignedIntSize, 0),873Context->UnsignedIntTy, SourceLocation());874Zero = NoTypeInfoCStyleCastExpr(Context, PtrStructIMPL, CK_BitCast, Zero);875ParenExpr *PE = new (Context) ParenExpr(SourceLocation(), SourceLocation(),876Zero);877FieldDecl *FD = FieldDecl::Create(*Context, nullptr, SourceLocation(),878SourceLocation(),879&Context->Idents.get(D->getNameAsString()),880IvarT, nullptr,881/*BitWidth=*/nullptr, /*Mutable=*/true,882ICIS_NoInit);883MemberExpr *ME = MemberExpr::CreateImplicit(884*Context, PE, true, FD, FD->getType(), VK_LValue, OK_Ordinary);885IvarT = Context->getDecltypeType(ME, ME->getType());886}887}888convertObjCTypeToCStyleType(IvarT);889QualType castT = Context->getPointerType(IvarT);890std::string TypeString(castT.getAsString(Context->getPrintingPolicy()));891S += TypeString;892S += ")";893894// ((char *)self + IVAR_OFFSET_SYMBOL_NAME)895S += "((char *)self + ";896S += IvarOffsetName;897S += "))";898if (D->isBitField()) {899S += ".";900S += D->getNameAsString();901}902ReferencedIvars[const_cast<ObjCInterfaceDecl *>(ClassDecl)].insert(D);903return S;904}905906/// mustSynthesizeSetterGetterMethod - returns true if setter or getter has not907/// been found in the class implementation. In this case, it must be synthesized.908static bool mustSynthesizeSetterGetterMethod(ObjCImplementationDecl *IMP,909ObjCPropertyDecl *PD,910bool getter) {911auto *OMD = IMP->getInstanceMethod(getter ? PD->getGetterName()912: PD->getSetterName());913return !OMD || OMD->isSynthesizedAccessorStub();914}915916void RewriteModernObjC::RewritePropertyImplDecl(ObjCPropertyImplDecl *PID,917ObjCImplementationDecl *IMD,918ObjCCategoryImplDecl *CID) {919static bool objcGetPropertyDefined = false;920static bool objcSetPropertyDefined = false;921SourceLocation startGetterSetterLoc;922923if (PID->getBeginLoc().isValid()) {924SourceLocation startLoc = PID->getBeginLoc();925InsertText(startLoc, "// ");926const char *startBuf = SM->getCharacterData(startLoc);927assert((*startBuf == '@') && "bogus @synthesize location");928const char *semiBuf = strchr(startBuf, ';');929assert((*semiBuf == ';') && "@synthesize: can't find ';'");930startGetterSetterLoc = startLoc.getLocWithOffset(semiBuf-startBuf+1);931} else932startGetterSetterLoc = IMD ? IMD->getEndLoc() : CID->getEndLoc();933934if (PID->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic)935return; // FIXME: is this correct?936937// Generate the 'getter' function.938ObjCPropertyDecl *PD = PID->getPropertyDecl();939ObjCIvarDecl *OID = PID->getPropertyIvarDecl();940assert(IMD && OID && "Synthesized ivars must be attached to @implementation");941942unsigned Attributes = PD->getPropertyAttributes();943if (mustSynthesizeSetterGetterMethod(IMD, PD, true /*getter*/)) {944bool GenGetProperty =945!(Attributes & ObjCPropertyAttribute::kind_nonatomic) &&946(Attributes & (ObjCPropertyAttribute::kind_retain |947ObjCPropertyAttribute::kind_copy));948std::string Getr;949if (GenGetProperty && !objcGetPropertyDefined) {950objcGetPropertyDefined = true;951// FIXME. Is this attribute correct in all cases?952Getr = "\nextern \"C\" __declspec(dllimport) "953"id objc_getProperty(id, SEL, long, bool);\n";954}955RewriteObjCMethodDecl(OID->getContainingInterface(),956PID->getGetterMethodDecl(), Getr);957Getr += "{ ";958// Synthesize an explicit cast to gain access to the ivar.959// See objc-act.c:objc_synthesize_new_getter() for details.960if (GenGetProperty) {961// return objc_getProperty(self, _cmd, offsetof(ClassDecl, OID), 1)962Getr += "typedef ";963const FunctionType *FPRetType = nullptr;964RewriteTypeIntoString(PID->getGetterMethodDecl()->getReturnType(), Getr,965FPRetType);966Getr += " _TYPE";967if (FPRetType) {968Getr += ")"; // close the precedence "scope" for "*".969970// Now, emit the argument types (if any).971if (const FunctionProtoType *FT = dyn_cast<FunctionProtoType>(FPRetType)){972Getr += "(";973for (unsigned i = 0, e = FT->getNumParams(); i != e; ++i) {974if (i) Getr += ", ";975std::string ParamStr =976FT->getParamType(i).getAsString(Context->getPrintingPolicy());977Getr += ParamStr;978}979if (FT->isVariadic()) {980if (FT->getNumParams())981Getr += ", ";982Getr += "...";983}984Getr += ")";985} else986Getr += "()";987}988Getr += ";\n";989Getr += "return (_TYPE)";990Getr += "objc_getProperty(self, _cmd, ";991RewriteIvarOffsetComputation(OID, Getr);992Getr += ", 1)";993}994else995Getr += "return " + getIvarAccessString(OID);996Getr += "; }";997InsertText(startGetterSetterLoc, Getr);998}9991000if (PD->isReadOnly() ||1001!mustSynthesizeSetterGetterMethod(IMD, PD, false /*setter*/))1002return;10031004// Generate the 'setter' function.1005std::string Setr;1006bool GenSetProperty = Attributes & (ObjCPropertyAttribute::kind_retain |1007ObjCPropertyAttribute::kind_copy);1008if (GenSetProperty && !objcSetPropertyDefined) {1009objcSetPropertyDefined = true;1010// FIXME. Is this attribute correct in all cases?1011Setr = "\nextern \"C\" __declspec(dllimport) "1012"void objc_setProperty (id, SEL, long, id, bool, bool);\n";1013}10141015RewriteObjCMethodDecl(OID->getContainingInterface(),1016PID->getSetterMethodDecl(), Setr);1017Setr += "{ ";1018// Synthesize an explicit cast to initialize the ivar.1019// See objc-act.c:objc_synthesize_new_setter() for details.1020if (GenSetProperty) {1021Setr += "objc_setProperty (self, _cmd, ";1022RewriteIvarOffsetComputation(OID, Setr);1023Setr += ", (id)";1024Setr += PD->getName();1025Setr += ", ";1026if (Attributes & ObjCPropertyAttribute::kind_nonatomic)1027Setr += "0, ";1028else1029Setr += "1, ";1030if (Attributes & ObjCPropertyAttribute::kind_copy)1031Setr += "1)";1032else1033Setr += "0)";1034}1035else {1036Setr += getIvarAccessString(OID) + " = ";1037Setr += PD->getName();1038}1039Setr += "; }\n";1040InsertText(startGetterSetterLoc, Setr);1041}10421043static void RewriteOneForwardClassDecl(ObjCInterfaceDecl *ForwardDecl,1044std::string &typedefString) {1045typedefString += "\n#ifndef _REWRITER_typedef_";1046typedefString += ForwardDecl->getNameAsString();1047typedefString += "\n";1048typedefString += "#define _REWRITER_typedef_";1049typedefString += ForwardDecl->getNameAsString();1050typedefString += "\n";1051typedefString += "typedef struct objc_object ";1052typedefString += ForwardDecl->getNameAsString();1053// typedef struct { } _objc_exc_Classname;1054typedefString += ";\ntypedef struct {} _objc_exc_";1055typedefString += ForwardDecl->getNameAsString();1056typedefString += ";\n#endif\n";1057}10581059void RewriteModernObjC::RewriteForwardClassEpilogue(ObjCInterfaceDecl *ClassDecl,1060const std::string &typedefString) {1061SourceLocation startLoc = ClassDecl->getBeginLoc();1062const char *startBuf = SM->getCharacterData(startLoc);1063const char *semiPtr = strchr(startBuf, ';');1064// Replace the @class with typedefs corresponding to the classes.1065ReplaceText(startLoc, semiPtr-startBuf+1, typedefString);1066}10671068void RewriteModernObjC::RewriteForwardClassDecl(DeclGroupRef D) {1069std::string typedefString;1070for (DeclGroupRef::iterator I = D.begin(), E = D.end(); I != E; ++I) {1071if (ObjCInterfaceDecl *ForwardDecl = dyn_cast<ObjCInterfaceDecl>(*I)) {1072if (I == D.begin()) {1073// Translate to typedef's that forward reference structs with the same name1074// as the class. As a convenience, we include the original declaration1075// as a comment.1076typedefString += "// @class ";1077typedefString += ForwardDecl->getNameAsString();1078typedefString += ";";1079}1080RewriteOneForwardClassDecl(ForwardDecl, typedefString);1081}1082else1083HandleTopLevelSingleDecl(*I);1084}1085DeclGroupRef::iterator I = D.begin();1086RewriteForwardClassEpilogue(cast<ObjCInterfaceDecl>(*I), typedefString);1087}10881089void RewriteModernObjC::RewriteForwardClassDecl(1090const SmallVectorImpl<Decl *> &D) {1091std::string typedefString;1092for (unsigned i = 0; i < D.size(); i++) {1093ObjCInterfaceDecl *ForwardDecl = cast<ObjCInterfaceDecl>(D[i]);1094if (i == 0) {1095typedefString += "// @class ";1096typedefString += ForwardDecl->getNameAsString();1097typedefString += ";";1098}1099RewriteOneForwardClassDecl(ForwardDecl, typedefString);1100}1101RewriteForwardClassEpilogue(cast<ObjCInterfaceDecl>(D[0]), typedefString);1102}11031104void RewriteModernObjC::RewriteMethodDeclaration(ObjCMethodDecl *Method) {1105// When method is a synthesized one, such as a getter/setter there is1106// nothing to rewrite.1107if (Method->isImplicit())1108return;1109SourceLocation LocStart = Method->getBeginLoc();1110SourceLocation LocEnd = Method->getEndLoc();11111112if (SM->getExpansionLineNumber(LocEnd) >1113SM->getExpansionLineNumber(LocStart)) {1114InsertText(LocStart, "#if 0\n");1115ReplaceText(LocEnd, 1, ";\n#endif\n");1116} else {1117InsertText(LocStart, "// ");1118}1119}11201121void RewriteModernObjC::RewriteProperty(ObjCPropertyDecl *prop) {1122SourceLocation Loc = prop->getAtLoc();11231124ReplaceText(Loc, 0, "// ");1125// FIXME: handle properties that are declared across multiple lines.1126}11271128void RewriteModernObjC::RewriteCategoryDecl(ObjCCategoryDecl *CatDecl) {1129SourceLocation LocStart = CatDecl->getBeginLoc();11301131// FIXME: handle category headers that are declared across multiple lines.1132if (CatDecl->getIvarRBraceLoc().isValid()) {1133ReplaceText(LocStart, 1, "/** ");1134ReplaceText(CatDecl->getIvarRBraceLoc(), 1, "**/ ");1135}1136else {1137ReplaceText(LocStart, 0, "// ");1138}11391140for (auto *I : CatDecl->instance_properties())1141RewriteProperty(I);11421143for (auto *I : CatDecl->instance_methods())1144RewriteMethodDeclaration(I);1145for (auto *I : CatDecl->class_methods())1146RewriteMethodDeclaration(I);11471148// Lastly, comment out the @end.1149ReplaceText(CatDecl->getAtEndRange().getBegin(),1150strlen("@end"), "/* @end */\n");1151}11521153void RewriteModernObjC::RewriteProtocolDecl(ObjCProtocolDecl *PDecl) {1154SourceLocation LocStart = PDecl->getBeginLoc();1155assert(PDecl->isThisDeclarationADefinition());11561157// FIXME: handle protocol headers that are declared across multiple lines.1158ReplaceText(LocStart, 0, "// ");11591160for (auto *I : PDecl->instance_methods())1161RewriteMethodDeclaration(I);1162for (auto *I : PDecl->class_methods())1163RewriteMethodDeclaration(I);1164for (auto *I : PDecl->instance_properties())1165RewriteProperty(I);11661167// Lastly, comment out the @end.1168SourceLocation LocEnd = PDecl->getAtEndRange().getBegin();1169ReplaceText(LocEnd, strlen("@end"), "/* @end */\n");11701171// Must comment out @optional/@required1172const char *startBuf = SM->getCharacterData(LocStart);1173const char *endBuf = SM->getCharacterData(LocEnd);1174for (const char *p = startBuf; p < endBuf; p++) {1175if (*p == '@' && !strncmp(p+1, "optional", strlen("optional"))) {1176SourceLocation OptionalLoc = LocStart.getLocWithOffset(p-startBuf);1177ReplaceText(OptionalLoc, strlen("@optional"), "/* @optional */");11781179}1180else if (*p == '@' && !strncmp(p+1, "required", strlen("required"))) {1181SourceLocation OptionalLoc = LocStart.getLocWithOffset(p-startBuf);1182ReplaceText(OptionalLoc, strlen("@required"), "/* @required */");11831184}1185}1186}11871188void RewriteModernObjC::RewriteForwardProtocolDecl(DeclGroupRef D) {1189SourceLocation LocStart = (*D.begin())->getBeginLoc();1190if (LocStart.isInvalid())1191llvm_unreachable("Invalid SourceLocation");1192// FIXME: handle forward protocol that are declared across multiple lines.1193ReplaceText(LocStart, 0, "// ");1194}11951196void1197RewriteModernObjC::RewriteForwardProtocolDecl(const SmallVectorImpl<Decl *> &DG) {1198SourceLocation LocStart = DG[0]->getBeginLoc();1199if (LocStart.isInvalid())1200llvm_unreachable("Invalid SourceLocation");1201// FIXME: handle forward protocol that are declared across multiple lines.1202ReplaceText(LocStart, 0, "// ");1203}12041205void RewriteModernObjC::RewriteTypeIntoString(QualType T, std::string &ResultStr,1206const FunctionType *&FPRetType) {1207if (T->isObjCQualifiedIdType())1208ResultStr += "id";1209else if (T->isFunctionPointerType() ||1210T->isBlockPointerType()) {1211// needs special handling, since pointer-to-functions have special1212// syntax (where a decaration models use).1213QualType retType = T;1214QualType PointeeTy;1215if (const PointerType* PT = retType->getAs<PointerType>())1216PointeeTy = PT->getPointeeType();1217else if (const BlockPointerType *BPT = retType->getAs<BlockPointerType>())1218PointeeTy = BPT->getPointeeType();1219if ((FPRetType = PointeeTy->getAs<FunctionType>())) {1220ResultStr +=1221FPRetType->getReturnType().getAsString(Context->getPrintingPolicy());1222ResultStr += "(*";1223}1224} else1225ResultStr += T.getAsString(Context->getPrintingPolicy());1226}12271228void RewriteModernObjC::RewriteObjCMethodDecl(const ObjCInterfaceDecl *IDecl,1229ObjCMethodDecl *OMD,1230std::string &ResultStr) {1231//fprintf(stderr,"In RewriteObjCMethodDecl\n");1232const FunctionType *FPRetType = nullptr;1233ResultStr += "\nstatic ";1234RewriteTypeIntoString(OMD->getReturnType(), ResultStr, FPRetType);1235ResultStr += " ";12361237// Unique method name1238std::string NameStr;12391240if (OMD->isInstanceMethod())1241NameStr += "_I_";1242else1243NameStr += "_C_";12441245NameStr += IDecl->getNameAsString();1246NameStr += "_";12471248if (ObjCCategoryImplDecl *CID =1249dyn_cast<ObjCCategoryImplDecl>(OMD->getDeclContext())) {1250NameStr += CID->getNameAsString();1251NameStr += "_";1252}1253// Append selector names, replacing ':' with '_'1254{1255std::string selString = OMD->getSelector().getAsString();1256int len = selString.size();1257for (int i = 0; i < len; i++)1258if (selString[i] == ':')1259selString[i] = '_';1260NameStr += selString;1261}1262// Remember this name for metadata emission1263MethodInternalNames[OMD] = NameStr;1264ResultStr += NameStr;12651266// Rewrite arguments1267ResultStr += "(";12681269// invisible arguments1270if (OMD->isInstanceMethod()) {1271QualType selfTy = Context->getObjCInterfaceType(IDecl);1272selfTy = Context->getPointerType(selfTy);1273if (!LangOpts.MicrosoftExt) {1274if (ObjCSynthesizedStructs.count(const_cast<ObjCInterfaceDecl*>(IDecl)))1275ResultStr += "struct ";1276}1277// When rewriting for Microsoft, explicitly omit the structure name.1278ResultStr += IDecl->getNameAsString();1279ResultStr += " *";1280}1281else1282ResultStr += Context->getObjCClassType().getAsString(1283Context->getPrintingPolicy());12841285ResultStr += " self, ";1286ResultStr += Context->getObjCSelType().getAsString(Context->getPrintingPolicy());1287ResultStr += " _cmd";12881289// Method arguments.1290for (const auto *PDecl : OMD->parameters()) {1291ResultStr += ", ";1292if (PDecl->getType()->isObjCQualifiedIdType()) {1293ResultStr += "id ";1294ResultStr += PDecl->getNameAsString();1295} else {1296std::string Name = PDecl->getNameAsString();1297QualType QT = PDecl->getType();1298// Make sure we convert "t (^)(...)" to "t (*)(...)".1299(void)convertBlockPointerToFunctionPointer(QT);1300QT.getAsStringInternal(Name, Context->getPrintingPolicy());1301ResultStr += Name;1302}1303}1304if (OMD->isVariadic())1305ResultStr += ", ...";1306ResultStr += ") ";13071308if (FPRetType) {1309ResultStr += ")"; // close the precedence "scope" for "*".13101311// Now, emit the argument types (if any).1312if (const FunctionProtoType *FT = dyn_cast<FunctionProtoType>(FPRetType)) {1313ResultStr += "(";1314for (unsigned i = 0, e = FT->getNumParams(); i != e; ++i) {1315if (i) ResultStr += ", ";1316std::string ParamStr =1317FT->getParamType(i).getAsString(Context->getPrintingPolicy());1318ResultStr += ParamStr;1319}1320if (FT->isVariadic()) {1321if (FT->getNumParams())1322ResultStr += ", ";1323ResultStr += "...";1324}1325ResultStr += ")";1326} else {1327ResultStr += "()";1328}1329}1330}13311332void RewriteModernObjC::RewriteImplementationDecl(Decl *OID) {1333ObjCImplementationDecl *IMD = dyn_cast<ObjCImplementationDecl>(OID);1334ObjCCategoryImplDecl *CID = dyn_cast<ObjCCategoryImplDecl>(OID);1335assert((IMD || CID) && "Unknown implementation type");13361337if (IMD) {1338if (IMD->getIvarRBraceLoc().isValid()) {1339ReplaceText(IMD->getBeginLoc(), 1, "/** ");1340ReplaceText(IMD->getIvarRBraceLoc(), 1, "**/ ");1341}1342else {1343InsertText(IMD->getBeginLoc(), "// ");1344}1345}1346else1347InsertText(CID->getBeginLoc(), "// ");13481349for (auto *OMD : IMD ? IMD->instance_methods() : CID->instance_methods()) {1350if (!OMD->getBody())1351continue;1352std::string ResultStr;1353RewriteObjCMethodDecl(OMD->getClassInterface(), OMD, ResultStr);1354SourceLocation LocStart = OMD->getBeginLoc();1355SourceLocation LocEnd = OMD->getCompoundBody()->getBeginLoc();13561357const char *startBuf = SM->getCharacterData(LocStart);1358const char *endBuf = SM->getCharacterData(LocEnd);1359ReplaceText(LocStart, endBuf-startBuf, ResultStr);1360}13611362for (auto *OMD : IMD ? IMD->class_methods() : CID->class_methods()) {1363if (!OMD->getBody())1364continue;1365std::string ResultStr;1366RewriteObjCMethodDecl(OMD->getClassInterface(), OMD, ResultStr);1367SourceLocation LocStart = OMD->getBeginLoc();1368SourceLocation LocEnd = OMD->getCompoundBody()->getBeginLoc();13691370const char *startBuf = SM->getCharacterData(LocStart);1371const char *endBuf = SM->getCharacterData(LocEnd);1372ReplaceText(LocStart, endBuf-startBuf, ResultStr);1373}1374for (auto *I : IMD ? IMD->property_impls() : CID->property_impls())1375RewritePropertyImplDecl(I, IMD, CID);13761377InsertText(IMD ? IMD->getEndLoc() : CID->getEndLoc(), "// ");1378}13791380void RewriteModernObjC::RewriteInterfaceDecl(ObjCInterfaceDecl *ClassDecl) {1381// Do not synthesize more than once.1382if (ObjCSynthesizedStructs.count(ClassDecl))1383return;1384// Make sure super class's are written before current class is written.1385ObjCInterfaceDecl *SuperClass = ClassDecl->getSuperClass();1386while (SuperClass) {1387RewriteInterfaceDecl(SuperClass);1388SuperClass = SuperClass->getSuperClass();1389}1390std::string ResultStr;1391if (!ObjCWrittenInterfaces.count(ClassDecl->getCanonicalDecl())) {1392// we haven't seen a forward decl - generate a typedef.1393RewriteOneForwardClassDecl(ClassDecl, ResultStr);1394RewriteIvarOffsetSymbols(ClassDecl, ResultStr);13951396RewriteObjCInternalStruct(ClassDecl, ResultStr);1397// Mark this typedef as having been written into its c++ equivalent.1398ObjCWrittenInterfaces.insert(ClassDecl->getCanonicalDecl());13991400for (auto *I : ClassDecl->instance_properties())1401RewriteProperty(I);1402for (auto *I : ClassDecl->instance_methods())1403RewriteMethodDeclaration(I);1404for (auto *I : ClassDecl->class_methods())1405RewriteMethodDeclaration(I);14061407// Lastly, comment out the @end.1408ReplaceText(ClassDecl->getAtEndRange().getBegin(), strlen("@end"),1409"/* @end */\n");1410}1411}14121413Stmt *RewriteModernObjC::RewritePropertyOrImplicitSetter(PseudoObjectExpr *PseudoOp) {1414SourceRange OldRange = PseudoOp->getSourceRange();14151416// We just magically know some things about the structure of this1417// expression.1418ObjCMessageExpr *OldMsg =1419cast<ObjCMessageExpr>(PseudoOp->getSemanticExpr(1420PseudoOp->getNumSemanticExprs() - 1));14211422// Because the rewriter doesn't allow us to rewrite rewritten code,1423// we need to suppress rewriting the sub-statements.1424Expr *Base;1425SmallVector<Expr*, 2> Args;1426{1427DisableReplaceStmtScope S(*this);14281429// Rebuild the base expression if we have one.1430Base = nullptr;1431if (OldMsg->getReceiverKind() == ObjCMessageExpr::Instance) {1432Base = OldMsg->getInstanceReceiver();1433Base = cast<OpaqueValueExpr>(Base)->getSourceExpr();1434Base = cast<Expr>(RewriteFunctionBodyOrGlobalInitializer(Base));1435}14361437unsigned numArgs = OldMsg->getNumArgs();1438for (unsigned i = 0; i < numArgs; i++) {1439Expr *Arg = OldMsg->getArg(i);1440if (isa<OpaqueValueExpr>(Arg))1441Arg = cast<OpaqueValueExpr>(Arg)->getSourceExpr();1442Arg = cast<Expr>(RewriteFunctionBodyOrGlobalInitializer(Arg));1443Args.push_back(Arg);1444}1445}14461447// TODO: avoid this copy.1448SmallVector<SourceLocation, 1> SelLocs;1449OldMsg->getSelectorLocs(SelLocs);14501451ObjCMessageExpr *NewMsg = nullptr;1452switch (OldMsg->getReceiverKind()) {1453case ObjCMessageExpr::Class:1454NewMsg = ObjCMessageExpr::Create(*Context, OldMsg->getType(),1455OldMsg->getValueKind(),1456OldMsg->getLeftLoc(),1457OldMsg->getClassReceiverTypeInfo(),1458OldMsg->getSelector(),1459SelLocs,1460OldMsg->getMethodDecl(),1461Args,1462OldMsg->getRightLoc(),1463OldMsg->isImplicit());1464break;14651466case ObjCMessageExpr::Instance:1467NewMsg = ObjCMessageExpr::Create(*Context, OldMsg->getType(),1468OldMsg->getValueKind(),1469OldMsg->getLeftLoc(),1470Base,1471OldMsg->getSelector(),1472SelLocs,1473OldMsg->getMethodDecl(),1474Args,1475OldMsg->getRightLoc(),1476OldMsg->isImplicit());1477break;14781479case ObjCMessageExpr::SuperClass:1480case ObjCMessageExpr::SuperInstance:1481NewMsg = ObjCMessageExpr::Create(*Context, OldMsg->getType(),1482OldMsg->getValueKind(),1483OldMsg->getLeftLoc(),1484OldMsg->getSuperLoc(),1485OldMsg->getReceiverKind() == ObjCMessageExpr::SuperInstance,1486OldMsg->getSuperType(),1487OldMsg->getSelector(),1488SelLocs,1489OldMsg->getMethodDecl(),1490Args,1491OldMsg->getRightLoc(),1492OldMsg->isImplicit());1493break;1494}14951496Stmt *Replacement = SynthMessageExpr(NewMsg);1497ReplaceStmtWithRange(PseudoOp, Replacement, OldRange);1498return Replacement;1499}15001501Stmt *RewriteModernObjC::RewritePropertyOrImplicitGetter(PseudoObjectExpr *PseudoOp) {1502SourceRange OldRange = PseudoOp->getSourceRange();15031504// We just magically know some things about the structure of this1505// expression.1506ObjCMessageExpr *OldMsg =1507cast<ObjCMessageExpr>(PseudoOp->getResultExpr()->IgnoreImplicit());15081509// Because the rewriter doesn't allow us to rewrite rewritten code,1510// we need to suppress rewriting the sub-statements.1511Expr *Base = nullptr;1512SmallVector<Expr*, 1> Args;1513{1514DisableReplaceStmtScope S(*this);1515// Rebuild the base expression if we have one.1516if (OldMsg->getReceiverKind() == ObjCMessageExpr::Instance) {1517Base = OldMsg->getInstanceReceiver();1518Base = cast<OpaqueValueExpr>(Base)->getSourceExpr();1519Base = cast<Expr>(RewriteFunctionBodyOrGlobalInitializer(Base));1520}1521unsigned numArgs = OldMsg->getNumArgs();1522for (unsigned i = 0; i < numArgs; i++) {1523Expr *Arg = OldMsg->getArg(i);1524if (isa<OpaqueValueExpr>(Arg))1525Arg = cast<OpaqueValueExpr>(Arg)->getSourceExpr();1526Arg = cast<Expr>(RewriteFunctionBodyOrGlobalInitializer(Arg));1527Args.push_back(Arg);1528}1529}15301531// Intentionally empty.1532SmallVector<SourceLocation, 1> SelLocs;15331534ObjCMessageExpr *NewMsg = nullptr;1535switch (OldMsg->getReceiverKind()) {1536case ObjCMessageExpr::Class:1537NewMsg = ObjCMessageExpr::Create(*Context, OldMsg->getType(),1538OldMsg->getValueKind(),1539OldMsg->getLeftLoc(),1540OldMsg->getClassReceiverTypeInfo(),1541OldMsg->getSelector(),1542SelLocs,1543OldMsg->getMethodDecl(),1544Args,1545OldMsg->getRightLoc(),1546OldMsg->isImplicit());1547break;15481549case ObjCMessageExpr::Instance:1550NewMsg = ObjCMessageExpr::Create(*Context, OldMsg->getType(),1551OldMsg->getValueKind(),1552OldMsg->getLeftLoc(),1553Base,1554OldMsg->getSelector(),1555SelLocs,1556OldMsg->getMethodDecl(),1557Args,1558OldMsg->getRightLoc(),1559OldMsg->isImplicit());1560break;15611562case ObjCMessageExpr::SuperClass:1563case ObjCMessageExpr::SuperInstance:1564NewMsg = ObjCMessageExpr::Create(*Context, OldMsg->getType(),1565OldMsg->getValueKind(),1566OldMsg->getLeftLoc(),1567OldMsg->getSuperLoc(),1568OldMsg->getReceiverKind() == ObjCMessageExpr::SuperInstance,1569OldMsg->getSuperType(),1570OldMsg->getSelector(),1571SelLocs,1572OldMsg->getMethodDecl(),1573Args,1574OldMsg->getRightLoc(),1575OldMsg->isImplicit());1576break;1577}15781579Stmt *Replacement = SynthMessageExpr(NewMsg);1580ReplaceStmtWithRange(PseudoOp, Replacement, OldRange);1581return Replacement;1582}15831584/// SynthCountByEnumWithState - To print:1585/// ((NSUInteger (*)1586/// (id, SEL, struct __objcFastEnumerationState *, id *, NSUInteger))1587/// (void *)objc_msgSend)((id)l_collection,1588/// sel_registerName(1589/// "countByEnumeratingWithState:objects:count:"),1590/// &enumState,1591/// (id *)__rw_items, (NSUInteger)16)1592///1593void RewriteModernObjC::SynthCountByEnumWithState(std::string &buf) {1594buf += "((_WIN_NSUInteger (*) (id, SEL, struct __objcFastEnumerationState *, "1595"id *, _WIN_NSUInteger))(void *)objc_msgSend)";1596buf += "\n\t\t";1597buf += "((id)l_collection,\n\t\t";1598buf += "sel_registerName(\"countByEnumeratingWithState:objects:count:\"),";1599buf += "\n\t\t";1600buf += "&enumState, "1601"(id *)__rw_items, (_WIN_NSUInteger)16)";1602}16031604/// RewriteBreakStmt - Rewrite for a break-stmt inside an ObjC2's foreach1605/// statement to exit to its outer synthesized loop.1606///1607Stmt *RewriteModernObjC::RewriteBreakStmt(BreakStmt *S) {1608if (Stmts.empty() || !isa<ObjCForCollectionStmt>(Stmts.back()))1609return S;1610// replace break with goto __break_label1611std::string buf;16121613SourceLocation startLoc = S->getBeginLoc();1614buf = "goto __break_label_";1615buf += utostr(ObjCBcLabelNo.back());1616ReplaceText(startLoc, strlen("break"), buf);16171618return nullptr;1619}16201621void RewriteModernObjC::ConvertSourceLocationToLineDirective(1622SourceLocation Loc,1623std::string &LineString) {1624if (Loc.isFileID() && GenerateLineInfo) {1625LineString += "\n#line ";1626PresumedLoc PLoc = SM->getPresumedLoc(Loc);1627LineString += utostr(PLoc.getLine());1628LineString += " \"";1629LineString += Lexer::Stringify(PLoc.getFilename());1630LineString += "\"\n";1631}1632}16331634/// RewriteContinueStmt - Rewrite for a continue-stmt inside an ObjC2's foreach1635/// statement to continue with its inner synthesized loop.1636///1637Stmt *RewriteModernObjC::RewriteContinueStmt(ContinueStmt *S) {1638if (Stmts.empty() || !isa<ObjCForCollectionStmt>(Stmts.back()))1639return S;1640// replace continue with goto __continue_label1641std::string buf;16421643SourceLocation startLoc = S->getBeginLoc();1644buf = "goto __continue_label_";1645buf += utostr(ObjCBcLabelNo.back());1646ReplaceText(startLoc, strlen("continue"), buf);16471648return nullptr;1649}16501651/// RewriteObjCForCollectionStmt - Rewriter for ObjC2's foreach statement.1652/// It rewrites:1653/// for ( type elem in collection) { stmts; }16541655/// Into:1656/// {1657/// type elem;1658/// struct __objcFastEnumerationState enumState = { 0 };1659/// id __rw_items[16];1660/// id l_collection = (id)collection;1661/// NSUInteger limit = [l_collection countByEnumeratingWithState:&enumState1662/// objects:__rw_items count:16];1663/// if (limit) {1664/// unsigned long startMutations = *enumState.mutationsPtr;1665/// do {1666/// unsigned long counter = 0;1667/// do {1668/// if (startMutations != *enumState.mutationsPtr)1669/// objc_enumerationMutation(l_collection);1670/// elem = (type)enumState.itemsPtr[counter++];1671/// stmts;1672/// __continue_label: ;1673/// } while (counter < limit);1674/// } while ((limit = [l_collection countByEnumeratingWithState:&enumState1675/// objects:__rw_items count:16]));1676/// elem = nil;1677/// __break_label: ;1678/// }1679/// else1680/// elem = nil;1681/// }1682///1683Stmt *RewriteModernObjC::RewriteObjCForCollectionStmt(ObjCForCollectionStmt *S,1684SourceLocation OrigEnd) {1685assert(!Stmts.empty() && "ObjCForCollectionStmt - Statement stack empty");1686assert(isa<ObjCForCollectionStmt>(Stmts.back()) &&1687"ObjCForCollectionStmt Statement stack mismatch");1688assert(!ObjCBcLabelNo.empty() &&1689"ObjCForCollectionStmt - Label No stack empty");16901691SourceLocation startLoc = S->getBeginLoc();1692const char *startBuf = SM->getCharacterData(startLoc);1693StringRef elementName;1694std::string elementTypeAsString;1695std::string buf;1696// line directive first.1697SourceLocation ForEachLoc = S->getForLoc();1698ConvertSourceLocationToLineDirective(ForEachLoc, buf);1699buf += "{\n\t";1700if (DeclStmt *DS = dyn_cast<DeclStmt>(S->getElement())) {1701// type elem;1702NamedDecl* D = cast<NamedDecl>(DS->getSingleDecl());1703QualType ElementType = cast<ValueDecl>(D)->getType();1704if (ElementType->isObjCQualifiedIdType() ||1705ElementType->isObjCQualifiedInterfaceType())1706// Simply use 'id' for all qualified types.1707elementTypeAsString = "id";1708else1709elementTypeAsString = ElementType.getAsString(Context->getPrintingPolicy());1710buf += elementTypeAsString;1711buf += " ";1712elementName = D->getName();1713buf += elementName;1714buf += ";\n\t";1715}1716else {1717DeclRefExpr *DR = cast<DeclRefExpr>(S->getElement());1718elementName = DR->getDecl()->getName();1719ValueDecl *VD = DR->getDecl();1720if (VD->getType()->isObjCQualifiedIdType() ||1721VD->getType()->isObjCQualifiedInterfaceType())1722// Simply use 'id' for all qualified types.1723elementTypeAsString = "id";1724else1725elementTypeAsString = VD->getType().getAsString(Context->getPrintingPolicy());1726}17271728// struct __objcFastEnumerationState enumState = { 0 };1729buf += "struct __objcFastEnumerationState enumState = { 0 };\n\t";1730// id __rw_items[16];1731buf += "id __rw_items[16];\n\t";1732// id l_collection = (id)1733buf += "id l_collection = (id)";1734// Find start location of 'collection' the hard way!1735const char *startCollectionBuf = startBuf;1736startCollectionBuf += 3; // skip 'for'1737startCollectionBuf = strchr(startCollectionBuf, '(');1738startCollectionBuf++; // skip '('1739// find 'in' and skip it.1740while (*startCollectionBuf != ' ' ||1741*(startCollectionBuf+1) != 'i' || *(startCollectionBuf+2) != 'n' ||1742(*(startCollectionBuf+3) != ' ' &&1743*(startCollectionBuf+3) != '[' && *(startCollectionBuf+3) != '('))1744startCollectionBuf++;1745startCollectionBuf += 3;17461747// Replace: "for (type element in" with string constructed thus far.1748ReplaceText(startLoc, startCollectionBuf - startBuf, buf);1749// Replace ')' in for '(' type elem in collection ')' with ';'1750SourceLocation rightParenLoc = S->getRParenLoc();1751const char *rparenBuf = SM->getCharacterData(rightParenLoc);1752SourceLocation lparenLoc = startLoc.getLocWithOffset(rparenBuf-startBuf);1753buf = ";\n\t";17541755// unsigned long limit = [l_collection countByEnumeratingWithState:&enumState1756// objects:__rw_items count:16];1757// which is synthesized into:1758// NSUInteger limit =1759// ((NSUInteger (*)1760// (id, SEL, struct __objcFastEnumerationState *, id *, NSUInteger))1761// (void *)objc_msgSend)((id)l_collection,1762// sel_registerName(1763// "countByEnumeratingWithState:objects:count:"),1764// (struct __objcFastEnumerationState *)&state,1765// (id *)__rw_items, (NSUInteger)16);1766buf += "_WIN_NSUInteger limit =\n\t\t";1767SynthCountByEnumWithState(buf);1768buf += ";\n\t";1769/// if (limit) {1770/// unsigned long startMutations = *enumState.mutationsPtr;1771/// do {1772/// unsigned long counter = 0;1773/// do {1774/// if (startMutations != *enumState.mutationsPtr)1775/// objc_enumerationMutation(l_collection);1776/// elem = (type)enumState.itemsPtr[counter++];1777buf += "if (limit) {\n\t";1778buf += "unsigned long startMutations = *enumState.mutationsPtr;\n\t";1779buf += "do {\n\t\t";1780buf += "unsigned long counter = 0;\n\t\t";1781buf += "do {\n\t\t\t";1782buf += "if (startMutations != *enumState.mutationsPtr)\n\t\t\t\t";1783buf += "objc_enumerationMutation(l_collection);\n\t\t\t";1784buf += elementName;1785buf += " = (";1786buf += elementTypeAsString;1787buf += ")enumState.itemsPtr[counter++];";1788// Replace ')' in for '(' type elem in collection ')' with all of these.1789ReplaceText(lparenLoc, 1, buf);17901791/// __continue_label: ;1792/// } while (counter < limit);1793/// } while ((limit = [l_collection countByEnumeratingWithState:&enumState1794/// objects:__rw_items count:16]));1795/// elem = nil;1796/// __break_label: ;1797/// }1798/// else1799/// elem = nil;1800/// }1801///1802buf = ";\n\t";1803buf += "__continue_label_";1804buf += utostr(ObjCBcLabelNo.back());1805buf += ": ;";1806buf += "\n\t\t";1807buf += "} while (counter < limit);\n\t";1808buf += "} while ((limit = ";1809SynthCountByEnumWithState(buf);1810buf += "));\n\t";1811buf += elementName;1812buf += " = ((";1813buf += elementTypeAsString;1814buf += ")0);\n\t";1815buf += "__break_label_";1816buf += utostr(ObjCBcLabelNo.back());1817buf += ": ;\n\t";1818buf += "}\n\t";1819buf += "else\n\t\t";1820buf += elementName;1821buf += " = ((";1822buf += elementTypeAsString;1823buf += ")0);\n\t";1824buf += "}\n";18251826// Insert all these *after* the statement body.1827// FIXME: If this should support Obj-C++, support CXXTryStmt1828if (isa<CompoundStmt>(S->getBody())) {1829SourceLocation endBodyLoc = OrigEnd.getLocWithOffset(1);1830InsertText(endBodyLoc, buf);1831} else {1832/* Need to treat single statements specially. For example:1833*1834* for (A *a in b) if (stuff()) break;1835* for (A *a in b) xxxyy;1836*1837* The following code simply scans ahead to the semi to find the actual end.1838*/1839const char *stmtBuf = SM->getCharacterData(OrigEnd);1840const char *semiBuf = strchr(stmtBuf, ';');1841assert(semiBuf && "Can't find ';'");1842SourceLocation endBodyLoc = OrigEnd.getLocWithOffset(semiBuf-stmtBuf+1);1843InsertText(endBodyLoc, buf);1844}1845Stmts.pop_back();1846ObjCBcLabelNo.pop_back();1847return nullptr;1848}18491850static void Write_RethrowObject(std::string &buf) {1851buf += "{ struct _FIN { _FIN(id reth) : rethrow(reth) {}\n";1852buf += "\t~_FIN() { if (rethrow) objc_exception_throw(rethrow); }\n";1853buf += "\tid rethrow;\n";1854buf += "\t} _fin_force_rethow(_rethrow);";1855}18561857/// RewriteObjCSynchronizedStmt -1858/// This routine rewrites @synchronized(expr) stmt;1859/// into:1860/// objc_sync_enter(expr);1861/// @try stmt @finally { objc_sync_exit(expr); }1862///1863Stmt *RewriteModernObjC::RewriteObjCSynchronizedStmt(ObjCAtSynchronizedStmt *S) {1864// Get the start location and compute the semi location.1865SourceLocation startLoc = S->getBeginLoc();1866const char *startBuf = SM->getCharacterData(startLoc);18671868assert((*startBuf == '@') && "bogus @synchronized location");18691870std::string buf;1871SourceLocation SynchLoc = S->getAtSynchronizedLoc();1872ConvertSourceLocationToLineDirective(SynchLoc, buf);1873buf += "{ id _rethrow = 0; id _sync_obj = (id)";18741875const char *lparenBuf = startBuf;1876while (*lparenBuf != '(') lparenBuf++;1877ReplaceText(startLoc, lparenBuf-startBuf+1, buf);18781879buf = "; objc_sync_enter(_sync_obj);\n";1880buf += "try {\n\tstruct _SYNC_EXIT { _SYNC_EXIT(id arg) : sync_exit(arg) {}";1881buf += "\n\t~_SYNC_EXIT() {objc_sync_exit(sync_exit);}";1882buf += "\n\tid sync_exit;";1883buf += "\n\t} _sync_exit(_sync_obj);\n";18841885// We can't use S->getSynchExpr()->getEndLoc() to find the end location, since1886// the sync expression is typically a message expression that's already1887// been rewritten! (which implies the SourceLocation's are invalid).1888SourceLocation RParenExprLoc = S->getSynchBody()->getBeginLoc();1889const char *RParenExprLocBuf = SM->getCharacterData(RParenExprLoc);1890while (*RParenExprLocBuf != ')') RParenExprLocBuf--;1891RParenExprLoc = startLoc.getLocWithOffset(RParenExprLocBuf-startBuf);18921893SourceLocation LBranceLoc = S->getSynchBody()->getBeginLoc();1894const char *LBraceLocBuf = SM->getCharacterData(LBranceLoc);1895assert (*LBraceLocBuf == '{');1896ReplaceText(RParenExprLoc, (LBraceLocBuf - SM->getCharacterData(RParenExprLoc) + 1), buf);18971898SourceLocation startRBraceLoc = S->getSynchBody()->getEndLoc();1899assert((*SM->getCharacterData(startRBraceLoc) == '}') &&1900"bogus @synchronized block");19011902buf = "} catch (id e) {_rethrow = e;}\n";1903Write_RethrowObject(buf);1904buf += "}\n";1905buf += "}\n";19061907ReplaceText(startRBraceLoc, 1, buf);19081909return nullptr;1910}19111912void RewriteModernObjC::WarnAboutReturnGotoStmts(Stmt *S)1913{1914// Perform a bottom up traversal of all children.1915for (Stmt *SubStmt : S->children())1916if (SubStmt)1917WarnAboutReturnGotoStmts(SubStmt);19181919if (isa<ReturnStmt>(S) || isa<GotoStmt>(S)) {1920Diags.Report(Context->getFullLoc(S->getBeginLoc()),1921TryFinallyContainsReturnDiag);1922}1923}19241925Stmt *RewriteModernObjC::RewriteObjCAutoreleasePoolStmt(ObjCAutoreleasePoolStmt *S) {1926SourceLocation startLoc = S->getAtLoc();1927ReplaceText(startLoc, strlen("@autoreleasepool"), "/* @autoreleasepool */");1928ReplaceText(S->getSubStmt()->getBeginLoc(), 1,1929"{ __AtAutoreleasePool __autoreleasepool; ");19301931return nullptr;1932}19331934Stmt *RewriteModernObjC::RewriteObjCTryStmt(ObjCAtTryStmt *S) {1935ObjCAtFinallyStmt *finalStmt = S->getFinallyStmt();1936bool noCatch = S->getNumCatchStmts() == 0;1937std::string buf;1938SourceLocation TryLocation = S->getAtTryLoc();1939ConvertSourceLocationToLineDirective(TryLocation, buf);19401941if (finalStmt) {1942if (noCatch)1943buf += "{ id volatile _rethrow = 0;\n";1944else {1945buf += "{ id volatile _rethrow = 0;\ntry {\n";1946}1947}1948// Get the start location and compute the semi location.1949SourceLocation startLoc = S->getBeginLoc();1950const char *startBuf = SM->getCharacterData(startLoc);19511952assert((*startBuf == '@') && "bogus @try location");1953if (finalStmt)1954ReplaceText(startLoc, 1, buf);1955else1956// @try -> try1957ReplaceText(startLoc, 1, "");19581959for (ObjCAtCatchStmt *Catch : S->catch_stmts()) {1960VarDecl *catchDecl = Catch->getCatchParamDecl();19611962startLoc = Catch->getBeginLoc();1963bool AtRemoved = false;1964if (catchDecl) {1965QualType t = catchDecl->getType();1966if (const ObjCObjectPointerType *Ptr =1967t->getAs<ObjCObjectPointerType>()) {1968// Should be a pointer to a class.1969ObjCInterfaceDecl *IDecl = Ptr->getObjectType()->getInterface();1970if (IDecl) {1971std::string Result;1972ConvertSourceLocationToLineDirective(Catch->getBeginLoc(), Result);19731974startBuf = SM->getCharacterData(startLoc);1975assert((*startBuf == '@') && "bogus @catch location");1976SourceLocation rParenLoc = Catch->getRParenLoc();1977const char *rParenBuf = SM->getCharacterData(rParenLoc);19781979// _objc_exc_Foo *_e as argument to catch.1980Result += "catch (_objc_exc_"; Result += IDecl->getNameAsString();1981Result += " *_"; Result += catchDecl->getNameAsString();1982Result += ")";1983ReplaceText(startLoc, rParenBuf-startBuf+1, Result);1984// Foo *e = (Foo *)_e;1985Result.clear();1986Result = "{ ";1987Result += IDecl->getNameAsString();1988Result += " *"; Result += catchDecl->getNameAsString();1989Result += " = ("; Result += IDecl->getNameAsString(); Result += "*)";1990Result += "_"; Result += catchDecl->getNameAsString();19911992Result += "; ";1993SourceLocation lBraceLoc = Catch->getCatchBody()->getBeginLoc();1994ReplaceText(lBraceLoc, 1, Result);1995AtRemoved = true;1996}1997}1998}1999if (!AtRemoved)2000// @catch -> catch2001ReplaceText(startLoc, 1, "");20022003}2004if (finalStmt) {2005buf.clear();2006SourceLocation FinallyLoc = finalStmt->getBeginLoc();20072008if (noCatch) {2009ConvertSourceLocationToLineDirective(FinallyLoc, buf);2010buf += "catch (id e) {_rethrow = e;}\n";2011}2012else {2013buf += "}\n";2014ConvertSourceLocationToLineDirective(FinallyLoc, buf);2015buf += "catch (id e) {_rethrow = e;}\n";2016}20172018SourceLocation startFinalLoc = finalStmt->getBeginLoc();2019ReplaceText(startFinalLoc, 8, buf);2020Stmt *body = finalStmt->getFinallyBody();2021SourceLocation startFinalBodyLoc = body->getBeginLoc();2022buf.clear();2023Write_RethrowObject(buf);2024ReplaceText(startFinalBodyLoc, 1, buf);20252026SourceLocation endFinalBodyLoc = body->getEndLoc();2027ReplaceText(endFinalBodyLoc, 1, "}\n}");2028// Now check for any return/continue/go statements within the @try.2029WarnAboutReturnGotoStmts(S->getTryBody());2030}20312032return nullptr;2033}20342035// This can't be done with ReplaceStmt(S, ThrowExpr), since2036// the throw expression is typically a message expression that's already2037// been rewritten! (which implies the SourceLocation's are invalid).2038Stmt *RewriteModernObjC::RewriteObjCThrowStmt(ObjCAtThrowStmt *S) {2039// Get the start location and compute the semi location.2040SourceLocation startLoc = S->getBeginLoc();2041const char *startBuf = SM->getCharacterData(startLoc);20422043assert((*startBuf == '@') && "bogus @throw location");20442045std::string buf;2046/* void objc_exception_throw(id) __attribute__((noreturn)); */2047if (S->getThrowExpr())2048buf = "objc_exception_throw(";2049else2050buf = "throw";20512052// handle "@ throw" correctly.2053const char *wBuf = strchr(startBuf, 'w');2054assert((*wBuf == 'w') && "@throw: can't find 'w'");2055ReplaceText(startLoc, wBuf-startBuf+1, buf);20562057SourceLocation endLoc = S->getEndLoc();2058const char *endBuf = SM->getCharacterData(endLoc);2059const char *semiBuf = strchr(endBuf, ';');2060assert((*semiBuf == ';') && "@throw: can't find ';'");2061SourceLocation semiLoc = startLoc.getLocWithOffset(semiBuf-startBuf);2062if (S->getThrowExpr())2063ReplaceText(semiLoc, 1, ");");2064return nullptr;2065}20662067Stmt *RewriteModernObjC::RewriteAtEncode(ObjCEncodeExpr *Exp) {2068// Create a new string expression.2069std::string StrEncoding;2070Context->getObjCEncodingForType(Exp->getEncodedType(), StrEncoding);2071Expr *Replacement = getStringLiteral(StrEncoding);2072ReplaceStmt(Exp, Replacement);20732074// Replace this subexpr in the parent.2075// delete Exp; leak for now, see RewritePropertyOrImplicitSetter() usage for more info.2076return Replacement;2077}20782079Stmt *RewriteModernObjC::RewriteAtSelector(ObjCSelectorExpr *Exp) {2080if (!SelGetUidFunctionDecl)2081SynthSelGetUidFunctionDecl();2082assert(SelGetUidFunctionDecl && "Can't find sel_registerName() decl");2083// Create a call to sel_registerName("selName").2084SmallVector<Expr*, 8> SelExprs;2085SelExprs.push_back(getStringLiteral(Exp->getSelector().getAsString()));2086CallExpr *SelExp = SynthesizeCallToFunctionDecl(SelGetUidFunctionDecl,2087SelExprs);2088ReplaceStmt(Exp, SelExp);2089// delete Exp; leak for now, see RewritePropertyOrImplicitSetter() usage for more info.2090return SelExp;2091}20922093CallExpr *2094RewriteModernObjC::SynthesizeCallToFunctionDecl(FunctionDecl *FD,2095ArrayRef<Expr *> Args,2096SourceLocation StartLoc,2097SourceLocation EndLoc) {2098// Get the type, we will need to reference it in a couple spots.2099QualType msgSendType = FD->getType();21002101// Create a reference to the objc_msgSend() declaration.2102DeclRefExpr *DRE = new (Context) DeclRefExpr(*Context, FD, false, msgSendType,2103VK_LValue, SourceLocation());21042105// Now, we cast the reference to a pointer to the objc_msgSend type.2106QualType pToFunc = Context->getPointerType(msgSendType);2107ImplicitCastExpr *ICE =2108ImplicitCastExpr::Create(*Context, pToFunc, CK_FunctionToPointerDecay,2109DRE, nullptr, VK_PRValue, FPOptionsOverride());21102111const auto *FT = msgSendType->castAs<FunctionType>();2112CallExpr *Exp =2113CallExpr::Create(*Context, ICE, Args, FT->getCallResultType(*Context),2114VK_PRValue, EndLoc, FPOptionsOverride());2115return Exp;2116}21172118static bool scanForProtocolRefs(const char *startBuf, const char *endBuf,2119const char *&startRef, const char *&endRef) {2120while (startBuf < endBuf) {2121if (*startBuf == '<')2122startRef = startBuf; // mark the start.2123if (*startBuf == '>') {2124if (startRef && *startRef == '<') {2125endRef = startBuf; // mark the end.2126return true;2127}2128return false;2129}2130startBuf++;2131}2132return false;2133}21342135static void scanToNextArgument(const char *&argRef) {2136int angle = 0;2137while (*argRef != ')' && (*argRef != ',' || angle > 0)) {2138if (*argRef == '<')2139angle++;2140else if (*argRef == '>')2141angle--;2142argRef++;2143}2144assert(angle == 0 && "scanToNextArgument - bad protocol type syntax");2145}21462147bool RewriteModernObjC::needToScanForQualifiers(QualType T) {2148if (T->isObjCQualifiedIdType())2149return true;2150if (const PointerType *PT = T->getAs<PointerType>()) {2151if (PT->getPointeeType()->isObjCQualifiedIdType())2152return true;2153}2154if (T->isObjCObjectPointerType()) {2155T = T->getPointeeType();2156return T->isObjCQualifiedInterfaceType();2157}2158if (T->isArrayType()) {2159QualType ElemTy = Context->getBaseElementType(T);2160return needToScanForQualifiers(ElemTy);2161}2162return false;2163}21642165void RewriteModernObjC::RewriteObjCQualifiedInterfaceTypes(Expr *E) {2166QualType Type = E->getType();2167if (needToScanForQualifiers(Type)) {2168SourceLocation Loc, EndLoc;21692170if (const CStyleCastExpr *ECE = dyn_cast<CStyleCastExpr>(E)) {2171Loc = ECE->getLParenLoc();2172EndLoc = ECE->getRParenLoc();2173} else {2174Loc = E->getBeginLoc();2175EndLoc = E->getEndLoc();2176}2177// This will defend against trying to rewrite synthesized expressions.2178if (Loc.isInvalid() || EndLoc.isInvalid())2179return;21802181const char *startBuf = SM->getCharacterData(Loc);2182const char *endBuf = SM->getCharacterData(EndLoc);2183const char *startRef = nullptr, *endRef = nullptr;2184if (scanForProtocolRefs(startBuf, endBuf, startRef, endRef)) {2185// Get the locations of the startRef, endRef.2186SourceLocation LessLoc = Loc.getLocWithOffset(startRef-startBuf);2187SourceLocation GreaterLoc = Loc.getLocWithOffset(endRef-startBuf+1);2188// Comment out the protocol references.2189InsertText(LessLoc, "/*");2190InsertText(GreaterLoc, "*/");2191}2192}2193}21942195void RewriteModernObjC::RewriteObjCQualifiedInterfaceTypes(Decl *Dcl) {2196SourceLocation Loc;2197QualType Type;2198const FunctionProtoType *proto = nullptr;2199if (VarDecl *VD = dyn_cast<VarDecl>(Dcl)) {2200Loc = VD->getLocation();2201Type = VD->getType();2202}2203else if (FunctionDecl *FD = dyn_cast<FunctionDecl>(Dcl)) {2204Loc = FD->getLocation();2205// Check for ObjC 'id' and class types that have been adorned with protocol2206// information (id<p>, C<p>*). The protocol references need to be rewritten!2207const FunctionType *funcType = FD->getType()->getAs<FunctionType>();2208assert(funcType && "missing function type");2209proto = dyn_cast<FunctionProtoType>(funcType);2210if (!proto)2211return;2212Type = proto->getReturnType();2213}2214else if (FieldDecl *FD = dyn_cast<FieldDecl>(Dcl)) {2215Loc = FD->getLocation();2216Type = FD->getType();2217}2218else if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(Dcl)) {2219Loc = TD->getLocation();2220Type = TD->getUnderlyingType();2221}2222else2223return;22242225if (needToScanForQualifiers(Type)) {2226// Since types are unique, we need to scan the buffer.22272228const char *endBuf = SM->getCharacterData(Loc);2229const char *startBuf = endBuf;2230while (*startBuf != ';' && *startBuf != '<' && startBuf != MainFileStart)2231startBuf--; // scan backward (from the decl location) for return type.2232const char *startRef = nullptr, *endRef = nullptr;2233if (scanForProtocolRefs(startBuf, endBuf, startRef, endRef)) {2234// Get the locations of the startRef, endRef.2235SourceLocation LessLoc = Loc.getLocWithOffset(startRef-endBuf);2236SourceLocation GreaterLoc = Loc.getLocWithOffset(endRef-endBuf+1);2237// Comment out the protocol references.2238InsertText(LessLoc, "/*");2239InsertText(GreaterLoc, "*/");2240}2241}2242if (!proto)2243return; // most likely, was a variable2244// Now check arguments.2245const char *startBuf = SM->getCharacterData(Loc);2246const char *startFuncBuf = startBuf;2247for (unsigned i = 0; i < proto->getNumParams(); i++) {2248if (needToScanForQualifiers(proto->getParamType(i))) {2249// Since types are unique, we need to scan the buffer.22502251const char *endBuf = startBuf;2252// scan forward (from the decl location) for argument types.2253scanToNextArgument(endBuf);2254const char *startRef = nullptr, *endRef = nullptr;2255if (scanForProtocolRefs(startBuf, endBuf, startRef, endRef)) {2256// Get the locations of the startRef, endRef.2257SourceLocation LessLoc =2258Loc.getLocWithOffset(startRef-startFuncBuf);2259SourceLocation GreaterLoc =2260Loc.getLocWithOffset(endRef-startFuncBuf+1);2261// Comment out the protocol references.2262InsertText(LessLoc, "/*");2263InsertText(GreaterLoc, "*/");2264}2265startBuf = ++endBuf;2266}2267else {2268// If the function name is derived from a macro expansion, then the2269// argument buffer will not follow the name. Need to speak with Chris.2270while (*startBuf && *startBuf != ')' && *startBuf != ',')2271startBuf++; // scan forward (from the decl location) for argument types.2272startBuf++;2273}2274}2275}22762277void RewriteModernObjC::RewriteTypeOfDecl(VarDecl *ND) {2278QualType QT = ND->getType();2279const Type* TypePtr = QT->getAs<Type>();2280if (!isa<TypeOfExprType>(TypePtr))2281return;2282while (isa<TypeOfExprType>(TypePtr)) {2283const TypeOfExprType *TypeOfExprTypePtr = cast<TypeOfExprType>(TypePtr);2284QT = TypeOfExprTypePtr->getUnderlyingExpr()->getType();2285TypePtr = QT->getAs<Type>();2286}2287// FIXME. This will not work for multiple declarators; as in:2288// __typeof__(a) b,c,d;2289std::string TypeAsString(QT.getAsString(Context->getPrintingPolicy()));2290SourceLocation DeclLoc = ND->getTypeSpecStartLoc();2291const char *startBuf = SM->getCharacterData(DeclLoc);2292if (ND->getInit()) {2293std::string Name(ND->getNameAsString());2294TypeAsString += " " + Name + " = ";2295Expr *E = ND->getInit();2296SourceLocation startLoc;2297if (const CStyleCastExpr *ECE = dyn_cast<CStyleCastExpr>(E))2298startLoc = ECE->getLParenLoc();2299else2300startLoc = E->getBeginLoc();2301startLoc = SM->getExpansionLoc(startLoc);2302const char *endBuf = SM->getCharacterData(startLoc);2303ReplaceText(DeclLoc, endBuf-startBuf-1, TypeAsString);2304}2305else {2306SourceLocation X = ND->getEndLoc();2307X = SM->getExpansionLoc(X);2308const char *endBuf = SM->getCharacterData(X);2309ReplaceText(DeclLoc, endBuf-startBuf-1, TypeAsString);2310}2311}23122313// SynthSelGetUidFunctionDecl - SEL sel_registerName(const char *str);2314void RewriteModernObjC::SynthSelGetUidFunctionDecl() {2315IdentifierInfo *SelGetUidIdent = &Context->Idents.get("sel_registerName");2316SmallVector<QualType, 16> ArgTys;2317ArgTys.push_back(Context->getPointerType(Context->CharTy.withConst()));2318QualType getFuncType =2319getSimpleFunctionType(Context->getObjCSelType(), ArgTys);2320SelGetUidFunctionDecl = FunctionDecl::Create(*Context, TUDecl,2321SourceLocation(),2322SourceLocation(),2323SelGetUidIdent, getFuncType,2324nullptr, SC_Extern);2325}23262327void RewriteModernObjC::RewriteFunctionDecl(FunctionDecl *FD) {2328// declared in <objc/objc.h>2329if (FD->getIdentifier() &&2330FD->getName() == "sel_registerName") {2331SelGetUidFunctionDecl = FD;2332return;2333}2334RewriteObjCQualifiedInterfaceTypes(FD);2335}23362337void RewriteModernObjC::RewriteBlockPointerType(std::string& Str, QualType Type) {2338std::string TypeString(Type.getAsString(Context->getPrintingPolicy()));2339const char *argPtr = TypeString.c_str();2340if (!strchr(argPtr, '^')) {2341Str += TypeString;2342return;2343}2344while (*argPtr) {2345Str += (*argPtr == '^' ? '*' : *argPtr);2346argPtr++;2347}2348}23492350// FIXME. Consolidate this routine with RewriteBlockPointerType.2351void RewriteModernObjC::RewriteBlockPointerTypeVariable(std::string& Str,2352ValueDecl *VD) {2353QualType Type = VD->getType();2354std::string TypeString(Type.getAsString(Context->getPrintingPolicy()));2355const char *argPtr = TypeString.c_str();2356int paren = 0;2357while (*argPtr) {2358switch (*argPtr) {2359case '(':2360Str += *argPtr;2361paren++;2362break;2363case ')':2364Str += *argPtr;2365paren--;2366break;2367case '^':2368Str += '*';2369if (paren == 1)2370Str += VD->getNameAsString();2371break;2372default:2373Str += *argPtr;2374break;2375}2376argPtr++;2377}2378}23792380void RewriteModernObjC::RewriteBlockLiteralFunctionDecl(FunctionDecl *FD) {2381SourceLocation FunLocStart = FD->getTypeSpecStartLoc();2382const FunctionType *funcType = FD->getType()->getAs<FunctionType>();2383const FunctionProtoType *proto = dyn_cast<FunctionProtoType>(funcType);2384if (!proto)2385return;2386QualType Type = proto->getReturnType();2387std::string FdStr = Type.getAsString(Context->getPrintingPolicy());2388FdStr += " ";2389FdStr += FD->getName();2390FdStr += "(";2391unsigned numArgs = proto->getNumParams();2392for (unsigned i = 0; i < numArgs; i++) {2393QualType ArgType = proto->getParamType(i);2394RewriteBlockPointerType(FdStr, ArgType);2395if (i+1 < numArgs)2396FdStr += ", ";2397}2398if (FD->isVariadic()) {2399FdStr += (numArgs > 0) ? ", ...);\n" : "...);\n";2400}2401else2402FdStr += ");\n";2403InsertText(FunLocStart, FdStr);2404}24052406// SynthSuperConstructorFunctionDecl - id __rw_objc_super(id obj, id super);2407void RewriteModernObjC::SynthSuperConstructorFunctionDecl() {2408if (SuperConstructorFunctionDecl)2409return;2410IdentifierInfo *msgSendIdent = &Context->Idents.get("__rw_objc_super");2411SmallVector<QualType, 16> ArgTys;2412QualType argT = Context->getObjCIdType();2413assert(!argT.isNull() && "Can't find 'id' type");2414ArgTys.push_back(argT);2415ArgTys.push_back(argT);2416QualType msgSendType = getSimpleFunctionType(Context->getObjCIdType(),2417ArgTys);2418SuperConstructorFunctionDecl = FunctionDecl::Create(*Context, TUDecl,2419SourceLocation(),2420SourceLocation(),2421msgSendIdent, msgSendType,2422nullptr, SC_Extern);2423}24242425// SynthMsgSendFunctionDecl - id objc_msgSend(id self, SEL op, ...);2426void RewriteModernObjC::SynthMsgSendFunctionDecl() {2427IdentifierInfo *msgSendIdent = &Context->Idents.get("objc_msgSend");2428SmallVector<QualType, 16> ArgTys;2429QualType argT = Context->getObjCIdType();2430assert(!argT.isNull() && "Can't find 'id' type");2431ArgTys.push_back(argT);2432argT = Context->getObjCSelType();2433assert(!argT.isNull() && "Can't find 'SEL' type");2434ArgTys.push_back(argT);2435QualType msgSendType = getSimpleFunctionType(Context->getObjCIdType(),2436ArgTys, /*variadic=*/true);2437MsgSendFunctionDecl = FunctionDecl::Create(*Context, TUDecl,2438SourceLocation(),2439SourceLocation(),2440msgSendIdent, msgSendType, nullptr,2441SC_Extern);2442}24432444// SynthMsgSendSuperFunctionDecl - id objc_msgSendSuper(void);2445void RewriteModernObjC::SynthMsgSendSuperFunctionDecl() {2446IdentifierInfo *msgSendIdent = &Context->Idents.get("objc_msgSendSuper");2447SmallVector<QualType, 2> ArgTys;2448ArgTys.push_back(Context->VoidTy);2449QualType msgSendType = getSimpleFunctionType(Context->getObjCIdType(),2450ArgTys, /*variadic=*/true);2451MsgSendSuperFunctionDecl = FunctionDecl::Create(*Context, TUDecl,2452SourceLocation(),2453SourceLocation(),2454msgSendIdent, msgSendType,2455nullptr, SC_Extern);2456}24572458// SynthMsgSendStretFunctionDecl - id objc_msgSend_stret(id self, SEL op, ...);2459void RewriteModernObjC::SynthMsgSendStretFunctionDecl() {2460IdentifierInfo *msgSendIdent = &Context->Idents.get("objc_msgSend_stret");2461SmallVector<QualType, 16> ArgTys;2462QualType argT = Context->getObjCIdType();2463assert(!argT.isNull() && "Can't find 'id' type");2464ArgTys.push_back(argT);2465argT = Context->getObjCSelType();2466assert(!argT.isNull() && "Can't find 'SEL' type");2467ArgTys.push_back(argT);2468QualType msgSendType = getSimpleFunctionType(Context->getObjCIdType(),2469ArgTys, /*variadic=*/true);2470MsgSendStretFunctionDecl = FunctionDecl::Create(*Context, TUDecl,2471SourceLocation(),2472SourceLocation(),2473msgSendIdent, msgSendType,2474nullptr, SC_Extern);2475}24762477// SynthMsgSendSuperStretFunctionDecl -2478// id objc_msgSendSuper_stret(void);2479void RewriteModernObjC::SynthMsgSendSuperStretFunctionDecl() {2480IdentifierInfo *msgSendIdent =2481&Context->Idents.get("objc_msgSendSuper_stret");2482SmallVector<QualType, 2> ArgTys;2483ArgTys.push_back(Context->VoidTy);2484QualType msgSendType = getSimpleFunctionType(Context->getObjCIdType(),2485ArgTys, /*variadic=*/true);2486MsgSendSuperStretFunctionDecl = FunctionDecl::Create(*Context, TUDecl,2487SourceLocation(),2488SourceLocation(),2489msgSendIdent,2490msgSendType, nullptr,2491SC_Extern);2492}24932494// SynthMsgSendFpretFunctionDecl - double objc_msgSend_fpret(id self, SEL op, ...);2495void RewriteModernObjC::SynthMsgSendFpretFunctionDecl() {2496IdentifierInfo *msgSendIdent = &Context->Idents.get("objc_msgSend_fpret");2497SmallVector<QualType, 16> ArgTys;2498QualType argT = Context->getObjCIdType();2499assert(!argT.isNull() && "Can't find 'id' type");2500ArgTys.push_back(argT);2501argT = Context->getObjCSelType();2502assert(!argT.isNull() && "Can't find 'SEL' type");2503ArgTys.push_back(argT);2504QualType msgSendType = getSimpleFunctionType(Context->DoubleTy,2505ArgTys, /*variadic=*/true);2506MsgSendFpretFunctionDecl = FunctionDecl::Create(*Context, TUDecl,2507SourceLocation(),2508SourceLocation(),2509msgSendIdent, msgSendType,2510nullptr, SC_Extern);2511}25122513// SynthGetClassFunctionDecl - Class objc_getClass(const char *name);2514void RewriteModernObjC::SynthGetClassFunctionDecl() {2515IdentifierInfo *getClassIdent = &Context->Idents.get("objc_getClass");2516SmallVector<QualType, 16> ArgTys;2517ArgTys.push_back(Context->getPointerType(Context->CharTy.withConst()));2518QualType getClassType = getSimpleFunctionType(Context->getObjCClassType(),2519ArgTys);2520GetClassFunctionDecl = FunctionDecl::Create(*Context, TUDecl,2521SourceLocation(),2522SourceLocation(),2523getClassIdent, getClassType,2524nullptr, SC_Extern);2525}25262527// SynthGetSuperClassFunctionDecl - Class class_getSuperclass(Class cls);2528void RewriteModernObjC::SynthGetSuperClassFunctionDecl() {2529IdentifierInfo *getSuperClassIdent =2530&Context->Idents.get("class_getSuperclass");2531SmallVector<QualType, 16> ArgTys;2532ArgTys.push_back(Context->getObjCClassType());2533QualType getClassType = getSimpleFunctionType(Context->getObjCClassType(),2534ArgTys);2535GetSuperClassFunctionDecl = FunctionDecl::Create(*Context, TUDecl,2536SourceLocation(),2537SourceLocation(),2538getSuperClassIdent,2539getClassType, nullptr,2540SC_Extern);2541}25422543// SynthGetMetaClassFunctionDecl - Class objc_getMetaClass(const char *name);2544void RewriteModernObjC::SynthGetMetaClassFunctionDecl() {2545IdentifierInfo *getClassIdent = &Context->Idents.get("objc_getMetaClass");2546SmallVector<QualType, 16> ArgTys;2547ArgTys.push_back(Context->getPointerType(Context->CharTy.withConst()));2548QualType getClassType = getSimpleFunctionType(Context->getObjCClassType(),2549ArgTys);2550GetMetaClassFunctionDecl = FunctionDecl::Create(*Context, TUDecl,2551SourceLocation(),2552SourceLocation(),2553getClassIdent, getClassType,2554nullptr, SC_Extern);2555}25562557Stmt *RewriteModernObjC::RewriteObjCStringLiteral(ObjCStringLiteral *Exp) {2558assert (Exp != nullptr && "Expected non-null ObjCStringLiteral");2559QualType strType = getConstantStringStructType();25602561std::string S = "__NSConstantStringImpl_";25622563std::string tmpName = InFileName;2564unsigned i;2565for (i=0; i < tmpName.length(); i++) {2566char c = tmpName.at(i);2567// replace any non-alphanumeric characters with '_'.2568if (!isAlphanumeric(c))2569tmpName[i] = '_';2570}2571S += tmpName;2572S += "_";2573S += utostr(NumObjCStringLiterals++);25742575Preamble += "static __NSConstantStringImpl " + S;2576Preamble += " __attribute__ ((section (\"__DATA, __cfstring\"))) = {__CFConstantStringClassReference,";2577Preamble += "0x000007c8,"; // utf8_str2578// The pretty printer for StringLiteral handles escape characters properly.2579std::string prettyBufS;2580llvm::raw_string_ostream prettyBuf(prettyBufS);2581Exp->getString()->printPretty(prettyBuf, nullptr, PrintingPolicy(LangOpts));2582Preamble += prettyBufS;2583Preamble += ",";2584Preamble += utostr(Exp->getString()->getByteLength()) + "};\n";25852586VarDecl *NewVD = VarDecl::Create(*Context, TUDecl, SourceLocation(),2587SourceLocation(), &Context->Idents.get(S),2588strType, nullptr, SC_Static);2589DeclRefExpr *DRE = new (Context)2590DeclRefExpr(*Context, NewVD, false, strType, VK_LValue, SourceLocation());2591Expr *Unop = UnaryOperator::Create(2592const_cast<ASTContext &>(*Context), DRE, UO_AddrOf,2593Context->getPointerType(DRE->getType()), VK_PRValue, OK_Ordinary,2594SourceLocation(), false, FPOptionsOverride());2595// cast to NSConstantString *2596CastExpr *cast = NoTypeInfoCStyleCastExpr(Context, Exp->getType(),2597CK_CPointerToObjCPointerCast, Unop);2598ReplaceStmt(Exp, cast);2599// delete Exp; leak for now, see RewritePropertyOrImplicitSetter() usage for more info.2600return cast;2601}26022603Stmt *RewriteModernObjC::RewriteObjCBoolLiteralExpr(ObjCBoolLiteralExpr *Exp) {2604unsigned IntSize =2605static_cast<unsigned>(Context->getTypeSize(Context->IntTy));26062607Expr *FlagExp = IntegerLiteral::Create(*Context,2608llvm::APInt(IntSize, Exp->getValue()),2609Context->IntTy, Exp->getLocation());2610CastExpr *cast = NoTypeInfoCStyleCastExpr(Context, Context->ObjCBuiltinBoolTy,2611CK_BitCast, FlagExp);2612ParenExpr *PE = new (Context) ParenExpr(Exp->getLocation(), Exp->getExprLoc(),2613cast);2614ReplaceStmt(Exp, PE);2615return PE;2616}26172618Stmt *RewriteModernObjC::RewriteObjCBoxedExpr(ObjCBoxedExpr *Exp) {2619// synthesize declaration of helper functions needed in this routine.2620if (!SelGetUidFunctionDecl)2621SynthSelGetUidFunctionDecl();2622// use objc_msgSend() for all.2623if (!MsgSendFunctionDecl)2624SynthMsgSendFunctionDecl();2625if (!GetClassFunctionDecl)2626SynthGetClassFunctionDecl();26272628FunctionDecl *MsgSendFlavor = MsgSendFunctionDecl;2629SourceLocation StartLoc = Exp->getBeginLoc();2630SourceLocation EndLoc = Exp->getEndLoc();26312632// Synthesize a call to objc_msgSend().2633SmallVector<Expr*, 4> MsgExprs;2634SmallVector<Expr*, 4> ClsExprs;26352636// Create a call to objc_getClass("<BoxingClass>"). It will be the 1st argument.2637ObjCMethodDecl *BoxingMethod = Exp->getBoxingMethod();2638ObjCInterfaceDecl *BoxingClass = BoxingMethod->getClassInterface();26392640IdentifierInfo *clsName = BoxingClass->getIdentifier();2641ClsExprs.push_back(getStringLiteral(clsName->getName()));2642CallExpr *Cls = SynthesizeCallToFunctionDecl(GetClassFunctionDecl, ClsExprs,2643StartLoc, EndLoc);2644MsgExprs.push_back(Cls);26452646// Create a call to sel_registerName("<BoxingMethod>:"), etc.2647// it will be the 2nd argument.2648SmallVector<Expr*, 4> SelExprs;2649SelExprs.push_back(2650getStringLiteral(BoxingMethod->getSelector().getAsString()));2651CallExpr *SelExp = SynthesizeCallToFunctionDecl(SelGetUidFunctionDecl,2652SelExprs, StartLoc, EndLoc);2653MsgExprs.push_back(SelExp);26542655// User provided sub-expression is the 3rd, and last, argument.2656Expr *subExpr = Exp->getSubExpr();2657if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(subExpr)) {2658QualType type = ICE->getType();2659const Expr *SubExpr = ICE->IgnoreParenImpCasts();2660CastKind CK = CK_BitCast;2661if (SubExpr->getType()->isIntegralType(*Context) && type->isBooleanType())2662CK = CK_IntegralToBoolean;2663subExpr = NoTypeInfoCStyleCastExpr(Context, type, CK, subExpr);2664}2665MsgExprs.push_back(subExpr);26662667SmallVector<QualType, 4> ArgTypes;2668ArgTypes.push_back(Context->getObjCClassType());2669ArgTypes.push_back(Context->getObjCSelType());2670for (const auto PI : BoxingMethod->parameters())2671ArgTypes.push_back(PI->getType());26722673QualType returnType = Exp->getType();2674// Get the type, we will need to reference it in a couple spots.2675QualType msgSendType = MsgSendFlavor->getType();26762677// Create a reference to the objc_msgSend() declaration.2678DeclRefExpr *DRE = new (Context) DeclRefExpr(2679*Context, MsgSendFlavor, false, msgSendType, VK_LValue, SourceLocation());26802681CastExpr *cast = NoTypeInfoCStyleCastExpr(2682Context, Context->getPointerType(Context->VoidTy), CK_BitCast, DRE);26832684// Now do the "normal" pointer to function cast.2685QualType castType =2686getSimpleFunctionType(returnType, ArgTypes, BoxingMethod->isVariadic());2687castType = Context->getPointerType(castType);2688cast = NoTypeInfoCStyleCastExpr(Context, castType, CK_BitCast,2689cast);26902691// Don't forget the parens to enforce the proper binding.2692ParenExpr *PE = new (Context) ParenExpr(StartLoc, EndLoc, cast);26932694auto *FT = msgSendType->castAs<FunctionType>();2695CallExpr *CE = CallExpr::Create(*Context, PE, MsgExprs, FT->getReturnType(),2696VK_PRValue, EndLoc, FPOptionsOverride());2697ReplaceStmt(Exp, CE);2698return CE;2699}27002701Stmt *RewriteModernObjC::RewriteObjCArrayLiteralExpr(ObjCArrayLiteral *Exp) {2702// synthesize declaration of helper functions needed in this routine.2703if (!SelGetUidFunctionDecl)2704SynthSelGetUidFunctionDecl();2705// use objc_msgSend() for all.2706if (!MsgSendFunctionDecl)2707SynthMsgSendFunctionDecl();2708if (!GetClassFunctionDecl)2709SynthGetClassFunctionDecl();27102711FunctionDecl *MsgSendFlavor = MsgSendFunctionDecl;2712SourceLocation StartLoc = Exp->getBeginLoc();2713SourceLocation EndLoc = Exp->getEndLoc();27142715// Build the expression: __NSContainer_literal(int, ...).arr2716QualType IntQT = Context->IntTy;2717QualType NSArrayFType =2718getSimpleFunctionType(Context->VoidTy, IntQT, true);2719std::string NSArrayFName("__NSContainer_literal");2720FunctionDecl *NSArrayFD = SynthBlockInitFunctionDecl(NSArrayFName);2721DeclRefExpr *NSArrayDRE = new (Context) DeclRefExpr(2722*Context, NSArrayFD, false, NSArrayFType, VK_PRValue, SourceLocation());27232724SmallVector<Expr*, 16> InitExprs;2725unsigned NumElements = Exp->getNumElements();2726unsigned UnsignedIntSize =2727static_cast<unsigned>(Context->getTypeSize(Context->UnsignedIntTy));2728Expr *count = IntegerLiteral::Create(*Context,2729llvm::APInt(UnsignedIntSize, NumElements),2730Context->UnsignedIntTy, SourceLocation());2731InitExprs.push_back(count);2732for (unsigned i = 0; i < NumElements; i++)2733InitExprs.push_back(Exp->getElement(i));2734Expr *NSArrayCallExpr =2735CallExpr::Create(*Context, NSArrayDRE, InitExprs, NSArrayFType, VK_LValue,2736SourceLocation(), FPOptionsOverride());27372738FieldDecl *ARRFD = FieldDecl::Create(*Context, nullptr, SourceLocation(),2739SourceLocation(),2740&Context->Idents.get("arr"),2741Context->getPointerType(Context->VoidPtrTy),2742nullptr, /*BitWidth=*/nullptr,2743/*Mutable=*/true, ICIS_NoInit);2744MemberExpr *ArrayLiteralME =2745MemberExpr::CreateImplicit(*Context, NSArrayCallExpr, false, ARRFD,2746ARRFD->getType(), VK_LValue, OK_Ordinary);2747QualType ConstIdT = Context->getObjCIdType().withConst();2748CStyleCastExpr * ArrayLiteralObjects =2749NoTypeInfoCStyleCastExpr(Context,2750Context->getPointerType(ConstIdT),2751CK_BitCast,2752ArrayLiteralME);27532754// Synthesize a call to objc_msgSend().2755SmallVector<Expr*, 32> MsgExprs;2756SmallVector<Expr*, 4> ClsExprs;2757QualType expType = Exp->getType();27582759// Create a call to objc_getClass("NSArray"). It will be th 1st argument.2760ObjCInterfaceDecl *Class =2761expType->getPointeeType()->castAs<ObjCObjectType>()->getInterface();27622763IdentifierInfo *clsName = Class->getIdentifier();2764ClsExprs.push_back(getStringLiteral(clsName->getName()));2765CallExpr *Cls = SynthesizeCallToFunctionDecl(GetClassFunctionDecl, ClsExprs,2766StartLoc, EndLoc);2767MsgExprs.push_back(Cls);27682769// Create a call to sel_registerName("arrayWithObjects:count:").2770// it will be the 2nd argument.2771SmallVector<Expr*, 4> SelExprs;2772ObjCMethodDecl *ArrayMethod = Exp->getArrayWithObjectsMethod();2773SelExprs.push_back(2774getStringLiteral(ArrayMethod->getSelector().getAsString()));2775CallExpr *SelExp = SynthesizeCallToFunctionDecl(SelGetUidFunctionDecl,2776SelExprs, StartLoc, EndLoc);2777MsgExprs.push_back(SelExp);27782779// (const id [])objects2780MsgExprs.push_back(ArrayLiteralObjects);27812782// (NSUInteger)cnt2783Expr *cnt = IntegerLiteral::Create(*Context,2784llvm::APInt(UnsignedIntSize, NumElements),2785Context->UnsignedIntTy, SourceLocation());2786MsgExprs.push_back(cnt);27872788SmallVector<QualType, 4> ArgTypes;2789ArgTypes.push_back(Context->getObjCClassType());2790ArgTypes.push_back(Context->getObjCSelType());2791for (const auto *PI : ArrayMethod->parameters())2792ArgTypes.push_back(PI->getType());27932794QualType returnType = Exp->getType();2795// Get the type, we will need to reference it in a couple spots.2796QualType msgSendType = MsgSendFlavor->getType();27972798// Create a reference to the objc_msgSend() declaration.2799DeclRefExpr *DRE = new (Context) DeclRefExpr(2800*Context, MsgSendFlavor, false, msgSendType, VK_LValue, SourceLocation());28012802CastExpr *cast = NoTypeInfoCStyleCastExpr(2803Context, Context->getPointerType(Context->VoidTy), CK_BitCast, DRE);28042805// Now do the "normal" pointer to function cast.2806QualType castType =2807getSimpleFunctionType(returnType, ArgTypes, ArrayMethod->isVariadic());2808castType = Context->getPointerType(castType);2809cast = NoTypeInfoCStyleCastExpr(Context, castType, CK_BitCast,2810cast);28112812// Don't forget the parens to enforce the proper binding.2813ParenExpr *PE = new (Context) ParenExpr(StartLoc, EndLoc, cast);28142815const FunctionType *FT = msgSendType->castAs<FunctionType>();2816CallExpr *CE = CallExpr::Create(*Context, PE, MsgExprs, FT->getReturnType(),2817VK_PRValue, EndLoc, FPOptionsOverride());2818ReplaceStmt(Exp, CE);2819return CE;2820}28212822Stmt *RewriteModernObjC::RewriteObjCDictionaryLiteralExpr(ObjCDictionaryLiteral *Exp) {2823// synthesize declaration of helper functions needed in this routine.2824if (!SelGetUidFunctionDecl)2825SynthSelGetUidFunctionDecl();2826// use objc_msgSend() for all.2827if (!MsgSendFunctionDecl)2828SynthMsgSendFunctionDecl();2829if (!GetClassFunctionDecl)2830SynthGetClassFunctionDecl();28312832FunctionDecl *MsgSendFlavor = MsgSendFunctionDecl;2833SourceLocation StartLoc = Exp->getBeginLoc();2834SourceLocation EndLoc = Exp->getEndLoc();28352836// Build the expression: __NSContainer_literal(int, ...).arr2837QualType IntQT = Context->IntTy;2838QualType NSDictFType =2839getSimpleFunctionType(Context->VoidTy, IntQT, true);2840std::string NSDictFName("__NSContainer_literal");2841FunctionDecl *NSDictFD = SynthBlockInitFunctionDecl(NSDictFName);2842DeclRefExpr *NSDictDRE = new (Context) DeclRefExpr(2843*Context, NSDictFD, false, NSDictFType, VK_PRValue, SourceLocation());28442845SmallVector<Expr*, 16> KeyExprs;2846SmallVector<Expr*, 16> ValueExprs;28472848unsigned NumElements = Exp->getNumElements();2849unsigned UnsignedIntSize =2850static_cast<unsigned>(Context->getTypeSize(Context->UnsignedIntTy));2851Expr *count = IntegerLiteral::Create(*Context,2852llvm::APInt(UnsignedIntSize, NumElements),2853Context->UnsignedIntTy, SourceLocation());2854KeyExprs.push_back(count);2855ValueExprs.push_back(count);2856for (unsigned i = 0; i < NumElements; i++) {2857ObjCDictionaryElement Element = Exp->getKeyValueElement(i);2858KeyExprs.push_back(Element.Key);2859ValueExprs.push_back(Element.Value);2860}28612862// (const id [])objects2863Expr *NSValueCallExpr =2864CallExpr::Create(*Context, NSDictDRE, ValueExprs, NSDictFType, VK_LValue,2865SourceLocation(), FPOptionsOverride());28662867FieldDecl *ARRFD = FieldDecl::Create(*Context, nullptr, SourceLocation(),2868SourceLocation(),2869&Context->Idents.get("arr"),2870Context->getPointerType(Context->VoidPtrTy),2871nullptr, /*BitWidth=*/nullptr,2872/*Mutable=*/true, ICIS_NoInit);2873MemberExpr *DictLiteralValueME =2874MemberExpr::CreateImplicit(*Context, NSValueCallExpr, false, ARRFD,2875ARRFD->getType(), VK_LValue, OK_Ordinary);2876QualType ConstIdT = Context->getObjCIdType().withConst();2877CStyleCastExpr * DictValueObjects =2878NoTypeInfoCStyleCastExpr(Context,2879Context->getPointerType(ConstIdT),2880CK_BitCast,2881DictLiteralValueME);2882// (const id <NSCopying> [])keys2883Expr *NSKeyCallExpr =2884CallExpr::Create(*Context, NSDictDRE, KeyExprs, NSDictFType, VK_LValue,2885SourceLocation(), FPOptionsOverride());28862887MemberExpr *DictLiteralKeyME =2888MemberExpr::CreateImplicit(*Context, NSKeyCallExpr, false, ARRFD,2889ARRFD->getType(), VK_LValue, OK_Ordinary);28902891CStyleCastExpr * DictKeyObjects =2892NoTypeInfoCStyleCastExpr(Context,2893Context->getPointerType(ConstIdT),2894CK_BitCast,2895DictLiteralKeyME);28962897// Synthesize a call to objc_msgSend().2898SmallVector<Expr*, 32> MsgExprs;2899SmallVector<Expr*, 4> ClsExprs;2900QualType expType = Exp->getType();29012902// Create a call to objc_getClass("NSArray"). It will be th 1st argument.2903ObjCInterfaceDecl *Class =2904expType->getPointeeType()->castAs<ObjCObjectType>()->getInterface();29052906IdentifierInfo *clsName = Class->getIdentifier();2907ClsExprs.push_back(getStringLiteral(clsName->getName()));2908CallExpr *Cls = SynthesizeCallToFunctionDecl(GetClassFunctionDecl, ClsExprs,2909StartLoc, EndLoc);2910MsgExprs.push_back(Cls);29112912// Create a call to sel_registerName("arrayWithObjects:count:").2913// it will be the 2nd argument.2914SmallVector<Expr*, 4> SelExprs;2915ObjCMethodDecl *DictMethod = Exp->getDictWithObjectsMethod();2916SelExprs.push_back(getStringLiteral(DictMethod->getSelector().getAsString()));2917CallExpr *SelExp = SynthesizeCallToFunctionDecl(SelGetUidFunctionDecl,2918SelExprs, StartLoc, EndLoc);2919MsgExprs.push_back(SelExp);29202921// (const id [])objects2922MsgExprs.push_back(DictValueObjects);29232924// (const id <NSCopying> [])keys2925MsgExprs.push_back(DictKeyObjects);29262927// (NSUInteger)cnt2928Expr *cnt = IntegerLiteral::Create(*Context,2929llvm::APInt(UnsignedIntSize, NumElements),2930Context->UnsignedIntTy, SourceLocation());2931MsgExprs.push_back(cnt);29322933SmallVector<QualType, 8> ArgTypes;2934ArgTypes.push_back(Context->getObjCClassType());2935ArgTypes.push_back(Context->getObjCSelType());2936for (const auto *PI : DictMethod->parameters()) {2937QualType T = PI->getType();2938if (const PointerType* PT = T->getAs<PointerType>()) {2939QualType PointeeTy = PT->getPointeeType();2940convertToUnqualifiedObjCType(PointeeTy);2941T = Context->getPointerType(PointeeTy);2942}2943ArgTypes.push_back(T);2944}29452946QualType returnType = Exp->getType();2947// Get the type, we will need to reference it in a couple spots.2948QualType msgSendType = MsgSendFlavor->getType();29492950// Create a reference to the objc_msgSend() declaration.2951DeclRefExpr *DRE = new (Context) DeclRefExpr(2952*Context, MsgSendFlavor, false, msgSendType, VK_LValue, SourceLocation());29532954CastExpr *cast = NoTypeInfoCStyleCastExpr(2955Context, Context->getPointerType(Context->VoidTy), CK_BitCast, DRE);29562957// Now do the "normal" pointer to function cast.2958QualType castType =2959getSimpleFunctionType(returnType, ArgTypes, DictMethod->isVariadic());2960castType = Context->getPointerType(castType);2961cast = NoTypeInfoCStyleCastExpr(Context, castType, CK_BitCast,2962cast);29632964// Don't forget the parens to enforce the proper binding.2965ParenExpr *PE = new (Context) ParenExpr(StartLoc, EndLoc, cast);29662967const FunctionType *FT = msgSendType->castAs<FunctionType>();2968CallExpr *CE = CallExpr::Create(*Context, PE, MsgExprs, FT->getReturnType(),2969VK_PRValue, EndLoc, FPOptionsOverride());2970ReplaceStmt(Exp, CE);2971return CE;2972}29732974// struct __rw_objc_super {2975// struct objc_object *object; struct objc_object *superClass;2976// };2977QualType RewriteModernObjC::getSuperStructType() {2978if (!SuperStructDecl) {2979SuperStructDecl = RecordDecl::Create(2980*Context, TagTypeKind::Struct, TUDecl, SourceLocation(),2981SourceLocation(), &Context->Idents.get("__rw_objc_super"));2982QualType FieldTypes[2];29832984// struct objc_object *object;2985FieldTypes[0] = Context->getObjCIdType();2986// struct objc_object *superClass;2987FieldTypes[1] = Context->getObjCIdType();29882989// Create fields2990for (unsigned i = 0; i < 2; ++i) {2991SuperStructDecl->addDecl(FieldDecl::Create(*Context, SuperStructDecl,2992SourceLocation(),2993SourceLocation(), nullptr,2994FieldTypes[i], nullptr,2995/*BitWidth=*/nullptr,2996/*Mutable=*/false,2997ICIS_NoInit));2998}29993000SuperStructDecl->completeDefinition();3001}3002return Context->getTagDeclType(SuperStructDecl);3003}30043005QualType RewriteModernObjC::getConstantStringStructType() {3006if (!ConstantStringDecl) {3007ConstantStringDecl = RecordDecl::Create(3008*Context, TagTypeKind::Struct, TUDecl, SourceLocation(),3009SourceLocation(), &Context->Idents.get("__NSConstantStringImpl"));3010QualType FieldTypes[4];30113012// struct objc_object *receiver;3013FieldTypes[0] = Context->getObjCIdType();3014// int flags;3015FieldTypes[1] = Context->IntTy;3016// char *str;3017FieldTypes[2] = Context->getPointerType(Context->CharTy);3018// long length;3019FieldTypes[3] = Context->LongTy;30203021// Create fields3022for (unsigned i = 0; i < 4; ++i) {3023ConstantStringDecl->addDecl(FieldDecl::Create(*Context,3024ConstantStringDecl,3025SourceLocation(),3026SourceLocation(), nullptr,3027FieldTypes[i], nullptr,3028/*BitWidth=*/nullptr,3029/*Mutable=*/true,3030ICIS_NoInit));3031}30323033ConstantStringDecl->completeDefinition();3034}3035return Context->getTagDeclType(ConstantStringDecl);3036}30373038/// getFunctionSourceLocation - returns start location of a function3039/// definition. Complication arises when function has declared as3040/// extern "C" or extern "C" {...}3041static SourceLocation getFunctionSourceLocation (RewriteModernObjC &R,3042FunctionDecl *FD) {3043if (FD->isExternC() && !FD->isMain()) {3044const DeclContext *DC = FD->getDeclContext();3045if (const LinkageSpecDecl *LSD = dyn_cast<LinkageSpecDecl>(DC))3046// if it is extern "C" {...}, return function decl's own location.3047if (!LSD->getRBraceLoc().isValid())3048return LSD->getExternLoc();3049}3050if (FD->getStorageClass() != SC_None)3051R.RewriteBlockLiteralFunctionDecl(FD);3052return FD->getTypeSpecStartLoc();3053}30543055void RewriteModernObjC::RewriteLineDirective(const Decl *D) {30563057SourceLocation Location = D->getLocation();30583059if (Location.isFileID() && GenerateLineInfo) {3060std::string LineString("\n#line ");3061PresumedLoc PLoc = SM->getPresumedLoc(Location);3062LineString += utostr(PLoc.getLine());3063LineString += " \"";3064LineString += Lexer::Stringify(PLoc.getFilename());3065if (isa<ObjCMethodDecl>(D))3066LineString += "\"";3067else LineString += "\"\n";30683069Location = D->getBeginLoc();3070if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {3071if (FD->isExternC() && !FD->isMain()) {3072const DeclContext *DC = FD->getDeclContext();3073if (const LinkageSpecDecl *LSD = dyn_cast<LinkageSpecDecl>(DC))3074// if it is extern "C" {...}, return function decl's own location.3075if (!LSD->getRBraceLoc().isValid())3076Location = LSD->getExternLoc();3077}3078}3079InsertText(Location, LineString);3080}3081}30823083/// SynthMsgSendStretCallExpr - This routine translates message expression3084/// into a call to objc_msgSend_stret() entry point. Tricky part is that3085/// nil check on receiver must be performed before calling objc_msgSend_stret.3086/// MsgSendStretFlavor - function declaration objc_msgSend_stret(...)3087/// msgSendType - function type of objc_msgSend_stret(...)3088/// returnType - Result type of the method being synthesized.3089/// ArgTypes - type of the arguments passed to objc_msgSend_stret, starting with receiver type.3090/// MsgExprs - list of argument expressions being passed to objc_msgSend_stret,3091/// starting with receiver.3092/// Method - Method being rewritten.3093Expr *RewriteModernObjC::SynthMsgSendStretCallExpr(FunctionDecl *MsgSendStretFlavor,3094QualType returnType,3095SmallVectorImpl<QualType> &ArgTypes,3096SmallVectorImpl<Expr*> &MsgExprs,3097ObjCMethodDecl *Method) {3098// Now do the "normal" pointer to function cast.3099QualType FuncType = getSimpleFunctionType(3100returnType, ArgTypes, Method ? Method->isVariadic() : false);3101QualType castType = Context->getPointerType(FuncType);31023103// build type for containing the objc_msgSend_stret object.3104static unsigned stretCount=0;3105std::string name = "__Stret"; name += utostr(stretCount);3106std::string str =3107"extern \"C\" void * __cdecl memset(void *_Dst, int _Val, size_t _Size);\n";3108str += "namespace {\n";3109str += "struct "; str += name;3110str += " {\n\t";3111str += name;3112str += "(id receiver, SEL sel";3113for (unsigned i = 2; i < ArgTypes.size(); i++) {3114std::string ArgName = "arg"; ArgName += utostr(i);3115ArgTypes[i].getAsStringInternal(ArgName, Context->getPrintingPolicy());3116str += ", "; str += ArgName;3117}3118// could be vararg.3119for (unsigned i = ArgTypes.size(); i < MsgExprs.size(); i++) {3120std::string ArgName = "arg"; ArgName += utostr(i);3121MsgExprs[i]->getType().getAsStringInternal(ArgName,3122Context->getPrintingPolicy());3123str += ", "; str += ArgName;3124}31253126str += ") {\n";3127str += "\t unsigned size = sizeof(";3128str += returnType.getAsString(Context->getPrintingPolicy()); str += ");\n";31293130str += "\t if (size == 1 || size == 2 || size == 4 || size == 8)\n";31313132str += "\t s = (("; str += castType.getAsString(Context->getPrintingPolicy());3133str += ")(void *)objc_msgSend)(receiver, sel";3134for (unsigned i = 2; i < ArgTypes.size(); i++) {3135str += ", arg"; str += utostr(i);3136}3137// could be vararg.3138for (unsigned i = ArgTypes.size(); i < MsgExprs.size(); i++) {3139str += ", arg"; str += utostr(i);3140}3141str+= ");\n";31423143str += "\t else if (receiver == 0)\n";3144str += "\t memset((void*)&s, 0, sizeof(s));\n";3145str += "\t else\n";31463147str += "\t s = (("; str += castType.getAsString(Context->getPrintingPolicy());3148str += ")(void *)objc_msgSend_stret)(receiver, sel";3149for (unsigned i = 2; i < ArgTypes.size(); i++) {3150str += ", arg"; str += utostr(i);3151}3152// could be vararg.3153for (unsigned i = ArgTypes.size(); i < MsgExprs.size(); i++) {3154str += ", arg"; str += utostr(i);3155}3156str += ");\n";31573158str += "\t}\n";3159str += "\t"; str += returnType.getAsString(Context->getPrintingPolicy());3160str += " s;\n";3161str += "};\n};\n\n";3162SourceLocation FunLocStart;3163if (CurFunctionDef)3164FunLocStart = getFunctionSourceLocation(*this, CurFunctionDef);3165else {3166assert(CurMethodDef && "SynthMsgSendStretCallExpr - CurMethodDef is null");3167FunLocStart = CurMethodDef->getBeginLoc();3168}31693170InsertText(FunLocStart, str);3171++stretCount;31723173// AST for __Stretn(receiver, args).s;3174IdentifierInfo *ID = &Context->Idents.get(name);3175FunctionDecl *FD =3176FunctionDecl::Create(*Context, TUDecl, SourceLocation(), SourceLocation(),3177ID, FuncType, nullptr, SC_Extern, false, false);3178DeclRefExpr *DRE = new (Context)3179DeclRefExpr(*Context, FD, false, castType, VK_PRValue, SourceLocation());3180CallExpr *STCE =3181CallExpr::Create(*Context, DRE, MsgExprs, castType, VK_LValue,3182SourceLocation(), FPOptionsOverride());31833184FieldDecl *FieldD = FieldDecl::Create(*Context, nullptr, SourceLocation(),3185SourceLocation(),3186&Context->Idents.get("s"),3187returnType, nullptr,3188/*BitWidth=*/nullptr,3189/*Mutable=*/true, ICIS_NoInit);3190MemberExpr *ME = MemberExpr::CreateImplicit(3191*Context, STCE, false, FieldD, FieldD->getType(), VK_LValue, OK_Ordinary);31923193return ME;3194}31953196Stmt *RewriteModernObjC::SynthMessageExpr(ObjCMessageExpr *Exp,3197SourceLocation StartLoc,3198SourceLocation EndLoc) {3199if (!SelGetUidFunctionDecl)3200SynthSelGetUidFunctionDecl();3201if (!MsgSendFunctionDecl)3202SynthMsgSendFunctionDecl();3203if (!MsgSendSuperFunctionDecl)3204SynthMsgSendSuperFunctionDecl();3205if (!MsgSendStretFunctionDecl)3206SynthMsgSendStretFunctionDecl();3207if (!MsgSendSuperStretFunctionDecl)3208SynthMsgSendSuperStretFunctionDecl();3209if (!MsgSendFpretFunctionDecl)3210SynthMsgSendFpretFunctionDecl();3211if (!GetClassFunctionDecl)3212SynthGetClassFunctionDecl();3213if (!GetSuperClassFunctionDecl)3214SynthGetSuperClassFunctionDecl();3215if (!GetMetaClassFunctionDecl)3216SynthGetMetaClassFunctionDecl();32173218// default to objc_msgSend().3219FunctionDecl *MsgSendFlavor = MsgSendFunctionDecl;3220// May need to use objc_msgSend_stret() as well.3221FunctionDecl *MsgSendStretFlavor = nullptr;3222if (ObjCMethodDecl *mDecl = Exp->getMethodDecl()) {3223QualType resultType = mDecl->getReturnType();3224if (resultType->isRecordType())3225MsgSendStretFlavor = MsgSendStretFunctionDecl;3226else if (resultType->isRealFloatingType())3227MsgSendFlavor = MsgSendFpretFunctionDecl;3228}32293230// Synthesize a call to objc_msgSend().3231SmallVector<Expr*, 8> MsgExprs;3232switch (Exp->getReceiverKind()) {3233case ObjCMessageExpr::SuperClass: {3234MsgSendFlavor = MsgSendSuperFunctionDecl;3235if (MsgSendStretFlavor)3236MsgSendStretFlavor = MsgSendSuperStretFunctionDecl;3237assert(MsgSendFlavor && "MsgSendFlavor is NULL!");32383239ObjCInterfaceDecl *ClassDecl = CurMethodDef->getClassInterface();32403241SmallVector<Expr*, 4> InitExprs;32423243// set the receiver to self, the first argument to all methods.3244InitExprs.push_back(NoTypeInfoCStyleCastExpr(3245Context, Context->getObjCIdType(), CK_BitCast,3246new (Context) DeclRefExpr(*Context, CurMethodDef->getSelfDecl(), false,3247Context->getObjCIdType(), VK_PRValue,3248SourceLocation()))); // set the 'receiver'.32493250// (id)class_getSuperclass((Class)objc_getClass("CurrentClass"))3251SmallVector<Expr*, 8> ClsExprs;3252ClsExprs.push_back(getStringLiteral(ClassDecl->getIdentifier()->getName()));3253// (Class)objc_getClass("CurrentClass")3254CallExpr *Cls = SynthesizeCallToFunctionDecl(GetMetaClassFunctionDecl,3255ClsExprs, StartLoc, EndLoc);3256ClsExprs.clear();3257ClsExprs.push_back(Cls);3258Cls = SynthesizeCallToFunctionDecl(GetSuperClassFunctionDecl, ClsExprs,3259StartLoc, EndLoc);32603261// (id)class_getSuperclass((Class)objc_getClass("CurrentClass"))3262// To turn off a warning, type-cast to 'id'3263InitExprs.push_back( // set 'super class', using class_getSuperclass().3264NoTypeInfoCStyleCastExpr(Context,3265Context->getObjCIdType(),3266CK_BitCast, Cls));3267// struct __rw_objc_super3268QualType superType = getSuperStructType();3269Expr *SuperRep;32703271if (LangOpts.MicrosoftExt) {3272SynthSuperConstructorFunctionDecl();3273// Simulate a constructor call...3274DeclRefExpr *DRE = new (Context)3275DeclRefExpr(*Context, SuperConstructorFunctionDecl, false, superType,3276VK_LValue, SourceLocation());3277SuperRep =3278CallExpr::Create(*Context, DRE, InitExprs, superType, VK_LValue,3279SourceLocation(), FPOptionsOverride());3280// The code for super is a little tricky to prevent collision with3281// the structure definition in the header. The rewriter has it's own3282// internal definition (__rw_objc_super) that is uses. This is why3283// we need the cast below. For example:3284// (struct __rw_objc_super *)&__rw_objc_super((id)self, (id)objc_getClass("SUPER"))3285//3286SuperRep = UnaryOperator::Create(3287const_cast<ASTContext &>(*Context), SuperRep, UO_AddrOf,3288Context->getPointerType(SuperRep->getType()), VK_PRValue, OK_Ordinary,3289SourceLocation(), false, FPOptionsOverride());3290SuperRep = NoTypeInfoCStyleCastExpr(Context,3291Context->getPointerType(superType),3292CK_BitCast, SuperRep);3293} else {3294// (struct __rw_objc_super) { <exprs from above> }3295InitListExpr *ILE =3296new (Context) InitListExpr(*Context, SourceLocation(), InitExprs,3297SourceLocation());3298TypeSourceInfo *superTInfo3299= Context->getTrivialTypeSourceInfo(superType);3300SuperRep = new (Context) CompoundLiteralExpr(SourceLocation(), superTInfo,3301superType, VK_LValue,3302ILE, false);3303// struct __rw_objc_super *3304SuperRep = UnaryOperator::Create(3305const_cast<ASTContext &>(*Context), SuperRep, UO_AddrOf,3306Context->getPointerType(SuperRep->getType()), VK_PRValue, OK_Ordinary,3307SourceLocation(), false, FPOptionsOverride());3308}3309MsgExprs.push_back(SuperRep);3310break;3311}33123313case ObjCMessageExpr::Class: {3314SmallVector<Expr*, 8> ClsExprs;3315ObjCInterfaceDecl *Class3316= Exp->getClassReceiver()->castAs<ObjCObjectType>()->getInterface();3317IdentifierInfo *clsName = Class->getIdentifier();3318ClsExprs.push_back(getStringLiteral(clsName->getName()));3319CallExpr *Cls = SynthesizeCallToFunctionDecl(GetClassFunctionDecl, ClsExprs,3320StartLoc, EndLoc);3321CastExpr *ArgExpr = NoTypeInfoCStyleCastExpr(Context,3322Context->getObjCIdType(),3323CK_BitCast, Cls);3324MsgExprs.push_back(ArgExpr);3325break;3326}33273328case ObjCMessageExpr::SuperInstance:{3329MsgSendFlavor = MsgSendSuperFunctionDecl;3330if (MsgSendStretFlavor)3331MsgSendStretFlavor = MsgSendSuperStretFunctionDecl;3332assert(MsgSendFlavor && "MsgSendFlavor is NULL!");3333ObjCInterfaceDecl *ClassDecl = CurMethodDef->getClassInterface();3334SmallVector<Expr*, 4> InitExprs;33353336InitExprs.push_back(NoTypeInfoCStyleCastExpr(3337Context, Context->getObjCIdType(), CK_BitCast,3338new (Context) DeclRefExpr(*Context, CurMethodDef->getSelfDecl(), false,3339Context->getObjCIdType(), VK_PRValue,3340SourceLocation()))); // set the 'receiver'.33413342// (id)class_getSuperclass((Class)objc_getClass("CurrentClass"))3343SmallVector<Expr*, 8> ClsExprs;3344ClsExprs.push_back(getStringLiteral(ClassDecl->getIdentifier()->getName()));3345// (Class)objc_getClass("CurrentClass")3346CallExpr *Cls = SynthesizeCallToFunctionDecl(GetClassFunctionDecl, ClsExprs,3347StartLoc, EndLoc);3348ClsExprs.clear();3349ClsExprs.push_back(Cls);3350Cls = SynthesizeCallToFunctionDecl(GetSuperClassFunctionDecl, ClsExprs,3351StartLoc, EndLoc);33523353// (id)class_getSuperclass((Class)objc_getClass("CurrentClass"))3354// To turn off a warning, type-cast to 'id'3355InitExprs.push_back(3356// set 'super class', using class_getSuperclass().3357NoTypeInfoCStyleCastExpr(Context, Context->getObjCIdType(),3358CK_BitCast, Cls));3359// struct __rw_objc_super3360QualType superType = getSuperStructType();3361Expr *SuperRep;33623363if (LangOpts.MicrosoftExt) {3364SynthSuperConstructorFunctionDecl();3365// Simulate a constructor call...3366DeclRefExpr *DRE = new (Context)3367DeclRefExpr(*Context, SuperConstructorFunctionDecl, false, superType,3368VK_LValue, SourceLocation());3369SuperRep =3370CallExpr::Create(*Context, DRE, InitExprs, superType, VK_LValue,3371SourceLocation(), FPOptionsOverride());3372// The code for super is a little tricky to prevent collision with3373// the structure definition in the header. The rewriter has it's own3374// internal definition (__rw_objc_super) that is uses. This is why3375// we need the cast below. For example:3376// (struct __rw_objc_super *)&__rw_objc_super((id)self, (id)objc_getClass("SUPER"))3377//3378SuperRep = UnaryOperator::Create(3379const_cast<ASTContext &>(*Context), SuperRep, UO_AddrOf,3380Context->getPointerType(SuperRep->getType()), VK_PRValue, OK_Ordinary,3381SourceLocation(), false, FPOptionsOverride());3382SuperRep = NoTypeInfoCStyleCastExpr(Context,3383Context->getPointerType(superType),3384CK_BitCast, SuperRep);3385} else {3386// (struct __rw_objc_super) { <exprs from above> }3387InitListExpr *ILE =3388new (Context) InitListExpr(*Context, SourceLocation(), InitExprs,3389SourceLocation());3390TypeSourceInfo *superTInfo3391= Context->getTrivialTypeSourceInfo(superType);3392SuperRep = new (Context) CompoundLiteralExpr(3393SourceLocation(), superTInfo, superType, VK_PRValue, ILE, false);3394}3395MsgExprs.push_back(SuperRep);3396break;3397}33983399case ObjCMessageExpr::Instance: {3400// Remove all type-casts because it may contain objc-style types; e.g.3401// Foo<Proto> *.3402Expr *recExpr = Exp->getInstanceReceiver();3403while (CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(recExpr))3404recExpr = CE->getSubExpr();3405CastKind CK = recExpr->getType()->isObjCObjectPointerType()3406? CK_BitCast : recExpr->getType()->isBlockPointerType()3407? CK_BlockPointerToObjCPointerCast3408: CK_CPointerToObjCPointerCast;34093410recExpr = NoTypeInfoCStyleCastExpr(Context, Context->getObjCIdType(),3411CK, recExpr);3412MsgExprs.push_back(recExpr);3413break;3414}3415}34163417// Create a call to sel_registerName("selName"), it will be the 2nd argument.3418SmallVector<Expr*, 8> SelExprs;3419SelExprs.push_back(getStringLiteral(Exp->getSelector().getAsString()));3420CallExpr *SelExp = SynthesizeCallToFunctionDecl(SelGetUidFunctionDecl,3421SelExprs, StartLoc, EndLoc);3422MsgExprs.push_back(SelExp);34233424// Now push any user supplied arguments.3425for (unsigned i = 0; i < Exp->getNumArgs(); i++) {3426Expr *userExpr = Exp->getArg(i);3427// Make all implicit casts explicit...ICE comes in handy:-)3428if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(userExpr)) {3429// Reuse the ICE type, it is exactly what the doctor ordered.3430QualType type = ICE->getType();3431if (needToScanForQualifiers(type))3432type = Context->getObjCIdType();3433// Make sure we convert "type (^)(...)" to "type (*)(...)".3434(void)convertBlockPointerToFunctionPointer(type);3435const Expr *SubExpr = ICE->IgnoreParenImpCasts();3436CastKind CK;3437if (SubExpr->getType()->isIntegralType(*Context) &&3438type->isBooleanType()) {3439CK = CK_IntegralToBoolean;3440} else if (type->isObjCObjectPointerType()) {3441if (SubExpr->getType()->isBlockPointerType()) {3442CK = CK_BlockPointerToObjCPointerCast;3443} else if (SubExpr->getType()->isPointerType()) {3444CK = CK_CPointerToObjCPointerCast;3445} else {3446CK = CK_BitCast;3447}3448} else {3449CK = CK_BitCast;3450}34513452userExpr = NoTypeInfoCStyleCastExpr(Context, type, CK, userExpr);3453}3454// Make id<P...> cast into an 'id' cast.3455else if (CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(userExpr)) {3456if (CE->getType()->isObjCQualifiedIdType()) {3457while ((CE = dyn_cast<CStyleCastExpr>(userExpr)))3458userExpr = CE->getSubExpr();3459CastKind CK;3460if (userExpr->getType()->isIntegralType(*Context)) {3461CK = CK_IntegralToPointer;3462} else if (userExpr->getType()->isBlockPointerType()) {3463CK = CK_BlockPointerToObjCPointerCast;3464} else if (userExpr->getType()->isPointerType()) {3465CK = CK_CPointerToObjCPointerCast;3466} else {3467CK = CK_BitCast;3468}3469userExpr = NoTypeInfoCStyleCastExpr(Context, Context->getObjCIdType(),3470CK, userExpr);3471}3472}3473MsgExprs.push_back(userExpr);3474// We've transferred the ownership to MsgExprs. For now, we *don't* null3475// out the argument in the original expression (since we aren't deleting3476// the ObjCMessageExpr). See RewritePropertyOrImplicitSetter() usage for more info.3477//Exp->setArg(i, 0);3478}3479// Generate the funky cast.3480CastExpr *cast;3481SmallVector<QualType, 8> ArgTypes;3482QualType returnType;34833484// Push 'id' and 'SEL', the 2 implicit arguments.3485if (MsgSendFlavor == MsgSendSuperFunctionDecl)3486ArgTypes.push_back(Context->getPointerType(getSuperStructType()));3487else3488ArgTypes.push_back(Context->getObjCIdType());3489ArgTypes.push_back(Context->getObjCSelType());3490if (ObjCMethodDecl *OMD = Exp->getMethodDecl()) {3491// Push any user argument types.3492for (const auto *PI : OMD->parameters()) {3493QualType t = PI->getType()->isObjCQualifiedIdType()3494? Context->getObjCIdType()3495: PI->getType();3496// Make sure we convert "t (^)(...)" to "t (*)(...)".3497(void)convertBlockPointerToFunctionPointer(t);3498ArgTypes.push_back(t);3499}3500returnType = Exp->getType();3501convertToUnqualifiedObjCType(returnType);3502(void)convertBlockPointerToFunctionPointer(returnType);3503} else {3504returnType = Context->getObjCIdType();3505}3506// Get the type, we will need to reference it in a couple spots.3507QualType msgSendType = MsgSendFlavor->getType();35083509// Create a reference to the objc_msgSend() declaration.3510DeclRefExpr *DRE = new (Context) DeclRefExpr(3511*Context, MsgSendFlavor, false, msgSendType, VK_LValue, SourceLocation());35123513// Need to cast objc_msgSend to "void *" (to workaround a GCC bandaid).3514// If we don't do this cast, we get the following bizarre warning/note:3515// xx.m:13: warning: function called through a non-compatible type3516// xx.m:13: note: if this code is reached, the program will abort3517cast = NoTypeInfoCStyleCastExpr(Context,3518Context->getPointerType(Context->VoidTy),3519CK_BitCast, DRE);35203521// Now do the "normal" pointer to function cast.3522// If we don't have a method decl, force a variadic cast.3523const ObjCMethodDecl *MD = Exp->getMethodDecl();3524QualType castType =3525getSimpleFunctionType(returnType, ArgTypes, MD ? MD->isVariadic() : true);3526castType = Context->getPointerType(castType);3527cast = NoTypeInfoCStyleCastExpr(Context, castType, CK_BitCast,3528cast);35293530// Don't forget the parens to enforce the proper binding.3531ParenExpr *PE = new (Context) ParenExpr(StartLoc, EndLoc, cast);35323533const FunctionType *FT = msgSendType->castAs<FunctionType>();3534CallExpr *CE = CallExpr::Create(*Context, PE, MsgExprs, FT->getReturnType(),3535VK_PRValue, EndLoc, FPOptionsOverride());3536Stmt *ReplacingStmt = CE;3537if (MsgSendStretFlavor) {3538// We have the method which returns a struct/union. Must also generate3539// call to objc_msgSend_stret and hang both varieties on a conditional3540// expression which dictate which one to envoke depending on size of3541// method's return type.35423543Expr *STCE = SynthMsgSendStretCallExpr(MsgSendStretFlavor,3544returnType,3545ArgTypes, MsgExprs,3546Exp->getMethodDecl());3547ReplacingStmt = STCE;3548}3549// delete Exp; leak for now, see RewritePropertyOrImplicitSetter() usage for more info.3550return ReplacingStmt;3551}35523553Stmt *RewriteModernObjC::RewriteMessageExpr(ObjCMessageExpr *Exp) {3554Stmt *ReplacingStmt =3555SynthMessageExpr(Exp, Exp->getBeginLoc(), Exp->getEndLoc());35563557// Now do the actual rewrite.3558ReplaceStmt(Exp, ReplacingStmt);35593560// delete Exp; leak for now, see RewritePropertyOrImplicitSetter() usage for more info.3561return ReplacingStmt;3562}35633564// typedef struct objc_object Protocol;3565QualType RewriteModernObjC::getProtocolType() {3566if (!ProtocolTypeDecl) {3567TypeSourceInfo *TInfo3568= Context->getTrivialTypeSourceInfo(Context->getObjCIdType());3569ProtocolTypeDecl = TypedefDecl::Create(*Context, TUDecl,3570SourceLocation(), SourceLocation(),3571&Context->Idents.get("Protocol"),3572TInfo);3573}3574return Context->getTypeDeclType(ProtocolTypeDecl);3575}35763577/// RewriteObjCProtocolExpr - Rewrite a protocol expression into3578/// a synthesized/forward data reference (to the protocol's metadata).3579/// The forward references (and metadata) are generated in3580/// RewriteModernObjC::HandleTranslationUnit().3581Stmt *RewriteModernObjC::RewriteObjCProtocolExpr(ObjCProtocolExpr *Exp) {3582std::string Name = "_OBJC_PROTOCOL_REFERENCE_$_" +3583Exp->getProtocol()->getNameAsString();3584IdentifierInfo *ID = &Context->Idents.get(Name);3585VarDecl *VD = VarDecl::Create(*Context, TUDecl, SourceLocation(),3586SourceLocation(), ID, getProtocolType(),3587nullptr, SC_Extern);3588DeclRefExpr *DRE = new (Context) DeclRefExpr(3589*Context, VD, false, getProtocolType(), VK_LValue, SourceLocation());3590CastExpr *castExpr = NoTypeInfoCStyleCastExpr(3591Context, Context->getPointerType(DRE->getType()), CK_BitCast, DRE);3592ReplaceStmt(Exp, castExpr);3593ProtocolExprDecls.insert(Exp->getProtocol()->getCanonicalDecl());3594// delete Exp; leak for now, see RewritePropertyOrImplicitSetter() usage for more info.3595return castExpr;3596}35973598/// IsTagDefinedInsideClass - This routine checks that a named tagged type3599/// is defined inside an objective-c class. If so, it returns true.3600bool RewriteModernObjC::IsTagDefinedInsideClass(ObjCContainerDecl *IDecl,3601TagDecl *Tag,3602bool &IsNamedDefinition) {3603if (!IDecl)3604return false;3605SourceLocation TagLocation;3606if (RecordDecl *RD = dyn_cast<RecordDecl>(Tag)) {3607RD = RD->getDefinition();3608if (!RD || !RD->getDeclName().getAsIdentifierInfo())3609return false;3610IsNamedDefinition = true;3611TagLocation = RD->getLocation();3612return Context->getSourceManager().isBeforeInTranslationUnit(3613IDecl->getLocation(), TagLocation);3614}3615if (EnumDecl *ED = dyn_cast<EnumDecl>(Tag)) {3616if (!ED || !ED->getDeclName().getAsIdentifierInfo())3617return false;3618IsNamedDefinition = true;3619TagLocation = ED->getLocation();3620return Context->getSourceManager().isBeforeInTranslationUnit(3621IDecl->getLocation(), TagLocation);3622}3623return false;3624}36253626/// RewriteObjCFieldDeclType - This routine rewrites a type into the buffer.3627/// It handles elaborated types, as well as enum types in the process.3628bool RewriteModernObjC::RewriteObjCFieldDeclType(QualType &Type,3629std::string &Result) {3630if (Type->getAs<TypedefType>()) {3631Result += "\t";3632return false;3633}36343635if (Type->isArrayType()) {3636QualType ElemTy = Context->getBaseElementType(Type);3637return RewriteObjCFieldDeclType(ElemTy, Result);3638}3639else if (Type->isRecordType()) {3640RecordDecl *RD = Type->castAs<RecordType>()->getDecl();3641if (RD->isCompleteDefinition()) {3642if (RD->isStruct())3643Result += "\n\tstruct ";3644else if (RD->isUnion())3645Result += "\n\tunion ";3646else3647assert(false && "class not allowed as an ivar type");36483649Result += RD->getName();3650if (GlobalDefinedTags.count(RD)) {3651// struct/union is defined globally, use it.3652Result += " ";3653return true;3654}3655Result += " {\n";3656for (auto *FD : RD->fields())3657RewriteObjCFieldDecl(FD, Result);3658Result += "\t} ";3659return true;3660}3661}3662else if (Type->isEnumeralType()) {3663EnumDecl *ED = Type->castAs<EnumType>()->getDecl();3664if (ED->isCompleteDefinition()) {3665Result += "\n\tenum ";3666Result += ED->getName();3667if (GlobalDefinedTags.count(ED)) {3668// Enum is globall defined, use it.3669Result += " ";3670return true;3671}36723673Result += " {\n";3674for (const auto *EC : ED->enumerators()) {3675Result += "\t"; Result += EC->getName(); Result += " = ";3676Result += toString(EC->getInitVal(), 10);3677Result += ",\n";3678}3679Result += "\t} ";3680return true;3681}3682}36833684Result += "\t";3685convertObjCTypeToCStyleType(Type);3686return false;3687}368836893690/// 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,3693std::string &Result) {3694QualType Type = fieldDecl->getType();3695std::string Name = fieldDecl->getNameAsString();36963697bool EleboratedType = RewriteObjCFieldDeclType(Type, Result);3698if (!EleboratedType)3699Type.getAsStringInternal(Name, Context->getPrintingPolicy());3700Result += Name;3701if (fieldDecl->isBitField()) {3702Result += " : "; Result += utostr(fieldDecl->getBitWidthValue(*Context));3703}3704else if (EleboratedType && Type->isArrayType()) {3705const ArrayType *AT = Context->getAsArrayType(Type);3706do {3707if (const ConstantArrayType *CAT = dyn_cast<ConstantArrayType>(AT)) {3708Result += "[";3709llvm::APInt Dim = CAT->getSize();3710Result += utostr(Dim.getZExtValue());3711Result += "]";3712}3713AT = Context->getAsArrayType(AT->getElementType());3714} while (AT);3715}37163717Result += ";\n";3718}37193720/// RewriteLocallyDefinedNamedAggregates - This routine rewrites locally defined3721/// named aggregate types into the input buffer.3722void RewriteModernObjC::RewriteLocallyDefinedNamedAggregates(FieldDecl *fieldDecl,3723std::string &Result) {3724QualType Type = fieldDecl->getType();3725if (Type->getAs<TypedefType>())3726return;3727if (Type->isArrayType())3728Type = Context->getBaseElementType(Type);37293730auto *IDecl = dyn_cast<ObjCContainerDecl>(fieldDecl->getDeclContext());37313732TagDecl *TD = nullptr;3733if (Type->isRecordType()) {3734TD = Type->castAs<RecordType>()->getDecl();3735}3736else if (Type->isEnumeralType()) {3737TD = Type->castAs<EnumType>()->getDecl();3738}37393740if (TD) {3741if (GlobalDefinedTags.count(TD))3742return;37433744bool IsNamedDefinition = false;3745if (IsTagDefinedInsideClass(IDecl, TD, IsNamedDefinition)) {3746RewriteObjCFieldDeclType(Type, Result);3747Result += ";";3748}3749if (IsNamedDefinition)3750GlobalDefinedTags.insert(TD);3751}3752}37533754unsigned RewriteModernObjC::ObjCIvarBitfieldGroupNo(ObjCIvarDecl *IV) {3755const ObjCInterfaceDecl *CDecl = IV->getContainingInterface();3756if (ObjCInterefaceHasBitfieldGroups.count(CDecl)) {3757return IvarGroupNumber[IV];3758}3759unsigned GroupNo = 0;3760SmallVector<const ObjCIvarDecl *, 8> IVars;3761for (const ObjCIvarDecl *IVD = CDecl->all_declared_ivar_begin();3762IVD; IVD = IVD->getNextIvar())3763IVars.push_back(IVD);37643765for (unsigned i = 0, e = IVars.size(); i < e; i++)3766if (IVars[i]->isBitField()) {3767IvarGroupNumber[IVars[i++]] = ++GroupNo;3768while (i < e && IVars[i]->isBitField())3769IvarGroupNumber[IVars[i++]] = GroupNo;3770if (i < e)3771--i;3772}37733774ObjCInterefaceHasBitfieldGroups.insert(CDecl);3775return IvarGroupNumber[IV];3776}37773778QualType RewriteModernObjC::SynthesizeBitfieldGroupStructType(3779ObjCIvarDecl *IV,3780SmallVectorImpl<ObjCIvarDecl *> &IVars) {3781std::string StructTagName;3782ObjCIvarBitfieldGroupType(IV, StructTagName);3783RecordDecl *RD = RecordDecl::Create(3784*Context, TagTypeKind::Struct, Context->getTranslationUnitDecl(),3785SourceLocation(), SourceLocation(), &Context->Idents.get(StructTagName));3786for (unsigned i=0, e = IVars.size(); i < e; i++) {3787ObjCIvarDecl *Ivar = IVars[i];3788RD->addDecl(FieldDecl::Create(*Context, RD, SourceLocation(), SourceLocation(),3789&Context->Idents.get(Ivar->getName()),3790Ivar->getType(),3791nullptr, /*Expr *BW */Ivar->getBitWidth(),3792false, ICIS_NoInit));3793}3794RD->completeDefinition();3795return Context->getTagDeclType(RD);3796}37973798QualType RewriteModernObjC::GetGroupRecordTypeForObjCIvarBitfield(ObjCIvarDecl *IV) {3799const ObjCInterfaceDecl *CDecl = IV->getContainingInterface();3800unsigned GroupNo = ObjCIvarBitfieldGroupNo(IV);3801std::pair<const ObjCInterfaceDecl*, unsigned> tuple = std::make_pair(CDecl, GroupNo);3802if (GroupRecordType.count(tuple))3803return GroupRecordType[tuple];38043805SmallVector<ObjCIvarDecl *, 8> IVars;3806for (const ObjCIvarDecl *IVD = CDecl->all_declared_ivar_begin();3807IVD; IVD = IVD->getNextIvar()) {3808if (IVD->isBitField())3809IVars.push_back(const_cast<ObjCIvarDecl *>(IVD));3810else {3811if (!IVars.empty()) {3812unsigned GroupNo = ObjCIvarBitfieldGroupNo(IVars[0]);3813// Generate the struct type for this group of bitfield ivars.3814GroupRecordType[std::make_pair(CDecl, GroupNo)] =3815SynthesizeBitfieldGroupStructType(IVars[0], IVars);3816IVars.clear();3817}3818}3819}3820if (!IVars.empty()) {3821// Do the last one.3822unsigned GroupNo = ObjCIvarBitfieldGroupNo(IVars[0]);3823GroupRecordType[std::make_pair(CDecl, GroupNo)] =3824SynthesizeBitfieldGroupStructType(IVars[0], IVars);3825}3826QualType RetQT = GroupRecordType[tuple];3827assert(!RetQT.isNull() && "GetGroupRecordTypeForObjCIvarBitfield struct type is NULL");38283829return RetQT;3830}38313832/// ObjCIvarBitfieldGroupDecl - Names field decl. for ivar bitfield group.3833/// Name would be: classname__GRBF_n where n is the group number for this ivar.3834void RewriteModernObjC::ObjCIvarBitfieldGroupDecl(ObjCIvarDecl *IV,3835std::string &Result) {3836const ObjCInterfaceDecl *CDecl = IV->getContainingInterface();3837Result += CDecl->getName();3838Result += "__GRBF_";3839unsigned GroupNo = ObjCIvarBitfieldGroupNo(IV);3840Result += utostr(GroupNo);3841}38423843/// ObjCIvarBitfieldGroupType - Names struct type for ivar bitfield group.3844/// Name of the struct would be: classname__T_n where n is the group number for3845/// this ivar.3846void RewriteModernObjC::ObjCIvarBitfieldGroupType(ObjCIvarDecl *IV,3847std::string &Result) {3848const ObjCInterfaceDecl *CDecl = IV->getContainingInterface();3849Result += CDecl->getName();3850Result += "__T_";3851unsigned GroupNo = ObjCIvarBitfieldGroupNo(IV);3852Result += utostr(GroupNo);3853}38543855/// ObjCIvarBitfieldGroupOffset - Names symbol for ivar bitfield group field offset.3856/// Name would be: OBJC_IVAR_$_classname__GRBF_n where n is the group number for3857/// this ivar.3858void RewriteModernObjC::ObjCIvarBitfieldGroupOffset(ObjCIvarDecl *IV,3859std::string &Result) {3860Result += "OBJC_IVAR_$_";3861ObjCIvarBitfieldGroupDecl(IV, Result);3862}38633864#define SKIP_BITFIELDS(IX, ENDIX, VEC) { \3865while ((IX < ENDIX) && VEC[IX]->isBitField()) \3866++IX; \3867if (IX < ENDIX) \3868--IX; \3869}38703871/// RewriteObjCInternalStruct - Rewrite one internal struct corresponding to3872/// an objective-c class with ivars.3873void RewriteModernObjC::RewriteObjCInternalStruct(ObjCInterfaceDecl *CDecl,3874std::string &Result) {3875assert(CDecl && "Class missing in SynthesizeObjCInternalStruct");3876assert(CDecl->getName() != "" &&3877"Name missing in SynthesizeObjCInternalStruct");3878ObjCInterfaceDecl *RCDecl = CDecl->getSuperClass();3879SmallVector<ObjCIvarDecl *, 8> IVars;3880for (ObjCIvarDecl *IVD = CDecl->all_declared_ivar_begin();3881IVD; IVD = IVD->getNextIvar())3882IVars.push_back(IVD);38833884SourceLocation LocStart = CDecl->getBeginLoc();3885SourceLocation LocEnd = CDecl->getEndOfDefinitionLoc();38863887const char *startBuf = SM->getCharacterData(LocStart);3888const char *endBuf = SM->getCharacterData(LocEnd);38893890// If no ivars and no root or if its root, directly or indirectly,3891// have no ivars (thus not synthesized) then no need to synthesize this class.3892if ((!CDecl->isThisDeclarationADefinition() || IVars.size() == 0) &&3893(!RCDecl || !ObjCSynthesizedStructs.count(RCDecl))) {3894endBuf += Lexer::MeasureTokenLength(LocEnd, *SM, LangOpts);3895ReplaceText(LocStart, endBuf-startBuf, Result);3896return;3897}38983899// Insert named struct/union definitions inside class to3900// outer scope. This follows semantics of locally defined3901// struct/unions in objective-c classes.3902for (unsigned i = 0, e = IVars.size(); i < e; i++)3903RewriteLocallyDefinedNamedAggregates(IVars[i], Result);39043905// Insert named structs which are syntheized to group ivar bitfields3906// to outer scope as well.3907for (unsigned i = 0, e = IVars.size(); i < e; i++)3908if (IVars[i]->isBitField()) {3909ObjCIvarDecl *IV = IVars[i];3910QualType QT = GetGroupRecordTypeForObjCIvarBitfield(IV);3911RewriteObjCFieldDeclType(QT, Result);3912Result += ";";3913// skip over ivar bitfields in this group.3914SKIP_BITFIELDS(i , e, IVars);3915}39163917Result += "\nstruct ";3918Result += CDecl->getNameAsString();3919Result += "_IMPL {\n";39203921if (RCDecl && ObjCSynthesizedStructs.count(RCDecl)) {3922Result += "\tstruct "; Result += RCDecl->getNameAsString();3923Result += "_IMPL "; Result += RCDecl->getNameAsString();3924Result += "_IVARS;\n";3925}39263927for (unsigned i = 0, e = IVars.size(); i < e; i++) {3928if (IVars[i]->isBitField()) {3929ObjCIvarDecl *IV = IVars[i];3930Result += "\tstruct ";3931ObjCIvarBitfieldGroupType(IV, Result); Result += " ";3932ObjCIvarBitfieldGroupDecl(IV, Result); Result += ";\n";3933// skip over ivar bitfields in this group.3934SKIP_BITFIELDS(i , e, IVars);3935}3936else3937RewriteObjCFieldDecl(IVars[i], Result);3938}39393940Result += "};\n";3941endBuf += Lexer::MeasureTokenLength(LocEnd, *SM, LangOpts);3942ReplaceText(LocStart, endBuf-startBuf, Result);3943// Mark this struct as having been generated.3944if (!ObjCSynthesizedStructs.insert(CDecl).second)3945llvm_unreachable("struct already synthesize- RewriteObjCInternalStruct");3946}39473948/// RewriteIvarOffsetSymbols - Rewrite ivar offset symbols of those ivars which3949/// have been referenced in an ivar access expression.3950void RewriteModernObjC::RewriteIvarOffsetSymbols(ObjCInterfaceDecl *CDecl,3951std::string &Result) {3952// write out ivar offset symbols which have been referenced in an ivar3953// access expression.3954llvm::SmallSetVector<ObjCIvarDecl *, 8> Ivars = ReferencedIvars[CDecl];39553956if (Ivars.empty())3957return;39583959llvm::DenseSet<std::pair<const ObjCInterfaceDecl*, unsigned> > GroupSymbolOutput;3960for (ObjCIvarDecl *IvarDecl : Ivars) {3961const ObjCInterfaceDecl *IDecl = IvarDecl->getContainingInterface();3962unsigned GroupNo = 0;3963if (IvarDecl->isBitField()) {3964GroupNo = ObjCIvarBitfieldGroupNo(IvarDecl);3965if (GroupSymbolOutput.count(std::make_pair(IDecl, GroupNo)))3966continue;3967}3968Result += "\n";3969if (LangOpts.MicrosoftExt)3970Result += "__declspec(allocate(\".objc_ivar$B\")) ";3971Result += "extern \"C\" ";3972if (LangOpts.MicrosoftExt &&3973IvarDecl->getAccessControl() != ObjCIvarDecl::Private &&3974IvarDecl->getAccessControl() != ObjCIvarDecl::Package)3975Result += "__declspec(dllimport) ";39763977Result += "unsigned long ";3978if (IvarDecl->isBitField()) {3979ObjCIvarBitfieldGroupOffset(IvarDecl, Result);3980GroupSymbolOutput.insert(std::make_pair(IDecl, GroupNo));3981}3982else3983WriteInternalIvarName(CDecl, IvarDecl, Result);3984Result += ";";3985}3986}39873988//===----------------------------------------------------------------------===//3989// Meta Data Emission3990//===----------------------------------------------------------------------===//39913992/// RewriteImplementations - This routine rewrites all method implementations3993/// and emits meta-data.39943995void RewriteModernObjC::RewriteImplementations() {3996int ClsDefCount = ClassImplementation.size();3997int CatDefCount = CategoryImplementation.size();39983999// Rewrite implemented methods4000for (int i = 0; i < ClsDefCount; i++) {4001ObjCImplementationDecl *OIMP = ClassImplementation[i];4002ObjCInterfaceDecl *CDecl = OIMP->getClassInterface();4003if (CDecl->isImplicitInterfaceDecl())4004assert(false &&4005"Legacy implicit interface rewriting not supported in moder abi");4006RewriteImplementationDecl(OIMP);4007}40084009for (int i = 0; i < CatDefCount; i++) {4010ObjCCategoryImplDecl *CIMP = CategoryImplementation[i];4011ObjCInterfaceDecl *CDecl = CIMP->getClassInterface();4012if (CDecl->isImplicitInterfaceDecl())4013assert(false &&4014"Legacy implicit interface rewriting not supported in moder abi");4015RewriteImplementationDecl(CIMP);4016}4017}40184019void RewriteModernObjC::RewriteByRefString(std::string &ResultStr,4020const std::string &Name,4021ValueDecl *VD, bool def) {4022assert(BlockByRefDeclNo.count(VD) &&4023"RewriteByRefString: ByRef decl missing");4024if (def)4025ResultStr += "struct ";4026ResultStr += "__Block_byref_" + Name +4027"_" + utostr(BlockByRefDeclNo[VD]) ;4028}40294030static bool HasLocalVariableExternalStorage(ValueDecl *VD) {4031if (VarDecl *Var = dyn_cast<VarDecl>(VD))4032return (Var->isFunctionOrMethodVarDecl() && !Var->hasLocalStorage());4033return false;4034}40354036std::string RewriteModernObjC::SynthesizeBlockFunc(BlockExpr *CE, int i,4037StringRef funcName,4038const std::string &Tag) {4039const FunctionType *AFT = CE->getFunctionType();4040QualType RT = AFT->getReturnType();4041std::string StructRef = "struct " + Tag;4042SourceLocation BlockLoc = CE->getExprLoc();4043std::string S;4044ConvertSourceLocationToLineDirective(BlockLoc, S);40454046S += "static " + RT.getAsString(Context->getPrintingPolicy()) + " __" +4047funcName.str() + "_block_func_" + utostr(i);40484049BlockDecl *BD = CE->getBlockDecl();40504051if (isa<FunctionNoProtoType>(AFT)) {4052// No user-supplied arguments. Still need to pass in a pointer to the4053// block (to reference imported block decl refs).4054S += "(" + StructRef + " *__cself)";4055} else if (BD->param_empty()) {4056S += "(" + StructRef + " *__cself)";4057} else {4058const FunctionProtoType *FT = cast<FunctionProtoType>(AFT);4059assert(FT && "SynthesizeBlockFunc: No function proto");4060S += '(';4061// first add the implicit argument.4062S += StructRef + " *__cself, ";4063std::string ParamStr;4064for (BlockDecl::param_iterator AI = BD->param_begin(),4065E = BD->param_end(); AI != E; ++AI) {4066if (AI != BD->param_begin()) S += ", ";4067ParamStr = (*AI)->getNameAsString();4068QualType QT = (*AI)->getType();4069(void)convertBlockPointerToFunctionPointer(QT);4070QT.getAsStringInternal(ParamStr, Context->getPrintingPolicy());4071S += ParamStr;4072}4073if (FT->isVariadic()) {4074if (!BD->param_empty()) S += ", ";4075S += "...";4076}4077S += ')';4078}4079S += " {\n";40804081// Create local declarations to avoid rewriting all closure decl ref exprs.4082// First, emit a declaration for all "by ref" decls.4083for (SmallVectorImpl<ValueDecl *>::iterator I = BlockByRefDecls.begin(),4084E = BlockByRefDecls.end(); I != E; ++I) {4085S += " ";4086std::string Name = (*I)->getNameAsString();4087std::string TypeString;4088RewriteByRefString(TypeString, Name, (*I));4089TypeString += " *";4090Name = TypeString + Name;4091S += Name + " = __cself->" + (*I)->getNameAsString() + "; // bound by ref\n";4092}4093// Next, emit a declaration for all "by copy" declarations.4094for (SmallVectorImpl<ValueDecl *>::iterator I = BlockByCopyDecls.begin(),4095E = BlockByCopyDecls.end(); I != E; ++I) {4096S += " ";4097// Handle nested closure invocation. For example:4098//4099// void (^myImportedClosure)(void);4100// myImportedClosure = ^(void) { setGlobalInt(x + y); };4101//4102// void (^anotherClosure)(void);4103// anotherClosure = ^(void) {4104// myImportedClosure(); // import and invoke the closure4105// };4106//4107if (isTopLevelBlockPointerType((*I)->getType())) {4108RewriteBlockPointerTypeVariable(S, (*I));4109S += " = (";4110RewriteBlockPointerType(S, (*I)->getType());4111S += ")";4112S += "__cself->" + (*I)->getNameAsString() + "; // bound by copy\n";4113}4114else {4115std::string Name = (*I)->getNameAsString();4116QualType QT = (*I)->getType();4117if (HasLocalVariableExternalStorage(*I))4118QT = Context->getPointerType(QT);4119QT.getAsStringInternal(Name, Context->getPrintingPolicy());4120S += Name + " = __cself->" +4121(*I)->getNameAsString() + "; // bound by copy\n";4122}4123}4124std::string RewrittenStr = RewrittenBlockExprs[CE];4125const char *cstr = RewrittenStr.c_str();4126while (*cstr++ != '{') ;4127S += cstr;4128S += "\n";4129return S;4130}41314132std::string RewriteModernObjC::SynthesizeBlockHelperFuncs(4133BlockExpr *CE, int i, StringRef funcName, const std::string &Tag) {4134std::string StructRef = "struct " + Tag;4135std::string S = "static void __";41364137S += funcName;4138S += "_block_copy_" + utostr(i);4139S += "(" + StructRef;4140S += "*dst, " + StructRef;4141S += "*src) {";4142for (ValueDecl *VD : ImportedBlockDecls) {4143S += "_Block_object_assign((void*)&dst->";4144S += VD->getNameAsString();4145S += ", (void*)src->";4146S += VD->getNameAsString();4147if (BlockByRefDeclsPtrSet.count(VD))4148S += ", " + utostr(BLOCK_FIELD_IS_BYREF) + "/*BLOCK_FIELD_IS_BYREF*/);";4149else if (VD->getType()->isBlockPointerType())4150S += ", " + utostr(BLOCK_FIELD_IS_BLOCK) + "/*BLOCK_FIELD_IS_BLOCK*/);";4151else4152S += ", " + utostr(BLOCK_FIELD_IS_OBJECT) + "/*BLOCK_FIELD_IS_OBJECT*/);";4153}4154S += "}\n";41554156S += "\nstatic void __";4157S += funcName;4158S += "_block_dispose_" + utostr(i);4159S += "(" + StructRef;4160S += "*src) {";4161for (ValueDecl *VD : ImportedBlockDecls) {4162S += "_Block_object_dispose((void*)src->";4163S += VD->getNameAsString();4164if (BlockByRefDeclsPtrSet.count(VD))4165S += ", " + utostr(BLOCK_FIELD_IS_BYREF) + "/*BLOCK_FIELD_IS_BYREF*/);";4166else if (VD->getType()->isBlockPointerType())4167S += ", " + utostr(BLOCK_FIELD_IS_BLOCK) + "/*BLOCK_FIELD_IS_BLOCK*/);";4168else4169S += ", " + utostr(BLOCK_FIELD_IS_OBJECT) + "/*BLOCK_FIELD_IS_OBJECT*/);";4170}4171S += "}\n";4172return S;4173}41744175std::string RewriteModernObjC::SynthesizeBlockImpl(BlockExpr *CE,4176const std::string &Tag,4177const std::string &Desc) {4178std::string S = "\nstruct " + Tag;4179std::string Constructor = " " + Tag;41804181S += " {\n struct __block_impl impl;\n";4182S += " struct " + Desc;4183S += "* Desc;\n";41844185Constructor += "(void *fp, "; // Invoke function pointer.4186Constructor += "struct " + Desc; // Descriptor pointer.4187Constructor += " *desc";41884189if (BlockDeclRefs.size()) {4190// Output all "by copy" declarations.4191for (SmallVectorImpl<ValueDecl *>::iterator I = BlockByCopyDecls.begin(),4192E = BlockByCopyDecls.end(); I != E; ++I) {4193S += " ";4194std::string FieldName = (*I)->getNameAsString();4195std::string ArgName = "_" + FieldName;4196// Handle nested closure invocation. For example:4197//4198// void (^myImportedBlock)(void);4199// myImportedBlock = ^(void) { setGlobalInt(x + y); };4200//4201// void (^anotherBlock)(void);4202// anotherBlock = ^(void) {4203// myImportedBlock(); // import and invoke the closure4204// };4205//4206if (isTopLevelBlockPointerType((*I)->getType())) {4207S += "struct __block_impl *";4208Constructor += ", void *" + ArgName;4209} else {4210QualType QT = (*I)->getType();4211if (HasLocalVariableExternalStorage(*I))4212QT = Context->getPointerType(QT);4213QT.getAsStringInternal(FieldName, Context->getPrintingPolicy());4214QT.getAsStringInternal(ArgName, Context->getPrintingPolicy());4215Constructor += ", " + ArgName;4216}4217S += FieldName + ";\n";4218}4219// Output all "by ref" declarations.4220for (SmallVectorImpl<ValueDecl *>::iterator I = BlockByRefDecls.begin(),4221E = BlockByRefDecls.end(); I != E; ++I) {4222S += " ";4223std::string FieldName = (*I)->getNameAsString();4224std::string ArgName = "_" + FieldName;4225{4226std::string TypeString;4227RewriteByRefString(TypeString, FieldName, (*I));4228TypeString += " *";4229FieldName = TypeString + FieldName;4230ArgName = TypeString + ArgName;4231Constructor += ", " + ArgName;4232}4233S += FieldName + "; // by ref\n";4234}4235// Finish writing the constructor.4236Constructor += ", int flags=0)";4237// Initialize all "by copy" arguments.4238bool firsTime = true;4239for (SmallVectorImpl<ValueDecl *>::iterator I = BlockByCopyDecls.begin(),4240E = BlockByCopyDecls.end(); I != E; ++I) {4241std::string Name = (*I)->getNameAsString();4242if (firsTime) {4243Constructor += " : ";4244firsTime = false;4245}4246else4247Constructor += ", ";4248if (isTopLevelBlockPointerType((*I)->getType()))4249Constructor += Name + "((struct __block_impl *)_" + Name + ")";4250else4251Constructor += Name + "(_" + Name + ")";4252}4253// Initialize all "by ref" arguments.4254for (SmallVectorImpl<ValueDecl *>::iterator I = BlockByRefDecls.begin(),4255E = BlockByRefDecls.end(); I != E; ++I) {4256std::string Name = (*I)->getNameAsString();4257if (firsTime) {4258Constructor += " : ";4259firsTime = false;4260}4261else4262Constructor += ", ";4263Constructor += Name + "(_" + Name + "->__forwarding)";4264}42654266Constructor += " {\n";4267if (GlobalVarDecl)4268Constructor += " impl.isa = &_NSConcreteGlobalBlock;\n";4269else4270Constructor += " impl.isa = &_NSConcreteStackBlock;\n";4271Constructor += " impl.Flags = flags;\n impl.FuncPtr = fp;\n";42724273Constructor += " Desc = desc;\n";4274} else {4275// Finish writing the constructor.4276Constructor += ", int flags=0) {\n";4277if (GlobalVarDecl)4278Constructor += " impl.isa = &_NSConcreteGlobalBlock;\n";4279else4280Constructor += " impl.isa = &_NSConcreteStackBlock;\n";4281Constructor += " impl.Flags = flags;\n impl.FuncPtr = fp;\n";4282Constructor += " Desc = desc;\n";4283}4284Constructor += " ";4285Constructor += "}\n";4286S += Constructor;4287S += "};\n";4288return S;4289}42904291std::string RewriteModernObjC::SynthesizeBlockDescriptor(4292const std::string &DescTag, const std::string &ImplTag, int i,4293StringRef FunName, unsigned hasCopy) {4294std::string S = "\nstatic struct " + DescTag;42954296S += " {\n size_t reserved;\n";4297S += " size_t Block_size;\n";4298if (hasCopy) {4299S += " void (*copy)(struct ";4300S += ImplTag; S += "*, struct ";4301S += ImplTag; S += "*);\n";43024303S += " void (*dispose)(struct ";4304S += ImplTag; S += "*);\n";4305}4306S += "} ";43074308S += DescTag + "_DATA = { 0, sizeof(struct ";4309S += ImplTag + ")";4310if (hasCopy) {4311S += ", __" + FunName.str() + "_block_copy_" + utostr(i);4312S += ", __" + FunName.str() + "_block_dispose_" + utostr(i);4313}4314S += "};\n";4315return S;4316}43174318void RewriteModernObjC::SynthesizeBlockLiterals(SourceLocation FunLocStart,4319StringRef FunName) {4320bool RewriteSC = (GlobalVarDecl &&4321!Blocks.empty() &&4322GlobalVarDecl->getStorageClass() == SC_Static &&4323GlobalVarDecl->getType().getCVRQualifiers());4324if (RewriteSC) {4325std::string SC(" void __");4326SC += GlobalVarDecl->getNameAsString();4327SC += "() {}";4328InsertText(FunLocStart, SC);4329}43304331// Insert closures that were part of the function.4332for (unsigned i = 0, count=0; i < Blocks.size(); i++) {4333CollectBlockDeclRefInfo(Blocks[i]);4334// Need to copy-in the inner copied-in variables not actually used in this4335// block.4336for (int j = 0; j < InnerDeclRefsCount[i]; j++) {4337DeclRefExpr *Exp = InnerDeclRefs[count++];4338ValueDecl *VD = Exp->getDecl();4339BlockDeclRefs.push_back(Exp);4340if (!VD->hasAttr<BlocksAttr>()) {4341if (!BlockByCopyDeclsPtrSet.count(VD)) {4342BlockByCopyDeclsPtrSet.insert(VD);4343BlockByCopyDecls.push_back(VD);4344}4345continue;4346}43474348if (!BlockByRefDeclsPtrSet.count(VD)) {4349BlockByRefDeclsPtrSet.insert(VD);4350BlockByRefDecls.push_back(VD);4351}43524353// imported objects in the inner blocks not used in the outer4354// blocks must be copied/disposed in the outer block as well.4355if (VD->getType()->isObjCObjectPointerType() ||4356VD->getType()->isBlockPointerType())4357ImportedBlockDecls.insert(VD);4358}43594360std::string ImplTag = "__" + FunName.str() + "_block_impl_" + utostr(i);4361std::string DescTag = "__" + FunName.str() + "_block_desc_" + utostr(i);43624363std::string CI = SynthesizeBlockImpl(Blocks[i], ImplTag, DescTag);43644365InsertText(FunLocStart, CI);43664367std::string CF = SynthesizeBlockFunc(Blocks[i], i, FunName, ImplTag);43684369InsertText(FunLocStart, CF);43704371if (ImportedBlockDecls.size()) {4372std::string HF = SynthesizeBlockHelperFuncs(Blocks[i], i, FunName, ImplTag);4373InsertText(FunLocStart, HF);4374}4375std::string BD = SynthesizeBlockDescriptor(DescTag, ImplTag, i, FunName,4376ImportedBlockDecls.size() > 0);4377InsertText(FunLocStart, BD);43784379BlockDeclRefs.clear();4380BlockByRefDecls.clear();4381BlockByRefDeclsPtrSet.clear();4382BlockByCopyDecls.clear();4383BlockByCopyDeclsPtrSet.clear();4384ImportedBlockDecls.clear();4385}4386if (RewriteSC) {4387// Must insert any 'const/volatile/static here. Since it has been4388// removed as result of rewriting of block literals.4389std::string SC;4390if (GlobalVarDecl->getStorageClass() == SC_Static)4391SC = "static ";4392if (GlobalVarDecl->getType().isConstQualified())4393SC += "const ";4394if (GlobalVarDecl->getType().isVolatileQualified())4395SC += "volatile ";4396if (GlobalVarDecl->getType().isRestrictQualified())4397SC += "restrict ";4398InsertText(FunLocStart, SC);4399}4400if (GlobalConstructionExp) {4401// extra fancy dance for global literal expression.44024403// Always the latest block expression on the block stack.4404std::string Tag = "__";4405Tag += FunName;4406Tag += "_block_impl_";4407Tag += utostr(Blocks.size()-1);4408std::string globalBuf = "static ";4409globalBuf += Tag; globalBuf += " ";4410std::string SStr;44114412llvm::raw_string_ostream constructorExprBuf(SStr);4413GlobalConstructionExp->printPretty(constructorExprBuf, nullptr,4414PrintingPolicy(LangOpts));4415globalBuf += SStr;4416globalBuf += ";\n";4417InsertText(FunLocStart, globalBuf);4418GlobalConstructionExp = nullptr;4419}44204421Blocks.clear();4422InnerDeclRefsCount.clear();4423InnerDeclRefs.clear();4424RewrittenBlockExprs.clear();4425}44264427void RewriteModernObjC::InsertBlockLiteralsWithinFunction(FunctionDecl *FD) {4428SourceLocation FunLocStart =4429(!Blocks.empty()) ? getFunctionSourceLocation(*this, FD)4430: FD->getTypeSpecStartLoc();4431StringRef FuncName = FD->getName();44324433SynthesizeBlockLiterals(FunLocStart, FuncName);4434}44354436static void BuildUniqueMethodName(std::string &Name,4437ObjCMethodDecl *MD) {4438ObjCInterfaceDecl *IFace = MD->getClassInterface();4439Name = std::string(IFace->getName());4440Name += "__" + MD->getSelector().getAsString();4441// Convert colons to underscores.4442std::string::size_type loc = 0;4443while ((loc = Name.find(':', loc)) != std::string::npos)4444Name.replace(loc, 1, "_");4445}44464447void RewriteModernObjC::InsertBlockLiteralsWithinMethod(ObjCMethodDecl *MD) {4448// fprintf(stderr,"In InsertBlockLiteralsWitinMethod\n");4449// SourceLocation FunLocStart = MD->getBeginLoc();4450SourceLocation FunLocStart = MD->getBeginLoc();4451std::string FuncName;4452BuildUniqueMethodName(FuncName, MD);4453SynthesizeBlockLiterals(FunLocStart, FuncName);4454}44554456void RewriteModernObjC::GetBlockDeclRefExprs(Stmt *S) {4457for (Stmt *SubStmt : S->children())4458if (SubStmt) {4459if (BlockExpr *CBE = dyn_cast<BlockExpr>(SubStmt))4460GetBlockDeclRefExprs(CBE->getBody());4461else4462GetBlockDeclRefExprs(SubStmt);4463}4464// Handle specific things.4465if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(S))4466if (DRE->refersToEnclosingVariableOrCapture() ||4467HasLocalVariableExternalStorage(DRE->getDecl()))4468// FIXME: Handle enums.4469BlockDeclRefs.push_back(DRE);4470}44714472void RewriteModernObjC::GetInnerBlockDeclRefExprs(Stmt *S,4473SmallVectorImpl<DeclRefExpr *> &InnerBlockDeclRefs,4474llvm::SmallPtrSetImpl<const DeclContext *> &InnerContexts) {4475for (Stmt *SubStmt : S->children())4476if (SubStmt) {4477if (BlockExpr *CBE = dyn_cast<BlockExpr>(SubStmt)) {4478InnerContexts.insert(cast<DeclContext>(CBE->getBlockDecl()));4479GetInnerBlockDeclRefExprs(CBE->getBody(),4480InnerBlockDeclRefs,4481InnerContexts);4482}4483else4484GetInnerBlockDeclRefExprs(SubStmt, InnerBlockDeclRefs, InnerContexts);4485}4486// Handle specific things.4487if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(S)) {4488if (DRE->refersToEnclosingVariableOrCapture() ||4489HasLocalVariableExternalStorage(DRE->getDecl())) {4490if (!InnerContexts.count(DRE->getDecl()->getDeclContext()))4491InnerBlockDeclRefs.push_back(DRE);4492if (VarDecl *Var = cast<VarDecl>(DRE->getDecl()))4493if (Var->isFunctionOrMethodVarDecl())4494ImportedLocalExternalDecls.insert(Var);4495}4496}4497}44984499/// convertObjCTypeToCStyleType - This routine converts such objc types4500/// as qualified objects, and blocks to their closest c/c++ types that4501/// it can. It returns true if input type was modified.4502bool RewriteModernObjC::convertObjCTypeToCStyleType(QualType &T) {4503QualType oldT = T;4504convertBlockPointerToFunctionPointer(T);4505if (T->isFunctionPointerType()) {4506QualType PointeeTy;4507if (const PointerType* PT = T->getAs<PointerType>()) {4508PointeeTy = PT->getPointeeType();4509if (const FunctionType *FT = PointeeTy->getAs<FunctionType>()) {4510T = convertFunctionTypeOfBlocks(FT);4511T = Context->getPointerType(T);4512}4513}4514}45154516convertToUnqualifiedObjCType(T);4517return T != oldT;4518}45194520/// convertFunctionTypeOfBlocks - This routine converts a function type4521/// whose result type may be a block pointer or whose argument type(s)4522/// might be block pointers to an equivalent function type replacing4523/// all block pointers to function pointers.4524QualType RewriteModernObjC::convertFunctionTypeOfBlocks(const FunctionType *FT) {4525const FunctionProtoType *FTP = dyn_cast<FunctionProtoType>(FT);4526// FTP will be null for closures that don't take arguments.4527// Generate a funky cast.4528SmallVector<QualType, 8> ArgTypes;4529QualType Res = FT->getReturnType();4530bool modified = convertObjCTypeToCStyleType(Res);45314532if (FTP) {4533for (auto &I : FTP->param_types()) {4534QualType t = I;4535// Make sure we convert "t (^)(...)" to "t (*)(...)".4536if (convertObjCTypeToCStyleType(t))4537modified = true;4538ArgTypes.push_back(t);4539}4540}4541QualType FuncType;4542if (modified)4543FuncType = getSimpleFunctionType(Res, ArgTypes);4544else FuncType = QualType(FT, 0);4545return FuncType;4546}45474548Stmt *RewriteModernObjC::SynthesizeBlockCall(CallExpr *Exp, const Expr *BlockExp) {4549// Navigate to relevant type information.4550const BlockPointerType *CPT = nullptr;45514552if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(BlockExp)) {4553CPT = DRE->getType()->getAs<BlockPointerType>();4554} else if (const MemberExpr *MExpr = dyn_cast<MemberExpr>(BlockExp)) {4555CPT = MExpr->getType()->getAs<BlockPointerType>();4556}4557else if (const ParenExpr *PRE = dyn_cast<ParenExpr>(BlockExp)) {4558return SynthesizeBlockCall(Exp, PRE->getSubExpr());4559}4560else if (const ImplicitCastExpr *IEXPR = dyn_cast<ImplicitCastExpr>(BlockExp))4561CPT = IEXPR->getType()->getAs<BlockPointerType>();4562else if (const ConditionalOperator *CEXPR =4563dyn_cast<ConditionalOperator>(BlockExp)) {4564Expr *LHSExp = CEXPR->getLHS();4565Stmt *LHSStmt = SynthesizeBlockCall(Exp, LHSExp);4566Expr *RHSExp = CEXPR->getRHS();4567Stmt *RHSStmt = SynthesizeBlockCall(Exp, RHSExp);4568Expr *CONDExp = CEXPR->getCond();4569ConditionalOperator *CondExpr = new (Context) ConditionalOperator(4570CONDExp, SourceLocation(), cast<Expr>(LHSStmt), SourceLocation(),4571cast<Expr>(RHSStmt), Exp->getType(), VK_PRValue, OK_Ordinary);4572return CondExpr;4573} else if (const ObjCIvarRefExpr *IRE = dyn_cast<ObjCIvarRefExpr>(BlockExp)) {4574CPT = IRE->getType()->getAs<BlockPointerType>();4575} else if (const PseudoObjectExpr *POE4576= dyn_cast<PseudoObjectExpr>(BlockExp)) {4577CPT = POE->getType()->castAs<BlockPointerType>();4578} else {4579assert(false && "RewriteBlockClass: Bad type");4580}4581assert(CPT && "RewriteBlockClass: Bad type");4582const FunctionType *FT = CPT->getPointeeType()->getAs<FunctionType>();4583assert(FT && "RewriteBlockClass: Bad type");4584const FunctionProtoType *FTP = dyn_cast<FunctionProtoType>(FT);4585// FTP will be null for closures that don't take arguments.45864587RecordDecl *RD = RecordDecl::Create(*Context, TagTypeKind::Struct, TUDecl,4588SourceLocation(), SourceLocation(),4589&Context->Idents.get("__block_impl"));4590QualType PtrBlock = Context->getPointerType(Context->getTagDeclType(RD));45914592// Generate a funky cast.4593SmallVector<QualType, 8> ArgTypes;45944595// Push the block argument type.4596ArgTypes.push_back(PtrBlock);4597if (FTP) {4598for (auto &I : FTP->param_types()) {4599QualType t = I;4600// Make sure we convert "t (^)(...)" to "t (*)(...)".4601if (!convertBlockPointerToFunctionPointer(t))4602convertToUnqualifiedObjCType(t);4603ArgTypes.push_back(t);4604}4605}4606// Now do the pointer to function cast.4607QualType PtrToFuncCastType = getSimpleFunctionType(Exp->getType(), ArgTypes);46084609PtrToFuncCastType = Context->getPointerType(PtrToFuncCastType);46104611CastExpr *BlkCast = NoTypeInfoCStyleCastExpr(Context, PtrBlock,4612CK_BitCast,4613const_cast<Expr*>(BlockExp));4614// Don't forget the parens to enforce the proper binding.4615ParenExpr *PE = new (Context) ParenExpr(SourceLocation(), SourceLocation(),4616BlkCast);4617//PE->dump();46184619FieldDecl *FD = FieldDecl::Create(*Context, nullptr, SourceLocation(),4620SourceLocation(),4621&Context->Idents.get("FuncPtr"),4622Context->VoidPtrTy, nullptr,4623/*BitWidth=*/nullptr, /*Mutable=*/true,4624ICIS_NoInit);4625MemberExpr *ME = MemberExpr::CreateImplicit(4626*Context, PE, true, FD, FD->getType(), VK_LValue, OK_Ordinary);46274628CastExpr *FunkCast = NoTypeInfoCStyleCastExpr(Context, PtrToFuncCastType,4629CK_BitCast, ME);4630PE = new (Context) ParenExpr(SourceLocation(), SourceLocation(), FunkCast);46314632SmallVector<Expr*, 8> BlkExprs;4633// Add the implicit argument.4634BlkExprs.push_back(BlkCast);4635// Add the user arguments.4636for (CallExpr::arg_iterator I = Exp->arg_begin(),4637E = Exp->arg_end(); I != E; ++I) {4638BlkExprs.push_back(*I);4639}4640CallExpr *CE =4641CallExpr::Create(*Context, PE, BlkExprs, Exp->getType(), VK_PRValue,4642SourceLocation(), FPOptionsOverride());4643return CE;4644}46454646// We need to return the rewritten expression to handle cases where the4647// DeclRefExpr is embedded in another expression being rewritten.4648// For example:4649//4650// int main() {4651// __block Foo *f;4652// __block int i;4653//4654// void (^myblock)() = ^() {4655// [f test]; // f is a DeclRefExpr embedded in a message (which is being rewritten).4656// i = 77;4657// };4658//}4659Stmt *RewriteModernObjC::RewriteBlockDeclRefExpr(DeclRefExpr *DeclRefExp) {4660// Rewrite the byref variable into BYREFVAR->__forwarding->BYREFVAR4661// for each DeclRefExp where BYREFVAR is name of the variable.4662ValueDecl *VD = DeclRefExp->getDecl();4663bool isArrow = DeclRefExp->refersToEnclosingVariableOrCapture() ||4664HasLocalVariableExternalStorage(DeclRefExp->getDecl());46654666FieldDecl *FD = FieldDecl::Create(*Context, nullptr, SourceLocation(),4667SourceLocation(),4668&Context->Idents.get("__forwarding"),4669Context->VoidPtrTy, nullptr,4670/*BitWidth=*/nullptr, /*Mutable=*/true,4671ICIS_NoInit);4672MemberExpr *ME = MemberExpr::CreateImplicit(4673*Context, DeclRefExp, isArrow, FD, FD->getType(), VK_LValue, OK_Ordinary);46744675StringRef Name = VD->getName();4676FD = FieldDecl::Create(*Context, nullptr, SourceLocation(), SourceLocation(),4677&Context->Idents.get(Name),4678Context->VoidPtrTy, nullptr,4679/*BitWidth=*/nullptr, /*Mutable=*/true,4680ICIS_NoInit);4681ME = MemberExpr::CreateImplicit(*Context, ME, true, FD, DeclRefExp->getType(),4682VK_LValue, OK_Ordinary);46834684// Need parens to enforce precedence.4685ParenExpr *PE = new (Context) ParenExpr(DeclRefExp->getExprLoc(),4686DeclRefExp->getExprLoc(),4687ME);4688ReplaceStmt(DeclRefExp, PE);4689return PE;4690}46914692// Rewrites the imported local variable V with external storage4693// (static, extern, etc.) as *V4694//4695Stmt *RewriteModernObjC::RewriteLocalVariableExternalStorage(DeclRefExpr *DRE) {4696ValueDecl *VD = DRE->getDecl();4697if (VarDecl *Var = dyn_cast<VarDecl>(VD))4698if (!ImportedLocalExternalDecls.count(Var))4699return DRE;4700Expr *Exp = UnaryOperator::Create(4701const_cast<ASTContext &>(*Context), DRE, UO_Deref, DRE->getType(),4702VK_LValue, OK_Ordinary, DRE->getLocation(), false, FPOptionsOverride());4703// Need parens to enforce precedence.4704ParenExpr *PE = new (Context) ParenExpr(SourceLocation(), SourceLocation(),4705Exp);4706ReplaceStmt(DRE, PE);4707return PE;4708}47094710void RewriteModernObjC::RewriteCastExpr(CStyleCastExpr *CE) {4711SourceLocation LocStart = CE->getLParenLoc();4712SourceLocation LocEnd = CE->getRParenLoc();47134714// Need to avoid trying to rewrite synthesized casts.4715if (LocStart.isInvalid())4716return;4717// Need to avoid trying to rewrite casts contained in macros.4718if (!Rewriter::isRewritable(LocStart) || !Rewriter::isRewritable(LocEnd))4719return;47204721const char *startBuf = SM->getCharacterData(LocStart);4722const char *endBuf = SM->getCharacterData(LocEnd);4723QualType QT = CE->getType();4724const Type* TypePtr = QT->getAs<Type>();4725if (isa<TypeOfExprType>(TypePtr)) {4726const TypeOfExprType *TypeOfExprTypePtr = cast<TypeOfExprType>(TypePtr);4727QT = TypeOfExprTypePtr->getUnderlyingExpr()->getType();4728std::string TypeAsString = "(";4729RewriteBlockPointerType(TypeAsString, QT);4730TypeAsString += ")";4731ReplaceText(LocStart, endBuf-startBuf+1, TypeAsString);4732return;4733}4734// advance the location to startArgList.4735const char *argPtr = startBuf;47364737while (*argPtr++ && (argPtr < endBuf)) {4738switch (*argPtr) {4739case '^':4740// Replace the '^' with '*'.4741LocStart = LocStart.getLocWithOffset(argPtr-startBuf);4742ReplaceText(LocStart, 1, "*");4743break;4744}4745}4746}47474748void RewriteModernObjC::RewriteImplicitCastObjCExpr(CastExpr *IC) {4749CastKind CastKind = IC->getCastKind();4750if (CastKind != CK_BlockPointerToObjCPointerCast &&4751CastKind != CK_AnyPointerToBlockPointerCast)4752return;47534754QualType QT = IC->getType();4755(void)convertBlockPointerToFunctionPointer(QT);4756std::string TypeString(QT.getAsString(Context->getPrintingPolicy()));4757std::string Str = "(";4758Str += TypeString;4759Str += ")";4760InsertText(IC->getSubExpr()->getBeginLoc(), Str);4761}47624763void RewriteModernObjC::RewriteBlockPointerFunctionArgs(FunctionDecl *FD) {4764SourceLocation DeclLoc = FD->getLocation();4765unsigned parenCount = 0;47664767// We have 1 or more arguments that have closure pointers.4768const char *startBuf = SM->getCharacterData(DeclLoc);4769const char *startArgList = strchr(startBuf, '(');47704771assert((*startArgList == '(') && "Rewriter fuzzy parser confused");47724773parenCount++;4774// advance the location to startArgList.4775DeclLoc = DeclLoc.getLocWithOffset(startArgList-startBuf);4776assert((DeclLoc.isValid()) && "Invalid DeclLoc");47774778const char *argPtr = startArgList;47794780while (*argPtr++ && parenCount) {4781switch (*argPtr) {4782case '^':4783// Replace the '^' with '*'.4784DeclLoc = DeclLoc.getLocWithOffset(argPtr-startArgList);4785ReplaceText(DeclLoc, 1, "*");4786break;4787case '(':4788parenCount++;4789break;4790case ')':4791parenCount--;4792break;4793}4794}4795}47964797bool RewriteModernObjC::PointerTypeTakesAnyBlockArguments(QualType QT) {4798const FunctionProtoType *FTP;4799const PointerType *PT = QT->getAs<PointerType>();4800if (PT) {4801FTP = PT->getPointeeType()->getAs<FunctionProtoType>();4802} else {4803const BlockPointerType *BPT = QT->getAs<BlockPointerType>();4804assert(BPT && "BlockPointerTypeTakeAnyBlockArguments(): not a block pointer type");4805FTP = BPT->getPointeeType()->getAs<FunctionProtoType>();4806}4807if (FTP) {4808for (const auto &I : FTP->param_types())4809if (isTopLevelBlockPointerType(I))4810return true;4811}4812return false;4813}48144815bool RewriteModernObjC::PointerTypeTakesAnyObjCQualifiedType(QualType QT) {4816const FunctionProtoType *FTP;4817const PointerType *PT = QT->getAs<PointerType>();4818if (PT) {4819FTP = PT->getPointeeType()->getAs<FunctionProtoType>();4820} else {4821const BlockPointerType *BPT = QT->getAs<BlockPointerType>();4822assert(BPT && "BlockPointerTypeTakeAnyBlockArguments(): not a block pointer type");4823FTP = BPT->getPointeeType()->getAs<FunctionProtoType>();4824}4825if (FTP) {4826for (const auto &I : FTP->param_types()) {4827if (I->isObjCQualifiedIdType())4828return true;4829if (I->isObjCObjectPointerType() &&4830I->getPointeeType()->isObjCQualifiedInterfaceType())4831return true;4832}48334834}4835return false;4836}48374838void RewriteModernObjC::GetExtentOfArgList(const char *Name, const char *&LParen,4839const char *&RParen) {4840const char *argPtr = strchr(Name, '(');4841assert((*argPtr == '(') && "Rewriter fuzzy parser confused");48424843LParen = argPtr; // output the start.4844argPtr++; // skip past the left paren.4845unsigned parenCount = 1;48464847while (*argPtr && parenCount) {4848switch (*argPtr) {4849case '(': parenCount++; break;4850case ')': parenCount--; break;4851default: break;4852}4853if (parenCount) argPtr++;4854}4855assert((*argPtr == ')') && "Rewriter fuzzy parser confused");4856RParen = argPtr; // output the end4857}48584859void RewriteModernObjC::RewriteBlockPointerDecl(NamedDecl *ND) {4860if (FunctionDecl *FD = dyn_cast<FunctionDecl>(ND)) {4861RewriteBlockPointerFunctionArgs(FD);4862return;4863}4864// Handle Variables and Typedefs.4865SourceLocation DeclLoc = ND->getLocation();4866QualType DeclT;4867if (VarDecl *VD = dyn_cast<VarDecl>(ND))4868DeclT = VD->getType();4869else if (TypedefNameDecl *TDD = dyn_cast<TypedefNameDecl>(ND))4870DeclT = TDD->getUnderlyingType();4871else if (FieldDecl *FD = dyn_cast<FieldDecl>(ND))4872DeclT = FD->getType();4873else4874llvm_unreachable("RewriteBlockPointerDecl(): Decl type not yet handled");48754876const char *startBuf = SM->getCharacterData(DeclLoc);4877const char *endBuf = startBuf;4878// scan backward (from the decl location) for the end of the previous decl.4879while (*startBuf != '^' && *startBuf != ';' && startBuf != MainFileStart)4880startBuf--;4881SourceLocation Start = DeclLoc.getLocWithOffset(startBuf-endBuf);4882std::string buf;4883unsigned OrigLength=0;4884// *startBuf != '^' if we are dealing with a pointer to function that4885// may take block argument types (which will be handled below).4886if (*startBuf == '^') {4887// Replace the '^' with '*', computing a negative offset.4888buf = '*';4889startBuf++;4890OrigLength++;4891}4892while (*startBuf != ')') {4893buf += *startBuf;4894startBuf++;4895OrigLength++;4896}4897buf += ')';4898OrigLength++;48994900if (PointerTypeTakesAnyBlockArguments(DeclT) ||4901PointerTypeTakesAnyObjCQualifiedType(DeclT)) {4902// Replace the '^' with '*' for arguments.4903// Replace id<P> with id/*<>*/4904DeclLoc = ND->getLocation();4905startBuf = SM->getCharacterData(DeclLoc);4906const char *argListBegin, *argListEnd;4907GetExtentOfArgList(startBuf, argListBegin, argListEnd);4908while (argListBegin < argListEnd) {4909if (*argListBegin == '^')4910buf += '*';4911else if (*argListBegin == '<') {4912buf += "/*";4913buf += *argListBegin++;4914OrigLength++;4915while (*argListBegin != '>') {4916buf += *argListBegin++;4917OrigLength++;4918}4919buf += *argListBegin;4920buf += "*/";4921}4922else4923buf += *argListBegin;4924argListBegin++;4925OrigLength++;4926}4927buf += ')';4928OrigLength++;4929}4930ReplaceText(Start, OrigLength, buf);4931}49324933/// SynthesizeByrefCopyDestroyHelper - This routine synthesizes:4934/// void __Block_byref_id_object_copy(struct Block_byref_id_object *dst,4935/// struct Block_byref_id_object *src) {4936/// _Block_object_assign (&_dest->object, _src->object,4937/// BLOCK_BYREF_CALLER | BLOCK_FIELD_IS_OBJECT4938/// [|BLOCK_FIELD_IS_WEAK]) // object4939/// _Block_object_assign(&_dest->object, _src->object,4940/// BLOCK_BYREF_CALLER | BLOCK_FIELD_IS_BLOCK4941/// [|BLOCK_FIELD_IS_WEAK]) // block4942/// }4943/// And:4944/// void __Block_byref_id_object_dispose(struct Block_byref_id_object *_src) {4945/// _Block_object_dispose(_src->object,4946/// BLOCK_BYREF_CALLER | BLOCK_FIELD_IS_OBJECT4947/// [|BLOCK_FIELD_IS_WEAK]) // object4948/// _Block_object_dispose(_src->object,4949/// BLOCK_BYREF_CALLER | BLOCK_FIELD_IS_BLOCK4950/// [|BLOCK_FIELD_IS_WEAK]) // block4951/// }49524953std::string RewriteModernObjC::SynthesizeByrefCopyDestroyHelper(VarDecl *VD,4954int flag) {4955std::string S;4956if (CopyDestroyCache.count(flag))4957return S;4958CopyDestroyCache.insert(flag);4959S = "static void __Block_byref_id_object_copy_";4960S += utostr(flag);4961S += "(void *dst, void *src) {\n";49624963// offset into the object pointer is computed as:4964// void * + void* + int + int + void* + void *4965unsigned IntSize =4966static_cast<unsigned>(Context->getTypeSize(Context->IntTy));4967unsigned VoidPtrSize =4968static_cast<unsigned>(Context->getTypeSize(Context->VoidPtrTy));49694970unsigned offset = (VoidPtrSize*4 + IntSize + IntSize)/Context->getCharWidth();4971S += " _Block_object_assign((char*)dst + ";4972S += utostr(offset);4973S += ", *(void * *) ((char*)src + ";4974S += utostr(offset);4975S += "), ";4976S += utostr(flag);4977S += ");\n}\n";49784979S += "static void __Block_byref_id_object_dispose_";4980S += utostr(flag);4981S += "(void *src) {\n";4982S += " _Block_object_dispose(*(void * *) ((char*)src + ";4983S += utostr(offset);4984S += "), ";4985S += utostr(flag);4986S += ");\n}\n";4987return S;4988}49894990/// RewriteByRefVar - For each __block typex ND variable this routine transforms4991/// the declaration into:4992/// struct __Block_byref_ND {4993/// void *__isa; // NULL for everything except __weak pointers4994/// struct __Block_byref_ND *__forwarding;4995/// int32_t __flags;4996/// int32_t __size;4997/// void *__Block_byref_id_object_copy; // If variable is __block ObjC object4998/// void *__Block_byref_id_object_dispose; // If variable is __block ObjC object4999/// typex ND;5000/// };5001///5002/// It then replaces declaration of ND variable with:5003/// struct __Block_byref_ND ND = {__isa=0B, __forwarding=&ND, __flags=some_flag,5004/// __size=sizeof(struct __Block_byref_ND),5005/// ND=initializer-if-any};5006///5007///5008void RewriteModernObjC::RewriteByRefVar(VarDecl *ND, bool firstDecl,5009bool lastDecl) {5010int flag = 0;5011int isa = 0;5012SourceLocation DeclLoc = ND->getTypeSpecStartLoc();5013if (DeclLoc.isInvalid())5014// If type location is missing, it is because of missing type (a warning).5015// Use variable's location which is good for this case.5016DeclLoc = ND->getLocation();5017const char *startBuf = SM->getCharacterData(DeclLoc);5018SourceLocation X = ND->getEndLoc();5019X = SM->getExpansionLoc(X);5020const char *endBuf = SM->getCharacterData(X);5021std::string Name(ND->getNameAsString());5022std::string ByrefType;5023RewriteByRefString(ByrefType, Name, ND, true);5024ByrefType += " {\n";5025ByrefType += " void *__isa;\n";5026RewriteByRefString(ByrefType, Name, ND);5027ByrefType += " *__forwarding;\n";5028ByrefType += " int __flags;\n";5029ByrefType += " int __size;\n";5030// Add void *__Block_byref_id_object_copy;5031// void *__Block_byref_id_object_dispose; if needed.5032QualType Ty = ND->getType();5033bool HasCopyAndDispose = Context->BlockRequiresCopying(Ty, ND);5034if (HasCopyAndDispose) {5035ByrefType += " void (*__Block_byref_id_object_copy)(void*, void*);\n";5036ByrefType += " void (*__Block_byref_id_object_dispose)(void*);\n";5037}50385039QualType T = Ty;5040(void)convertBlockPointerToFunctionPointer(T);5041T.getAsStringInternal(Name, Context->getPrintingPolicy());50425043ByrefType += " " + Name + ";\n";5044ByrefType += "};\n";5045// Insert this type in global scope. It is needed by helper function.5046SourceLocation FunLocStart;5047if (CurFunctionDef)5048FunLocStart = getFunctionSourceLocation(*this, CurFunctionDef);5049else {5050assert(CurMethodDef && "RewriteByRefVar - CurMethodDef is null");5051FunLocStart = CurMethodDef->getBeginLoc();5052}5053InsertText(FunLocStart, ByrefType);50545055if (Ty.isObjCGCWeak()) {5056flag |= BLOCK_FIELD_IS_WEAK;5057isa = 1;5058}5059if (HasCopyAndDispose) {5060flag = BLOCK_BYREF_CALLER;5061QualType Ty = ND->getType();5062// FIXME. Handle __weak variable (BLOCK_FIELD_IS_WEAK) as well.5063if (Ty->isBlockPointerType())5064flag |= BLOCK_FIELD_IS_BLOCK;5065else5066flag |= BLOCK_FIELD_IS_OBJECT;5067std::string HF = SynthesizeByrefCopyDestroyHelper(ND, flag);5068if (!HF.empty())5069Preamble += HF;5070}50715072// struct __Block_byref_ND ND =5073// {0, &ND, some_flag, __size=sizeof(struct __Block_byref_ND),5074// initializer-if-any};5075bool hasInit = (ND->getInit() != nullptr);5076// FIXME. rewriter does not support __block c++ objects which5077// require construction.5078if (hasInit)5079if (CXXConstructExpr *CExp = dyn_cast<CXXConstructExpr>(ND->getInit())) {5080CXXConstructorDecl *CXXDecl = CExp->getConstructor();5081if (CXXDecl && CXXDecl->isDefaultConstructor())5082hasInit = false;5083}50845085unsigned flags = 0;5086if (HasCopyAndDispose)5087flags |= BLOCK_HAS_COPY_DISPOSE;5088Name = ND->getNameAsString();5089ByrefType.clear();5090RewriteByRefString(ByrefType, Name, ND);5091std::string ForwardingCastType("(");5092ForwardingCastType += ByrefType + " *)";5093ByrefType += " " + Name + " = {(void*)";5094ByrefType += utostr(isa);5095ByrefType += "," + ForwardingCastType + "&" + Name + ", ";5096ByrefType += utostr(flags);5097ByrefType += ", ";5098ByrefType += "sizeof(";5099RewriteByRefString(ByrefType, Name, ND);5100ByrefType += ")";5101if (HasCopyAndDispose) {5102ByrefType += ", __Block_byref_id_object_copy_";5103ByrefType += utostr(flag);5104ByrefType += ", __Block_byref_id_object_dispose_";5105ByrefType += utostr(flag);5106}51075108if (!firstDecl) {5109// In multiple __block declarations, and for all but 1st declaration,5110// find location of the separating comma. This would be start location5111// where new text is to be inserted.5112DeclLoc = ND->getLocation();5113const char *startDeclBuf = SM->getCharacterData(DeclLoc);5114const char *commaBuf = startDeclBuf;5115while (*commaBuf != ',')5116commaBuf--;5117assert((*commaBuf == ',') && "RewriteByRefVar: can't find ','");5118DeclLoc = DeclLoc.getLocWithOffset(commaBuf - startDeclBuf);5119startBuf = commaBuf;5120}51215122if (!hasInit) {5123ByrefType += "};\n";5124unsigned nameSize = Name.size();5125// for block or function pointer declaration. Name is already5126// part of the declaration.5127if (Ty->isBlockPointerType() || Ty->isFunctionPointerType())5128nameSize = 1;5129ReplaceText(DeclLoc, endBuf-startBuf+nameSize, ByrefType);5130}5131else {5132ByrefType += ", ";5133SourceLocation startLoc;5134Expr *E = ND->getInit();5135if (const CStyleCastExpr *ECE = dyn_cast<CStyleCastExpr>(E))5136startLoc = ECE->getLParenLoc();5137else5138startLoc = E->getBeginLoc();5139startLoc = SM->getExpansionLoc(startLoc);5140endBuf = SM->getCharacterData(startLoc);5141ReplaceText(DeclLoc, endBuf-startBuf, ByrefType);51425143const char separator = lastDecl ? ';' : ',';5144const char *startInitializerBuf = SM->getCharacterData(startLoc);5145const char *separatorBuf = strchr(startInitializerBuf, separator);5146assert((*separatorBuf == separator) &&5147"RewriteByRefVar: can't find ';' or ','");5148SourceLocation separatorLoc =5149startLoc.getLocWithOffset(separatorBuf-startInitializerBuf);51505151InsertText(separatorLoc, lastDecl ? "}" : "};\n");5152}5153}51545155void RewriteModernObjC::CollectBlockDeclRefInfo(BlockExpr *Exp) {5156// Add initializers for any closure decl refs.5157GetBlockDeclRefExprs(Exp->getBody());5158if (BlockDeclRefs.size()) {5159// Unique all "by copy" declarations.5160for (unsigned i = 0; i < BlockDeclRefs.size(); i++)5161if (!BlockDeclRefs[i]->getDecl()->hasAttr<BlocksAttr>()) {5162if (!BlockByCopyDeclsPtrSet.count(BlockDeclRefs[i]->getDecl())) {5163BlockByCopyDeclsPtrSet.insert(BlockDeclRefs[i]->getDecl());5164BlockByCopyDecls.push_back(BlockDeclRefs[i]->getDecl());5165}5166}5167// Unique all "by ref" declarations.5168for (unsigned i = 0; i < BlockDeclRefs.size(); i++)5169if (BlockDeclRefs[i]->getDecl()->hasAttr<BlocksAttr>()) {5170if (!BlockByRefDeclsPtrSet.count(BlockDeclRefs[i]->getDecl())) {5171BlockByRefDeclsPtrSet.insert(BlockDeclRefs[i]->getDecl());5172BlockByRefDecls.push_back(BlockDeclRefs[i]->getDecl());5173}5174}5175// Find any imported blocks...they will need special attention.5176for (unsigned i = 0; i < BlockDeclRefs.size(); i++)5177if (BlockDeclRefs[i]->getDecl()->hasAttr<BlocksAttr>() ||5178BlockDeclRefs[i]->getType()->isObjCObjectPointerType() ||5179BlockDeclRefs[i]->getType()->isBlockPointerType())5180ImportedBlockDecls.insert(BlockDeclRefs[i]->getDecl());5181}5182}51835184FunctionDecl *RewriteModernObjC::SynthBlockInitFunctionDecl(StringRef name) {5185IdentifierInfo *ID = &Context->Idents.get(name);5186QualType FType = Context->getFunctionNoProtoType(Context->VoidPtrTy);5187return FunctionDecl::Create(*Context, TUDecl, SourceLocation(),5188SourceLocation(), ID, FType, nullptr, SC_Extern,5189false, false);5190}51915192Stmt *RewriteModernObjC::SynthBlockInitExpr(BlockExpr *Exp,5193const SmallVectorImpl<DeclRefExpr *> &InnerBlockDeclRefs) {5194const BlockDecl *block = Exp->getBlockDecl();51955196Blocks.push_back(Exp);51975198CollectBlockDeclRefInfo(Exp);51995200// Add inner imported variables now used in current block.5201int countOfInnerDecls = 0;5202if (!InnerBlockDeclRefs.empty()) {5203for (unsigned i = 0; i < InnerBlockDeclRefs.size(); i++) {5204DeclRefExpr *Exp = InnerBlockDeclRefs[i];5205ValueDecl *VD = Exp->getDecl();5206if (!VD->hasAttr<BlocksAttr>() && !BlockByCopyDeclsPtrSet.count(VD)) {5207// We need to save the copied-in variables in nested5208// blocks because it is needed at the end for some of the API generations.5209// See SynthesizeBlockLiterals routine.5210InnerDeclRefs.push_back(Exp); countOfInnerDecls++;5211BlockDeclRefs.push_back(Exp);5212BlockByCopyDeclsPtrSet.insert(VD);5213BlockByCopyDecls.push_back(VD);5214}5215if (VD->hasAttr<BlocksAttr>() && !BlockByRefDeclsPtrSet.count(VD)) {5216InnerDeclRefs.push_back(Exp); countOfInnerDecls++;5217BlockDeclRefs.push_back(Exp);5218BlockByRefDeclsPtrSet.insert(VD);5219BlockByRefDecls.push_back(VD);5220}5221}5222// Find any imported blocks...they will need special attention.5223for (unsigned i = 0; i < InnerBlockDeclRefs.size(); i++)5224if (InnerBlockDeclRefs[i]->getDecl()->hasAttr<BlocksAttr>() ||5225InnerBlockDeclRefs[i]->getType()->isObjCObjectPointerType() ||5226InnerBlockDeclRefs[i]->getType()->isBlockPointerType())5227ImportedBlockDecls.insert(InnerBlockDeclRefs[i]->getDecl());5228}5229InnerDeclRefsCount.push_back(countOfInnerDecls);52305231std::string FuncName;52325233if (CurFunctionDef)5234FuncName = CurFunctionDef->getNameAsString();5235else if (CurMethodDef)5236BuildUniqueMethodName(FuncName, CurMethodDef);5237else if (GlobalVarDecl)5238FuncName = std::string(GlobalVarDecl->getNameAsString());52395240bool GlobalBlockExpr =5241block->getDeclContext()->getRedeclContext()->isFileContext();52425243if (GlobalBlockExpr && !GlobalVarDecl) {5244Diags.Report(block->getLocation(), GlobalBlockRewriteFailedDiag);5245GlobalBlockExpr = false;5246}52475248std::string BlockNumber = utostr(Blocks.size()-1);52495250std::string Func = "__" + FuncName + "_block_func_" + BlockNumber;52515252// Get a pointer to the function type so we can cast appropriately.5253QualType BFT = convertFunctionTypeOfBlocks(Exp->getFunctionType());5254QualType FType = Context->getPointerType(BFT);52555256FunctionDecl *FD;5257Expr *NewRep;52585259// Simulate a constructor call...5260std::string Tag;52615262if (GlobalBlockExpr)5263Tag = "__global_";5264else5265Tag = "__";5266Tag += FuncName + "_block_impl_" + BlockNumber;52675268FD = SynthBlockInitFunctionDecl(Tag);5269DeclRefExpr *DRE = new (Context)5270DeclRefExpr(*Context, FD, false, FType, VK_PRValue, SourceLocation());52715272SmallVector<Expr*, 4> InitExprs;52735274// Initialize the block function.5275FD = SynthBlockInitFunctionDecl(Func);5276DeclRefExpr *Arg = new (Context) DeclRefExpr(5277*Context, FD, false, FD->getType(), VK_LValue, SourceLocation());5278CastExpr *castExpr = NoTypeInfoCStyleCastExpr(Context, Context->VoidPtrTy,5279CK_BitCast, Arg);5280InitExprs.push_back(castExpr);52815282// Initialize the block descriptor.5283std::string DescData = "__" + FuncName + "_block_desc_" + BlockNumber + "_DATA";52845285VarDecl *NewVD = VarDecl::Create(5286*Context, TUDecl, SourceLocation(), SourceLocation(),5287&Context->Idents.get(DescData), Context->VoidPtrTy, nullptr, SC_Static);5288UnaryOperator *DescRefExpr = UnaryOperator::Create(5289const_cast<ASTContext &>(*Context),5290new (Context) DeclRefExpr(*Context, NewVD, false, Context->VoidPtrTy,5291VK_LValue, SourceLocation()),5292UO_AddrOf, Context->getPointerType(Context->VoidPtrTy), VK_PRValue,5293OK_Ordinary, SourceLocation(), false, FPOptionsOverride());5294InitExprs.push_back(DescRefExpr);52955296// Add initializers for any closure decl refs.5297if (BlockDeclRefs.size()) {5298Expr *Exp;5299// Output all "by copy" declarations.5300for (SmallVectorImpl<ValueDecl *>::iterator I = BlockByCopyDecls.begin(),5301E = BlockByCopyDecls.end(); I != E; ++I) {5302if (isObjCType((*I)->getType())) {5303// FIXME: Conform to ABI ([[obj retain] autorelease]).5304FD = SynthBlockInitFunctionDecl((*I)->getName());5305Exp = new (Context) DeclRefExpr(*Context, FD, false, FD->getType(),5306VK_LValue, SourceLocation());5307if (HasLocalVariableExternalStorage(*I)) {5308QualType QT = (*I)->getType();5309QT = Context->getPointerType(QT);5310Exp = UnaryOperator::Create(const_cast<ASTContext &>(*Context), Exp,5311UO_AddrOf, QT, VK_PRValue, OK_Ordinary,5312SourceLocation(), false,5313FPOptionsOverride());5314}5315} else if (isTopLevelBlockPointerType((*I)->getType())) {5316FD = SynthBlockInitFunctionDecl((*I)->getName());5317Arg = new (Context) DeclRefExpr(*Context, FD, false, FD->getType(),5318VK_LValue, SourceLocation());5319Exp = NoTypeInfoCStyleCastExpr(Context, Context->VoidPtrTy,5320CK_BitCast, Arg);5321} else {5322FD = SynthBlockInitFunctionDecl((*I)->getName());5323Exp = new (Context) DeclRefExpr(*Context, FD, false, FD->getType(),5324VK_LValue, SourceLocation());5325if (HasLocalVariableExternalStorage(*I)) {5326QualType QT = (*I)->getType();5327QT = Context->getPointerType(QT);5328Exp = UnaryOperator::Create(const_cast<ASTContext &>(*Context), Exp,5329UO_AddrOf, QT, VK_PRValue, OK_Ordinary,5330SourceLocation(), false,5331FPOptionsOverride());5332}53335334}5335InitExprs.push_back(Exp);5336}5337// Output all "by ref" declarations.5338for (SmallVectorImpl<ValueDecl *>::iterator I = BlockByRefDecls.begin(),5339E = BlockByRefDecls.end(); I != E; ++I) {5340ValueDecl *ND = (*I);5341std::string Name(ND->getNameAsString());5342std::string RecName;5343RewriteByRefString(RecName, Name, ND, true);5344IdentifierInfo *II = &Context->Idents.get(RecName.c_str()5345+ sizeof("struct"));5346RecordDecl *RD =5347RecordDecl::Create(*Context, TagTypeKind::Struct, TUDecl,5348SourceLocation(), SourceLocation(), II);5349assert(RD && "SynthBlockInitExpr(): Can't find RecordDecl");5350QualType castT = Context->getPointerType(Context->getTagDeclType(RD));53515352FD = SynthBlockInitFunctionDecl((*I)->getName());5353Exp = new (Context) DeclRefExpr(*Context, FD, false, FD->getType(),5354VK_LValue, SourceLocation());5355bool isNestedCapturedVar = false;5356for (const auto &CI : block->captures()) {5357const VarDecl *variable = CI.getVariable();5358if (variable == ND && CI.isNested()) {5359assert(CI.isByRef() &&5360"SynthBlockInitExpr - captured block variable is not byref");5361isNestedCapturedVar = true;5362break;5363}5364}5365// captured nested byref variable has its address passed. Do not take5366// its address again.5367if (!isNestedCapturedVar)5368Exp = UnaryOperator::Create(5369const_cast<ASTContext &>(*Context), Exp, UO_AddrOf,5370Context->getPointerType(Exp->getType()), VK_PRValue, OK_Ordinary,5371SourceLocation(), false, FPOptionsOverride());5372Exp = NoTypeInfoCStyleCastExpr(Context, castT, CK_BitCast, Exp);5373InitExprs.push_back(Exp);5374}5375}5376if (ImportedBlockDecls.size()) {5377// generate BLOCK_HAS_COPY_DISPOSE(have helper funcs) | BLOCK_HAS_DESCRIPTOR5378int flag = (BLOCK_HAS_COPY_DISPOSE | BLOCK_HAS_DESCRIPTOR);5379unsigned IntSize =5380static_cast<unsigned>(Context->getTypeSize(Context->IntTy));5381Expr *FlagExp = IntegerLiteral::Create(*Context, llvm::APInt(IntSize, flag),5382Context->IntTy, SourceLocation());5383InitExprs.push_back(FlagExp);5384}5385NewRep = CallExpr::Create(*Context, DRE, InitExprs, FType, VK_LValue,5386SourceLocation(), FPOptionsOverride());53875388if (GlobalBlockExpr) {5389assert (!GlobalConstructionExp &&5390"SynthBlockInitExpr - GlobalConstructionExp must be null");5391GlobalConstructionExp = NewRep;5392NewRep = DRE;5393}53945395NewRep = UnaryOperator::Create(5396const_cast<ASTContext &>(*Context), NewRep, UO_AddrOf,5397Context->getPointerType(NewRep->getType()), VK_PRValue, OK_Ordinary,5398SourceLocation(), false, FPOptionsOverride());5399NewRep = NoTypeInfoCStyleCastExpr(Context, FType, CK_BitCast,5400NewRep);5401// Put Paren around the call.5402NewRep = new (Context) ParenExpr(SourceLocation(), SourceLocation(),5403NewRep);54045405BlockDeclRefs.clear();5406BlockByRefDecls.clear();5407BlockByRefDeclsPtrSet.clear();5408BlockByCopyDecls.clear();5409BlockByCopyDeclsPtrSet.clear();5410ImportedBlockDecls.clear();5411return NewRep;5412}54135414bool RewriteModernObjC::IsDeclStmtInForeachHeader(DeclStmt *DS) {5415if (const ObjCForCollectionStmt * CS =5416dyn_cast<ObjCForCollectionStmt>(Stmts.back()))5417return CS->getElement() == DS;5418return false;5419}54205421//===----------------------------------------------------------------------===//5422// Function Body / Expression rewriting5423//===----------------------------------------------------------------------===//54245425Stmt *RewriteModernObjC::RewriteFunctionBodyOrGlobalInitializer(Stmt *S) {5426if (isa<SwitchStmt>(S) || isa<WhileStmt>(S) ||5427isa<DoStmt>(S) || isa<ForStmt>(S))5428Stmts.push_back(S);5429else if (isa<ObjCForCollectionStmt>(S)) {5430Stmts.push_back(S);5431ObjCBcLabelNo.push_back(++BcLabelCount);5432}54335434// Pseudo-object operations and ivar references need special5435// treatment because we're going to recursively rewrite them.5436if (PseudoObjectExpr *PseudoOp = dyn_cast<PseudoObjectExpr>(S)) {5437if (isa<BinaryOperator>(PseudoOp->getSyntacticForm())) {5438return RewritePropertyOrImplicitSetter(PseudoOp);5439} else {5440return RewritePropertyOrImplicitGetter(PseudoOp);5441}5442} else if (ObjCIvarRefExpr *IvarRefExpr = dyn_cast<ObjCIvarRefExpr>(S)) {5443return RewriteObjCIvarRefExpr(IvarRefExpr);5444}5445else if (isa<OpaqueValueExpr>(S))5446S = cast<OpaqueValueExpr>(S)->getSourceExpr();54475448SourceRange OrigStmtRange = S->getSourceRange();54495450// Perform a bottom up rewrite of all children.5451for (Stmt *&childStmt : S->children())5452if (childStmt) {5453Stmt *newStmt = RewriteFunctionBodyOrGlobalInitializer(childStmt);5454if (newStmt) {5455childStmt = newStmt;5456}5457}54585459if (BlockExpr *BE = dyn_cast<BlockExpr>(S)) {5460SmallVector<DeclRefExpr *, 8> InnerBlockDeclRefs;5461llvm::SmallPtrSet<const DeclContext *, 8> InnerContexts;5462InnerContexts.insert(BE->getBlockDecl());5463ImportedLocalExternalDecls.clear();5464GetInnerBlockDeclRefExprs(BE->getBody(),5465InnerBlockDeclRefs, InnerContexts);5466// Rewrite the block body in place.5467Stmt *SaveCurrentBody = CurrentBody;5468CurrentBody = BE->getBody();5469PropParentMap = nullptr;5470// block literal on rhs of a property-dot-sytax assignment5471// must be replaced by its synthesize ast so getRewrittenText5472// works as expected. In this case, what actually ends up on RHS5473// is the blockTranscribed which is the helper function for the5474// block literal; as in: self.c = ^() {[ace ARR];};5475bool saveDisableReplaceStmt = DisableReplaceStmt;5476DisableReplaceStmt = false;5477RewriteFunctionBodyOrGlobalInitializer(BE->getBody());5478DisableReplaceStmt = saveDisableReplaceStmt;5479CurrentBody = SaveCurrentBody;5480PropParentMap = nullptr;5481ImportedLocalExternalDecls.clear();5482// Now we snarf the rewritten text and stash it away for later use.5483std::string Str = Rewrite.getRewrittenText(BE->getSourceRange());5484RewrittenBlockExprs[BE] = Str;54855486Stmt *blockTranscribed = SynthBlockInitExpr(BE, InnerBlockDeclRefs);54875488//blockTranscribed->dump();5489ReplaceStmt(S, blockTranscribed);5490return blockTranscribed;5491}5492// Handle specific things.5493if (ObjCEncodeExpr *AtEncode = dyn_cast<ObjCEncodeExpr>(S))5494return RewriteAtEncode(AtEncode);54955496if (ObjCSelectorExpr *AtSelector = dyn_cast<ObjCSelectorExpr>(S))5497return RewriteAtSelector(AtSelector);54985499if (ObjCStringLiteral *AtString = dyn_cast<ObjCStringLiteral>(S))5500return RewriteObjCStringLiteral(AtString);55015502if (ObjCBoolLiteralExpr *BoolLitExpr = dyn_cast<ObjCBoolLiteralExpr>(S))5503return RewriteObjCBoolLiteralExpr(BoolLitExpr);55045505if (ObjCBoxedExpr *BoxedExpr = dyn_cast<ObjCBoxedExpr>(S))5506return RewriteObjCBoxedExpr(BoxedExpr);55075508if (ObjCArrayLiteral *ArrayLitExpr = dyn_cast<ObjCArrayLiteral>(S))5509return RewriteObjCArrayLiteralExpr(ArrayLitExpr);55105511if (ObjCDictionaryLiteral *DictionaryLitExpr =5512dyn_cast<ObjCDictionaryLiteral>(S))5513return RewriteObjCDictionaryLiteralExpr(DictionaryLitExpr);55145515if (ObjCMessageExpr *MessExpr = dyn_cast<ObjCMessageExpr>(S)) {5516#if 05517// Before we rewrite it, put the original message expression in a comment.5518SourceLocation startLoc = MessExpr->getBeginLoc();5519SourceLocation endLoc = MessExpr->getEndLoc();55205521const char *startBuf = SM->getCharacterData(startLoc);5522const char *endBuf = SM->getCharacterData(endLoc);55235524std::string messString;5525messString += "// ";5526messString.append(startBuf, endBuf-startBuf+1);5527messString += "\n";55285529// FIXME: Missing definition of5530// InsertText(clang::SourceLocation, char const*, unsigned int).5531// InsertText(startLoc, messString);5532// Tried this, but it didn't work either...5533// ReplaceText(startLoc, 0, messString.c_str(), messString.size());5534#endif5535return RewriteMessageExpr(MessExpr);5536}55375538if (ObjCAutoreleasePoolStmt *StmtAutoRelease =5539dyn_cast<ObjCAutoreleasePoolStmt>(S)) {5540return RewriteObjCAutoreleasePoolStmt(StmtAutoRelease);5541}55425543if (ObjCAtTryStmt *StmtTry = dyn_cast<ObjCAtTryStmt>(S))5544return RewriteObjCTryStmt(StmtTry);55455546if (ObjCAtSynchronizedStmt *StmtTry = dyn_cast<ObjCAtSynchronizedStmt>(S))5547return RewriteObjCSynchronizedStmt(StmtTry);55485549if (ObjCAtThrowStmt *StmtThrow = dyn_cast<ObjCAtThrowStmt>(S))5550return RewriteObjCThrowStmt(StmtThrow);55515552if (ObjCProtocolExpr *ProtocolExp = dyn_cast<ObjCProtocolExpr>(S))5553return RewriteObjCProtocolExpr(ProtocolExp);55545555if (ObjCForCollectionStmt *StmtForCollection =5556dyn_cast<ObjCForCollectionStmt>(S))5557return RewriteObjCForCollectionStmt(StmtForCollection,5558OrigStmtRange.getEnd());5559if (BreakStmt *StmtBreakStmt =5560dyn_cast<BreakStmt>(S))5561return RewriteBreakStmt(StmtBreakStmt);5562if (ContinueStmt *StmtContinueStmt =5563dyn_cast<ContinueStmt>(S))5564return RewriteContinueStmt(StmtContinueStmt);55655566// Need to check for protocol refs (id <P>, Foo <P> *) in variable decls5567// and cast exprs.5568if (DeclStmt *DS = dyn_cast<DeclStmt>(S)) {5569// FIXME: What we're doing here is modifying the type-specifier that5570// precedes the first Decl. In the future the DeclGroup should have5571// a separate type-specifier that we can rewrite.5572// NOTE: We need to avoid rewriting the DeclStmt if it is within5573// the context of an ObjCForCollectionStmt. For example:5574// NSArray *someArray;5575// for (id <FooProtocol> index in someArray) ;5576// This is because RewriteObjCForCollectionStmt() does textual rewriting5577// and it depends on the original text locations/positions.5578if (Stmts.empty() || !IsDeclStmtInForeachHeader(DS))5579RewriteObjCQualifiedInterfaceTypes(*DS->decl_begin());55805581// Blocks rewrite rules.5582for (DeclStmt::decl_iterator DI = DS->decl_begin(), DE = DS->decl_end();5583DI != DE; ++DI) {5584Decl *SD = *DI;5585if (ValueDecl *ND = dyn_cast<ValueDecl>(SD)) {5586if (isTopLevelBlockPointerType(ND->getType()))5587RewriteBlockPointerDecl(ND);5588else if (ND->getType()->isFunctionPointerType())5589CheckFunctionPointerDecl(ND->getType(), ND);5590if (VarDecl *VD = dyn_cast<VarDecl>(SD)) {5591if (VD->hasAttr<BlocksAttr>()) {5592static unsigned uniqueByrefDeclCount = 0;5593assert(!BlockByRefDeclNo.count(ND) &&5594"RewriteFunctionBodyOrGlobalInitializer: Duplicate byref decl");5595BlockByRefDeclNo[ND] = uniqueByrefDeclCount++;5596RewriteByRefVar(VD, (DI == DS->decl_begin()), ((DI+1) == DE));5597}5598else5599RewriteTypeOfDecl(VD);5600}5601}5602if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(SD)) {5603if (isTopLevelBlockPointerType(TD->getUnderlyingType()))5604RewriteBlockPointerDecl(TD);5605else if (TD->getUnderlyingType()->isFunctionPointerType())5606CheckFunctionPointerDecl(TD->getUnderlyingType(), TD);5607}5608}5609}56105611if (CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(S))5612RewriteObjCQualifiedInterfaceTypes(CE);56135614if (isa<SwitchStmt>(S) || isa<WhileStmt>(S) ||5615isa<DoStmt>(S) || isa<ForStmt>(S)) {5616assert(!Stmts.empty() && "Statement stack is empty");5617assert ((isa<SwitchStmt>(Stmts.back()) || isa<WhileStmt>(Stmts.back()) ||5618isa<DoStmt>(Stmts.back()) || isa<ForStmt>(Stmts.back()))5619&& "Statement stack mismatch");5620Stmts.pop_back();5621}5622// Handle blocks rewriting.5623if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(S)) {5624ValueDecl *VD = DRE->getDecl();5625if (VD->hasAttr<BlocksAttr>())5626return RewriteBlockDeclRefExpr(DRE);5627if (HasLocalVariableExternalStorage(VD))5628return RewriteLocalVariableExternalStorage(DRE);5629}56305631if (CallExpr *CE = dyn_cast<CallExpr>(S)) {5632if (CE->getCallee()->getType()->isBlockPointerType()) {5633Stmt *BlockCall = SynthesizeBlockCall(CE, CE->getCallee());5634ReplaceStmt(S, BlockCall);5635return BlockCall;5636}5637}5638if (CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(S)) {5639RewriteCastExpr(CE);5640}5641if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(S)) {5642RewriteImplicitCastObjCExpr(ICE);5643}5644#if 056455646if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(S)) {5647CastExpr *Replacement = new (Context) CastExpr(ICE->getType(),5648ICE->getSubExpr(),5649SourceLocation());5650// Get the new text.5651std::string SStr;5652llvm::raw_string_ostream Buf(SStr);5653Replacement->printPretty(Buf);5654const std::string &Str = Buf.str();56555656printf("CAST = %s\n", &Str[0]);5657InsertText(ICE->getSubExpr()->getBeginLoc(), Str);5658delete S;5659return Replacement;5660}5661#endif5662// Return this stmt unmodified.5663return S;5664}56655666void RewriteModernObjC::RewriteRecordBody(RecordDecl *RD) {5667for (auto *FD : RD->fields()) {5668if (isTopLevelBlockPointerType(FD->getType()))5669RewriteBlockPointerDecl(FD);5670if (FD->getType()->isObjCQualifiedIdType() ||5671FD->getType()->isObjCQualifiedInterfaceType())5672RewriteObjCQualifiedInterfaceTypes(FD);5673}5674}56755676/// HandleDeclInMainFile - This is called for each top-level decl defined in the5677/// main file of the input.5678void RewriteModernObjC::HandleDeclInMainFile(Decl *D) {5679switch (D->getKind()) {5680case Decl::Function: {5681FunctionDecl *FD = cast<FunctionDecl>(D);5682if (FD->isOverloadedOperator())5683return;56845685// Since function prototypes don't have ParmDecl's, we check the function5686// prototype. This enables us to rewrite function declarations and5687// definitions using the same code.5688RewriteBlocksInFunctionProtoType(FD->getType(), FD);56895690if (!FD->isThisDeclarationADefinition())5691break;56925693// FIXME: If this should support Obj-C++, support CXXTryStmt5694if (CompoundStmt *Body = dyn_cast_or_null<CompoundStmt>(FD->getBody())) {5695CurFunctionDef = FD;5696CurrentBody = Body;5697Body =5698cast_or_null<CompoundStmt>(RewriteFunctionBodyOrGlobalInitializer(Body));5699FD->setBody(Body);5700CurrentBody = nullptr;5701if (PropParentMap) {5702delete PropParentMap;5703PropParentMap = nullptr;5704}5705// This synthesizes and inserts the block "impl" struct, invoke function,5706// and any copy/dispose helper functions.5707InsertBlockLiteralsWithinFunction(FD);5708RewriteLineDirective(D);5709CurFunctionDef = nullptr;5710}5711break;5712}5713case Decl::ObjCMethod: {5714ObjCMethodDecl *MD = cast<ObjCMethodDecl>(D);5715if (CompoundStmt *Body = MD->getCompoundBody()) {5716CurMethodDef = MD;5717CurrentBody = Body;5718Body =5719cast_or_null<CompoundStmt>(RewriteFunctionBodyOrGlobalInitializer(Body));5720MD->setBody(Body);5721CurrentBody = nullptr;5722if (PropParentMap) {5723delete PropParentMap;5724PropParentMap = nullptr;5725}5726InsertBlockLiteralsWithinMethod(MD);5727RewriteLineDirective(D);5728CurMethodDef = nullptr;5729}5730break;5731}5732case Decl::ObjCImplementation: {5733ObjCImplementationDecl *CI = cast<ObjCImplementationDecl>(D);5734ClassImplementation.push_back(CI);5735break;5736}5737case Decl::ObjCCategoryImpl: {5738ObjCCategoryImplDecl *CI = cast<ObjCCategoryImplDecl>(D);5739CategoryImplementation.push_back(CI);5740break;5741}5742case Decl::Var: {5743VarDecl *VD = cast<VarDecl>(D);5744RewriteObjCQualifiedInterfaceTypes(VD);5745if (isTopLevelBlockPointerType(VD->getType()))5746RewriteBlockPointerDecl(VD);5747else if (VD->getType()->isFunctionPointerType()) {5748CheckFunctionPointerDecl(VD->getType(), VD);5749if (VD->getInit()) {5750if (CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(VD->getInit())) {5751RewriteCastExpr(CE);5752}5753}5754} else if (VD->getType()->isRecordType()) {5755RecordDecl *RD = VD->getType()->castAs<RecordType>()->getDecl();5756if (RD->isCompleteDefinition())5757RewriteRecordBody(RD);5758}5759if (VD->getInit()) {5760GlobalVarDecl = VD;5761CurrentBody = VD->getInit();5762RewriteFunctionBodyOrGlobalInitializer(VD->getInit());5763CurrentBody = nullptr;5764if (PropParentMap) {5765delete PropParentMap;5766PropParentMap = nullptr;5767}5768SynthesizeBlockLiterals(VD->getTypeSpecStartLoc(), VD->getName());5769GlobalVarDecl = nullptr;57705771// This is needed for blocks.5772if (CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(VD->getInit())) {5773RewriteCastExpr(CE);5774}5775}5776break;5777}5778case Decl::TypeAlias:5779case Decl::Typedef: {5780if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(D)) {5781if (isTopLevelBlockPointerType(TD->getUnderlyingType()))5782RewriteBlockPointerDecl(TD);5783else if (TD->getUnderlyingType()->isFunctionPointerType())5784CheckFunctionPointerDecl(TD->getUnderlyingType(), TD);5785else5786RewriteObjCQualifiedInterfaceTypes(TD);5787}5788break;5789}5790case Decl::CXXRecord:5791case Decl::Record: {5792RecordDecl *RD = cast<RecordDecl>(D);5793if (RD->isCompleteDefinition())5794RewriteRecordBody(RD);5795break;5796}5797default:5798break;5799}5800// Nothing yet.5801}58025803/// Write_ProtocolExprReferencedMetadata - This routine writer out the5804/// protocol reference symbols in the for of:5805/// struct _protocol_t *PROTOCOL_REF = &PROTOCOL_METADATA.5806static void Write_ProtocolExprReferencedMetadata(ASTContext *Context,5807ObjCProtocolDecl *PDecl,5808std::string &Result) {5809// Also output .objc_protorefs$B section and its meta-data.5810if (Context->getLangOpts().MicrosoftExt)5811Result += "static ";5812Result += "struct _protocol_t *";5813Result += "_OBJC_PROTOCOL_REFERENCE_$_";5814Result += PDecl->getNameAsString();5815Result += " = &";5816Result += "_OBJC_PROTOCOL_"; Result += PDecl->getNameAsString();5817Result += ";\n";5818}58195820void RewriteModernObjC::HandleTranslationUnit(ASTContext &C) {5821if (Diags.hasErrorOccurred())5822return;58235824RewriteInclude();58255826for (unsigned i = 0, e = FunctionDefinitionsSeen.size(); i < e; i++) {5827// translation of function bodies were postponed until all class and5828// their extensions and implementations are seen. This is because, we5829// cannot build grouping structs for bitfields until they are all seen.5830FunctionDecl *FDecl = FunctionDefinitionsSeen[i];5831HandleTopLevelSingleDecl(FDecl);5832}58335834// Here's a great place to add any extra declarations that may be needed.5835// Write out meta data for each @protocol(<expr>).5836for (ObjCProtocolDecl *ProtDecl : ProtocolExprDecls) {5837RewriteObjCProtocolMetaData(ProtDecl, Preamble);5838Write_ProtocolExprReferencedMetadata(Context, ProtDecl, Preamble);5839}58405841InsertText(SM->getLocForStartOfFile(MainFileID), Preamble, false);58425843if (ClassImplementation.size() || CategoryImplementation.size())5844RewriteImplementations();58455846for (unsigned i = 0, e = ObjCInterfacesSeen.size(); i < e; i++) {5847ObjCInterfaceDecl *CDecl = ObjCInterfacesSeen[i];5848// Write struct declaration for the class matching its ivar declarations.5849// Note that for modern abi, this is postponed until the end of TU5850// because class extensions and the implementation might declare their own5851// private ivars.5852RewriteInterfaceDecl(CDecl);5853}58545855// Get the buffer corresponding to MainFileID. If we haven't changed it, then5856// we are done.5857if (const RewriteBuffer *RewriteBuf =5858Rewrite.getRewriteBufferFor(MainFileID)) {5859//printf("Changed:\n");5860*OutFile << std::string(RewriteBuf->begin(), RewriteBuf->end());5861} else {5862llvm::errs() << "No changes\n";5863}58645865if (ClassImplementation.size() || CategoryImplementation.size() ||5866ProtocolExprDecls.size()) {5867// Rewrite Objective-c meta data*5868std::string ResultStr;5869RewriteMetaDataIntoBuffer(ResultStr);5870// Emit metadata.5871*OutFile << ResultStr;5872}5873// Emit ImageInfo;5874{5875std::string ResultStr;5876WriteImageInfo(ResultStr);5877*OutFile << ResultStr;5878}5879OutFile->flush();5880}58815882void RewriteModernObjC::Initialize(ASTContext &context) {5883InitializeCommon(context);58845885Preamble += "#ifndef __OBJC2__\n";5886Preamble += "#define __OBJC2__\n";5887Preamble += "#endif\n";58885889// declaring objc_selector outside the parameter list removes a silly5890// scope related warning...5891if (IsHeader)5892Preamble = "#pragma once\n";5893Preamble += "struct objc_selector; struct objc_class;\n";5894Preamble += "struct __rw_objc_super { \n\tstruct objc_object *object; ";5895Preamble += "\n\tstruct objc_object *superClass; ";5896// Add a constructor for creating temporary objects.5897Preamble += "\n\t__rw_objc_super(struct objc_object *o, struct objc_object *s) ";5898Preamble += ": object(o), superClass(s) {} ";5899Preamble += "\n};\n";59005901if (LangOpts.MicrosoftExt) {5902// Define all sections using syntax that makes sense.5903// These are currently generated.5904Preamble += "\n#pragma section(\".objc_classlist$B\", long, read, write)\n";5905Preamble += "#pragma section(\".objc_catlist$B\", long, read, write)\n";5906Preamble += "#pragma section(\".objc_imageinfo$B\", long, read, write)\n";5907Preamble += "#pragma section(\".objc_nlclslist$B\", long, read, write)\n";5908Preamble += "#pragma section(\".objc_nlcatlist$B\", long, read, write)\n";5909// These are generated but not necessary for functionality.5910Preamble += "#pragma section(\".cat_cls_meth$B\", long, read, write)\n";5911Preamble += "#pragma section(\".inst_meth$B\", long, read, write)\n";5912Preamble += "#pragma section(\".cls_meth$B\", long, read, write)\n";5913Preamble += "#pragma section(\".objc_ivar$B\", long, read, write)\n";59145915// These need be generated for performance. Currently they are not,5916// using API calls instead.5917Preamble += "#pragma section(\".objc_selrefs$B\", long, read, write)\n";5918Preamble += "#pragma section(\".objc_classrefs$B\", long, read, write)\n";5919Preamble += "#pragma section(\".objc_superrefs$B\", long, read, write)\n";59205921}5922Preamble += "#ifndef _REWRITER_typedef_Protocol\n";5923Preamble += "typedef struct objc_object Protocol;\n";5924Preamble += "#define _REWRITER_typedef_Protocol\n";5925Preamble += "#endif\n";5926if (LangOpts.MicrosoftExt) {5927Preamble += "#define __OBJC_RW_DLLIMPORT extern \"C\" __declspec(dllimport)\n";5928Preamble += "#define __OBJC_RW_STATICIMPORT extern \"C\"\n";5929}5930else5931Preamble += "#define __OBJC_RW_DLLIMPORT extern\n";59325933Preamble += "__OBJC_RW_DLLIMPORT void objc_msgSend(void);\n";5934Preamble += "__OBJC_RW_DLLIMPORT void objc_msgSendSuper(void);\n";5935Preamble += "__OBJC_RW_DLLIMPORT void objc_msgSend_stret(void);\n";5936Preamble += "__OBJC_RW_DLLIMPORT void objc_msgSendSuper_stret(void);\n";5937Preamble += "__OBJC_RW_DLLIMPORT void objc_msgSend_fpret(void);\n";59385939Preamble += "__OBJC_RW_DLLIMPORT struct objc_class *objc_getClass";5940Preamble += "(const char *);\n";5941Preamble += "__OBJC_RW_DLLIMPORT struct objc_class *class_getSuperclass";5942Preamble += "(struct objc_class *);\n";5943Preamble += "__OBJC_RW_DLLIMPORT struct objc_class *objc_getMetaClass";5944Preamble += "(const char *);\n";5945Preamble += "__OBJC_RW_DLLIMPORT void objc_exception_throw( struct objc_object *);\n";5946// @synchronized hooks.5947Preamble += "__OBJC_RW_DLLIMPORT int objc_sync_enter( struct objc_object *);\n";5948Preamble += "__OBJC_RW_DLLIMPORT int objc_sync_exit( struct objc_object *);\n";5949Preamble += "__OBJC_RW_DLLIMPORT Protocol *objc_getProtocol(const char *);\n";5950Preamble += "#ifdef _WIN64\n";5951Preamble += "typedef unsigned long long _WIN_NSUInteger;\n";5952Preamble += "#else\n";5953Preamble += "typedef unsigned int _WIN_NSUInteger;\n";5954Preamble += "#endif\n";5955Preamble += "#ifndef __FASTENUMERATIONSTATE\n";5956Preamble += "struct __objcFastEnumerationState {\n\t";5957Preamble += "unsigned long state;\n\t";5958Preamble += "void **itemsPtr;\n\t";5959Preamble += "unsigned long *mutationsPtr;\n\t";5960Preamble += "unsigned long extra[5];\n};\n";5961Preamble += "__OBJC_RW_DLLIMPORT void objc_enumerationMutation(struct objc_object *);\n";5962Preamble += "#define __FASTENUMERATIONSTATE\n";5963Preamble += "#endif\n";5964Preamble += "#ifndef __NSCONSTANTSTRINGIMPL\n";5965Preamble += "struct __NSConstantStringImpl {\n";5966Preamble += " int *isa;\n";5967Preamble += " int flags;\n";5968Preamble += " char *str;\n";5969Preamble += "#if _WIN64\n";5970Preamble += " long long length;\n";5971Preamble += "#else\n";5972Preamble += " long length;\n";5973Preamble += "#endif\n";5974Preamble += "};\n";5975Preamble += "#ifdef CF_EXPORT_CONSTANT_STRING\n";5976Preamble += "extern \"C\" __declspec(dllexport) int __CFConstantStringClassReference[];\n";5977Preamble += "#else\n";5978Preamble += "__OBJC_RW_DLLIMPORT int __CFConstantStringClassReference[];\n";5979Preamble += "#endif\n";5980Preamble += "#define __NSCONSTANTSTRINGIMPL\n";5981Preamble += "#endif\n";5982// Blocks preamble.5983Preamble += "#ifndef BLOCK_IMPL\n";5984Preamble += "#define BLOCK_IMPL\n";5985Preamble += "struct __block_impl {\n";5986Preamble += " void *isa;\n";5987Preamble += " int Flags;\n";5988Preamble += " int Reserved;\n";5989Preamble += " void *FuncPtr;\n";5990Preamble += "};\n";5991Preamble += "// Runtime copy/destroy helper functions (from Block_private.h)\n";5992Preamble += "#ifdef __OBJC_EXPORT_BLOCKS\n";5993Preamble += "extern \"C\" __declspec(dllexport) "5994"void _Block_object_assign(void *, const void *, const int);\n";5995Preamble += "extern \"C\" __declspec(dllexport) void _Block_object_dispose(const void *, const int);\n";5996Preamble += "extern \"C\" __declspec(dllexport) void *_NSConcreteGlobalBlock[32];\n";5997Preamble += "extern \"C\" __declspec(dllexport) void *_NSConcreteStackBlock[32];\n";5998Preamble += "#else\n";5999Preamble += "__OBJC_RW_DLLIMPORT void _Block_object_assign(void *, const void *, const int);\n";6000Preamble += "__OBJC_RW_DLLIMPORT void _Block_object_dispose(const void *, const int);\n";6001Preamble += "__OBJC_RW_DLLIMPORT void *_NSConcreteGlobalBlock[32];\n";6002Preamble += "__OBJC_RW_DLLIMPORT void *_NSConcreteStackBlock[32];\n";6003Preamble += "#endif\n";6004Preamble += "#endif\n";6005if (LangOpts.MicrosoftExt) {6006Preamble += "#undef __OBJC_RW_DLLIMPORT\n";6007Preamble += "#undef __OBJC_RW_STATICIMPORT\n";6008Preamble += "#ifndef KEEP_ATTRIBUTES\n"; // We use this for clang tests.6009Preamble += "#define __attribute__(X)\n";6010Preamble += "#endif\n";6011Preamble += "#ifndef __weak\n";6012Preamble += "#define __weak\n";6013Preamble += "#endif\n";6014Preamble += "#ifndef __block\n";6015Preamble += "#define __block\n";6016Preamble += "#endif\n";6017}6018else {6019Preamble += "#define __block\n";6020Preamble += "#define __weak\n";6021}60226023// Declarations required for modern objective-c array and dictionary literals.6024Preamble += "\n#include <stdarg.h>\n";6025Preamble += "struct __NSContainer_literal {\n";6026Preamble += " void * *arr;\n";6027Preamble += " __NSContainer_literal (unsigned int count, ...) {\n";6028Preamble += "\tva_list marker;\n";6029Preamble += "\tva_start(marker, count);\n";6030Preamble += "\tarr = new void *[count];\n";6031Preamble += "\tfor (unsigned i = 0; i < count; i++)\n";6032Preamble += "\t arr[i] = va_arg(marker, void *);\n";6033Preamble += "\tva_end( marker );\n";6034Preamble += " };\n";6035Preamble += " ~__NSContainer_literal() {\n";6036Preamble += "\tdelete[] arr;\n";6037Preamble += " }\n";6038Preamble += "};\n";60396040// Declaration required for implementation of @autoreleasepool statement.6041Preamble += "extern \"C\" __declspec(dllimport) void * objc_autoreleasePoolPush(void);\n";6042Preamble += "extern \"C\" __declspec(dllimport) void objc_autoreleasePoolPop(void *);\n\n";6043Preamble += "struct __AtAutoreleasePool {\n";6044Preamble += " __AtAutoreleasePool() {atautoreleasepoolobj = objc_autoreleasePoolPush();}\n";6045Preamble += " ~__AtAutoreleasePool() {objc_autoreleasePoolPop(atautoreleasepoolobj);}\n";6046Preamble += " void * atautoreleasepoolobj;\n";6047Preamble += "};\n";60486049// NOTE! Windows uses LLP64 for 64bit mode. So, cast pointer to long long6050// as this avoids warning in any 64bit/32bit compilation model.6051Preamble += "\n#define __OFFSETOFIVAR__(TYPE, MEMBER) ((long long) &((TYPE *)0)->MEMBER)\n";6052}60536054/// RewriteIvarOffsetComputation - This routine synthesizes computation of6055/// ivar offset.6056void RewriteModernObjC::RewriteIvarOffsetComputation(ObjCIvarDecl *ivar,6057std::string &Result) {6058Result += "__OFFSETOFIVAR__(struct ";6059Result += ivar->getContainingInterface()->getNameAsString();6060if (LangOpts.MicrosoftExt)6061Result += "_IMPL";6062Result += ", ";6063if (ivar->isBitField())6064ObjCIvarBitfieldGroupDecl(ivar, Result);6065else6066Result += ivar->getNameAsString();6067Result += ")";6068}60696070/// WriteModernMetadataDeclarations - Writes out metadata declarations for modern ABI.6071/// struct _prop_t {6072/// const char *name;6073/// char *attributes;6074/// }60756076/// struct _prop_list_t {6077/// uint32_t entsize; // sizeof(struct _prop_t)6078/// uint32_t count_of_properties;6079/// struct _prop_t prop_list[count_of_properties];6080/// }60816082/// struct _protocol_t;60836084/// struct _protocol_list_t {6085/// long protocol_count; // Note, this is 32/64 bit6086/// struct _protocol_t * protocol_list[protocol_count];6087/// }60886089/// struct _objc_method {6090/// SEL _cmd;6091/// const char *method_type;6092/// char *_imp;6093/// }60946095/// struct _method_list_t {6096/// uint32_t entsize; // sizeof(struct _objc_method)6097/// uint32_t method_count;6098/// struct _objc_method method_list[method_count];6099/// }61006101/// struct _protocol_t {6102/// id isa; // NULL6103/// const char *protocol_name;6104/// const struct _protocol_list_t * protocol_list; // super protocols6105/// const struct method_list_t *instance_methods;6106/// const struct method_list_t *class_methods;6107/// const struct method_list_t *optionalInstanceMethods;6108/// const struct method_list_t *optionalClassMethods;6109/// const struct _prop_list_t * properties;6110/// const uint32_t size; // sizeof(struct _protocol_t)6111/// const uint32_t flags; // = 06112/// const char ** extendedMethodTypes;6113/// }61146115/// struct _ivar_t {6116/// unsigned long int *offset; // pointer to ivar offset location6117/// const char *name;6118/// const char *type;6119/// uint32_t alignment;6120/// uint32_t size;6121/// }61226123/// struct _ivar_list_t {6124/// uint32 entsize; // sizeof(struct _ivar_t)6125/// uint32 count;6126/// struct _ivar_t list[count];6127/// }61286129/// struct _class_ro_t {6130/// uint32_t flags;6131/// uint32_t instanceStart;6132/// uint32_t instanceSize;6133/// uint32_t reserved; // only when building for 64bit targets6134/// const uint8_t *ivarLayout;6135/// const char *name;6136/// const struct _method_list_t *baseMethods;6137/// const struct _protocol_list_t *baseProtocols;6138/// const struct _ivar_list_t *ivars;6139/// const uint8_t *weakIvarLayout;6140/// const struct _prop_list_t *properties;6141/// }61426143/// struct _class_t {6144/// struct _class_t *isa;6145/// struct _class_t *superclass;6146/// void *cache;6147/// IMP *vtable;6148/// struct _class_ro_t *ro;6149/// }61506151/// struct _category_t {6152/// const char *name;6153/// struct _class_t *cls;6154/// const struct _method_list_t *instance_methods;6155/// const struct _method_list_t *class_methods;6156/// const struct _protocol_list_t *protocols;6157/// const struct _prop_list_t *properties;6158/// }61596160/// MessageRefTy - LLVM for:6161/// struct _message_ref_t {6162/// IMP messenger;6163/// SEL name;6164/// };61656166/// SuperMessageRefTy - LLVM for:6167/// struct _super_message_ref_t {6168/// SUPER_IMP messenger;6169/// SEL name;6170/// };61716172static void WriteModernMetadataDeclarations(ASTContext *Context, std::string &Result) {6173static bool meta_data_declared = false;6174if (meta_data_declared)6175return;61766177Result += "\nstruct _prop_t {\n";6178Result += "\tconst char *name;\n";6179Result += "\tconst char *attributes;\n";6180Result += "};\n";61816182Result += "\nstruct _protocol_t;\n";61836184Result += "\nstruct _objc_method {\n";6185Result += "\tstruct objc_selector * _cmd;\n";6186Result += "\tconst char *method_type;\n";6187Result += "\tvoid *_imp;\n";6188Result += "};\n";61896190Result += "\nstruct _protocol_t {\n";6191Result += "\tvoid * isa; // NULL\n";6192Result += "\tconst char *protocol_name;\n";6193Result += "\tconst struct _protocol_list_t * protocol_list; // super protocols\n";6194Result += "\tconst struct method_list_t *instance_methods;\n";6195Result += "\tconst struct method_list_t *class_methods;\n";6196Result += "\tconst struct method_list_t *optionalInstanceMethods;\n";6197Result += "\tconst struct method_list_t *optionalClassMethods;\n";6198Result += "\tconst struct _prop_list_t * properties;\n";6199Result += "\tconst unsigned int size; // sizeof(struct _protocol_t)\n";6200Result += "\tconst unsigned int flags; // = 0\n";6201Result += "\tconst char ** extendedMethodTypes;\n";6202Result += "};\n";62036204Result += "\nstruct _ivar_t {\n";6205Result += "\tunsigned long int *offset; // pointer to ivar offset location\n";6206Result += "\tconst char *name;\n";6207Result += "\tconst char *type;\n";6208Result += "\tunsigned int alignment;\n";6209Result += "\tunsigned int size;\n";6210Result += "};\n";62116212Result += "\nstruct _class_ro_t {\n";6213Result += "\tunsigned int flags;\n";6214Result += "\tunsigned int instanceStart;\n";6215Result += "\tunsigned int instanceSize;\n";6216const llvm::Triple &Triple(Context->getTargetInfo().getTriple());6217if (Triple.getArch() == llvm::Triple::x86_64)6218Result += "\tunsigned int reserved;\n";6219Result += "\tconst unsigned char *ivarLayout;\n";6220Result += "\tconst char *name;\n";6221Result += "\tconst struct _method_list_t *baseMethods;\n";6222Result += "\tconst struct _objc_protocol_list *baseProtocols;\n";6223Result += "\tconst struct _ivar_list_t *ivars;\n";6224Result += "\tconst unsigned char *weakIvarLayout;\n";6225Result += "\tconst struct _prop_list_t *properties;\n";6226Result += "};\n";62276228Result += "\nstruct _class_t {\n";6229Result += "\tstruct _class_t *isa;\n";6230Result += "\tstruct _class_t *superclass;\n";6231Result += "\tvoid *cache;\n";6232Result += "\tvoid *vtable;\n";6233Result += "\tstruct _class_ro_t *ro;\n";6234Result += "};\n";62356236Result += "\nstruct _category_t {\n";6237Result += "\tconst char *name;\n";6238Result += "\tstruct _class_t *cls;\n";6239Result += "\tconst struct _method_list_t *instance_methods;\n";6240Result += "\tconst struct _method_list_t *class_methods;\n";6241Result += "\tconst struct _protocol_list_t *protocols;\n";6242Result += "\tconst struct _prop_list_t *properties;\n";6243Result += "};\n";62446245Result += "extern \"C\" __declspec(dllimport) struct objc_cache _objc_empty_cache;\n";6246Result += "#pragma warning(disable:4273)\n";6247meta_data_declared = true;6248}62496250static void Write_protocol_list_t_TypeDecl(std::string &Result,6251long super_protocol_count) {6252Result += "struct /*_protocol_list_t*/"; Result += " {\n";6253Result += "\tlong protocol_count; // Note, this is 32/64 bit\n";6254Result += "\tstruct _protocol_t *super_protocols[";6255Result += utostr(super_protocol_count); Result += "];\n";6256Result += "}";6257}62586259static void Write_method_list_t_TypeDecl(std::string &Result,6260unsigned int method_count) {6261Result += "struct /*_method_list_t*/"; Result += " {\n";6262Result += "\tunsigned int entsize; // sizeof(struct _objc_method)\n";6263Result += "\tunsigned int method_count;\n";6264Result += "\tstruct _objc_method method_list[";6265Result += utostr(method_count); Result += "];\n";6266Result += "}";6267}62686269static void Write__prop_list_t_TypeDecl(std::string &Result,6270unsigned int property_count) {6271Result += "struct /*_prop_list_t*/"; Result += " {\n";6272Result += "\tunsigned int entsize; // sizeof(struct _prop_t)\n";6273Result += "\tunsigned int count_of_properties;\n";6274Result += "\tstruct _prop_t prop_list[";6275Result += utostr(property_count); Result += "];\n";6276Result += "}";6277}62786279static void Write__ivar_list_t_TypeDecl(std::string &Result,6280unsigned int ivar_count) {6281Result += "struct /*_ivar_list_t*/"; Result += " {\n";6282Result += "\tunsigned int entsize; // sizeof(struct _prop_t)\n";6283Result += "\tunsigned int count;\n";6284Result += "\tstruct _ivar_t ivar_list[";6285Result += utostr(ivar_count); Result += "];\n";6286Result += "}";6287}62886289static void Write_protocol_list_initializer(ASTContext *Context, std::string &Result,6290ArrayRef<ObjCProtocolDecl *> SuperProtocols,6291StringRef VarName,6292StringRef ProtocolName) {6293if (SuperProtocols.size() > 0) {6294Result += "\nstatic ";6295Write_protocol_list_t_TypeDecl(Result, SuperProtocols.size());6296Result += " "; Result += VarName;6297Result += ProtocolName;6298Result += " __attribute__ ((used, section (\"__DATA,__objc_const\"))) = {\n";6299Result += "\t"; Result += utostr(SuperProtocols.size()); Result += ",\n";6300for (unsigned i = 0, e = SuperProtocols.size(); i < e; i++) {6301ObjCProtocolDecl *SuperPD = SuperProtocols[i];6302Result += "\t&"; Result += "_OBJC_PROTOCOL_";6303Result += SuperPD->getNameAsString();6304if (i == e-1)6305Result += "\n};\n";6306else6307Result += ",\n";6308}6309}6310}63116312static void Write_method_list_t_initializer(RewriteModernObjC &RewriteObj,6313ASTContext *Context, std::string &Result,6314ArrayRef<ObjCMethodDecl *> Methods,6315StringRef VarName,6316StringRef TopLevelDeclName,6317bool MethodImpl) {6318if (Methods.size() > 0) {6319Result += "\nstatic ";6320Write_method_list_t_TypeDecl(Result, Methods.size());6321Result += " "; Result += VarName;6322Result += TopLevelDeclName;6323Result += " __attribute__ ((used, section (\"__DATA,__objc_const\"))) = {\n";6324Result += "\t"; Result += "sizeof(_objc_method)"; Result += ",\n";6325Result += "\t"; Result += utostr(Methods.size()); Result += ",\n";6326for (unsigned i = 0, e = Methods.size(); i < e; i++) {6327ObjCMethodDecl *MD = Methods[i];6328if (i == 0)6329Result += "\t{{(struct objc_selector *)\"";6330else6331Result += "\t{(struct objc_selector *)\"";6332Result += (MD)->getSelector().getAsString(); Result += "\"";6333Result += ", ";6334std::string MethodTypeString = Context->getObjCEncodingForMethodDecl(MD);6335Result += "\""; Result += MethodTypeString; Result += "\"";6336Result += ", ";6337if (!MethodImpl)6338Result += "0";6339else {6340Result += "(void *)";6341Result += RewriteObj.MethodInternalNames[MD];6342}6343if (i == e-1)6344Result += "}}\n";6345else6346Result += "},\n";6347}6348Result += "};\n";6349}6350}63516352static void Write_prop_list_t_initializer(RewriteModernObjC &RewriteObj,6353ASTContext *Context, std::string &Result,6354ArrayRef<ObjCPropertyDecl *> Properties,6355const Decl *Container,6356StringRef VarName,6357StringRef ProtocolName) {6358if (Properties.size() > 0) {6359Result += "\nstatic ";6360Write__prop_list_t_TypeDecl(Result, Properties.size());6361Result += " "; Result += VarName;6362Result += ProtocolName;6363Result += " __attribute__ ((used, section (\"__DATA,__objc_const\"))) = {\n";6364Result += "\t"; Result += "sizeof(_prop_t)"; Result += ",\n";6365Result += "\t"; Result += utostr(Properties.size()); Result += ",\n";6366for (unsigned i = 0, e = Properties.size(); i < e; i++) {6367ObjCPropertyDecl *PropDecl = Properties[i];6368if (i == 0)6369Result += "\t{{\"";6370else6371Result += "\t{\"";6372Result += PropDecl->getName(); Result += "\",";6373std::string PropertyTypeString =6374Context->getObjCEncodingForPropertyDecl(PropDecl, Container);6375std::string QuotePropertyTypeString;6376RewriteObj.QuoteDoublequotes(PropertyTypeString, QuotePropertyTypeString);6377Result += "\""; Result += QuotePropertyTypeString; Result += "\"";6378if (i == e-1)6379Result += "}}\n";6380else6381Result += "},\n";6382}6383Result += "};\n";6384}6385}63866387// Metadata flags6388enum MetaDataDlags {6389CLS = 0x0,6390CLS_META = 0x1,6391CLS_ROOT = 0x2,6392OBJC2_CLS_HIDDEN = 0x10,6393CLS_EXCEPTION = 0x20,63946395/// (Obsolete) ARC-specific: this class has a .release_ivars method6396CLS_HAS_IVAR_RELEASER = 0x40,6397/// class was compiled with -fobjc-arr6398CLS_COMPILED_BY_ARC = 0x80 // (1<<7)6399};64006401static void Write__class_ro_t_initializer(ASTContext *Context, std::string &Result,6402unsigned int flags,6403const std::string &InstanceStart,6404const std::string &InstanceSize,6405ArrayRef<ObjCMethodDecl *>baseMethods,6406ArrayRef<ObjCProtocolDecl *>baseProtocols,6407ArrayRef<ObjCIvarDecl *>ivars,6408ArrayRef<ObjCPropertyDecl *>Properties,6409StringRef VarName,6410StringRef ClassName) {6411Result += "\nstatic struct _class_ro_t ";6412Result += VarName; Result += ClassName;6413Result += " __attribute__ ((used, section (\"__DATA,__objc_const\"))) = {\n";6414Result += "\t";6415Result += llvm::utostr(flags); Result += ", ";6416Result += InstanceStart; Result += ", ";6417Result += InstanceSize; Result += ", \n";6418Result += "\t";6419const llvm::Triple &Triple(Context->getTargetInfo().getTriple());6420if (Triple.getArch() == llvm::Triple::x86_64)6421// uint32_t const reserved; // only when building for 64bit targets6422Result += "(unsigned int)0, \n\t";6423// const uint8_t * const ivarLayout;6424Result += "0, \n\t";6425Result += "\""; Result += ClassName; Result += "\",\n\t";6426bool metaclass = ((flags & CLS_META) != 0);6427if (baseMethods.size() > 0) {6428Result += "(const struct _method_list_t *)&";6429if (metaclass)6430Result += "_OBJC_$_CLASS_METHODS_";6431else6432Result += "_OBJC_$_INSTANCE_METHODS_";6433Result += ClassName;6434Result += ",\n\t";6435}6436else6437Result += "0, \n\t";64386439if (!metaclass && baseProtocols.size() > 0) {6440Result += "(const struct _objc_protocol_list *)&";6441Result += "_OBJC_CLASS_PROTOCOLS_$_"; Result += ClassName;6442Result += ",\n\t";6443}6444else6445Result += "0, \n\t";64466447if (!metaclass && ivars.size() > 0) {6448Result += "(const struct _ivar_list_t *)&";6449Result += "_OBJC_$_INSTANCE_VARIABLES_"; Result += ClassName;6450Result += ",\n\t";6451}6452else6453Result += "0, \n\t";64546455// weakIvarLayout6456Result += "0, \n\t";6457if (!metaclass && Properties.size() > 0) {6458Result += "(const struct _prop_list_t *)&";6459Result += "_OBJC_$_PROP_LIST_"; Result += ClassName;6460Result += ",\n";6461}6462else6463Result += "0, \n";64646465Result += "};\n";6466}64676468static void Write_class_t(ASTContext *Context, std::string &Result,6469StringRef VarName,6470const ObjCInterfaceDecl *CDecl, bool metaclass) {6471bool rootClass = (!CDecl->getSuperClass());6472const ObjCInterfaceDecl *RootClass = CDecl;64736474if (!rootClass) {6475// Find the Root class6476RootClass = CDecl->getSuperClass();6477while (RootClass->getSuperClass()) {6478RootClass = RootClass->getSuperClass();6479}6480}64816482if (metaclass && rootClass) {6483// Need to handle a case of use of forward declaration.6484Result += "\n";6485Result += "extern \"C\" ";6486if (CDecl->getImplementation())6487Result += "__declspec(dllexport) ";6488else6489Result += "__declspec(dllimport) ";64906491Result += "struct _class_t OBJC_CLASS_$_";6492Result += CDecl->getNameAsString();6493Result += ";\n";6494}6495// Also, for possibility of 'super' metadata class not having been defined yet.6496if (!rootClass) {6497ObjCInterfaceDecl *SuperClass = CDecl->getSuperClass();6498Result += "\n";6499Result += "extern \"C\" ";6500if (SuperClass->getImplementation())6501Result += "__declspec(dllexport) ";6502else6503Result += "__declspec(dllimport) ";65046505Result += "struct _class_t ";6506Result += VarName;6507Result += SuperClass->getNameAsString();6508Result += ";\n";65096510if (metaclass && RootClass != SuperClass) {6511Result += "extern \"C\" ";6512if (RootClass->getImplementation())6513Result += "__declspec(dllexport) ";6514else6515Result += "__declspec(dllimport) ";65166517Result += "struct _class_t ";6518Result += VarName;6519Result += RootClass->getNameAsString();6520Result += ";\n";6521}6522}65236524Result += "\nextern \"C\" __declspec(dllexport) struct _class_t ";6525Result += VarName; Result += CDecl->getNameAsString();6526Result += " __attribute__ ((used, section (\"__DATA,__objc_data\"))) = {\n";6527Result += "\t";6528if (metaclass) {6529if (!rootClass) {6530Result += "0, // &"; Result += VarName;6531Result += RootClass->getNameAsString();6532Result += ",\n\t";6533Result += "0, // &"; Result += VarName;6534Result += CDecl->getSuperClass()->getNameAsString();6535Result += ",\n\t";6536}6537else {6538Result += "0, // &"; Result += VarName;6539Result += CDecl->getNameAsString();6540Result += ",\n\t";6541Result += "0, // &OBJC_CLASS_$_"; Result += CDecl->getNameAsString();6542Result += ",\n\t";6543}6544}6545else {6546Result += "0, // &OBJC_METACLASS_$_";6547Result += CDecl->getNameAsString();6548Result += ",\n\t";6549if (!rootClass) {6550Result += "0, // &"; Result += VarName;6551Result += CDecl->getSuperClass()->getNameAsString();6552Result += ",\n\t";6553}6554else6555Result += "0,\n\t";6556}6557Result += "0, // (void *)&_objc_empty_cache,\n\t";6558Result += "0, // unused, was (void *)&_objc_empty_vtable,\n\t";6559if (metaclass)6560Result += "&_OBJC_METACLASS_RO_$_";6561else6562Result += "&_OBJC_CLASS_RO_$_";6563Result += CDecl->getNameAsString();6564Result += ",\n};\n";65656566// Add static function to initialize some of the meta-data fields.6567// avoid doing it twice.6568if (metaclass)6569return;65706571const ObjCInterfaceDecl *SuperClass =6572rootClass ? CDecl : CDecl->getSuperClass();65736574Result += "static void OBJC_CLASS_SETUP_$_";6575Result += CDecl->getNameAsString();6576Result += "(void ) {\n";6577Result += "\tOBJC_METACLASS_$_"; Result += CDecl->getNameAsString();6578Result += ".isa = "; Result += "&OBJC_METACLASS_$_";6579Result += RootClass->getNameAsString(); Result += ";\n";65806581Result += "\tOBJC_METACLASS_$_"; Result += CDecl->getNameAsString();6582Result += ".superclass = ";6583if (rootClass)6584Result += "&OBJC_CLASS_$_";6585else6586Result += "&OBJC_METACLASS_$_";65876588Result += SuperClass->getNameAsString(); Result += ";\n";65896590Result += "\tOBJC_METACLASS_$_"; Result += CDecl->getNameAsString();6591Result += ".cache = "; Result += "&_objc_empty_cache"; Result += ";\n";65926593Result += "\tOBJC_CLASS_$_"; Result += CDecl->getNameAsString();6594Result += ".isa = "; Result += "&OBJC_METACLASS_$_";6595Result += CDecl->getNameAsString(); Result += ";\n";65966597if (!rootClass) {6598Result += "\tOBJC_CLASS_$_"; Result += CDecl->getNameAsString();6599Result += ".superclass = "; Result += "&OBJC_CLASS_$_";6600Result += SuperClass->getNameAsString(); Result += ";\n";6601}66026603Result += "\tOBJC_CLASS_$_"; Result += CDecl->getNameAsString();6604Result += ".cache = "; Result += "&_objc_empty_cache"; Result += ";\n";6605Result += "}\n";6606}66076608static void Write_category_t(RewriteModernObjC &RewriteObj, ASTContext *Context,6609std::string &Result,6610ObjCCategoryDecl *CatDecl,6611ObjCInterfaceDecl *ClassDecl,6612ArrayRef<ObjCMethodDecl *> InstanceMethods,6613ArrayRef<ObjCMethodDecl *> ClassMethods,6614ArrayRef<ObjCProtocolDecl *> RefedProtocols,6615ArrayRef<ObjCPropertyDecl *> ClassProperties) {6616StringRef CatName = CatDecl->getName();6617StringRef ClassName = ClassDecl->getName();6618// must declare an extern class object in case this class is not implemented6619// in this TU.6620Result += "\n";6621Result += "extern \"C\" ";6622if (ClassDecl->getImplementation())6623Result += "__declspec(dllexport) ";6624else6625Result += "__declspec(dllimport) ";66266627Result += "struct _class_t ";6628Result += "OBJC_CLASS_$_"; Result += ClassName;6629Result += ";\n";66306631Result += "\nstatic struct _category_t ";6632Result += "_OBJC_$_CATEGORY_";6633Result += ClassName; Result += "_$_"; Result += CatName;6634Result += " __attribute__ ((used, section (\"__DATA,__objc_const\"))) = \n";6635Result += "{\n";6636Result += "\t\""; Result += ClassName; Result += "\",\n";6637Result += "\t0, // &"; Result += "OBJC_CLASS_$_"; Result += ClassName;6638Result += ",\n";6639if (InstanceMethods.size() > 0) {6640Result += "\t(const struct _method_list_t *)&";6641Result += "_OBJC_$_CATEGORY_INSTANCE_METHODS_";6642Result += ClassName; Result += "_$_"; Result += CatName;6643Result += ",\n";6644}6645else6646Result += "\t0,\n";66476648if (ClassMethods.size() > 0) {6649Result += "\t(const struct _method_list_t *)&";6650Result += "_OBJC_$_CATEGORY_CLASS_METHODS_";6651Result += ClassName; Result += "_$_"; Result += CatName;6652Result += ",\n";6653}6654else6655Result += "\t0,\n";66566657if (RefedProtocols.size() > 0) {6658Result += "\t(const struct _protocol_list_t *)&";6659Result += "_OBJC_CATEGORY_PROTOCOLS_$_";6660Result += ClassName; Result += "_$_"; Result += CatName;6661Result += ",\n";6662}6663else6664Result += "\t0,\n";66656666if (ClassProperties.size() > 0) {6667Result += "\t(const struct _prop_list_t *)&"; Result += "_OBJC_$_PROP_LIST_";6668Result += ClassName; Result += "_$_"; Result += CatName;6669Result += ",\n";6670}6671else6672Result += "\t0,\n";66736674Result += "};\n";66756676// Add static function to initialize the class pointer in the category structure.6677Result += "static void OBJC_CATEGORY_SETUP_$_";6678Result += ClassDecl->getNameAsString();6679Result += "_$_";6680Result += CatName;6681Result += "(void ) {\n";6682Result += "\t_OBJC_$_CATEGORY_";6683Result += ClassDecl->getNameAsString();6684Result += "_$_";6685Result += CatName;6686Result += ".cls = "; Result += "&OBJC_CLASS_$_"; Result += ClassName;6687Result += ";\n}\n";6688}66896690static void Write__extendedMethodTypes_initializer(RewriteModernObjC &RewriteObj,6691ASTContext *Context, std::string &Result,6692ArrayRef<ObjCMethodDecl *> Methods,6693StringRef VarName,6694StringRef ProtocolName) {6695if (Methods.size() == 0)6696return;66976698Result += "\nstatic const char *";6699Result += VarName; Result += ProtocolName;6700Result += " [] __attribute__ ((used, section (\"__DATA,__objc_const\"))) = \n";6701Result += "{\n";6702for (unsigned i = 0, e = Methods.size(); i < e; i++) {6703ObjCMethodDecl *MD = Methods[i];6704std::string MethodTypeString =6705Context->getObjCEncodingForMethodDecl(MD, true);6706std::string QuoteMethodTypeString;6707RewriteObj.QuoteDoublequotes(MethodTypeString, QuoteMethodTypeString);6708Result += "\t\""; Result += QuoteMethodTypeString; Result += "\"";6709if (i == e-1)6710Result += "\n};\n";6711else {6712Result += ",\n";6713}6714}6715}67166717static void Write_IvarOffsetVar(RewriteModernObjC &RewriteObj,6718ASTContext *Context,6719std::string &Result,6720ArrayRef<ObjCIvarDecl *> Ivars,6721ObjCInterfaceDecl *CDecl) {6722// FIXME. visibility of offset symbols may have to be set; for Darwin6723// this is what happens:6724/**6725if (Ivar->getAccessControl() == ObjCIvarDecl::Private ||6726Ivar->getAccessControl() == ObjCIvarDecl::Package ||6727Class->getVisibility() == HiddenVisibility)6728Visibility should be: HiddenVisibility;6729else6730Visibility should be: DefaultVisibility;6731*/67326733Result += "\n";6734for (unsigned i =0, e = Ivars.size(); i < e; i++) {6735ObjCIvarDecl *IvarDecl = Ivars[i];6736if (Context->getLangOpts().MicrosoftExt)6737Result += "__declspec(allocate(\".objc_ivar$B\")) ";67386739if (!Context->getLangOpts().MicrosoftExt ||6740IvarDecl->getAccessControl() == ObjCIvarDecl::Private ||6741IvarDecl->getAccessControl() == ObjCIvarDecl::Package)6742Result += "extern \"C\" unsigned long int ";6743else6744Result += "extern \"C\" __declspec(dllexport) unsigned long int ";6745if (Ivars[i]->isBitField())6746RewriteObj.ObjCIvarBitfieldGroupOffset(IvarDecl, Result);6747else6748WriteInternalIvarName(CDecl, IvarDecl, Result);6749Result += " __attribute__ ((used, section (\"__DATA,__objc_ivar\")))";6750Result += " = ";6751RewriteObj.RewriteIvarOffsetComputation(IvarDecl, Result);6752Result += ";\n";6753if (Ivars[i]->isBitField()) {6754// skip over rest of the ivar bitfields.6755SKIP_BITFIELDS(i , e, Ivars);6756}6757}6758}67596760static void Write__ivar_list_t_initializer(RewriteModernObjC &RewriteObj,6761ASTContext *Context, std::string &Result,6762ArrayRef<ObjCIvarDecl *> OriginalIvars,6763StringRef VarName,6764ObjCInterfaceDecl *CDecl) {6765if (OriginalIvars.size() > 0) {6766Write_IvarOffsetVar(RewriteObj, Context, Result, OriginalIvars, CDecl);6767SmallVector<ObjCIvarDecl *, 8> Ivars;6768// strip off all but the first ivar bitfield from each group of ivars.6769// Such ivars in the ivar list table will be replaced by their grouping struct6770// 'ivar'.6771for (unsigned i = 0, e = OriginalIvars.size(); i < e; i++) {6772if (OriginalIvars[i]->isBitField()) {6773Ivars.push_back(OriginalIvars[i]);6774// skip over rest of the ivar bitfields.6775SKIP_BITFIELDS(i , e, OriginalIvars);6776}6777else6778Ivars.push_back(OriginalIvars[i]);6779}67806781Result += "\nstatic ";6782Write__ivar_list_t_TypeDecl(Result, Ivars.size());6783Result += " "; Result += VarName;6784Result += CDecl->getNameAsString();6785Result += " __attribute__ ((used, section (\"__DATA,__objc_const\"))) = {\n";6786Result += "\t"; Result += "sizeof(_ivar_t)"; Result += ",\n";6787Result += "\t"; Result += utostr(Ivars.size()); Result += ",\n";6788for (unsigned i =0, e = Ivars.size(); i < e; i++) {6789ObjCIvarDecl *IvarDecl = Ivars[i];6790if (i == 0)6791Result += "\t{{";6792else6793Result += "\t {";6794Result += "(unsigned long int *)&";6795if (Ivars[i]->isBitField())6796RewriteObj.ObjCIvarBitfieldGroupOffset(IvarDecl, Result);6797else6798WriteInternalIvarName(CDecl, IvarDecl, Result);6799Result += ", ";68006801Result += "\"";6802if (Ivars[i]->isBitField())6803RewriteObj.ObjCIvarBitfieldGroupDecl(Ivars[i], Result);6804else6805Result += IvarDecl->getName();6806Result += "\", ";68076808QualType IVQT = IvarDecl->getType();6809if (IvarDecl->isBitField())6810IVQT = RewriteObj.GetGroupRecordTypeForObjCIvarBitfield(IvarDecl);68116812std::string IvarTypeString, QuoteIvarTypeString;6813Context->getObjCEncodingForType(IVQT, IvarTypeString,6814IvarDecl);6815RewriteObj.QuoteDoublequotes(IvarTypeString, QuoteIvarTypeString);6816Result += "\""; Result += QuoteIvarTypeString; Result += "\", ";68176818// FIXME. this alignment represents the host alignment and need be changed to6819// represent the target alignment.6820unsigned Align = Context->getTypeAlign(IVQT)/8;6821Align = llvm::Log2_32(Align);6822Result += llvm::utostr(Align); Result += ", ";6823CharUnits Size = Context->getTypeSizeInChars(IVQT);6824Result += llvm::utostr(Size.getQuantity());6825if (i == e-1)6826Result += "}}\n";6827else6828Result += "},\n";6829}6830Result += "};\n";6831}6832}68336834/// RewriteObjCProtocolMetaData - Rewrite protocols meta-data.6835void RewriteModernObjC::RewriteObjCProtocolMetaData(ObjCProtocolDecl *PDecl,6836std::string &Result) {68376838// Do not synthesize the protocol more than once.6839if (ObjCSynthesizedProtocols.count(PDecl->getCanonicalDecl()))6840return;6841WriteModernMetadataDeclarations(Context, Result);68426843if (ObjCProtocolDecl *Def = PDecl->getDefinition())6844PDecl = Def;6845// Must write out all protocol definitions in current qualifier list,6846// and in their nested qualifiers before writing out current definition.6847for (auto *I : PDecl->protocols())6848RewriteObjCProtocolMetaData(I, Result);68496850// Construct method lists.6851std::vector<ObjCMethodDecl *> InstanceMethods, ClassMethods;6852std::vector<ObjCMethodDecl *> OptInstanceMethods, OptClassMethods;6853for (auto *MD : PDecl->instance_methods()) {6854if (MD->getImplementationControl() == ObjCImplementationControl::Optional) {6855OptInstanceMethods.push_back(MD);6856} else {6857InstanceMethods.push_back(MD);6858}6859}68606861for (auto *MD : PDecl->class_methods()) {6862if (MD->getImplementationControl() == ObjCImplementationControl::Optional) {6863OptClassMethods.push_back(MD);6864} else {6865ClassMethods.push_back(MD);6866}6867}6868std::vector<ObjCMethodDecl *> AllMethods;6869for (unsigned i = 0, e = InstanceMethods.size(); i < e; i++)6870AllMethods.push_back(InstanceMethods[i]);6871for (unsigned i = 0, e = ClassMethods.size(); i < e; i++)6872AllMethods.push_back(ClassMethods[i]);6873for (unsigned i = 0, e = OptInstanceMethods.size(); i < e; i++)6874AllMethods.push_back(OptInstanceMethods[i]);6875for (unsigned i = 0, e = OptClassMethods.size(); i < e; i++)6876AllMethods.push_back(OptClassMethods[i]);68776878Write__extendedMethodTypes_initializer(*this, Context, Result,6879AllMethods,6880"_OBJC_PROTOCOL_METHOD_TYPES_",6881PDecl->getNameAsString());6882// Protocol's super protocol list6883SmallVector<ObjCProtocolDecl *, 8> SuperProtocols(PDecl->protocols());6884Write_protocol_list_initializer(Context, Result, SuperProtocols,6885"_OBJC_PROTOCOL_REFS_",6886PDecl->getNameAsString());68876888Write_method_list_t_initializer(*this, Context, Result, InstanceMethods,6889"_OBJC_PROTOCOL_INSTANCE_METHODS_",6890PDecl->getNameAsString(), false);68916892Write_method_list_t_initializer(*this, Context, Result, ClassMethods,6893"_OBJC_PROTOCOL_CLASS_METHODS_",6894PDecl->getNameAsString(), false);68956896Write_method_list_t_initializer(*this, Context, Result, OptInstanceMethods,6897"_OBJC_PROTOCOL_OPT_INSTANCE_METHODS_",6898PDecl->getNameAsString(), false);68996900Write_method_list_t_initializer(*this, Context, Result, OptClassMethods,6901"_OBJC_PROTOCOL_OPT_CLASS_METHODS_",6902PDecl->getNameAsString(), false);69036904// Protocol's property metadata.6905SmallVector<ObjCPropertyDecl *, 8> ProtocolProperties(6906PDecl->instance_properties());6907Write_prop_list_t_initializer(*this, Context, Result, ProtocolProperties,6908/* Container */nullptr,6909"_OBJC_PROTOCOL_PROPERTIES_",6910PDecl->getNameAsString());69116912// Writer out root metadata for current protocol: struct _protocol_t6913Result += "\n";6914if (LangOpts.MicrosoftExt)6915Result += "static ";6916Result += "struct _protocol_t _OBJC_PROTOCOL_";6917Result += PDecl->getNameAsString();6918Result += " __attribute__ ((used)) = {\n";6919Result += "\t0,\n"; // id is; is null6920Result += "\t\""; Result += PDecl->getNameAsString(); Result += "\",\n";6921if (SuperProtocols.size() > 0) {6922Result += "\t(const struct _protocol_list_t *)&"; Result += "_OBJC_PROTOCOL_REFS_";6923Result += PDecl->getNameAsString(); Result += ",\n";6924}6925else6926Result += "\t0,\n";6927if (InstanceMethods.size() > 0) {6928Result += "\t(const struct method_list_t *)&_OBJC_PROTOCOL_INSTANCE_METHODS_";6929Result += PDecl->getNameAsString(); Result += ",\n";6930}6931else6932Result += "\t0,\n";69336934if (ClassMethods.size() > 0) {6935Result += "\t(const struct method_list_t *)&_OBJC_PROTOCOL_CLASS_METHODS_";6936Result += PDecl->getNameAsString(); Result += ",\n";6937}6938else6939Result += "\t0,\n";69406941if (OptInstanceMethods.size() > 0) {6942Result += "\t(const struct method_list_t *)&_OBJC_PROTOCOL_OPT_INSTANCE_METHODS_";6943Result += PDecl->getNameAsString(); Result += ",\n";6944}6945else6946Result += "\t0,\n";69476948if (OptClassMethods.size() > 0) {6949Result += "\t(const struct method_list_t *)&_OBJC_PROTOCOL_OPT_CLASS_METHODS_";6950Result += PDecl->getNameAsString(); Result += ",\n";6951}6952else6953Result += "\t0,\n";69546955if (ProtocolProperties.size() > 0) {6956Result += "\t(const struct _prop_list_t *)&_OBJC_PROTOCOL_PROPERTIES_";6957Result += PDecl->getNameAsString(); Result += ",\n";6958}6959else6960Result += "\t0,\n";69616962Result += "\t"; Result += "sizeof(_protocol_t)"; Result += ",\n";6963Result += "\t0,\n";69646965if (AllMethods.size() > 0) {6966Result += "\t(const char **)&"; Result += "_OBJC_PROTOCOL_METHOD_TYPES_";6967Result += PDecl->getNameAsString();6968Result += "\n};\n";6969}6970else6971Result += "\t0\n};\n";69726973if (LangOpts.MicrosoftExt)6974Result += "static ";6975Result += "struct _protocol_t *";6976Result += "_OBJC_LABEL_PROTOCOL_$_"; Result += PDecl->getNameAsString();6977Result += " = &_OBJC_PROTOCOL_"; Result += PDecl->getNameAsString();6978Result += ";\n";69796980// Mark this protocol as having been generated.6981if (!ObjCSynthesizedProtocols.insert(PDecl->getCanonicalDecl()).second)6982llvm_unreachable("protocol already synthesized");6983}69846985/// hasObjCExceptionAttribute - Return true if this class or any super6986/// class has the __objc_exception__ attribute.6987/// FIXME. Move this to ASTContext.cpp as it is also used for IRGen.6988static bool hasObjCExceptionAttribute(ASTContext &Context,6989const ObjCInterfaceDecl *OID) {6990if (OID->hasAttr<ObjCExceptionAttr>())6991return true;6992if (const ObjCInterfaceDecl *Super = OID->getSuperClass())6993return hasObjCExceptionAttribute(Context, Super);6994return false;6995}69966997void RewriteModernObjC::RewriteObjCClassMetaData(ObjCImplementationDecl *IDecl,6998std::string &Result) {6999ObjCInterfaceDecl *CDecl = IDecl->getClassInterface();70007001// Explicitly declared @interface's are already synthesized.7002if (CDecl->isImplicitInterfaceDecl())7003assert(false &&7004"Legacy implicit interface rewriting not supported in moder abi");70057006WriteModernMetadataDeclarations(Context, Result);7007SmallVector<ObjCIvarDecl *, 8> IVars;70087009for (ObjCIvarDecl *IVD = CDecl->all_declared_ivar_begin();7010IVD; IVD = IVD->getNextIvar()) {7011// Ignore unnamed bit-fields.7012if (!IVD->getDeclName())7013continue;7014IVars.push_back(IVD);7015}70167017Write__ivar_list_t_initializer(*this, Context, Result, IVars,7018"_OBJC_$_INSTANCE_VARIABLES_",7019CDecl);70207021// Build _objc_method_list for class's instance methods if needed7022SmallVector<ObjCMethodDecl *, 32> InstanceMethods(IDecl->instance_methods());70237024// If any of our property implementations have associated getters or7025// setters, produce metadata for them as well.7026for (const auto *Prop : IDecl->property_impls()) {7027if (Prop->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic)7028continue;7029if (!Prop->getPropertyIvarDecl())7030continue;7031ObjCPropertyDecl *PD = Prop->getPropertyDecl();7032if (!PD)7033continue;7034if (ObjCMethodDecl *Getter = Prop->getGetterMethodDecl())7035if (mustSynthesizeSetterGetterMethod(IDecl, PD, true /*getter*/))7036InstanceMethods.push_back(Getter);7037if (PD->isReadOnly())7038continue;7039if (ObjCMethodDecl *Setter = Prop->getSetterMethodDecl())7040if (mustSynthesizeSetterGetterMethod(IDecl, PD, false /*setter*/))7041InstanceMethods.push_back(Setter);7042}70437044Write_method_list_t_initializer(*this, Context, Result, InstanceMethods,7045"_OBJC_$_INSTANCE_METHODS_",7046IDecl->getNameAsString(), true);70477048SmallVector<ObjCMethodDecl *, 32> ClassMethods(IDecl->class_methods());70497050Write_method_list_t_initializer(*this, Context, Result, ClassMethods,7051"_OBJC_$_CLASS_METHODS_",7052IDecl->getNameAsString(), true);70537054// Protocols referenced in class declaration?7055// Protocol's super protocol list7056std::vector<ObjCProtocolDecl *> RefedProtocols;7057const ObjCList<ObjCProtocolDecl> &Protocols = CDecl->getReferencedProtocols();7058for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),7059E = Protocols.end();7060I != E; ++I) {7061RefedProtocols.push_back(*I);7062// Must write out all protocol definitions in current qualifier list,7063// and in their nested qualifiers before writing out current definition.7064RewriteObjCProtocolMetaData(*I, Result);7065}70667067Write_protocol_list_initializer(Context, Result,7068RefedProtocols,7069"_OBJC_CLASS_PROTOCOLS_$_",7070IDecl->getNameAsString());70717072// Protocol's property metadata.7073SmallVector<ObjCPropertyDecl *, 8> ClassProperties(7074CDecl->instance_properties());7075Write_prop_list_t_initializer(*this, Context, Result, ClassProperties,7076/* Container */IDecl,7077"_OBJC_$_PROP_LIST_",7078CDecl->getNameAsString());70797080// Data for initializing _class_ro_t metaclass meta-data7081uint32_t flags = CLS_META;7082std::string InstanceSize;7083std::string InstanceStart;70847085bool classIsHidden = CDecl->getVisibility() == HiddenVisibility;7086if (classIsHidden)7087flags |= OBJC2_CLS_HIDDEN;70887089if (!CDecl->getSuperClass())7090// class is root7091flags |= CLS_ROOT;7092InstanceSize = "sizeof(struct _class_t)";7093InstanceStart = InstanceSize;7094Write__class_ro_t_initializer(Context, Result, flags,7095InstanceStart, InstanceSize,7096ClassMethods,7097nullptr,7098nullptr,7099nullptr,7100"_OBJC_METACLASS_RO_$_",7101CDecl->getNameAsString());71027103// Data for initializing _class_ro_t meta-data7104flags = CLS;7105if (classIsHidden)7106flags |= OBJC2_CLS_HIDDEN;71077108if (hasObjCExceptionAttribute(*Context, CDecl))7109flags |= CLS_EXCEPTION;71107111if (!CDecl->getSuperClass())7112// class is root7113flags |= CLS_ROOT;71147115InstanceSize.clear();7116InstanceStart.clear();7117if (!ObjCSynthesizedStructs.count(CDecl)) {7118InstanceSize = "0";7119InstanceStart = "0";7120}7121else {7122InstanceSize = "sizeof(struct ";7123InstanceSize += CDecl->getNameAsString();7124InstanceSize += "_IMPL)";71257126ObjCIvarDecl *IVD = CDecl->all_declared_ivar_begin();7127if (IVD) {7128RewriteIvarOffsetComputation(IVD, InstanceStart);7129}7130else7131InstanceStart = InstanceSize;7132}7133Write__class_ro_t_initializer(Context, Result, flags,7134InstanceStart, InstanceSize,7135InstanceMethods,7136RefedProtocols,7137IVars,7138ClassProperties,7139"_OBJC_CLASS_RO_$_",7140CDecl->getNameAsString());71417142Write_class_t(Context, Result,7143"OBJC_METACLASS_$_",7144CDecl, /*metaclass*/true);71457146Write_class_t(Context, Result,7147"OBJC_CLASS_$_",7148CDecl, /*metaclass*/false);71497150if (ImplementationIsNonLazy(IDecl))7151DefinedNonLazyClasses.push_back(CDecl);7152}71537154void RewriteModernObjC::RewriteClassSetupInitHook(std::string &Result) {7155int ClsDefCount = ClassImplementation.size();7156if (!ClsDefCount)7157return;7158Result += "#pragma section(\".objc_inithooks$B\", long, read, write)\n";7159Result += "__declspec(allocate(\".objc_inithooks$B\")) ";7160Result += "static void *OBJC_CLASS_SETUP[] = {\n";7161for (int i = 0; i < ClsDefCount; i++) {7162ObjCImplementationDecl *IDecl = ClassImplementation[i];7163ObjCInterfaceDecl *CDecl = IDecl->getClassInterface();7164Result += "\t(void *)&OBJC_CLASS_SETUP_$_";7165Result += CDecl->getName(); Result += ",\n";7166}7167Result += "};\n";7168}71697170void RewriteModernObjC::RewriteMetaDataIntoBuffer(std::string &Result) {7171int ClsDefCount = ClassImplementation.size();7172int CatDefCount = CategoryImplementation.size();71737174// For each implemented class, write out all its meta data.7175for (int i = 0; i < ClsDefCount; i++)7176RewriteObjCClassMetaData(ClassImplementation[i], Result);71777178RewriteClassSetupInitHook(Result);71797180// For each implemented category, write out all its meta data.7181for (int i = 0; i < CatDefCount; i++)7182RewriteObjCCategoryImplDecl(CategoryImplementation[i], Result);71837184RewriteCategorySetupInitHook(Result);71857186if (ClsDefCount > 0) {7187if (LangOpts.MicrosoftExt)7188Result += "__declspec(allocate(\".objc_classlist$B\")) ";7189Result += "static struct _class_t *L_OBJC_LABEL_CLASS_$ [";7190Result += llvm::utostr(ClsDefCount); Result += "]";7191Result +=7192" __attribute__((used, section (\"__DATA, __objc_classlist,"7193"regular,no_dead_strip\")))= {\n";7194for (int i = 0; i < ClsDefCount; i++) {7195Result += "\t&OBJC_CLASS_$_";7196Result += ClassImplementation[i]->getNameAsString();7197Result += ",\n";7198}7199Result += "};\n";72007201if (!DefinedNonLazyClasses.empty()) {7202if (LangOpts.MicrosoftExt)7203Result += "__declspec(allocate(\".objc_nlclslist$B\")) \n";7204Result += "static struct _class_t *_OBJC_LABEL_NONLAZY_CLASS_$[] = {\n\t";7205for (unsigned i = 0, e = DefinedNonLazyClasses.size(); i < e; i++) {7206Result += "\t&OBJC_CLASS_$_"; Result += DefinedNonLazyClasses[i]->getNameAsString();7207Result += ",\n";7208}7209Result += "};\n";7210}7211}72127213if (CatDefCount > 0) {7214if (LangOpts.MicrosoftExt)7215Result += "__declspec(allocate(\".objc_catlist$B\")) ";7216Result += "static struct _category_t *L_OBJC_LABEL_CATEGORY_$ [";7217Result += llvm::utostr(CatDefCount); Result += "]";7218Result +=7219" __attribute__((used, section (\"__DATA, __objc_catlist,"7220"regular,no_dead_strip\")))= {\n";7221for (int i = 0; i < CatDefCount; i++) {7222Result += "\t&_OBJC_$_CATEGORY_";7223Result +=7224CategoryImplementation[i]->getClassInterface()->getNameAsString();7225Result += "_$_";7226Result += CategoryImplementation[i]->getNameAsString();7227Result += ",\n";7228}7229Result += "};\n";7230}72317232if (!DefinedNonLazyCategories.empty()) {7233if (LangOpts.MicrosoftExt)7234Result += "__declspec(allocate(\".objc_nlcatlist$B\")) \n";7235Result += "static struct _category_t *_OBJC_LABEL_NONLAZY_CATEGORY_$[] = {\n\t";7236for (unsigned i = 0, e = DefinedNonLazyCategories.size(); i < e; i++) {7237Result += "\t&_OBJC_$_CATEGORY_";7238Result +=7239DefinedNonLazyCategories[i]->getClassInterface()->getNameAsString();7240Result += "_$_";7241Result += DefinedNonLazyCategories[i]->getNameAsString();7242Result += ",\n";7243}7244Result += "};\n";7245}7246}72477248void RewriteModernObjC::WriteImageInfo(std::string &Result) {7249if (LangOpts.MicrosoftExt)7250Result += "__declspec(allocate(\".objc_imageinfo$B\")) \n";72517252Result += "static struct IMAGE_INFO { unsigned version; unsigned flag; } ";7253// version 0, ObjCABI is 27254Result += "_OBJC_IMAGE_INFO = { 0, 2 };\n";7255}72567257/// RewriteObjCCategoryImplDecl - Rewrite metadata for each category7258/// implementation.7259void RewriteModernObjC::RewriteObjCCategoryImplDecl(ObjCCategoryImplDecl *IDecl,7260std::string &Result) {7261WriteModernMetadataDeclarations(Context, Result);7262ObjCInterfaceDecl *ClassDecl = IDecl->getClassInterface();7263// Find category declaration for this implementation.7264ObjCCategoryDecl *CDecl7265= ClassDecl->FindCategoryDeclaration(IDecl->getIdentifier());72667267std::string FullCategoryName = ClassDecl->getNameAsString();7268FullCategoryName += "_$_";7269FullCategoryName += CDecl->getNameAsString();72707271// Build _objc_method_list for class's instance methods if needed7272SmallVector<ObjCMethodDecl *, 32> InstanceMethods(IDecl->instance_methods());72737274// If any of our property implementations have associated getters or7275// setters, produce metadata for them as well.7276for (const auto *Prop : IDecl->property_impls()) {7277if (Prop->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic)7278continue;7279if (!Prop->getPropertyIvarDecl())7280continue;7281ObjCPropertyDecl *PD = Prop->getPropertyDecl();7282if (!PD)7283continue;7284if (ObjCMethodDecl *Getter = Prop->getGetterMethodDecl())7285InstanceMethods.push_back(Getter);7286if (PD->isReadOnly())7287continue;7288if (ObjCMethodDecl *Setter = Prop->getSetterMethodDecl())7289InstanceMethods.push_back(Setter);7290}72917292Write_method_list_t_initializer(*this, Context, Result, InstanceMethods,7293"_OBJC_$_CATEGORY_INSTANCE_METHODS_",7294FullCategoryName, true);72957296SmallVector<ObjCMethodDecl *, 32> ClassMethods(IDecl->class_methods());72977298Write_method_list_t_initializer(*this, Context, Result, ClassMethods,7299"_OBJC_$_CATEGORY_CLASS_METHODS_",7300FullCategoryName, true);73017302// Protocols referenced in class declaration?7303// Protocol's super protocol list7304SmallVector<ObjCProtocolDecl *, 8> RefedProtocols(CDecl->protocols());7305for (auto *I : CDecl->protocols())7306// Must write out all protocol definitions in current qualifier list,7307// and in their nested qualifiers before writing out current definition.7308RewriteObjCProtocolMetaData(I, Result);73097310Write_protocol_list_initializer(Context, Result,7311RefedProtocols,7312"_OBJC_CATEGORY_PROTOCOLS_$_",7313FullCategoryName);73147315// Protocol's property metadata.7316SmallVector<ObjCPropertyDecl *, 8> ClassProperties(7317CDecl->instance_properties());7318Write_prop_list_t_initializer(*this, Context, Result, ClassProperties,7319/* Container */IDecl,7320"_OBJC_$_PROP_LIST_",7321FullCategoryName);73227323Write_category_t(*this, Context, Result,7324CDecl,7325ClassDecl,7326InstanceMethods,7327ClassMethods,7328RefedProtocols,7329ClassProperties);73307331// Determine if this category is also "non-lazy".7332if (ImplementationIsNonLazy(IDecl))7333DefinedNonLazyCategories.push_back(CDecl);7334}73357336void RewriteModernObjC::RewriteCategorySetupInitHook(std::string &Result) {7337int CatDefCount = CategoryImplementation.size();7338if (!CatDefCount)7339return;7340Result += "#pragma section(\".objc_inithooks$B\", long, read, write)\n";7341Result += "__declspec(allocate(\".objc_inithooks$B\")) ";7342Result += "static void *OBJC_CATEGORY_SETUP[] = {\n";7343for (int i = 0; i < CatDefCount; i++) {7344ObjCCategoryImplDecl *IDecl = CategoryImplementation[i];7345ObjCCategoryDecl *CatDecl= IDecl->getCategoryDecl();7346ObjCInterfaceDecl *ClassDecl = IDecl->getClassInterface();7347Result += "\t(void *)&OBJC_CATEGORY_SETUP_$_";7348Result += ClassDecl->getName();7349Result += "_$_";7350Result += CatDecl->getName();7351Result += ",\n";7352}7353Result += "};\n";7354}73557356// RewriteObjCMethodsMetaData - Rewrite methods metadata for instance or7357/// class methods.7358template<typename MethodIterator>7359void RewriteModernObjC::RewriteObjCMethodsMetaData(MethodIterator MethodBegin,7360MethodIterator MethodEnd,7361bool IsInstanceMethod,7362StringRef prefix,7363StringRef ClassName,7364std::string &Result) {7365if (MethodBegin == MethodEnd) return;73667367if (!objc_impl_method) {7368/* struct _objc_method {7369SEL _cmd;7370char *method_types;7371void *_imp;7372}7373*/7374Result += "\nstruct _objc_method {\n";7375Result += "\tSEL _cmd;\n";7376Result += "\tchar *method_types;\n";7377Result += "\tvoid *_imp;\n";7378Result += "};\n";73797380objc_impl_method = true;7381}73827383// Build _objc_method_list for class's methods if needed73847385/* struct {7386struct _objc_method_list *next_method;7387int method_count;7388struct _objc_method method_list[];7389}7390*/7391unsigned NumMethods = std::distance(MethodBegin, MethodEnd);7392Result += "\n";7393if (LangOpts.MicrosoftExt) {7394if (IsInstanceMethod)7395Result += "__declspec(allocate(\".inst_meth$B\")) ";7396else7397Result += "__declspec(allocate(\".cls_meth$B\")) ";7398}7399Result += "static struct {\n";7400Result += "\tstruct _objc_method_list *next_method;\n";7401Result += "\tint method_count;\n";7402Result += "\tstruct _objc_method method_list[";7403Result += utostr(NumMethods);7404Result += "];\n} _OBJC_";7405Result += prefix;7406Result += IsInstanceMethod ? "INSTANCE" : "CLASS";7407Result += "_METHODS_";7408Result += ClassName;7409Result += " __attribute__ ((used, section (\"__OBJC, __";7410Result += IsInstanceMethod ? "inst" : "cls";7411Result += "_meth\")))= ";7412Result += "{\n\t0, " + utostr(NumMethods) + "\n";74137414Result += "\t,{{(SEL)\"";7415Result += (*MethodBegin)->getSelector().getAsString().c_str();7416std::string MethodTypeString;7417Context->getObjCEncodingForMethodDecl(*MethodBegin, MethodTypeString);7418Result += "\", \"";7419Result += MethodTypeString;7420Result += "\", (void *)";7421Result += MethodInternalNames[*MethodBegin];7422Result += "}\n";7423for (++MethodBegin; MethodBegin != MethodEnd; ++MethodBegin) {7424Result += "\t ,{(SEL)\"";7425Result += (*MethodBegin)->getSelector().getAsString().c_str();7426std::string MethodTypeString;7427Context->getObjCEncodingForMethodDecl(*MethodBegin, MethodTypeString);7428Result += "\", \"";7429Result += MethodTypeString;7430Result += "\", (void *)";7431Result += MethodInternalNames[*MethodBegin];7432Result += "}\n";7433}7434Result += "\t }\n};\n";7435}74367437Stmt *RewriteModernObjC::RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV) {7438SourceRange OldRange = IV->getSourceRange();7439Expr *BaseExpr = IV->getBase();74407441// Rewrite the base, but without actually doing replaces.7442{7443DisableReplaceStmtScope S(*this);7444BaseExpr = cast<Expr>(RewriteFunctionBodyOrGlobalInitializer(BaseExpr));7445IV->setBase(BaseExpr);7446}74477448ObjCIvarDecl *D = IV->getDecl();74497450Expr *Replacement = IV;74517452if (BaseExpr->getType()->isObjCObjectPointerType()) {7453const ObjCInterfaceType *iFaceDecl =7454dyn_cast<ObjCInterfaceType>(BaseExpr->getType()->getPointeeType());7455assert(iFaceDecl && "RewriteObjCIvarRefExpr - iFaceDecl is null");7456// lookup which class implements the instance variable.7457ObjCInterfaceDecl *clsDeclared = nullptr;7458iFaceDecl->getDecl()->lookupInstanceVariable(D->getIdentifier(),7459clsDeclared);7460assert(clsDeclared && "RewriteObjCIvarRefExpr(): Can't find class");74617462// Build name of symbol holding ivar offset.7463std::string IvarOffsetName;7464if (D->isBitField())7465ObjCIvarBitfieldGroupOffset(D, IvarOffsetName);7466else7467WriteInternalIvarName(clsDeclared, D, IvarOffsetName);74687469ReferencedIvars[clsDeclared].insert(D);74707471// cast offset to "char *".7472CastExpr *castExpr = NoTypeInfoCStyleCastExpr(Context,7473Context->getPointerType(Context->CharTy),7474CK_BitCast,7475BaseExpr);7476VarDecl *NewVD = VarDecl::Create(*Context, TUDecl, SourceLocation(),7477SourceLocation(), &Context->Idents.get(IvarOffsetName),7478Context->UnsignedLongTy, nullptr,7479SC_Extern);7480DeclRefExpr *DRE = new (Context)7481DeclRefExpr(*Context, NewVD, false, Context->UnsignedLongTy,7482VK_LValue, SourceLocation());7483BinaryOperator *addExpr = BinaryOperator::Create(7484*Context, castExpr, DRE, BO_Add,7485Context->getPointerType(Context->CharTy), VK_PRValue, OK_Ordinary,7486SourceLocation(), FPOptionsOverride());7487// Don't forget the parens to enforce the proper binding.7488ParenExpr *PE = new (Context) ParenExpr(SourceLocation(),7489SourceLocation(),7490addExpr);7491QualType IvarT = D->getType();7492if (D->isBitField())7493IvarT = GetGroupRecordTypeForObjCIvarBitfield(D);74947495if (!IvarT->getAs<TypedefType>() && IvarT->isRecordType()) {7496RecordDecl *RD = IvarT->castAs<RecordType>()->getDecl();7497RD = RD->getDefinition();7498if (RD && !RD->getDeclName().getAsIdentifierInfo()) {7499// decltype(((Foo_IMPL*)0)->bar) *7500auto *CDecl = cast<ObjCContainerDecl>(D->getDeclContext());7501// ivar in class extensions requires special treatment.7502if (ObjCCategoryDecl *CatDecl = dyn_cast<ObjCCategoryDecl>(CDecl))7503CDecl = CatDecl->getClassInterface();7504std::string RecName = std::string(CDecl->getName());7505RecName += "_IMPL";7506RecordDecl *RD = RecordDecl::Create(7507*Context, TagTypeKind::Struct, TUDecl, SourceLocation(),7508SourceLocation(), &Context->Idents.get(RecName));7509QualType PtrStructIMPL = Context->getPointerType(Context->getTagDeclType(RD));7510unsigned UnsignedIntSize =7511static_cast<unsigned>(Context->getTypeSize(Context->UnsignedIntTy));7512Expr *Zero = IntegerLiteral::Create(*Context,7513llvm::APInt(UnsignedIntSize, 0),7514Context->UnsignedIntTy, SourceLocation());7515Zero = NoTypeInfoCStyleCastExpr(Context, PtrStructIMPL, CK_BitCast, Zero);7516ParenExpr *PE = new (Context) ParenExpr(SourceLocation(), SourceLocation(),7517Zero);7518FieldDecl *FD = FieldDecl::Create(*Context, nullptr, SourceLocation(),7519SourceLocation(),7520&Context->Idents.get(D->getNameAsString()),7521IvarT, nullptr,7522/*BitWidth=*/nullptr,7523/*Mutable=*/true, ICIS_NoInit);7524MemberExpr *ME = MemberExpr::CreateImplicit(7525*Context, PE, true, FD, FD->getType(), VK_LValue, OK_Ordinary);7526IvarT = Context->getDecltypeType(ME, ME->getType());7527}7528}7529convertObjCTypeToCStyleType(IvarT);7530QualType castT = Context->getPointerType(IvarT);75317532castExpr = NoTypeInfoCStyleCastExpr(Context,7533castT,7534CK_BitCast,7535PE);75367537Expr *Exp = UnaryOperator::Create(7538const_cast<ASTContext &>(*Context), castExpr, UO_Deref, IvarT,7539VK_LValue, OK_Ordinary, SourceLocation(), false, FPOptionsOverride());7540PE = new (Context) ParenExpr(OldRange.getBegin(),7541OldRange.getEnd(),7542Exp);75437544if (D->isBitField()) {7545FieldDecl *FD = FieldDecl::Create(*Context, nullptr, SourceLocation(),7546SourceLocation(),7547&Context->Idents.get(D->getNameAsString()),7548D->getType(), nullptr,7549/*BitWidth=*/D->getBitWidth(),7550/*Mutable=*/true, ICIS_NoInit);7551MemberExpr *ME =7552MemberExpr::CreateImplicit(*Context, PE, /*isArrow*/ false, FD,7553FD->getType(), VK_LValue, OK_Ordinary);7554Replacement = ME;75557556}7557else7558Replacement = PE;7559}75607561ReplaceStmtWithRange(IV, Replacement, OldRange);7562return Replacement;7563}75647565#endif // CLANG_ENABLE_OBJC_REWRITER756675677568